gs2crmod 0.11.78 → 0.11.79

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