gs2crmod 0.5.2
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.
- 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
|
+
|