gs2crmod 0.11.78 → 0.11.79

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,112 +7,112 @@
7
7
  #
8
8
 
9
9
  class NumRu::NetCDF
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
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
- # 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
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
- #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]
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
- @directory + '/' + @run_name + '.out.nc'
50
+ @directory + '/' + @run_name + '.out.nc'
51
51
  end
52
52
 
53
53
 
54
54
  def ncclose
55
- cache[:netcdf_file].close
56
- cache.delete(:netcdf_file)
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
- 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
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
- 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{|i| i.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"
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
- # 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
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
- # 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
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
- 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]
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
- 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]
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
- 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]
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
- 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
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
- 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
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
- #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)
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
- #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
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
- #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
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
- 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"
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
- phi_array = netcdf_file.var("phi2_by_#{kxy}").get('start' => [0, 0], 'end' => [-1, -1]) #index = [kx or ky, t]
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
- 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
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
- def zonal_flow_velocity_over_x_gsl_vector(options)
1036
- Dir.chdir(@directory) do
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
- phi = gsl_vector_complex('phi_zonal', options)
1040
+ phi = gsl_vector_complex('phi_zonal', options)
1041
1041
 
1042
1042
  kx = gsl_vector(:kx).to_box_order
1043
- x = gsl_vector(:x)
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
- end
1060
- end
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
- 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
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
- end
1075
- end
1074
+ end
1075
+ end
1076
1076
 
1077
- def zonal_spectrum_gsl_vector(options)
1078
- Dir.chdir(@directory) do
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
- end
1084
- end
1085
-
1086
- end # module GSLVectors
1083
+ end
1084
+ end
1085
+
1086
+ end # module GSLVectors
1087
1087
  include GSLVectors
1088
1088
 
1089
1089
  def gsl_vector_complex(name, options={})
1090
- options = eval(options) if options.class == String
1090
+ options = eval(options) if options.class == String
1091
1091
 
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
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
- 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
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
- def phi_zonal_gsl_vector_complex(options)
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
- end
1181
- end
1182
- end
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
- 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
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
- 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
- temp = 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
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
- spectrum = spectrum.from_box_order
1303
- #ep spectrum.shape
1304
- spectrum = spectrum*gvky[ky_element]**2 unless options[:phi2_only]
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
- 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
- # Due to a strange GS2 convention, non zonal modes must be divided by 2:
1341
- for i in 1...naky_temp
1342
- for j in 0...ntheta0_temp
1343
- gm[i,j] = gm[i,j]/2.0
1344
- end
1345
- end
1346
-
1347
- if options[:no_zonal]
1348
- for i in 0...gm.shape[1]
1349
- gm[0,i] = GSL::Complex.alloc([0,0])
1350
- end
1351
- end
1352
- if xres = (options[:xres] or options[:x_resolution])
1353
- if xres < nx
1354
- puts "Warning: xres should be at least nx. Using nx instead of the xres you specified."
1355
- xres = nx
1356
- end
1357
- else
1358
- xres = nx
1359
- end
1360
- if yres = (options[:yres] or options[:y_resolution])
1361
- if yres < ny
1362
- puts "Warning: yres should be at least ny. Using ny instead of the yres you specified."
1363
- yres = ny
1364
- end
1365
- else
1366
- yres = ny
1367
- end
1368
-
1369
- # Next, pad with 0's:
1370
- padded = GSL::Matrix::Complex.calloc(yres, xres)
1371
- # Zonal modes first:
1372
- for ix in 0...((ntheta0_temp+1)/2)
1373
- padded[0, ix] = gm[0, ix]
1374
- end
1375
- for ix in ((ntheta0_temp+1)/2)...ntheta0_temp
1376
- padded[0, ix+xres-ntheta0_temp] = gm[0, ix]
1377
- end
1378
- # Now include the non-zonal modes in the padded matrix mat:
1379
- for iy in 1...naky_temp
1380
- for ix in 0...((ntheta0_temp + 1)/2)
1381
- padded[iy, ix] = gm[iy, ix]
1382
- end
1383
- for ix in ((ntheta0_temp+1)/2)...ntheta0_temp
1384
- padded[iy, ix+xres-ntheta0_temp] = gm[iy, ix]
1385
- end
1386
- padded[yres-iy, 0] = gm[iy,0].conj
1387
- for ix in 1...xres
1388
- padded[yres-iy, ix] = padded[iy, xres-ix].conj
1389
- end
1390
- end
1391
- gm = padded
1392
-
1393
- gm = gm.backward_cols_c2c(false).backward_rows_c2c(false)
1394
- # At this point, gm should be purely real (within machine precision), but let's check to be sure:
1395
- should_be_zero = gm.imag.abs.max
1396
- if should_be_zero > 1.0e-10
1397
- puts "should_be_zero = #{should_be_zero}"
1398
- raise "Something went wrong - reconstructed phi is not purely real."
1399
- end
1400
-
1401
- gm = gm.real
1402
-
1403
- if options[:limit]
1404
- for i in 0...gm.shape[0]
1405
- for j in 0...gm.shape[1]
1406
- gm[i, j] = [[gm[i,j], options[:limit][0]].max, options[:limit][1]].min
1407
- end
1408
- end
1409
- end
1410
-
1411
- return gm
1412
- end
1413
- end
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
- # ep options
1420
- return 0 unless @g_exb and @g_exb.abs > 0.0
1421
- #p options
1422
- return - list(:ky)[options[:ky_index]] * list(:t)[(options[:t_index] or list(:t).keys.max)] * @g_exb
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
- # ep 'kx_shift', kx_shift(options)
1427
- jump = ((kx_shift(options) / list(:kx)[2]).round)
1428
- case options[:t_index]
1429
- when 1
1430
- return jump
1431
- else
1432
- if @g_exb and @g_exb.abs > 0
1433
- return jump + 1
1434
- else
1435
- return 0
1436
- end
1437
- end
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
- # ikx_indexed (it+1-itmin(1)) = it
1454
- # end do
1455
- #
1456
- # do it=1,itmin(1)-1
1457
- # ikx_indexed (ntheta0 - itmin(1) + 1 + it)= it
1458
- # end do
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
- #eputs "Start eulerian_kx_index"
1474
- lagrangian_kx_index = options[:kx_index]
1475
- phys = physical_kx_index(lagrangian_kx_index)
1476
- #ep 'jump', jump(options)
1477
- index = phys + jump(options)
1478
- raise ArgumentError.new("Lagrangian kx out of range") if index <= 0
1479
- box= box_kx_index(index)
1480
- #eputs "End eulerian_kx_index"
1481
- return box
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
- return cache[:kx_indexed] if cache[:kx_indexed]
1486
- #kx = cache[:kx_array] ||= gsl_vector('kx').to_a
1487
- #kxphys = kx.from_box_order
1488
- #min_index = kx.min_index + 1
1489
- #cache[:kx_indexed] ||= kx.size.times.inject({}) do |hash, kx_element|
1490
- #hash[kx_element + 1] = kxphs
1491
- kx = gsl_vector('kx')
1492
- size = kx.size
1493
- box = GSL::Vector::Int.indgen(size) + 1
1494
- zero_element = kx.abs.min_index
1495
- phys = box.subvector(zero_element, size-zero_element).connect(box.subvector(0, zero_element))
1496
- cache[:kx_indexed] = [phys.to_a, box.to_a].transpose.inject({}){|hash, (phys, box)| hash[phys] = box; hash}
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
- return kx_indexed[physical_kx_index]
1502
+ return kx_indexed[physical_kx_index]
1502
1503
  end
1503
1504
 
1504
1505
  def physical_kx_index(box_kx_index)
1505
- return kx_indexed.key(box_kx_index)
1506
- kx = cache[:kx_gslv] ||= gsl_vector('kx')
1507
- return kx.from_box_order.to_a.index(kx[box_kx_index-1]) + 1
1508
- #kx = cache[:kx_gslv] ||= gsl_vector('kx')
1509
- #index_of_min_kx = cache[:index_of_min_kx] ||= kx.min_index + 1 # kx.min_index returns a 0-based index
1510
- #if box_kx_index < index_of_min_kx
1511
- #box_kx_index + (1 + kx.size - index_of_min_kx)
1512
- #else
1513
- #box_kx_index - (index_of_min_kx - 1)
1514
- #end
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
- options = eval(options) if options.class == String
1522
- # p @directory
1523
- Dir.chdir(@directory) do
1524
- # eputs Dir.pwd
1525
- case name
1526
- when /correcting_phase/
1527
- # options.convert_to_index(self, :ky)
1528
- # theta0 = (options[:theta0] or 0)
1529
- # # p 'options[:ky_index]', options[:ky_index]
1530
- # 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
1531
- # p 'phase_array', phase_array
1532
- # thetaelement0 = (list(:theta).key(0.0) - 1).to_i
1533
- # p 'list(:theta)[thetaelement0 + 1]', list(:theta)[thetaelement0 + 1]
1534
- # p 'thetaelement0', thetaelement0
1535
- # p 'theta0 - jump(options)', theta0 - jump(options) % @jtwist
1536
- # p 'list(:kx)[2] * (theta0 - jump(options)%@jtwist)', list(:kx)[2] * (theta0 - jump(options)%@jtwist)
1537
- # kx_element = list(:kx).key(list(:kx)[2] * (theta0 - jump(options)%@jtwist)) - 1
1538
- # 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
1539
- # p 'at_0', at_0
1540
- # at_0 = GSL::Complex.alloc(at_0)
1541
- # p 'at_0', at_0
1542
- # return (at_0 / at_0.mag).conj
1543
- # # pp 'theta0', theta0
1544
- # # pp phase_array[5][theta0]
1545
- # return GSL::Complex.alloc(phase_array)
1546
- # # new_options = options.dup
1547
- # new_options[:imrc] = :real
1548
- # thetas = gsl_vector('theta_along_field_line', new_options)
1549
- # at_0 = gsl_vector_complex('phi_along_field_line', new_options)[.to_a.index(0.0)]
1550
- # p at_0
1551
- exit
1552
- else
1553
- raise CRError.new("Unknown gsl_complex requested: #{name}")
1554
- end
1555
- # eputs data; gets
1556
- end
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
- # if options[:t_index] or options[:frame_index]
1561
- # return get_gsl_matrix(name, options)
1562
- # else
1563
- # return cache[[:gsl_vector, name, options]] ||= get_gsl_matrix(name, options)
1564
- # end
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