trinitycrmod 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/trinitycrmod/trinity.rb +495 -488
- data/lib/trinitycrmod/trinity_gs2.rb +2 -0
- data/trinitycrmod.gemspec +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 263fcbf368214eefd153d51f25a2b534648cc9c1
|
4
|
+
data.tar.gz: 2531ce2ed0f1e4ad4f93ded2682d61c448d0c598
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce88cd7e55086c24cb644bb32c3db7aff890c67c3a46206ac206b9bb95872633136f390aae4b00521691ae43ddc6f0267f804503511ea8221549f100692a321d
|
7
|
+
data.tar.gz: 96aa87aa1029a7e6ebe488fcf9dae8a6aaccfee712fa0293e53a8e025ba846c00421a2ce76e9f2da4181938e15706c90a9a7187fce7d59f1faec347cfabbeb8d
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/trinitycrmod/trinity.rb
CHANGED
@@ -2,138 +2,141 @@ require 'coderunner'
|
|
2
2
|
require 'text-data-tools'
|
3
3
|
|
4
4
|
class CodeRunner
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
5
|
+
# This is a customised subclass of the CodeRunner::Run class which allows CodeRunner to run and analyse the multiscale gyrokinetic turbulent transport solver Trinity.
|
6
|
+
#
|
7
|
+
# It generates the Trinity input file, and both analyses the results and allows easy plotting of them. It also interfaces with the GS2 CodeRunner module to allow analysis of the individual GS2 results if GS2 is being used as the flux code.
|
8
|
+
class Trinity < Run::FortranNamelist
|
9
|
+
#include CodeRunner::SYSTEM_MODULE
|
10
|
+
#
|
11
|
+
|
12
|
+
class FluxOptionError < StandardError; end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
# Where this file is
|
17
|
+
@code_module_folder = File.dirname(File.expand_path(__FILE__)) # i.e. the directory this file is in
|
18
|
+
|
19
|
+
# Use the Run::FortranNamelist tools to process the variable database
|
20
|
+
setup_namelists(@code_module_folder)
|
21
|
+
@variables += [:flux_pars]
|
22
|
+
require 'trinitycrmod/output_files'
|
23
|
+
require 'trinitycrmod/graphs'
|
24
|
+
require 'trinitycrmod/check_parameters'
|
25
|
+
require 'trinitycrmod/actual_parameter_values'
|
26
|
+
require 'trinitycrmod/chease'
|
27
|
+
|
28
|
+
# Setup gs2 in case people are using it
|
29
|
+
CodeRunner.setup_run_class('gs2')
|
30
|
+
require 'trinitycrmod/trinity_gs2'
|
31
|
+
|
32
|
+
################################################
|
33
|
+
# Quantities that are read or determined by CodeRunner
|
34
|
+
# after the simulation has ended
|
35
|
+
###################################################
|
36
|
+
|
37
|
+
@results = [
|
38
|
+
:pfus,
|
39
|
+
:fusionQ,
|
40
|
+
:pnet,
|
41
|
+
:alpha_power,
|
42
|
+
:aux_power,
|
43
|
+
:rad_power,
|
44
|
+
:ne0,
|
45
|
+
:ne95,
|
46
|
+
:ti0,
|
47
|
+
:ti95,
|
48
|
+
:te0,
|
49
|
+
:te95,
|
50
|
+
:omega0,
|
51
|
+
:omega95,
|
52
|
+
:wth
|
53
|
+
]
|
54
|
+
|
55
|
+
@code_long="Trinity Turbulent Transport Solver"
|
56
|
+
|
57
|
+
@run_info=[:time, :is_a_restart, :restart_id, :restart_run_name, :completed_timesteps, :percent_complete, :no_restart_gs2]
|
58
|
+
|
59
|
+
@uses_mpi = true
|
60
|
+
|
61
|
+
@modlet_required = false
|
62
|
+
|
63
|
+
@naming_pars = []
|
64
|
+
|
65
|
+
# Any folders which are a number will contain the results from flux simulations.
|
66
|
+
@excluded_sub_folders = (1...1000).to_a.map{|i| "flux_tube_" + i.to_s}
|
67
|
+
|
68
|
+
# A hook which gets called when printing the standard run information to the screen using the status command.
|
69
|
+
def print_out_line
|
70
|
+
#p ['id', id, 'ctd', ctd]
|
71
|
+
#p rcp.results.zip(rcp.results.map{|r| send(r)})
|
72
|
+
name = @run_name
|
73
|
+
name += " (res: #@restart_id)" if @restart_id
|
74
|
+
name += " real_id: #@real_id" if @real_id
|
75
|
+
beginning = sprintf("%2d:%d %-60s %1s:%2.1f(%s) %3s%1s", @id, @job_no, name, @status.to_s[0,1], @run_time.to_f / 60.0, @nprocs.to_s, percent_complete, "%")
|
76
|
+
if ctd
|
77
|
+
beginning += sprintf("Q:%f, Pfusion:%f MW, Ti0:%f keV, Te0:%f keV, n0:%f x10^20", fusionQ, pfus, ti0, te0, ne0)
|
78
|
+
end
|
79
|
+
beginning += " ---#{@comment}" if @comment
|
80
|
+
beginning
|
81
|
+
end
|
82
|
+
|
83
|
+
#def self.load(dir, runner)
|
84
|
+
#run = super(dir, runner)
|
85
|
+
#grun_list = run.instance_variable_get(:@gs2_run_list)
|
86
|
+
#grun_list.values.each{|r| r.runner=runner} if grun_list.kind_of? Hash
|
87
|
+
#run
|
88
|
+
#end
|
89
|
+
|
90
|
+
|
91
|
+
# Modify new_run so that it becomes a restart of self. Adusts
|
92
|
+
# all the parameters of the new run to be equal to the parameters
|
93
|
+
# of the run that calls this function, and sets up its run name
|
94
|
+
# correctly
|
95
|
+
def restart(new_run)
|
96
|
+
#new_run = self.dup
|
97
|
+
(rcp.variables).each{|v| new_run.set(v, send(v)) if send(v) or new_run.send(v)}
|
98
|
+
if @flux_option == "gs2"
|
99
|
+
gs2_runs.each_with_index do |run, i|
|
100
|
+
CodeRunner::Gs2.rcp.variables.each{|v|
|
101
101
|
next if [:ginit_option, :delt_option].include? v and new_run.no_restart_gs2
|
102
102
|
new_run.gs2_runs[i].set(v, run.send(v)) if run.send(v) or new_run.gs2_runs[i].send(v)
|
103
103
|
}
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
104
|
+
end
|
105
|
+
end
|
106
|
+
@naming_pars.delete(:preamble)
|
107
|
+
SUBMIT_OPTIONS.each{|v| new_run.set(v, self.send(v)) unless new_run.send(v)}
|
108
|
+
#(rcp.results + rcp.gs2_run_info).each{|result| new_run.set(result, nil)}
|
109
|
+
new_run.is_a_restart = true
|
110
|
+
new_run.restart_id = @id
|
111
|
+
new_run.restart_run_name = @run_name
|
112
|
+
new_run.init_option = "restart"
|
113
|
+
new_run.iternt_file = @run_name + ".iternt"
|
114
|
+
new_run.iterflx_file = @run_name + ".iterflx"
|
115
|
+
new_run.itercalib_file = @run_name + ".itercalib"
|
116
|
+
new_run.init_file = @run_name + ".tmp"
|
117
|
+
@runner.nprocs = @nprocs if @runner.nprocs == "1" # 1 is the default so this means the user probably didn't specify nprocs
|
118
118
|
# This is unnecessary for single restart file.
|
119
|
-
|
119
|
+
raise "Restart must be on the same number of processors as the previous run: new is #{new_run.nprocs.inspect} and old is #{@nprocs.inspect}" if not new_run.no_restart_gs2 and (!new_run.nprocs or new_run.nprocs != @nprocs)
|
120
120
|
raise "Restart cannot have a different sized jacobian: new is #{new_run.n_flux_tubes_jac} and old is #{n_flux_tubes_jac}" unless new_run.n_flux_tubes_jac == n_flux_tubes_jac
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
121
|
+
# @runner.parameters.each{|var, value| new_run.set(var,value)} if @runner.parameters
|
122
|
+
# ep @runner.parameters
|
123
|
+
new_run.run_name = nil
|
124
|
+
new_run.naming_pars = @naming_pars
|
125
|
+
new_run.update_submission_parameters(new_run.parameter_hash.inspect, false) if new_run.parameter_hash
|
126
|
+
new_run.naming_pars.delete(:restart_id)
|
127
|
+
new_run.generate_run_name
|
128
|
+
new_run.run_name += '_t'
|
129
|
+
eputs 'Copying Trinity Restart files', ''
|
130
|
+
#system "ls #@directory"
|
131
|
+
['iternt', 'iterflx', 'tmp', 'itercalib'].each do |ext|
|
132
132
|
next if ext=='itercalib' and not FileTest.exist?("#@directory/#@run_name.#{ext}")
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
# Unlike gs2, trinity always uses the current run name to generate the
|
134
|
+
# restart files. Thus, the name of the restart files changes with every
|
135
|
+
# run.
|
136
|
+
FileUtils.cp("#@directory/#@run_name.#{ext}", "#{new_run.directory}/.")
|
137
|
+
end
|
138
|
+
if new_run.flux_option == "gs2" and @flux_option == "gs2" and not new_run.no_restart_gs2
|
139
|
+
for i in 0...n_flux_tubes
|
137
140
|
break if i >= new_run.n_flux_tubes
|
138
141
|
#if i >= n_flux_tubes_jac
|
139
142
|
#jn = i - n_flux_tubes_jac + 1
|
@@ -143,50 +146,52 @@ class CodeRunner
|
|
143
146
|
#jn = i + 1
|
144
147
|
##run_name = @run_name + (jn).to_s
|
145
148
|
#folder = "flux_tube_#{jn}"
|
146
|
-
#end
|
149
|
+
#end
|
147
150
|
#
|
148
151
|
folder = gs2_folder_name(i)
|
149
152
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
153
|
+
new_run.gs2_runs[i].directory = new_run.directory + "/#{folder}"
|
154
|
+
FileUtils.makedirs(new_run.gs2_runs[i].directory)
|
155
|
+
#ep ['gs2_runs[i] before', gs2_runs[i].nwrite, new_run.gs2_runs[i].nwrite, new_run.gs2_runs[i].parameter_hash]
|
156
|
+
gs2_runs[i].restart(new_run.gs2_runs[i])
|
157
|
+
#ep ['gs2_runs[i] after', gs2_runs[i].nwrite, new_run.gs2_runs[i].nwrite, new_run.gs2_runs[i].parameter_hash]
|
158
|
+
#new_run.gs2_runs[i].run_name = new_run.run_name + (i+1).to_s
|
159
|
+
end
|
160
|
+
end
|
161
|
+
#@runner.submit(new_run)
|
162
|
+
new_run
|
163
|
+
end
|
164
|
+
# This is a hook which gets called just before submitting a simulation. It sets up the folder and generates any necessary input files.
|
165
|
+
def generate_input_file
|
166
|
+
@run_name += "_t"
|
167
|
+
if @restart_id
|
168
|
+
@runner.run_list[@restart_id].restart(self)
|
169
|
+
end
|
170
|
+
setup_chease if uses_chease?
|
171
|
+
check_parameters
|
172
|
+
write_input_file
|
173
|
+
generate_gs2_input_files if @flux_option == "gs2"
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
# Update submission parameters in the normal way then deal with parameters
|
178
|
+
# for the flux code. Each flux code will behave differently.
|
179
|
+
#
|
180
|
+
# * Gs2
|
181
|
+
# flux_pars: {nx: 43, delt: {1=> 0.01, 2=>0.05}}
|
182
|
+
# will set nx for all runs to be 43, and delt for run 1 to 0.01, delt
|
183
|
+
# for run 2 to be 0.05
|
184
|
+
def update_submission_parameters(parameters, start_from_defaults=true)
|
185
|
+
super(parameters, start_from_defaults)
|
186
|
+
if @flux_option == "gs2"
|
187
|
+
raise "set_flux_defaults_proc not defined" unless @set_flux_defaults_proc
|
188
|
+
@set_flux_defaults_proc.call
|
189
|
+
gs2_parameter_hashes = {}
|
190
|
+
if @flux_pars
|
191
|
+
@flux_pars.each do |par, val|
|
192
|
+
if val.kind_of? Hash
|
193
|
+
#val.each{|n,v| gs2_runs[n].set(par, v)}
|
194
|
+
val.each do |n,v|
|
190
195
|
if n == :jac
|
191
196
|
range = 0...n_flux_tubes_jac
|
192
197
|
elsif n == :calib
|
@@ -198,63 +203,63 @@ class CodeRunner
|
|
198
203
|
gs2_parameter_hashes[i] ||= {}
|
199
204
|
gs2_parameter_hashes[i][par] = v
|
200
205
|
end
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
206
|
+
#gs2_parameter_hashes[n] ||= {}
|
207
|
+
#gs2_parameter_hashes[n][par] = v
|
208
|
+
end
|
209
|
+
else
|
210
|
+
for i in 0...n_flux_tubes
|
211
|
+
#gs2_runs.each{|r| r.set(par, val)}
|
212
|
+
gs2_parameter_hashes[i] ||= {}
|
213
|
+
gs2_parameter_hashes[i][par] = val
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
for i in 0...n_flux_tubes
|
219
|
+
gs2_runs[i].parameter_hash = (gs2_parameter_hashes[i] || {}).inspect
|
220
|
+
gs2_runs[i].update_submission_parameters(gs2_runs[i].parameter_hash, false)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
self
|
224
|
+
end
|
225
|
+
|
226
|
+
# Override CodeRunner::Run method to deal with flux_pars properly
|
227
|
+
# when generating run_name
|
228
|
+
def generate_run_name
|
229
|
+
@run_name = %[v#@version] + @naming_pars.inject("") do |str, par|
|
230
|
+
case par
|
231
|
+
when :flux_pars
|
232
|
+
str+="_flx_#{send(par).map{|k,v| "#{k}_#{v.to_s[0..8]}"}.join("_")}}"
|
233
|
+
else
|
234
|
+
str+="_#{par}_#{send(par).to_s[0...8]}"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
@run_name = @run_name.gsub(/\s+/, "_").gsub(/[\/{}"><:=]/, '') + "_id_#@id"
|
238
|
+
end
|
239
|
+
|
240
|
+
# The number of separate flux tube results needed for the jacobian
|
241
|
+
def n_flux_tubes_jac
|
242
|
+
d1 = dflx_stencil_actual - 1
|
243
|
+
ngrads =d1 * case @grad_option
|
244
|
+
when "tigrad", "ngrad", "lgrad"
|
245
|
+
1
|
246
|
+
when "tgrads"
|
247
|
+
2
|
248
|
+
when "ltgrads", "ntgrads"
|
249
|
+
3
|
250
|
+
when "all"
|
251
|
+
4
|
252
|
+
else
|
253
|
+
raise "unknown grad_option: #@grad_option"
|
254
|
+
end
|
255
|
+
if evolve_grads_only_actual.fortran_true?
|
256
|
+
njac = ngrads + 1
|
257
|
+
else
|
258
|
+
njac = 2*ngrads+1
|
259
|
+
end
|
260
|
+
#p 'nraaad', @nrad
|
261
|
+
(@nrad-1) * njac
|
262
|
+
end
|
258
263
|
def n_flux_tubes
|
259
264
|
if @neval_calibrate and @neval_calibrate > 0
|
260
265
|
raise "neval_calibrate set but ncc_calibrate not set" unless @ncc_calibrate
|
@@ -264,18 +269,18 @@ class CodeRunner
|
|
264
269
|
end
|
265
270
|
end
|
266
271
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
272
|
+
# Writes the gs2 input files, creating separate subfolders
|
273
|
+
# for them if @subfolders is .true.
|
274
|
+
def generate_gs2_input_files
|
275
|
+
# At the moment we must use subfolders
|
276
|
+
for i in 0...n_flux_tubes
|
277
|
+
#gs2run = gs2_run(:base).dup
|
278
|
+
#gs2_run(i).instance_variables.each do |var|
|
279
|
+
#gs2run.instance_variable_set(var, gs2_run(i).instance_variable_get(var))
|
280
|
+
#end
|
281
|
+
gs2run = gs2_runs[i]
|
282
|
+
#ep ['gs2_runs[i] in generate', gs2_runs[i].nwrite]
|
283
|
+
#p ['i',i]
|
279
284
|
#if i >= n_flux_tubes_jac
|
280
285
|
#jn = i - n_flux_tubes_jac + 1
|
281
286
|
#run_name = "calibrate_" + @run_name + (jn).to_s
|
@@ -284,255 +289,257 @@ class CodeRunner
|
|
284
289
|
#jn = i + 1
|
285
290
|
#run_name = @run_name + (jn).to_s
|
286
291
|
#folder = "flux_tube_#{jn}"
|
287
|
-
#end
|
292
|
+
#end
|
288
293
|
|
289
294
|
folder = gs2_folder_name(i)
|
290
295
|
run_name = gs2_run_name(i)
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
296
|
+
|
297
|
+
if @subfolders and @subfolders.fortran_true?
|
298
|
+
gs2run.directory = @directory + "/" + folder
|
299
|
+
FileUtils.makedirs(gs2run.directory)
|
300
|
+
gs2run.relative_directory = @relative_directory + "/" + folder
|
301
|
+
gs2run.restart_dir = gs2run.directory + "/nc"
|
302
|
+
else
|
303
|
+
gs2run.directory = @directory
|
304
|
+
gs2run.relative_directory = @relative_directory
|
305
|
+
end
|
306
|
+
gs2run.run_name = run_name
|
307
|
+
gs2run.nprocs = @nprocs
|
308
|
+
if i==0
|
309
|
+
block = Proc.new{check_parameters}
|
310
|
+
else
|
311
|
+
block = Proc.new{}
|
312
|
+
end
|
313
|
+
#if @restart_id
|
314
|
+
#gs2run.restart_id =
|
315
|
+
Dir.chdir(gs2run.directory) do
|
316
|
+
gs2run.generate_input_file(&block)
|
317
|
+
gs2run.write_info
|
318
|
+
end
|
319
|
+
|
320
|
+
### Hack the input file so that gs2 gets the location of
|
321
|
+
# the restart dir correctly within trinity
|
322
|
+
if @subfolders and @subfolders.fortran_true?
|
323
|
+
infile = gs2run.directory + "/" + gs2run.run_name + ".in"
|
324
|
+
text = File.read(infile)
|
325
|
+
File.open(infile, 'w'){|f| f.puts text.sub(/restart_dir\s*=\s*"nc"/, "restart_dir = \"#{folder}/nc\"")}
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def vim_output
|
331
|
+
system "vim -Ro #{output_file} #{error_file} #@directory/#@run_name.error #@directory/#@run_name.out "
|
332
|
+
end
|
333
|
+
alias :vo :vim_output
|
334
|
+
|
335
|
+
# This command uses the infrastructure provided by Run::FortranNamelist, provided by CodeRunner itself.
|
336
|
+
def write_input_file
|
337
|
+
File.open(@run_name + ".trin", 'w'){|file| file.puts input_file_text}
|
338
|
+
end
|
339
|
+
|
340
|
+
# Parameters which follow the Trinity executable, in this case just the input file.
|
341
|
+
def parameter_string
|
342
|
+
@run_name + ".trin"
|
343
|
+
end
|
344
|
+
|
345
|
+
def parameter_transition
|
346
|
+
end
|
347
|
+
|
348
|
+
def generate_component_runs
|
349
|
+
#puts "HERE"
|
350
|
+
@component_runs ||= []
|
351
|
+
if @flux_option == "gs2"
|
352
|
+
#puts "HERE"
|
348
353
|
#puts "generate_component_runs", @component_runs.size, @runner.run_list.size, caller.to_a.slice(0..9)
|
349
354
|
#puts @component_runs[1].ginit_option if @component_runs.size > 0
|
350
355
|
#STDIN.gets
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
356
|
+
|
357
|
+
for i in 0...n_flux_tubes
|
358
|
+
component = @component_runs[i]
|
359
|
+
#p [i, '9,', component, '4', !@component_runs[i]]; STDIN.gets
|
360
|
+
if not component
|
361
|
+
#p "HEELO"
|
362
|
+
#p [i, '3,', component, '4', @component_runs.size]
|
363
|
+
component = @component_runs[i] = Gs2::TrinityComponent.new(@runner, self).create_component
|
364
|
+
#component.instance_variable_set(:@output_file, output_file)
|
365
|
+
#p [i, '3,', component, '4', @component_runs.size]
|
366
|
+
if false
|
367
|
+
if i > 0 and @component_runs[i-1]
|
368
|
+
component.rcp.variables.each do |var|
|
369
|
+
val = @component_runs[i-1].send(var)
|
370
|
+
component.set(var, val) if val
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
#p [i,'1', component, '2', @component_runs.size]; STDIN.gets
|
376
|
+
component = @component_runs[i]
|
377
|
+
#p [i,'1', component, '2']; STDIN.gets
|
378
|
+
|
379
|
+
|
380
|
+
component.component_runs = []
|
381
|
+
#component.runner = nil
|
382
|
+
#pp component; STDIN.gets
|
383
|
+
#component.instance_variables.each{|var| puts var; pp var; puts Marshal.dump(component.instance_variable_get(var)); STDIN.gets}
|
384
|
+
#puts Marshal.dump(component); STDIN.gets
|
385
|
+
#pp component; STDIN.gets
|
386
|
+
#p component.class
|
387
|
+
component.job_no = @job_no
|
388
|
+
#component.status = @status
|
389
|
+
#p ["HERE2", @component_runs.size, @component_runs[i]]
|
390
|
+
#Dir.chdir(@directory) {
|
391
|
+
compdir = gs2_folder_name(i) # "flux_tube_#{i+1}"
|
392
|
+
Dir.chdir(compdir){component.process_directory} if FileTest.exist? compdir
|
393
|
+
#}
|
394
|
+
component.component_runs = []
|
395
|
+
component.trinity_run = self
|
396
|
+
#@component_runs.push component
|
397
|
+
component.real_id = @id
|
398
|
+
#@gs2_run_list[i] = component
|
399
|
+
#pp component; STDIN.gets
|
400
|
+
#component.runner = nil
|
401
|
+
#puts Marshal.dump(component); STDIN.gets
|
402
|
+
#pp component; STDIN.gets
|
403
|
+
#component.component_runs = []
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
|
409
|
+
def save
|
410
|
+
#@gs2_run_list.values.each{|r| r.runner = nil; r.component_runs = []} if @gs2_run_list.kind_of? Hash
|
411
|
+
super
|
412
|
+
#@gs2_run_list.values.each{|r| r.runner = @runner} if @gs2_run_list.kind_of? Hash
|
413
|
+
|
414
|
+
#logf(:save)
|
415
|
+
#raise CRFatal.new("Something has gone horribly wrong: runner.class is #{@runner.class} instead of CodeRunner") unless @runner.class.to_s == "CodeRunner"
|
416
|
+
#runner, @runner = @runner, nil
|
417
|
+
#@system_triers, old_triers = nil, @system_triers
|
418
|
+
#@component_runs.each{|run| run.runner = nil; run.component_runs = []} if @component_runs
|
419
|
+
##@component_runs.each{|run| run.runner = nil} if @component_runs
|
420
|
+
## logi(self)
|
421
|
+
##pp self
|
422
|
+
##@component_runs.each{|ph| ph.instance_variables.each{|var| puts var; pp ph.instance_variable_get(var); STDIN.gets; puts ph.Marshal.dump(instance_variable_get(var))}} if @component_runs
|
423
|
+
##instance_variables.each{|var| puts var; instance_variable_get(var); puts Marshal.dump(instance_variable_get(var)); STDIN.gets}
|
424
|
+
#Dir.chdir(@directory){File.open(".code_runner_run_data", 'w'){|file| file.puts Marshal.dump(self)}}
|
425
|
+
#@runner = runner
|
426
|
+
#@component_runs.each{|run| run.runner = runner} if @component_runs
|
427
|
+
#@system_triers = old_triers
|
428
|
+
end
|
429
|
+
|
430
|
+
@source_code_subfolders = []
|
431
|
+
|
432
|
+
# This method, as its name suggests, is called whenever CodeRunner is asked to analyse a run directory. This happens if the run status is not :Complete, or if the user has specified recalc_all(-A on the command line) or reprocess_all (-a on the command line).
|
433
|
+
#
|
434
|
+
def process_directory_code_specific
|
435
|
+
get_status
|
436
|
+
#p ['id is', id, 'ctd is ', ctd]
|
437
|
+
if ctd
|
438
|
+
get_global_results
|
439
|
+
end
|
440
|
+
#p ['fusionQ is ', fusionQ]
|
441
|
+
@percent_complete = completed_timesteps.to_f / ntstep.to_f * 100.0
|
442
|
+
end
|
443
|
+
|
444
|
+
def get_status
|
445
|
+
if @running
|
446
|
+
get_completed_timesteps
|
447
|
+
if completed_timesteps == 0
|
448
|
+
@status = :NotStarted
|
449
|
+
else
|
450
|
+
@status = :Incomplete
|
451
|
+
end
|
452
|
+
else
|
453
|
+
get_completed_timesteps
|
454
|
+
if @completed_timesteps == @ntstep
|
455
|
+
@status = :Complete
|
456
|
+
else
|
457
|
+
if FileTest.exist?(output_file) and File.read(output_file) =~/trinity\s+finished/i
|
458
|
+
@status = :Complete
|
459
|
+
else
|
460
|
+
@status = :Failed
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def get_completed_timesteps
|
467
|
+
Dir.chdir(@directory) do
|
468
|
+
@completed_timesteps = time_outfile.exists? ?
|
469
|
+
time_outfile.get_1d_array_integer(/itstep/).max :
|
470
|
+
0
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
|
475
|
+
def get_global_results
|
476
|
+
@fusionQ = info_outfile.get_variable_value('Q').to_f
|
477
|
+
@pfus = info_outfile.get_variable_value(/fusion\s+power/i).to_f
|
478
|
+
@pnet = info_outfile.get_variable_value(/net\s+power/i).to_f
|
479
|
+
@aux_power = info_outfile.get_variable_value(/aux.*\s+power/i).to_f
|
480
|
+
@alpha_power = info_outfile.get_variable_value(/alpha\s+power/i).to_f
|
481
|
+
@rad_power = info_outfile.get_variable_value(/radiated\s+power/i).to_f
|
482
|
+
@ne0 = info_outfile.get_variable_value(/core\s+density/i).to_f
|
483
|
+
@ti0 = info_outfile.get_variable_value(/core\s+T_i/i).to_f
|
484
|
+
@te0 = info_outfile.get_variable_value(/core\s+T_e/i).to_f
|
485
|
+
@omega0 = info_outfile.get_variable_value(/core\s+omega/i).to_f rescue 0.0 # Old info files don't have omega
|
486
|
+
#p 'send(fusionQ)', send(:fusionQ)
|
487
|
+
end
|
488
|
+
|
489
|
+
def self.get_input_help_from_source_code(source_folder)
|
490
|
+
source = get_aggregated_source_code_text(source_folder)
|
491
|
+
rcp.namelists.each do |nmlst, hash|
|
492
|
+
hash[:variables].each do |var, var_hash|
|
493
|
+
|
494
|
+
# next unless var == :w_antenna
|
495
|
+
var = var_hash[:code_name] || var
|
496
|
+
values_text = source.scan(Regexp.new("\\W#{var}\\s*=\\s*.+")).join("\n")
|
497
|
+
ep values_text
|
498
|
+
values = scan_text_for_variables(values_text).map{|(_v,val)| val}
|
499
|
+
values.uniq!
|
500
|
+
# ep values if var == :nbeta
|
501
|
+
values.delete_if{|val| val.kind_of? String} if values.find{|val| val.kind_of? Numeric}
|
502
|
+
values.delete_if{|val| val.kind_of? String and not String::FORTRAN_BOOLS.include? val} if values.find{|val| val.kind_of? String and String::FORTRAN_BOOLS.include? val}
|
503
|
+
# values.sort!
|
504
|
+
# ep var
|
505
|
+
# ep values
|
506
|
+
sample_val = values[0]
|
507
|
+
p sample_val
|
508
|
+
help = values_text.scan(/ !(.*)/).flatten[0]
|
509
|
+
p help
|
510
|
+
#gets
|
511
|
+
var_hash[:help] = help
|
512
|
+
var_hash[:description] = help
|
513
|
+
save_namelists
|
514
|
+
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
def input_file_header
|
520
|
+
<<EOF
|
514
521
|
!==============================================================================
|
515
|
-
!
|
522
|
+
! Trinity INPUT FILE automatically generated by CodeRunner
|
516
523
|
!==============================================================================
|
517
524
|
!
|
518
525
|
! Trinity is a multiscale turbulent transport code for fusion plasmas.
|
519
|
-
!
|
520
|
-
! See http://gyrokinetics.sourceforge.net
|
521
526
|
!
|
522
|
-
!
|
523
|
-
!
|
527
|
+
! See http://gyrokinetics.sourceforge.net
|
528
|
+
!
|
529
|
+
! CodeRunner is a framework for the automated running and analysis
|
530
|
+
! of large simulations.
|
531
|
+
!
|
532
|
+
! See http://coderunner.sourceforge.net
|
524
533
|
!
|
525
|
-
! See http://coderunner.sourceforge.net
|
526
|
-
!
|
527
534
|
! Created #{Time.now.to_s}
|
528
535
|
! by CodeRunner version #{CodeRunner::CODE_RUNNER_VERSION.to_s}
|
529
536
|
!
|
530
537
|
!==============================================================================
|
531
538
|
|
532
539
|
EOF
|
533
|
-
|
534
|
-
|
535
|
-
|
540
|
+
end
|
541
|
+
def self.defaults_file_header
|
542
|
+
<<EOF1
|
536
543
|
############################################################################
|
537
544
|
# #
|
538
545
|
# Automatically generated defaults file for the Trinity CodeRunner module #
|
@@ -542,29 +549,29 @@ EOF
|
|
542
549
|
# #
|
543
550
|
############################################################################
|
544
551
|
|
545
|
-
# Created: #{Time.now.to_s}
|
552
|
+
# Created: #{Time.now.to_s}
|
546
553
|
|
547
554
|
@defaults_file_description = ""
|
548
555
|
EOF1
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
556
|
+
end
|
557
|
+
|
558
|
+
def run_heuristic_analysis
|
559
|
+
ep 'run_heuristic_analysis', Dir.pwd
|
560
|
+
infiles = Dir.entries.grep(/^[^\.].*\.trin$/)
|
561
|
+
ep infiles
|
562
|
+
raise CRMild.new('No input file') unless infiles[0]
|
563
|
+
raise CRError.new("More than one input file in this directory: \n\t#{infiles}") if infiles.size > 1
|
564
|
+
input_file = infiles[0]
|
565
|
+
#ep 'asdf'
|
566
|
+
@nprocs ||= "1"
|
567
|
+
@executable ||= "/dev/null"
|
568
|
+
make_info_file(input_file, false)
|
569
|
+
end
|
570
|
+
|
571
|
+
def input_file_extension
|
572
|
+
'.trin'
|
573
|
+
end
|
574
|
+
|
575
|
+
end
|
569
576
|
end
|
570
577
|
|
@@ -62,11 +62,13 @@ class CodeRunner
|
|
62
62
|
CodeRunner::Gs2.make_new_defaults_file(name + '_gs2tmp', gs2_input_file)
|
63
63
|
|
64
64
|
File.open(defaults_filename, 'a'){|file| file.puts <<EOF2
|
65
|
+
@set_flux_defaults_proc = Proc.new do
|
65
66
|
gs2_runs.each do |run|
|
66
67
|
run.instance_eval do
|
67
68
|
#{File.read(tmp_filename).gsub(/\A|\n/, "\n ")}
|
68
69
|
end
|
69
70
|
end
|
71
|
+
end
|
70
72
|
|
71
73
|
|
72
74
|
EOF2
|
data/trinitycrmod.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: trinitycrmod 0.
|
5
|
+
# stub: trinitycrmod 0.6.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "trinitycrmod"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.6.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Edmund Highcock"]
|
14
|
-
s.date = "2015-02-
|
14
|
+
s.date = "2015-02-02"
|
15
15
|
s.description = "This module allows Trinity, the Multiscale Gyrokinetic Turbulent Transport solver for Fusion Reactors, to harness the power of CodeRunner, a framework for the automated running and analysis of simulations."
|
16
16
|
s.email = "edmundhighcock@sourceforge.net"
|
17
17
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trinitycrmod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edmund Highcock
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coderunner
|