corfucrmod 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,352 @@
1
+ CodeRunner.setup_run_class('chease')
2
+
3
+ class CodeRunner::Chease
4
+ # We hotwire the execute command so that it just
5
+ # runs it instead of doing a batch submission
6
+ def execute
7
+ system "#{executable}"
8
+ end
9
+ end
10
+ class CodeRunner::Ecom
11
+ # We hotwire the execute command so that it just
12
+ # runs it instead of doing a batch submission
13
+ def execute
14
+ system "#{executable}"
15
+ end
16
+ end
17
+ class CodeRunner::Corfu::Optimisation
18
+ include GSL::MultiMin
19
+ # optimisation_spec is a hash of {:code_name => {:variable => [initial_guess, dimension_scale_factor]}}
20
+ # dimension_scale_factor is just some estimate of the length scale in which the result
21
+ # varies significantly
22
+ # code_name is either trinity or chease (both can be used simultaneously)
23
+ attr_reader :optimisation_spec
24
+ attr_reader :optimisation_variables
25
+ attr_accessor :trinity_runner
26
+ attr_accessor :gs_runner
27
+ attr_accessor :parameters_obj
28
+ attr_accessor :results_hash
29
+ def initialize(optimised_quantity, optimisation_spec)
30
+ #@folder = folder
31
+ @optimised_quantity = optimised_quantity
32
+ @optimisation_spec = optimisation_spec
33
+ @optimisation_variables = optimisation_spec.map{|code, hash| hash.map{|var, pars| [code, var]}}.flatten(1)
34
+ @optimisation_starts = optimisation_spec.map{|code, hash| hash.map{|var, pars| pars[0]}}.flatten(1)
35
+ @optimisation_steps = optimisation_spec.map{|code, hash| hash.map{|var, pars| pars[1]}}.flatten(1)
36
+ #@runner = CodeRunner.fetch_runner(
37
+ #p ['optimisation_variables', @optimisation_variables]
38
+ @results_hash = {}
39
+ @first_call = true
40
+ @ifspppl_converged = false
41
+ end
42
+ def dimension
43
+ @optimisation_variables.size
44
+ end
45
+ def serial_optimise(optimisation_method, parameters_obj)
46
+ optimisation_meth = case optimisation_method
47
+ when :simplex
48
+ FMinimizer::NMSIMPLEX
49
+ else
50
+ raise "Unknown optimisation_method"
51
+ end
52
+ @results_hash[:start_time] = Time.now.to_i
53
+ opt = FMinimizer.alloc(optimisation_meth, @optimisation_variables.size)
54
+ @parameters_obj = parameters_obj
55
+ catch(:out_of_time) do
56
+ func = Proc.new{|v, optimiser| optimiser.func(v)}
57
+ eputs 'Created func'
58
+ gsl_func = Function.alloc(func, dimension)
59
+ eputs 'Allocated gsl_func'
60
+ gsl_func.set_params(self)
61
+ eputs 'Set params'
62
+ opt.set(gsl_func, @optimisation_starts.to_gslv, @optimisation_steps.to_gslv)
63
+ eputs 'Set func and starting iteration'
64
+ parameters_obj.nit.times do |i|
65
+ opt.iterate
66
+ p ['status', opt.x, opt.minimum, i, parameters_obj.nit]
67
+ @results_hash[:iterations] ||= []
68
+ @results_hash[:iterations].push [opt.x.dup, opt.minimum]
69
+ @results_hash[:elapse_mins] = (Time.now.to_i - @results_hash[:start_time]).to_f/60
70
+ @results_hash[:current_time] = Time.now.to_i
71
+ File.open('results', 'w'){|f| f.puts @results_hash.pretty_inspect}
72
+ end
73
+ eputs 'Optimisation complete'
74
+ end
75
+ eputs 'Optimisation ended'
76
+ #MPI.Finalize
77
+
78
+ end
79
+ def func(v)
80
+ val = nil
81
+ count = 1
82
+ val_old, repeat = func_actual(v)
83
+ loop do
84
+ val, repeat, trinity_is_converged = func_actual(v)
85
+ if trinity_is_converged # This means that Trinity has reached steady state
86
+
87
+ # Now we check if the loop over recalculating the GS equation
88
+ # has converged
89
+ if ((val_old - val)/val).abs < @parameters_obj.convergence
90
+ if @parameters_obj.use_ifspppl_first and not @ifspppl_converged
91
+ @ifspppl_converged = true
92
+ else
93
+ break
94
+ end
95
+ end
96
+ break if count > @parameters_obj.max_func_evals
97
+
98
+ # If geometry is being evolved internally in Trinity, we don't
99
+ # need to run this loop
100
+ break if not repeat
101
+ val_old = val
102
+ #break if not repeat or (not @first_call and count > 1) or count > 4
103
+ count += 1 unless @parameters_obj.use_ifspppl_first and not @ifspppl_converged
104
+ end
105
+ end
106
+ @first_call = false
107
+ return val
108
+ end
109
+ def func_actual(v)
110
+ eputs 'Starting func'
111
+ @id||=1 # Id of the current trinity run which should always be equal to the number of func_actual calls
112
+ repeat = false
113
+ print_pars = {}
114
+ pars = {}
115
+ pars[:gs] = {}
116
+ pars[:trinity] = {}
117
+ pars[:trinity].absorb(@parameters_obj.trinity_pars) if @parameters_obj.trinity_pars
118
+ pars[:gs].absorb(@parameters_obj.gs_pars) if @parameters_obj.gs_pars
119
+ for i in 0...v.size
120
+ code, varname = @optimisation_variables[i]
121
+ val = v[i]
122
+ code = case code
123
+ when :chease, :ecom
124
+ :gs
125
+ else
126
+ :trinity
127
+ end
128
+ pars[code][varname] = val
129
+ print_pars[code] ||={}
130
+ print_pars[code][varname] = val
131
+ end
132
+ if not @first_run_done
133
+ pars[:trinity][:ntstep] = @parameters_obj.ntstep_first
134
+ #pars[:trinity][:nifspppl_initial] = -1
135
+ #pars[:trinity][:niter] = 2
136
+
137
+ # The line below assumes that the whole first run is done
138
+ # with ifspppl, in which case we don't want the timestep to get
139
+ # too large for the gryfx run afterwards.
140
+ #pars[:trinity][:ntdelt_max] = 0.05
141
+ #pars[:trinity][:convergetol] = -1.0
142
+ else
143
+ pars[:trinity][:ntstep] = @parameters_obj.ntstep
144
+ #pars[:trinity][:nifspppl_initial] = -1
145
+ #pars[:trinity][:niter] = 3
146
+ #pars[:trinity][:ntdelt_max] = 10.0
147
+ end
148
+ if @parameters_obj.use_ifspppl_first and not @ifspppl_converged
149
+ pars[:trinity][:nifspppl_initial] = pars[:trinity][:ntstep]
150
+ else
151
+ pars[:trinity][:nifspppl_initial] = -1
152
+ end
153
+
154
+
155
+ # Must fix this soon!
156
+ if @parameters_obj.gs_code == 'chease'
157
+ #pars[:gs][:ap] = [0.3,0.5,0.4,0.0,0.4,0.0,0.0]
158
+ #pars[:gs][:at] = [0.16,1.0,1.0,-1.1,-1.1]
159
+ end
160
+
161
+ trinity_runner.run_class.instance_variable_set(:@mpi_communicator, MPI::Comm::WORLD)
162
+ #if false and trinity_runner.run_list.size > 0
163
+ #else
164
+ if @first_run_done
165
+ #crun.nppfun=4
166
+ #crun.neqdsk=0
167
+ #crun.expeq_file = trinity_runner.run_list[@id]
168
+ end
169
+ if not @replay
170
+ if not @first_run_done and gs_runner.run_list.size > 0
171
+ #This means we are in a restart
172
+ @replay = true
173
+ @nrun = 1
174
+ if @parameters_obj.delete_final_run
175
+ eputs 'Removing final run: ' + trinity_runner.run_list.keys.max.to_s
176
+ trinity_runner.conditions = 'id==' + trinity_runner.run_list.keys.max.to_s
177
+ trinity_runner.destroy no_confirm: true
178
+ gs_runner.conditions = 'id==' + gs_runner.run_list.keys.max.to_s
179
+ gs_runner.destroy no_confirm: true
180
+ end
181
+ else
182
+ @nrun = nil
183
+ @replay = false
184
+ end
185
+ end
186
+ if @replay
187
+ eputs 'Replaying: ' + @nrun.to_s
188
+ run = trinity_runner.run_list[@nrun]
189
+ if not run
190
+ eputs 'Ending replay at ' + @nrun.to_s
191
+ @replay = false
192
+ @id = @gsid = @nrun-1
193
+ else
194
+ @id = @gsid = @nrun
195
+ end
196
+ @nrun += 1
197
+ end
198
+ Hash.phoenix('func_calls.rb') do |hash|
199
+ hash[@id+1] ||={}
200
+ hash[@id+1][:variables] = v.dup
201
+ hash[@id+1][:print_pars] = print_pars
202
+ hash
203
+ end
204
+ #raise "WORK!!"
205
+ eputs "Written parameters"
206
+ if not @replay
207
+ eputs "Not replaying... starting GS and Trinity runs"
208
+ remaining_wall_mins = (
209
+ @parameters_obj.wall_mins - @parameters_obj.wall_mins_margin -
210
+ (Time.now.to_i - @parameters_obj.start_time).to_f / 60.0
211
+ )
212
+ eputs "Remaining wall mins #{remaining_wall_mins}, wall mins #{@parameters_obj.wall_mins}, start time #{@parameters_obj.start_time}, time #{Time.now.to_i}, margin #{@parameters_obj.wall_mins_margin}"
213
+ if remaining_wall_mins < @parameters_obj.wall_mins_margin
214
+ eputs "Run out of time"
215
+ throw(:out_of_time)
216
+ end
217
+ eputs "Starting real run, @id = ",@id
218
+ # Create and initialize the gs run
219
+ gsrun = gs_runner.run_class.new(gs_runner)
220
+ raise "No gs_defaults strings" unless @parameters_obj.gs_defaults_strings.size > 0
221
+ @parameters_obj.gs_defaults_strings.each{|prc| gsrun.instance_eval(prc)}
222
+ if gs_runner.run_list.size > 0
223
+ #gsrun.restart_id = @gsid
224
+ if @parameters_obj.gs_code == 'chease'
225
+ last_converged = @id
226
+ #We need to find the last converged Trinity run to use as the pressure profile.
227
+ until last_converged == 0 or trinity_runner.combined_run_list[last_converged].is_converged?
228
+ eputs "Run #{last_converged} not converged"
229
+ last_converged -= 1
230
+ end
231
+ #unless (@parameters_obj.use_previous_pressure==0 and not @first_trinity_run_completed)
232
+ unless last_converged == 0
233
+ eputs "Using previous pressure profile"
234
+ # We give CHEASE the pressure profile from the previous run.
235
+ pars[:gs][:nppfun] = 4
236
+ pars[:gs][:nfunc] = 4
237
+ #if prid = @parameters_obj.use_previous_pressure and not @first_trinity_run_completed
238
+ # If the last trinity run did not converge we may want to run exactly
239
+ # the same case again, and in particular use the pressure profile from
240
+ # the previous Trinity run as input (as an unconverged pressure profile
241
+ # can lead to a wacky GS solution)
242
+ #gsrun.expeq_in=trinity_runner.combined_run_list[prid].directory + '/chease/EXPEQ.NOSURF'
243
+ #else
244
+ gsrun.expeq_in=trinity_runner.combined_run_list[last_converged].directory + '/chease/EXPEQ.NOSURF'
245
+ #end
246
+ # Don't optimise presssure profile.
247
+ pars[:gs][:nblopt] = 0
248
+ end
249
+ end
250
+ end
251
+ gsrun.update_submission_parameters(pars[:gs].inspect, false)
252
+
253
+ # Create and initialize the trinity run
254
+ run = trinity_runner.run_class.new(trinity_runner)
255
+ raise "No trinity_defaults_strings" unless @parameters_obj.trinity_defaults_strings.size > 0
256
+ run.instance_variable_set(:@set_flux_defaults_procs, []) unless run.instance_variable_get(:@set_flux_defaults_procs)
257
+ @parameters_obj.trinity_defaults_strings.each{|prc| run.instance_eval(prc)}
258
+ run.update_submission_parameters(pars[:trinity].inspect, false)
259
+
260
+ #if @parameters_obj.gs_code == 'chease' and (run.evolve_geometry and run.evolve_geometry.fortran_true?)
261
+ #pars[:gs][:nblopt] = 0
262
+ #end
263
+ gs_runner.submit(gsrun)
264
+ gsrun = gs_runner.run_list[@gsid = gs_runner.max_id]
265
+ gsrun.recheck
266
+ gs_runner.update
267
+ #gs_runner.print_out(0)
268
+ #FileUtils.cp(gsrun.directory + '/ogyropsi.dat', trinity_runner.root_folder + '/.')
269
+
270
+ run.gs_folder = gsrun.directory
271
+ while (
272
+ not FileTest.exist? run.gs_folder + '/ogyropsi.dat' or
273
+ File.read(run.gs_folder + '/ogyropsi.dat') =~ /nan/i
274
+ )
275
+ #eputs "GS solver failed: using previous solution"
276
+
277
+ gs_runner.conditions = 'id == ' + @gsid.to_s
278
+ gs_runner.destroy(no_confirm: true)
279
+ gs_runner.conditions = nil
280
+ eputs "GS solver failed for #{v.inspect}: returning 10000"
281
+ return [10000, false]
282
+ #run.gs_folder = gs_runner.run_list[@gsid -= 1].directory
283
+ end
284
+ #run.evolve_geometry = ".true."
285
+ eputs ['Set gs_folder', run.gs_folder]
286
+ trinity_runner.run_class.instance_variable_set(:@delay_execution, true)
287
+ if trinity_runner.run_list.size > 0
288
+ if (old_run = trinity_runner.run_list[@id]).is_converged?
289
+ eputs "Previous trinity run #@id converged: using profile as initial condition"
290
+ run.init_option="trinity"
291
+ ## We have to copy the file because we need to be able to access the original from R
292
+ #FileUtils.cp("../id_#@id/#{old_run.run_name}.out.nc", "../id_#@id/#{old_run.run_name}_copy.out.nc")
293
+ run.init_file = "../id_#@id/#{old_run.run_name}.out.nc"
294
+ run.init_time = old_run.new_netcdf_file.var("t").get[-1]
295
+ old_run.new_ncclose rescue nil # Make sure the file is closed
296
+ else
297
+ eputs "Previous trinity run #@id not converged: restarting"
298
+ run.restart_id = @id
299
+ end
300
+ end
301
+ eputs 'Submitting run'
302
+ run.wall_mins = remaining_wall_mins
303
+ trinity_runner.submit(run)
304
+ run = trinity_runner.run_list[@id = trinity_runner.max_id]
305
+
306
+
307
+ comm = MPI::Comm::WORLD
308
+ arr = NArray.int(1)
309
+ arr[0] = 1
310
+ eputs 'Sending message'
311
+ comm.Bcast(arr,0)
312
+ comm.Bcast_string(run.directory)
313
+ comm.Bcast_string(run.run_name)
314
+ eputs 'Running trinity'
315
+ Dir.chdir(run.directory){run.run_trinity(run.run_name+'.trin', comm)}
316
+ eputs 'Rechecking'
317
+ trinity_runner.update
318
+ eputs 'Queue', run.queue_status
319
+
320
+ trinity_runner.update
321
+ @first_trinity_run_completed
322
+ end # if not @replay
323
+ #trinity_runner.print_out(0)
324
+ Dir.chdir(run.directory) do
325
+ run.recheck
326
+ run.status = :Complete
327
+ run.get_global_results
328
+ if (run.evolve_geometry and run.evolve_geometry.fortran_true?)
329
+ repeat = false
330
+ else
331
+ repeat = true
332
+ end
333
+ end
334
+ result = run.instance_eval(@optimised_quantity)
335
+ p ['result is ', result, 'repeat: ', repeat]
336
+ @first_run_done = true
337
+ @results_hash[:func_calls] ||=[]
338
+ @results_hash[:func_calls].push [print_pars, result]
339
+ Hash.phoenix('func_calls.rb') do |hash|
340
+ hash[@id] ||={}
341
+ hash[@id][:result] = result
342
+ hash[@id][:repeat] = repeat
343
+ hash[@id][:is_converged] = run.is_converged?
344
+ hash
345
+ end
346
+ return [-result, repeat, run.is_converged?]
347
+ #end
348
+
349
+
350
+ #v.square.sum
351
+ end
352
+ end
@@ -0,0 +1,61 @@
1
+ require 'ffi'
2
+ class CodeRunner
3
+ class Trinity
4
+ module TrinityDriver
5
+ extend FFI::Library
6
+ ffi_lib ENV['TRINITY'] + '/libtrin.so'
7
+ attach_function :runtr, :run_trinity_c, [:string, :size_t], :void
8
+ attach_function :runtr2, :run_trinity_test, [], :void
9
+ end
10
+ def run_trin_actual2(input_file, mpicomm_int)
11
+ puts ['calling TrinityDriver.runtr',mpicomm_int.class]
12
+ TrinityDriver.runtr(input_file, mpicomm_int)
13
+ end
14
+ def self.run_trin_standalone(input_file)
15
+ require 'mpi'
16
+ MPI.Init
17
+ obj = CodeRunner::Trinity.new
18
+ obj.run_trinity(input_file, MPI::Comm::WORLD)
19
+ MPI.Finalize
20
+ end
21
+ private :run_trin_actual2
22
+ end
23
+ end
24
+ require 'corfucrmod/trinitycrdriver_ext'
25
+ require 'mpi'
26
+
27
+ class CodeRunner::Trinity
28
+ # We overwrite the system module's implemenation of this command.
29
+ # Instead of running trinity via a bash command or a batch script,
30
+ # we run it directly via its API.
31
+ @delay_execution = false
32
+ def queue_status
33
+ ""
34
+ end
35
+ def execute
36
+ if rcp.delay_execution
37
+ eputs 'Delaying execution...'
38
+ return
39
+ else
40
+ execute_actual
41
+ end
42
+ end
43
+ def execute_actual
44
+ Dir.chdir(@directory){
45
+ if rcp.mpi_communicator?
46
+ start_mpi = false
47
+ mpicomm = rcp.mpi_communicator
48
+ else
49
+ start_mpi = true
50
+ MPI.Init
51
+ mpicomm = MPI::Comm::WORLD
52
+ puts ["INITIALISED MPI", mpicomm.size ]
53
+ end
54
+ run_trinity(@run_name + ".trin", mpicomm)
55
+ if start_mpi
56
+ MPI.Finalize
57
+ end
58
+
59
+ }
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,261 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: corfucrmod
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Edmund Highcock
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-07-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: coderunner
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.14.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: text-data-tools
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: gs2crmod
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.11.33
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.11.33
55
+ - !ruby/object:Gem::Dependency
56
+ name: trinitycrmod
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.11
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.7.11
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby-mpi
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.2.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: cheasecrmod
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.1.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 0.1.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: tokfile
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.0.3
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: shoulda
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 3.0.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 3.0.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rdoc
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.12'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.12'
139
+ - !ruby/object:Gem::Dependency
140
+ name: bundler
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.0.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: jeweler
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 2.0.1
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 2.0.1
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: minitest
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '4'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '4'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rake-compiler
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: |-
210
+ CorFu, the Coderunner/Trinity Fusion Optimisation Framework
211
+ allows the optimisation of fusion performance using first principles
212
+ flux calculations via Trinity.
213
+ email: edmundhighcock@users.sourceforge.net
214
+ executables: []
215
+ extensions:
216
+ - ext/corfucrmod/extconf.rb
217
+ extra_rdoc_files:
218
+ - LICENSE.txt
219
+ - README.rdoc
220
+ - README.rdoc.orig
221
+ files:
222
+ - ".document"
223
+ - Gemfile
224
+ - LICENSE.txt
225
+ - README.rdoc
226
+ - README.rdoc.orig
227
+ - Rakefile
228
+ - VERSION
229
+ - clean.sh
230
+ - corfucrmod.gemspec
231
+ - ext/corfucrmod/extconf.rb
232
+ - ext/corfucrmod/trinitycrdriver_ext.c
233
+ - lib/corfucrmod.rb
234
+ - lib/corfucrmod/corfu.rb
235
+ - lib/corfucrmod/optimisation.rb
236
+ - lib/corfucrmod/trinitycrdriver.rb
237
+ homepage: http://github.com/edmundhighcock/corfucrmod
238
+ licenses:
239
+ - GPLv3.0
240
+ metadata: {}
241
+ post_install_message:
242
+ rdoc_options: []
243
+ require_paths:
244
+ - lib
245
+ required_ruby_version: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ version: '0'
250
+ required_rubygems_version: !ruby/object:Gem::Requirement
251
+ requirements:
252
+ - - ">="
253
+ - !ruby/object:Gem::Version
254
+ version: '0'
255
+ requirements: []
256
+ rubyforge_project:
257
+ rubygems_version: 2.6.8
258
+ signing_key:
259
+ specification_version: 4
260
+ summary: A gem which implements the CorFu Optimisation Framework.
261
+ test_files: []