gs2crmod 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +4 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +56 -0
  7. data/VERSION +1 -0
  8. data/ext/extconf.rb +9 -0
  9. data/ext/gs2crmod_ext.c +366 -0
  10. data/gs2crmod.gemspec +98 -0
  11. data/include/gs2crmod_ext.h +58 -0
  12. data/lib/gs2crmod/astrogk/astrogk.rb +201 -0
  13. data/lib/gs2crmod/astrogk/calculations.rb +57 -0
  14. data/lib/gs2crmod/astrogk/check_convergence.rb +7 -0
  15. data/lib/gs2crmod/astrogk/deleted_variables.rb +76 -0
  16. data/lib/gs2crmod/astrogk/graphs.rb +13 -0
  17. data/lib/gs2crmod/astrogk/gsl_data.rb +13 -0
  18. data/lib/gs2crmod/astrogk/gsl_tools.rb +182 -0
  19. data/lib/gs2crmod/astrogk/ingen.rb +18 -0
  20. data/lib/gs2crmod/astrogk/input_file_tools.rb +7 -0
  21. data/lib/gs2crmod/astrogk/namelist_tools.rb +14 -0
  22. data/lib/gs2crmod/astrogk/namelists.rb +2800 -0
  23. data/lib/gs2crmod/astrogk/properties.rb +17 -0
  24. data/lib/gs2crmod/astrogk/species_dependent_namelists.rb +228 -0
  25. data/lib/gs2crmod/astrogk/test_gs2.rb +231 -0
  26. data/lib/gs2crmod/astrogk.rb +200 -0
  27. data/lib/gs2crmod/calculations.rb +780 -0
  28. data/lib/gs2crmod/check_convergence.rb +179 -0
  29. data/lib/gs2crmod/deleted_variables.rb +916 -0
  30. data/lib/gs2crmod/graphs.rb +1899 -0
  31. data/lib/gs2crmod/graphs_rdoc.rb +556 -0
  32. data/lib/gs2crmod/gs2.rb +1143 -0
  33. data/lib/gs2crmod/gsl_data.rb +1181 -0
  34. data/lib/gs2crmod/gsl_data_3d.rb +705 -0
  35. data/lib/gs2crmod/gsl_tools.rb +187 -0
  36. data/lib/gs2crmod/ingen.rb +218 -0
  37. data/lib/gs2crmod/namelists.rb +5142 -0
  38. data/lib/gs2crmod/properties.rb +22 -0
  39. data/lib/gs2crmod/species_dependent_namelists.rb +228 -0
  40. data/lib/gs2crmod/test_gs2.rb +231 -0
  41. data/lib/gs2crmod.rb +2 -0
  42. data/lib/gs2crmod_extension.rb +1 -0
  43. data/test/helper.rb +18 -0
  44. data/test/test_gs2crmod.rb +7 -0
  45. metadata +176 -0
@@ -0,0 +1,780 @@
1
+ ##########################################
2
+ # Calculations for GS2 Code Runner Module
3
+ #
4
+ # This module contains any methods that
5
+ # begin with the word calculate.
6
+ #
7
+ # These methods calculate results and
8
+ # quantities that are not directly
9
+ # obtainable from the GS2 output files.
10
+ #
11
+ ##########################################
12
+
13
+
14
+ class CodeRunner
15
+ class Gs2
16
+
17
+
18
+
19
+ def calculate_time_averaged_fluxes
20
+ eputs 'Calculating time averaged fluxes'
21
+ calculate_saturation_time_index unless @saturation_time_index
22
+ return unless FileTest.exist?("#@run_name.out.nc")
23
+ @hflux_tot_stav = saturated_time_average('hflux_tot_over_time', {})
24
+ @hflux_tot_stav_error = saturated_time_average_error('hflux_tot_over_time', {})
25
+ @phi2_tot_stav = saturated_time_average('phi2tot_over_time', {})
26
+ #@par_mom_flux_stav = saturated_time_average('par_mom_flux_over_time', {}) rescue nil
27
+ #@perp_mom_flux_stav = saturated_time_average('perp_mom_flux_over_time', {}) rescue nil
28
+ @es_mom_flux_stav = {}
29
+ @es_heat_flux_stav = {}
30
+ @es_mom_flux_stav_error = {}
31
+ @es_heat_flux_stav_error = {}
32
+
33
+ @nspec.times do |i|
34
+ species_index = i + 1
35
+ @es_mom_flux_stav[species_index] = saturated_time_average('es_mom_flux_over_time', {species_index: species_index})
36
+ @es_heat_flux_stav[species_index] = saturated_time_average('es_heat_flux_over_time', {species_index: species_index})
37
+ @es_mom_flux_stav_error[species_index] = saturated_time_average_error('es_mom_flux_over_time', {species_index: species_index})
38
+ @es_heat_flux_stav_error[species_index] = saturated_time_average_error('es_heat_flux_over_time', {species_index: species_index})
39
+ end
40
+ # ep @es_mom_flux_stav, @es_heat_flux_stav
41
+ end
42
+
43
+ alias :ctaf :calculate_time_averaged_fluxes
44
+
45
+ def saturated_time_average(name, options)
46
+ # calculate_saturation_time_index unless @saturation_time_index
47
+ # p 'sat', @saturation_time_index, 'max', list(:t).keys.max
48
+ raise "saturation_time_index not calculated for #@run_name" unless @saturation_time_index
49
+ options[:t_index_window] = [@saturation_time_index, list(:t).keys.max - 1]
50
+ #ep gsl_vector(name, {}).size
51
+ #ep name, options
52
+ begin
53
+ vec = gsl_vector(name, options)
54
+ rescue GSL::ERROR::EINVAL
55
+ # IF the vector doesn't have enough values for each timestep (due to run aborting early?), this error will be thrown.
56
+ options[:t_index_window] = [@saturation_time_index, gsl_vector(name, {}).size]
57
+ retry
58
+ rescue NoMethodError
59
+ eputs "Warning: could not calculate #{name} saturated time average"
60
+ return nil
61
+ end
62
+
63
+
64
+ tvec = gsl_vector('t', options)
65
+
66
+
67
+ dt = tvec.subvector(1, tvec.size - 1) - tvec.subvector(0, tvec.size - 1)
68
+ trapezium = (vec.subvector(1, tvec.size - 1) + vec.subvector(0, tvec.size - 1)) / 2.0
69
+ return trapezium.mul(dt).sum / dt.sum
70
+ end
71
+
72
+ def saturated_time_average_error(name, options)
73
+ # calculate_saturation_time_index unless @saturation_time_index
74
+ options[:t_index_window] = [@saturation_time_index, list(:t).keys.max]
75
+ begin
76
+ vec = gsl_vector(name, options)
77
+ tavg = GSL::Vector.alloc(vec.size)
78
+ vec.size.times.each{|i| tavg[i] = vec.subvector(i+1).mean}
79
+ rescue NoMethodError
80
+ eputs "Warning: could not calculate #{name} saturated_time_average_error"
81
+ return nil
82
+ end
83
+ # tavg = 0.0; i = 0
84
+
85
+ # tavg_vec = vec.collect{|val| tavg += val; tavg = tavg / (i+=1); tavg}
86
+ # ind = GSL::Vector.indgen(vec.size)
87
+ # i = 0
88
+ # begin
89
+ # fit = GSL::Fit::linear(ind.subvector(i, ind.size - i) , vec.subvector(i, ind.size - i))
90
+ # # p fit[1].abs - 100.0 * fit[4].abs
91
+ # i += 1
92
+ # (eputs "Not Saturated"; break) if i > vec.size * 0.9
93
+ # end while (fit[1].abs - Math.sqrt(fit[4].abs)) > 0
94
+ # p fit
95
+ # fit_vec = ind * fit[1] + fit[0]
96
+ # # p tavg.size
97
+ # # GraphKit.autocreate({x: {data: gsl_vector(name, {})}})
98
+ # (GraphKit.autocreate({x: {data: tavg}}) + GraphKit.autocreate({x: {data: vec}}) + GraphKit.autocreate({x: {data: fit_vec}})).gnuplot
99
+ return tavg.sd
100
+ end
101
+
102
+
103
+ # I.e. the time at which the primary modes are saturated and the fluxes settle around a long term average.
104
+
105
+ def calculate_saturation_time_index(show_graph = false)
106
+
107
+ eprint "Checking for saturation..."
108
+
109
+ #hflux = gsl_vector('hflux_tot_over_time', {})
110
+ hflux = gsl_vector('phi2tot_over_time', {})
111
+
112
+ #eputs 'got hflux'
113
+ #ep 'hflux', hflux
114
+
115
+ #Check if it's decayed to 0
116
+ if hflux[-1] < 1.0e-10
117
+ for i in 1..hflux.size
118
+ # raise "negative heat flux: #{hflux[-i]} " if hflux[-i] < 0
119
+ (break) unless hflux[- i] < 1.0e-10
120
+ end
121
+ if i > hflux.size * 1.0/10.0 #i.e if was 0 for more than a tenth of the time
122
+ @saturated = true
123
+ @saturation_time_index = hflux.size - i + 1
124
+ eputs "saturation time = #{list(:t)[@saturation_time_index]}"
125
+ GraphKit.quick_create([gsl_vector('t',{}), hflux]).gnuplot(log_axis: 'y') if show_graph
126
+ return
127
+ end
128
+ end
129
+
130
+ # Get initial estimate for saturation time
131
+ for i in 0...hflux.size
132
+ rem = hflux.subvector(i, hflux.size - i)
133
+ break if (hflux[i] - rem.mean).abs < rem.sd / 2.0
134
+ break if i > 3.0/4.0*hflux.size
135
+ end
136
+
137
+ @saturation_time_index = [i + 1, hflux.size - 2].min
138
+
139
+ # fit = GSL::Fit::linear(GSL::Vector.indgen(rem.size), rem)
140
+ #
141
+ # slope, covar11 = fit[1], fit[4]
142
+ # range = [slope + Math.sqrt(covar11), slope - Math.sqrt(covar11)]
143
+ #
144
+ # unless range.min < 0 and range.max > 0
145
+ # eputs "Warning: This run (#{id}) has probably not reached a saturated state: the estimated slope of the heat flux is in this range: #{range.inspect}"
146
+ # @saturated = false
147
+ # end
148
+ #
149
+ # ep fit
150
+
151
+ # eputs "Saturation time estimate', @saturation_time_index = i + 1
152
+ # t_vec[@saturation_time_index - 1]
153
+ max_t_index = list(:t).keys.max
154
+ max_t = list(:t).values.max
155
+ min_t = list(:t).values.min
156
+ #hflux = gsl_vector('hflux_tot_over_time', {:t_index_window => [@saturation_time_index, max_t_index]})
157
+ hflux = gsl_vector('phi2tot_over_time', {:t_index_window => [@saturation_time_index, max_t_index]})
158
+ t_vec = gsl_vector('t', {:t_index_window => [@saturation_time_index, max_t_index]})
159
+ # p t_vec[0]
160
+ i = 0
161
+ t_arr = []; conf_arr = []
162
+ loop do
163
+ eprint '.'
164
+
165
+ # GraphKit.autocreate(x: {data: t_vec}, y: {data: hflux}).gnuplot
166
+
167
+ lomb = GSL::SpectralAnalysis::Lomb.alloc(t_vec.subvector(i, t_vec.size - i), hflux.subvector(i, hflux.size - i))
168
+ fs, periodogram = lomb.calculate_periodogram(1.0, 4.0, [0]) #(1.0) #0.1 * hflux.size / ( hflux.size - i))
169
+ # lomb.graphkit.gnuplot
170
+
171
+ # eputs 'Confidence that lowest frequency is not noise is: '
172
+ # pnoise is the probability of the strength of the lowest frequency signal in the heat flux given a hypothesis of gaussian noise. If it is high there is a low likelihood that there is a signal at the lowest frequency: ie. within that window the heat flux has reached a stationary state
173
+ pnoise = lomb.pnull(periodogram[0])
174
+ t_arr.push t_vec[i]; conf_arr.push pnoise
175
+
176
+ (@saturated = true; break) if pnoise > 0.9
177
+ step = (hflux.size / 25.0).to_i
178
+ step = 1 if step==0
179
+ i += step
180
+ #(@saturated = false; i ; break) if (i >= t_vec.size or t_vec[i] > (max_t - min_t) * 2.0 / 3.0 + min_t )
181
+ (@saturated = false; break) if (i >= t_vec.size or t_vec[i] > (max_t - min_t) * 2.0 / 3.0 + min_t )
182
+ @saturation_time_index += step
183
+ # ep '---i,t,size',i, t_vec[i], t_vec.size
184
+ end
185
+ (kit = GraphKit.autocreate({x: {data: t_vec}, y: {data: hflux / hflux.max}}, {x: {data: t_arr}, y: {data: conf_arr}}); kit.data[1].with = 'lp'; kit.gnuplot) if show_graph #(log_axis: 'y')
186
+ # puts
187
+ if @saturated
188
+ # p i
189
+ eputs "saturation time = #{list(:t)[@saturation_time_index]}"
190
+ else
191
+ eputs "run not saturated"
192
+ end
193
+
194
+ return
195
+ exit
196
+ # Get regularly spaced t vector
197
+
198
+ #
199
+ # t_delta_vec = GSL::Vector.alloc(t_vec.size - 1)
200
+ # t_delta_vec.size.times.each{|i| t_delta_vec[i] = t_vec[i+1] - t_vec[i]}
201
+ #
202
+ # ep t_delta_vec.max, t_delta_vec.min
203
+ #
204
+ # even_t = GSL::Vector.linspace(t_vec.min, t_vec.max, ((t_vec.max - t_vec.min) / t_delta_vec.max).round )
205
+ #
206
+ # # even_t = []
207
+ # # tm = t = t_vec[t_delta_vec.max_index]
208
+ #
209
+ # # loop do
210
+ # # even_t.push t
211
+ #
212
+ # #
213
+ # ep even_t.size, t_vec.size
214
+ #
215
+ # min_delt = t_delta_vec.min
216
+ # p even_t.any?{|el| bool = (not t_vec.any?{|ele| (ele - el).abs < 1.0e-1 * min_delt}); ep el if bool; bool}
217
+ #
218
+ # ep t_vec.dup.delete_if{|el| not (el - 71.3).abs < 0.5}
219
+ #
220
+ # exit
221
+
222
+
223
+
224
+
225
+ return
226
+
227
+ # Calculate a series of time averaged segments
228
+ pieces = hflux.pieces(20) # split into 20 pieces
229
+ avgs = GSL::Vector.alloc(pieces.map{|vec| vec.sum/vec.size})
230
+ # Calculate their variance
231
+ mean = (avgs.sum/avgs.size)
232
+ sig = Math.sqrt((avgs.square - mean**2).sum/avgs.size)
233
+ # Discount any at the start which are more than one standard deviation away from the average - they are from the linear growth phase
234
+ t_index = 1
235
+ kept_avgs = avgs.dup
236
+ for i in 0...pieces.size
237
+ if (avgs[i] - mean).abs > sig
238
+ kept_avgs.delete_at(i)
239
+ t_index += pieces[i].size
240
+ else
241
+ break
242
+ end
243
+ end
244
+ eputs "Warning: probably not saturated" if [kept_avgs, kept_avgs.reverse].include? kept_avgs.sort
245
+ ep kept_avgs
246
+ @saturation_time_index = t_index
247
+ # p t_index, list(:t)[t_index]
248
+ end
249
+
250
+ alias :csti :calculate_saturation_time_index
251
+
252
+ def calculate_growth_rates_and_frequencies
253
+ return if @grid_option == "single" and @aky == 0.0 # no meaningful results
254
+ Dir.chdir(@directory) do
255
+ logf(:calculate_growth_rates_and_frequencies)
256
+ logd
257
+
258
+ # get_list_of(:ky, :kx)
259
+ @growth_rates= FloatHash.new
260
+ @real_frequencies = FloatHash.new
261
+ gs2_out = FileUtils.tail(@run_name + ".out", list(:ky).size*list(:kx).size)
262
+ # a = gs2_out.split("\n")
263
+ final_timestep_list = gs2_out #a.slice((a.size-@ky_list.size*@kx_list.size-1)..a.size-1).join("\n")
264
+ log(final_timestep_list.slice(-2..-1))
265
+ # eputs final_timestep_list
266
+ f = LongRegexen::FLOAT.verbatim
267
+ logi(f)
268
+ regex = Regexp.new( "^.*aky=\\s*(?<aky>#{f}).*omav=\\s*(?<re>#{f})\\s*(?<gr>#{f})")
269
+ logi(regex)
270
+ final_timestep_list.gsub(regex) do
271
+ data = $~
272
+ # eputs data.inspect; gets
273
+ #raise CRFatal.new("Unknown value of ky read from output file: #{data[:aky].to_f}. Not in list:\n#{list(:ky).values.inspect}")
274
+
275
+ next unless (list(:ky).values).include? data[:aky].to_f
276
+ #@growth_rates[data[:aky].to_f] = data[:gr].to_f
277
+ aky = data[:aky].to_f
278
+ next if aky==0.0
279
+ @real_frequencies[data[:aky].to_f] = data[:re].to_f
280
+ end
281
+ # pp @ky_list
282
+
283
+ # With zero magnetic shear, calculate growth rates for both kx and ky
284
+ if @shat and @shat.abs < 1.0e-5 and @nx and @nx > 1
285
+ to_calc = [:kx, :ky]
286
+ @growth_rate_at_kx ||= FloatHash.new
287
+ else
288
+ to_calc = [:ky]
289
+ end
290
+
291
+ @growth_rate_at_ky ||= FloatHash.new
292
+ eputs
293
+ # p @growth_rate_at_kx; exit
294
+ to_calc.each do |kxy|
295
+ growth_rates = send(:growth_rate_at_ + kxy)
296
+ list(kxy).values.sort.each do |value|
297
+
298
+ #p growth_rates.keys, value, growth_rates[value.to_f-0.0],
299
+ #growth_rates.class, growth_rates.keys.include?(value); exit
300
+
301
+ next if growth_rates.keys.include? value
302
+
303
+
304
+ Terminal.erewind(1)
305
+ #ep growth_rates.keys
306
+ eputs sprintf("Calculating growth rate for #{kxy} = % 1.5e#{Terminal::CLEAR_LINE}", value)
307
+
308
+
309
+ # Mode has 0 growth rate at ky==0
310
+ (growth_rates[value] = 0.0; next) if value == 0.0 and kxy == :ky
311
+ if @g_exb_start_timestep
312
+ t_index_window = [1, [(g_exb_start_timestep-1)/@nwrite, list(:t).keys.max].min]
313
+ #ep "t_index_window", t_index_window
314
+ else
315
+ t_index_window = nil
316
+ end
317
+ if list(kxy).size == 1
318
+ phi2_vec = gsl_vector("phi2tot_over_time", t_index_window: t_index_window)
319
+ else
320
+ phi2_vec = gsl_vector("phi2_by_#{kxy}_over_time", kxy=>value, :t_index_window=> t_index_window)
321
+ end
322
+ (growth_rates[value] = 0.0; next) if phi2_vec.min <= 0.0
323
+ growth_rates[value] = calculate_growth_rate(phi2_vec)
324
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rate\n----------\n\n"; growth_rates[value] = -1; next) if growth_rates[value] == "NaN"
325
+ end
326
+ end
327
+
328
+ write_results
329
+
330
+ # ep "growth_rate_at_ky", @growth_rate_at_ky
331
+ if ENV['GS2_CALCULATE_ALL']
332
+ trap(0){eputs "Calculation of spectrum did not complete: run 'cgrf' (i.e. calculate_growth_rates_and_frequencies) for this run. E.g. from the command line \n $ coderunner rc 'cgrf' -j #{@id}"; exit}
333
+ @growth_rate_at_ky_at_kx ||= FloatHash.new
334
+ list(:ky).values.sort.each do |kyv|
335
+ @growth_rate_at_ky_at_kx[kyv] ||= FloatHash.new
336
+ #p @growth_rate_at_ky_at_kx[kyv]
337
+ list(:kx).values.sort.each do |kxv|
338
+ next if @growth_rate_at_ky_at_kx[kyv].keys.include? kxv
339
+ Terminal.erewind(1)
340
+ eputs sprintf("Calculating growth rate for kx = % 1.5e and ky = % 1.5e#{Terminal::CLEAR_LINE}", kxv, kyv)
341
+ (@growth_rate_at_ky_at_kx[kyv][kxv] = 0.0; next) if kyv == 0.0 # Mode has 0 growth rate at ky==0
342
+ phi2_vec = gsl_vector("phi2_by_mode_over_time", {:kx=>kxv, :ky=>kyv})
343
+ (@growth_rate_at_ky_at_kx[kyv][kxv] = 0.0; next) if phi2_vec.min <= 0.0
344
+ @growth_rate_at_ky_at_kx[kyv][kxv] = calculate_growth_rate(phi2_vec)
345
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rates\n----------\n\n"; @growth_rate_at_ky_at_kx[kyv][kxv] = -1; next) if @growth_rate_at_ky_at_kx[kyv][kxv] == "NaN"
346
+ end
347
+ write_results
348
+ end
349
+ trap(0){}
350
+ end
351
+ @growth_rates = @growth_rate_at_ky
352
+ @max_growth_rate = @growth_rates.values.max
353
+ @fastest_growing_mode = @growth_rates.key(@max_growth_rate)
354
+ @freq_of_max_growth_rate = @real_frequencies[@fastest_growing_mode]
355
+ ep @max_growth_rate, @growth_rates
356
+ @decaying = (@max_growth_rate < 0) if @max_growth_rate
357
+ @ky = @aky if @aky
358
+ if @grid_option == "single"
359
+ # ep @aky, @growth_rates
360
+ @gamma_r = @growth_rates[@aky.to_f]
361
+ @gamma_i = @real_frequencies[@aky.to_f]
362
+ end
363
+ # ep @gamma_r
364
+
365
+
366
+ # eputs @growth_rates; gets
367
+ end
368
+ end
369
+
370
+ alias :cgrf :calculate_growth_rates_and_frequencies
371
+
372
+ def calculate_growth_rate(vector, options={})
373
+ raise "This vector should be positive definite" if vector.min < 0.0
374
+ offset = 0
375
+ length = vector.length
376
+ offset+=1 while vector[offset] == 0.0
377
+ growth_rate = GSL::Fit::linear(gsl_vector(:t).subvector(offset, length-offset), 0.5*GSL::Sf::log(vector.subvector(offset, length - offset)))[1]
378
+ divisor = 1
379
+ while (growth_rate.to_s == "NaN")
380
+ #This corrects the growth rate if phi has grown all the way to NaN during the simulation
381
+ divisor *= 2
382
+ length = (vector.size.to_f / divisor.to_f).floor
383
+ # p length
384
+ return "NaN" if length <= offset + 1
385
+ growth_rate = GSL::Fit::linear(gsl_vector(:t).subvector(offset, length-offset), 0.5*GSL::Sf::log(vector.subvector(offset, length-offset)))[1]
386
+ end
387
+ growth_rate
388
+ end
389
+
390
+ # Not needed for GS2 built after 16/06/2010
391
+
392
+ def corrected_mom_flux_stav
393
+ par_mom_flux_stav - perp_mom_flux_stav
394
+ end
395
+
396
+ def calculate_transient_amplifications
397
+ return if @grid_option == "single" and @aky == 0.0 # no meaningful results
398
+ Dir.chdir(@directory) do
399
+ # With zero magnetic shear, calculate amplifications for both kx and ky
400
+ if @shat and @shat.abs < 1.0e-5 and @nx > 1
401
+ to_calc = [:kx, :ky]
402
+ @transient_amplification_at_kx ||= FloatHash.new
403
+ else
404
+ to_calc = [:ky]
405
+ end
406
+
407
+ @transient_amplification_at_ky ||= FloatHash.new
408
+ eputs
409
+ to_calc.each do |kxy|
410
+ transient_amplifications = send(:transient_amplification_at_ + kxy)
411
+ list(kxy).values.sort.each do |value|
412
+
413
+ #p transient_amplifications.keys, value, transient_amplifications[value.to_f-0.0],
414
+ #transient_amplifications.class, transient_amplifications.keys.include?(value); exit
415
+
416
+ next if transient_amplifications.keys.include? value
417
+
418
+
419
+ Terminal.erewind(1)
420
+ #ep transient_amplifications.keys
421
+ eputs sprintf("Calculating transient amplification for #{kxy} = % 1.5e#{Terminal::CLEAR_LINE}", value)
422
+
423
+
424
+ # Mode has 0 growth rate at ky==0
425
+ (transient_amplifications[value] = 0.0; next) if value == 0.0 and kxy == :ky
426
+ phi2_vec = gsl_vector("phi2_by_#{kxy}_over_time", {kxy=>value})
427
+ #(transient_amplifications[value] = 0.0; next) if phi2_vec.min <= 0.0
428
+ transient_amplifications[value] = calculate_transient_amplification(phi2_vec)
429
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rate\n----------\n\n"; transient_amplifications[value] = -1; next) if transient_amplifications[value].to_s == "NaN"
430
+ end
431
+ end
432
+
433
+ write_results
434
+
435
+ # ep "transient_amplification_at_ky", @transient_amplification_at_ky
436
+ if ENV['GS2_CALCULATE_ALL']
437
+ trap(0){eputs "Calculation of spectrum did not complete: run 'cgrf' (i.e. calculate_transient_amplifications_and_frequencies) for this run. E.g. from the command line \n $ coderunner rc 'cgrf' -j #{@id}"; exit}
438
+ @transient_amplification_at_ky_at_kx ||= FloatHash.new
439
+ list(:ky).values.sort.each do |kyv|
440
+ @transient_amplification_at_ky_at_kx[kyv] ||= FloatHash.new
441
+ #p @transient_amplification_at_ky_at_kx[kyv]
442
+ list(:kx).values.sort.each do |kxv|
443
+ next if @transient_amplification_at_ky_at_kx[kyv].keys.include? kxv
444
+ Terminal.erewind(1)
445
+ eputs sprintf("Calculating growth rate for kx = % 1.5e and ky = % 1.5e#{Terminal::CLEAR_LINE}", kxv, kyv)
446
+ (@transient_amplification_at_ky_at_kx[kyv][kxv] = 0.0; next) if kyv == 0.0 # Mode has 0 growth rate at ky==0
447
+ phi2_vec = gsl_vector("phi2_by_mode_over_time", {:kx=>kxv, :ky=>kyv})
448
+ #(@transient_amplification_at_ky_at_kx[kyv][kxv] = 0.0; next) if phi2_vec.min <= 0.0
449
+ @transient_amplification_at_ky_at_kx[kyv][kxv] = calculate_transient_amplification(phi2_vec)
450
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rates\n----------\n\n"; @transient_amplification_at_ky_at_kx[kyv][kxv] = -1; next) if @transient_amplification_at_ky_at_kx[kyv][kxv].to_s == "NaN"
451
+ end
452
+ write_results
453
+ end
454
+ trap(0){}
455
+ end
456
+ @transient_amplifications = @transient_amplification_at_ky
457
+ @max_transient_amplification = @transient_amplifications.values.max
458
+ @most_amplified_mode = @transient_amplifications.key(@max_transient_amplification)
459
+ #@freq_of_max_transient_amplification = @real_frequencies[@fastest_growing_mode]
460
+ #ep @max_transient_amplification, @transient_amplifications
461
+ #@decaying = (@max_transient_amplification < 0) if @max_transient_amplification
462
+ @ky = @aky if @aky
463
+ #if @grid_option == "single"
464
+ ## ep @aky, @transient_amplifications
465
+ #@gamma_r = @transient_amplifications[@aky.to_f]
466
+ #@gamma_i = @real_frequencies[@aky.to_f]
467
+ #end
468
+ # ep @gamma_r
469
+
470
+
471
+ # eputs @transient_amplifications; gets
472
+ end
473
+ end
474
+
475
+ alias :cta :calculate_transient_amplifications
476
+
477
+
478
+ def calculate_transient_es_heat_flux_amplifications
479
+ return if @grid_option == "single" and @aky == 0.0 # no meaningful results
480
+
481
+ @transient_es_heat_flux_amplification_at_species_at_kx = []
482
+ @transient_es_heat_flux_amplification_at_species_at_ky = []
483
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx = []
484
+ for species_index in 1..nspec
485
+
486
+ Dir.chdir(@directory) do
487
+ # With zero magnetic shear, calculate amplifications for both kx and ky
488
+ if @shat and @shat.abs < 1.0e-5 and @nx > 1 and !@ikx_init and false
489
+ to_calc = [:kx, :ky]
490
+ @transient_es_heat_flux_amplification_at_species_at_kx[species_index-1] ||= FloatHash.new
491
+ else
492
+ to_calc = [:ky]
493
+ end
494
+
495
+ @transient_es_heat_flux_amplification_at_species_at_ky[species_index-1] ||= FloatHash.new
496
+ eputs
497
+ to_calc.each do |kxy|
498
+ transient_es_heat_flux_amplifications = send(:transient_es_heat_flux_amplification_at_species_at_ + kxy)[species_index-1]
499
+ list(kxy).values.sort.each do |value|
500
+
501
+ #p transient_es_heat_flux_amplifications.keys, value, transient_es_heat_flux_amplifications[value.to_f-0.0],
502
+ #transient_es_heat_flux_amplifications.class, transient_es_heat_flux_amplifications.keys.include?(value); exit
503
+
504
+ next if transient_es_heat_flux_amplifications.keys.include? value
505
+
506
+
507
+ Terminal.erewind(1)
508
+ #ep transient_es_heat_flux_amplifications.keys
509
+ eputs sprintf("Calculating transient amplification for #{kxy} = % 1.5e#{Terminal::CLEAR_LINE}", value)
510
+
511
+
512
+ # Mode has 0 growth rate at ky==0
513
+ (transient_es_heat_flux_amplifications[value] = 0.0; next) if value == 0.0 and kxy == :ky
514
+ phi2_vec = gsl_vector("es_heat_by_#{kxy}_over_time", {kxy=>value, species_index: species_index})
515
+ #(transient_es_heat_flux_amplifications[value] = 0.0; next) if phi2_vec.min <= 0.0
516
+ transient_es_heat_flux_amplifications[value] = calculate_transient_amplification(phi2_vec)
517
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rate\n----------\n\n"; transient_es_heat_flux_amplifications[value] = -1; next) if transient_es_heat_flux_amplifications[value].to_s == "NaN"
518
+ end
519
+ end
520
+
521
+ write_results
522
+
523
+ # ep "transient_es_heat_flux_amplification_at_species_at_ky", @transient_es_heat_flux_amplification_at_species_at_ky
524
+ if ENV['GS2_CALCULATE_ALL']
525
+ trap(0){eputs "Calculation of spectrum did not complete: run 'ctehfa' (i.e. calculate_transient_es_heat_flux_amplifications) for this run. E.g. from the command line \n $ coderunner rc 'ctehfa' -j #{@id}"; exit}
526
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1] ||= FloatHash.new
527
+ list(:ky).values.sort.each do |kyv|
528
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv] ||= FloatHash.new
529
+ #p @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[kyv]
530
+ list(:kx).values.sort.each do |kxv|
531
+ next if @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv].keys.include? kxv
532
+ Terminal.erewind(1)
533
+ eputs sprintf("Calculating growth rate for kx = % 1.5e and ky = % 1.5e#{Terminal::CLEAR_LINE}", kxv, kyv)
534
+ (@transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = 0.0; next) if kyv == 0.0 # Mode has 0 growth rate at ky==0
535
+ phi2_vec = gsl_vector("phi2_by_mode_over_time", {:kx=>kxv, :ky=>kyv})
536
+ #(@transient_es_heat_flux_amplification_at_species_at_ky_at_kx[kyv][kxv] = 0.0; next) if phi2_vec.min <= 0.0
537
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = calculate_transient_es_heat_flux_amplification(phi2_vec)
538
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rates\n----------\n\n"; @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = -1; next) if @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv].to_s == "NaN"
539
+ end
540
+ write_results
541
+ end
542
+ trap(0){}
543
+ end
544
+ #@max_transient_es_heat_flux_amplification = @transient_es_heat_flux_amplifications.values.max
545
+ #@most_amplified_mode = @transient_es_heat_flux_amplifications.key(@max_transient_es_heat_flux_amplification)
546
+ #@ky = @aky if @aky
547
+ end
548
+ end # for species_index in 1..nspec
549
+ end
550
+
551
+ def calculate_transient_es_heat_flux_amplifications
552
+ return if @grid_option == "single" and @aky == 0.0 # no meaningful results
553
+ @transient_es_heat_flux_amplification_at_species_at_kx = []
554
+ @transient_es_heat_flux_amplification_at_species_at_ky = []
555
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx = []
556
+ for species_index in 1..nspec
557
+
558
+ Dir.chdir(@directory) do
559
+ #trap(0){eputs "Calculation of transient amplification did not complete: run 'ctehfa' (i.e. calculate_transient_es_heat_flux_amplifications) for this run. E.g. from the command line \n $ coderunner rc 'ctehfa' -j #{@id}"; exit}
560
+ es_heat_flux_narray = netcdf_file.var('es_heat_by_k').get
561
+
562
+ ep es_heat_flux_narray.shape, '', '', ''
563
+ t_size = es_heat_flux_narray.shape[-1]
564
+ temp_es_heat = GSL::Vector.alloc(t_size)
565
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1] ||= FloatHash.new
566
+ ky_index=0
567
+ list(:ky).values.each do |kyv|
568
+ ky_index +=1
569
+ kx_index = 0
570
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv] ||= FloatHash.new
571
+ #p @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[kyv]
572
+ list(:kx).values.each do |kxv|
573
+ kx_index +=1
574
+ next if @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv].keys.include? kxv
575
+ Terminal.erewind(1)
576
+ eputs sprintf("Calculating transient amplification for kx = % 1.5e and ky = % 1.5e#{Terminal::CLEAR_LINE}", kxv, kyv)
577
+ (@transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = 0.0; next) if kyv == 0.0 # Mode has 0 growth rate at ky==0
578
+ #phi2_vec = gsl_vector("phi2_by_mode_over_time", {:kx=>kxv, :ky=>kyv})
579
+
580
+ #ep({kx: kxv})
581
+ #hash = ({kx: kxv})
582
+ #ep(hash.convert_to_index(self, :kx))
583
+ #kx_index = {kx: kxv}.convert_to_index(self, :kx)[:kx_index]
584
+ #ky_index = {ky: kyv}.convert_to_index(self, :ky)[:ky_index]
585
+ #p t_size
586
+ for i in 0...t_size
587
+ #p i
588
+ temp_es_heat[i] = es_heat_flux_narray[kx_index-1, ky_index -1, species_index-1, i]
589
+ #temp_es_heat[i] = es_heat_flux_narray[i, species_index-1, ky_index-1, kx_index-1]
590
+ end
591
+ #(@transient_es_heat_flux_amplification_at_species_at_ky_at_kx[kyv][kxv] = 0.0; next) if phi2_vec.min <= 0.0
592
+ @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = calculate_transient_amplification(temp_es_heat)
593
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rates\n----------\n\n"; @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv] = -1; next) if @transient_es_heat_flux_amplification_at_species_at_ky_at_kx[species_index-1][kyv][kxv].to_s == "NaN"
594
+ end
595
+ write_results
596
+ end
597
+ #trap(0){}
598
+ # With zero magnetic shear, calculate amplifications for both kx and ky
599
+
600
+ #return
601
+ if @shat and @shat.abs < 1.0e-5 and @nx > 1 and !@ikx_init and false
602
+ to_calc = [:kx, :ky]
603
+ @transient_es_heat_flux_amplification_at_species_at_kx[species_index-1] ||= FloatHash.new
604
+ else
605
+ to_calc = [:ky]
606
+ end
607
+
608
+ @transient_es_heat_flux_amplification_at_species_at_ky[species_index-1] ||= FloatHash.new
609
+ eputs
610
+ to_calc.each do |kxy|
611
+ transient_es_heat_flux_amplifications = send(:transient_es_heat_flux_amplification_at_species_at_ + kxy)[species_index-1]
612
+ list(kxy).values.sort.each do |value|
613
+
614
+ #p transient_es_heat_flux_amplifications.keys, value, transient_es_heat_flux_amplifications[value.to_f-0.0],
615
+ #transient_es_heat_flux_amplifications.class, transient_es_heat_flux_amplifications.keys.include?(value); exit
616
+
617
+ next if transient_es_heat_flux_amplifications.keys.include? value
618
+
619
+
620
+ Terminal.erewind(1)
621
+ #ep transient_es_heat_flux_amplifications.keys
622
+ eputs sprintf("Calculating transient amplification for #{kxy} = % 1.5e#{Terminal::CLEAR_LINE}", value)
623
+
624
+
625
+ # Mode has 0 growth rate at ky==0
626
+ (transient_es_heat_flux_amplifications[value] = 0.0; next) if value == 0.0 and kxy == :ky
627
+ phi2_vec = gsl_vector("es_heat_by_#{kxy}_over_time", {kxy=>value, species_index: species_index})
628
+ #(transient_es_heat_flux_amplifications[value] = 0.0; next) if phi2_vec.min <= 0.0
629
+ transient_es_heat_flux_amplifications[value] = calculate_transient_amplification(phi2_vec)
630
+ (eputs "\n\n----------\nIn #@run_name:\n\nphi2_by_#{kxy}_over_time is all NaN; unable to calculate growth rate\n----------\n\n"; transient_es_heat_flux_amplifications[value] = -1; next) if transient_es_heat_flux_amplifications[value].to_s == "NaN"
631
+ end
632
+ end
633
+
634
+ write_results
635
+
636
+ # ep "transient_es_heat_flux_amplification_at_species_at_ky", @transient_es_heat_flux_amplification_at_species_at_ky
637
+
638
+ #@max_transient_es_heat_flux_amplification = @transient_es_heat_flux_amplifications.values.max
639
+ #@most_amplified_mode = @transient_es_heat_flux_amplifications.key(@max_transient_es_heat_flux_amplification)
640
+ #@ky = @aky if @aky
641
+ end # Dir.chdir
642
+ end # for species_index in 1..nspec
643
+ end
644
+
645
+ alias :ctehfa :calculate_transient_es_heat_flux_amplifications
646
+ alias :ctehfa :calculate_transient_es_heat_flux_amplifications
647
+
648
+ def calculate_transient_amplification(vector, options={})
649
+ turning_points = {}
650
+ old = vector[0]
651
+ i = 0
652
+ #for i in i...vector.size
653
+ #new = vector[i]
654
+ #if new > old
655
+ #turning_points[:first_min] = i-1
656
+ #ep "First turning point[#{i}]\n"
657
+ #break
658
+ #end
659
+ #old = new
660
+ #end
661
+
662
+ #for i in i...vector.size
663
+ #new = vector[i]
664
+ #if new < old
665
+ #turning_points[:first_max] = i-1
666
+ #ep "Second turning point[#{i}]\n"
667
+ #break
668
+ #end
669
+ #end
670
+
671
+ #unless turning_points[:first_max] # and turning_points[:first_min]
672
+ #return NaN
673
+ #end
674
+ ##t = gsl_vector('t')
675
+ ##for j in 0...vector.size
676
+ ##break if t[j] > 0.2
677
+ ##end
678
+ #ep "vector[0..5]: #{vector.subvector(0,5)}\n"
679
+ #return Math.sqrt(vector[turning_points[:first_max]]/@phiinit)
680
+ return vector.max/@phiinit
681
+ end
682
+
683
+ def ctan
684
+ list(:ky).each do |(ky_index, ky)|
685
+ eputs "ky: #{ky}"
686
+ phi_vec = gsl_vector("phi2_by_ky_over_time", ky_index: ky_index)
687
+ t_element = 0
688
+ old = phi_vec[0]
689
+
690
+ loop do
691
+ t_element+=1
692
+ #print t_element, ',', phi_vec.size
693
+ new = phi_vec[t_element]
694
+ break if new > old or t_element == phi_vec.size - 1
695
+ old = new
696
+ end
697
+
698
+ if t_element == phi_vec.size - 1
699
+ @transient_amplification_at_ky[ky] = -1
700
+ eputs "No Min"
701
+ next
702
+ end
703
+ first_min = t_element
704
+
705
+ eputs "ky: #{ky}, first_min: #{first_min}"
706
+ loop do
707
+ t_element+=1
708
+ #print t_element, ',', phi_vec.size
709
+ new = phi_vec[t_element]
710
+ break if new < old or t_element == phi_vec.size - 1
711
+ end
712
+ if t_element == phi_vec.size - 1
713
+ @transient_amplification_at_ky[ky] = -1
714
+ next
715
+ end
716
+ @transient_amplification_at_ky[ky] = phi_vec.subvector(t_element, phi_vec.size - t_element).max
717
+ end
718
+ end
719
+
720
+ def max_trans_phi
721
+ phivec = gsl_vector('phi2tot_over_time')
722
+ offset = 30
723
+ phivec.subvector(20, phivec.size - 20).max
724
+ end
725
+
726
+ def max_es_heat_amp(species_index)
727
+ @transient_es_heat_flux_amplification_at_species_at_ky[species_index-1].values.max
728
+ end
729
+
730
+ def calculate_spectral_checks
731
+ ky_spec = gsl_vector('spectrum_over_ky')
732
+ kx_spec = gsl_vector('spectrum_over_kx')
733
+ kpar_spec = gsl_vector('spectrum_over_kpar', ky_index: ky_spec.max_index + 1, kx_index: 1)
734
+
735
+ @spectrum_check = []
736
+ [kx_spec, ky_spec, kpar_spec].each do |spec|
737
+ begin
738
+ ends_max = [spec[0], spec[-1]].max + (10.0**(-9))
739
+ p ends_max
740
+ p spec.max
741
+ check = (Math.log(spec.max/ends_max)/Math.log(10)).round
742
+ rescue
743
+ check= -10
744
+ end
745
+ @spectrum_check.push check
746
+ end
747
+ end
748
+
749
+ def calculate_vspace_checks
750
+ @vspace_check = ['lpc_pitch_angle', 'vres_pitch_angle', 'lpc_energy', 'vres_energy'].map do |name|
751
+ saturated_time_average(name, {})
752
+ end
753
+
754
+ end
755
+
756
+ alias :cvc :calculate_vspace_checks
757
+
758
+ def spec_chec(min, *dirns)
759
+ return @spectrum_check.zip([0, 1, 2]).inject(true) do |bool, (check,dirn)|
760
+ unless dirns.include? dirn
761
+ bool and true
762
+ else
763
+ unless check >= min
764
+ false
765
+ else
766
+ bool and true
767
+ end
768
+ end
769
+ end
770
+ end
771
+
772
+ def sc(min)
773
+ return @spectrum_check.min >= min
774
+ end
775
+ alias :csc :calculate_spectral_checks
776
+
777
+
778
+ end
779
+ end
780
+