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