gs2crmod 0.11.78 → 0.11.79
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/VERSION +1 -1
- data/ext/gs2crmod_ext.c +0 -399
- data/gs2crmod.gemspec +7 -5
- data/lib/gs2crmod/calculations.rb +4 -35
- data/lib/gs2crmod/graphs.rb +1 -1
- data/lib/gs2crmod/gs2.rb +0 -236
- data/lib/gs2crmod/gsl_data.rb +1305 -1304
- metadata +22 -40
data/lib/gs2crmod/gs2.rb
CHANGED
@@ -1181,246 +1181,10 @@ end
|
|
1181
1181
|
end
|
1182
1182
|
end
|
1183
1183
|
|
1184
|
-
#This function will handle running the correlation analysis and writing the results to a NetCDF file.
|
1185
|
-
#Cases need to be handled differently since perp, par and full are just subsets of the full correlation function
|
1186
|
-
#but the time correlation calculation needs to deal with each radial location separately. Time correlation
|
1187
|
-
#uses the zonal flows in the toroidal direction to calculate the correlation time.
|
1188
|
-
#
|
1189
|
-
#This function takes in the same options as field_real_space_standard_representation, along with the following
|
1190
|
-
#new options dealing with interpolation and binning:
|
1191
|
-
#
|
1192
|
-
# correlation_type: determines which subset of correlation function should be calculated (perp/par/full/time)
|
1193
|
-
# nbins_array: array giving number of bins to use in the binning procedure. Index order (x, y, z ,t)
|
1194
|
-
# nt_reg: Most of the time you have many more time points than you need for spatial correlations. This sets
|
1195
|
-
# number of new interpolation points in time.
|
1196
|
-
#
|
1197
|
-
# Using this function: Since this can only be single threaded, this can be a very expensive calculation when
|
1198
|
-
# trying to do the full correlation function, so this is not recommended for highly resolved nonlinear runs. This is
|
1199
|
-
# why the perp/par/full splitting is implemented, allowing one dimension to be taken out essentially.
|
1200
|
-
def correlation_analysis(options={})
|
1201
|
-
|
1202
|
-
#Sanity checks:
|
1203
|
-
#Cannot only have one bin since require difference between bins for index calculation
|
1204
|
-
if options[:nbins_array].include?1
|
1205
|
-
raise('Cannot have only one bin in nbins_array. Minuimum is two.')
|
1206
|
-
end
|
1207
|
-
#Thetamin shouldn't be equal to thetamax to avoid possibili
|
1208
|
-
#
|
1209
|
-
|
1210
|
-
case options[:correlation_type]
|
1211
|
-
when 'perp', 'par', 'full'
|
1212
|
-
gsl_tensor = field_correlation_gsl_tensor(options)
|
1213
|
-
shape = gsl_tensor.shape
|
1214
|
-
|
1215
|
-
#Set up dimensions
|
1216
|
-
file = NumRu::NetCDF.create(@run_name + "_correlation_analysis_#{options[:correlation_type]}.nc")
|
1217
|
-
ydim = file.def_dim('x',shape[0])
|
1218
|
-
xdim = file.def_dim('y',shape[1])
|
1219
|
-
zdim = file.def_dim('z',shape[2])
|
1220
|
-
tdim = file.def_dim('t',shape[3])
|
1221
|
-
correlation_var = file.def_var("correlation", 'sfloat', [xdim, ydim, zdim, tdim])
|
1222
|
-
file.enddef
|
1223
|
-
#Write out array
|
1224
|
-
correlation_var.put(NArray.to_na(gsl_tensor.to_a))
|
1225
|
-
file.close
|
1226
|
-
when 'time'
|
1227
|
-
nakx_actual = NumRu::NetCDF.open(@run_name + ".out.nc").var('kx').get
|
1228
|
-
kx_len = nakx_actual.length
|
1229
|
-
if options[:nakx] == nil
|
1230
|
-
radial_pts = kx_len
|
1231
|
-
elsif options[:nakx] <= kx_len
|
1232
|
-
radial_pts = options[:nakx]
|
1233
|
-
else
|
1234
|
-
raise('nakx exceeds the total number of kx\'s in simulation')
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
#Check whether t_index_window is specified, if not, set to entire t range
|
1238
|
-
if options[:t_index_window] == nil
|
1239
|
-
options[:t_index_window] = [1, -1]
|
1240
|
-
end
|
1241
|
-
|
1242
|
-
|
1243
|
-
#Now loop through the radial locations and calculate the correlation function in y and t.
|
1244
|
-
for x in 0...radial_pts
|
1245
|
-
options[:xmin] = x
|
1246
|
-
options[:xmax] = x
|
1247
|
-
gsl_tensor = field_correlation_gsl_tensor(options)
|
1248
|
-
shape = gsl_tensor.shape
|
1249
|
-
|
1250
|
-
if x == 0 #Write dimensions to NetCDF file
|
1251
|
-
file = NumRu::NetCDF.create(@run_name + "_correlation_analysis_#{options[:correlation_type]}.nc")
|
1252
|
-
ydim = file.def_dim('x',shape[0])
|
1253
|
-
xdim = file.def_dim('y',shape[1])
|
1254
|
-
zdim = file.def_dim('z',shape[2])
|
1255
|
-
tdim = file.def_dim('t',shape[3])
|
1256
|
-
end
|
1257
|
-
file.redef
|
1258
|
-
correlation_var = file.def_var("correlation_x_#{x}", 'sfloat', [xdim, ydim, zdim, tdim])
|
1259
|
-
file.enddef
|
1260
|
-
#Write out array
|
1261
|
-
correlation_var.put(NArray.to_na(gsl_tensor.to_a))
|
1262
|
-
end
|
1263
|
-
file.close #only close after loop over radial points
|
1264
|
-
else
|
1265
|
-
raise 'Please specify correlation_type as perp/par/time/full'
|
1266
|
-
end
|
1267
|
-
end
|
1268
|
-
|
1269
1184
|
def input_file_extension
|
1270
1185
|
'.in'
|
1271
1186
|
end
|
1272
1187
|
|
1273
|
-
#This function will interpolate and output either phi or density at the outboard midplane
|
1274
|
-
#on a 40x40 grid appropriate to analyse as experimental data. It called as a run_command
|
1275
|
-
#e.g. rc 'bes_output(options)', j:<run number>. It will call field_real_space_poloidal_plane_graphkit
|
1276
|
-
#for every time step, interpolate at outboard midplane, and write fields and grids out to NetCDF file.
|
1277
|
-
#
|
1278
|
-
#Options: Same as field_real_space_poloidal_plane, field name must also be specified for generality. New options:
|
1279
|
-
#
|
1280
|
-
# no_flux_tube_copies: ensures only one flux tube is printed out with zeroes everywhere else.
|
1281
|
-
# amin: Minor radius (to which R,Z are normalized) so that grid is in right units
|
1282
|
-
# output_box_size: Array of sizes of output box (in units of amin) either side of middle of fluxtube at outboard midplane
|
1283
|
-
# in R direction and either side of outboard midplane in Z direction.
|
1284
|
-
# output_box_points: Array of number of points in output box (R,Z). Default will be 50x50.
|
1285
|
-
#
|
1286
|
-
#The interpolation routine used will only interpolate correctly inside the fluxtube and produce garbage outside. Regular points are checked
|
1287
|
-
#for being inside or outside the fluxtube and values of the field outside the fluxtube are set to zero.
|
1288
|
-
def bes_output(options={})
|
1289
|
-
#******************
|
1290
|
-
# Read in options *
|
1291
|
-
#******************
|
1292
|
-
#In order to interpolate on constant grids, ensure constant_torphi is set to some value (default 0.0)
|
1293
|
-
if options[:constant_torphi] == nil
|
1294
|
-
p 'constant_torphi not set! Setting it to 0.0.'
|
1295
|
-
options[:constant_torphi] = 0.0
|
1296
|
-
end
|
1297
|
-
#Check whether t_index_window is specified, if not, set to entire t range
|
1298
|
-
if options[:t_index_window] == nil
|
1299
|
-
t_index_beg = 1
|
1300
|
-
t_index_end = gsl_vector(:t).length
|
1301
|
-
else
|
1302
|
-
t_index_beg = options[:t_index_window][0]
|
1303
|
-
t_index_end = options[:t_index_window][1]
|
1304
|
-
end
|
1305
|
-
if options[:amin]
|
1306
|
-
amin = options[:amin]
|
1307
|
-
end
|
1308
|
-
if options[:v_ref] # velocity of reference species
|
1309
|
-
v_ref = options[:v_ref]
|
1310
|
-
end
|
1311
|
-
if options[:omega] # angular velocity of plasma
|
1312
|
-
omega = options[:omega]
|
1313
|
-
end
|
1314
|
-
if options[:omega] and (options[:v_ref] == nil or options[:amin] == nil)
|
1315
|
-
raise 'Need to specify amin AND v_ref options when specifying omega to move to LAB frame!'
|
1316
|
-
end
|
1317
|
-
if options[:output_box_size] and options[:output_box_size].kind_of?Array
|
1318
|
-
_r_box_size = options[:output_box_size][0] # EGH These variables are marked as unused... are they used anywhere?
|
1319
|
-
_z_box_size = options[:output_box_size][1]
|
1320
|
-
#else
|
1321
|
-
# raise 'Option output_box_size must be specified (in units of amin) and must be an Array.'
|
1322
|
-
end
|
1323
|
-
if options[:output_box_points] and options[:output_box_points].kind_of?Array
|
1324
|
-
r_box_pts = options[:output_box_points][0]
|
1325
|
-
z_box_pts = options[:output_box_points][1]
|
1326
|
-
else
|
1327
|
-
r_box_pts = 50
|
1328
|
-
z_box_pts = 50
|
1329
|
-
end
|
1330
|
-
|
1331
|
-
#Call at first time step to set up arrays and grids
|
1332
|
-
options[:t_index] = t_index_beg
|
1333
|
-
kit = field_real_space_poloidal_plane_graphkit(options)
|
1334
|
-
x = kit.data[0].x.data
|
1335
|
-
_y = kit.data[0].y.data
|
1336
|
-
z = kit.data[0].z.data
|
1337
|
-
|
1338
|
-
#Set up NetCDf file
|
1339
|
-
file = NumRu::NetCDF.create(@run_name + "_bes_output.nc")
|
1340
|
-
xdim = file.def_dim('y', x.shape[0])
|
1341
|
-
zdim = file.def_dim('z', z.shape[1])
|
1342
|
-
tdim = file.def_dim('t', 0) #zero means unlimited
|
1343
|
-
x_var = file.def_var("x", 'sfloat', [xdim, zdim])
|
1344
|
-
z_var = file.def_var("z", 'sfloat', [xdim, zdim])
|
1345
|
-
t_var = file.def_var("t", 'sfloat', [tdim])
|
1346
|
-
field_var = file.def_var("field", 'sfloat', [xdim, zdim, tdim])
|
1347
|
-
file.enddef
|
1348
|
-
#Write dimensions to file
|
1349
|
-
x_var.put(NArray.to_na(x.to_a))
|
1350
|
-
z_var.put(NArray.to_na(z.to_a))
|
1351
|
-
|
1352
|
-
#Loop over time, load field as function of space at each time index, write to file
|
1353
|
-
for i in t_index_beg...t_index_end #inclusive of end
|
1354
|
-
Terminal.erewind(1) #go back one line in terminal
|
1355
|
-
eputs sprintf("Writing time index = %d of %d#{Terminal::CLEAR_LINE}", i, t_index_end-t_index_beg+1) #clear line and print time index
|
1356
|
-
options[:t_index] = i
|
1357
|
-
#Need to test whether omega is specified to change torphi at each time step. If not, do nothing since torphi must be
|
1358
|
-
#set to a value to call the graphkit below
|
1359
|
-
if options[:omega]
|
1360
|
-
options[:torphi] = omega * (gsl_vector(:t)[i] - gsl_vector(:t)[0]) * (amin/v_ref)
|
1361
|
-
end
|
1362
|
-
kit = field_real_space_poloidal_plane_graphkit(options)
|
1363
|
-
t_var.put(gsl_vector(:t)[i], 'index'=>[i-t_index_beg]) #Write time to unlimited time NetCDF variable
|
1364
|
-
field_var.put(NArray.to_na((kit.data[0].f.data).to_a), 'start'=>[0,0,i-t_index_beg], 'end'=>[-1,-1,i-t_index_beg])
|
1365
|
-
end
|
1366
|
-
file.close
|
1367
|
-
|
1368
|
-
#Ignore this until interpolation issue is sorted
|
1369
|
-
=begin
|
1370
|
-
#**************************
|
1371
|
-
# Set up new regular grid *
|
1372
|
-
#**************************
|
1373
|
-
th_grid_size = x.shape[1]
|
1374
|
-
flux_tube_midpt = x[0, (th_grid_size-1)/2] + (x[-1, (th_grid_size-1)/2] - x[1, (th_grid_size-1)/2])/2
|
1375
|
-
x_vec_reg = GSL::Vector.linspace(flux_tube_midpt - r_box_size, flux_tube_midpt + r_box_size, r_box_pts)
|
1376
|
-
z_vec_reg = GSL::Vector.linspace(-z_box_size, z_box_size, z_box_pts)
|
1377
|
-
x_reg = GSL::Matrix.alloc(r_box_pts, z_box_pts)
|
1378
|
-
z_reg = GSL::Matrix.alloc(r_box_pts, z_box_pts)
|
1379
|
-
field_reg = GSL::Matrix.alloc(r_box_pts, z_box_pts)
|
1380
|
-
for i in 0...r_box_pts
|
1381
|
-
for j in 0...z_box_pts
|
1382
|
-
x_reg[i,j] = x_vec_reg[i]
|
1383
|
-
z_reg[i,j] = z_vec_reg[j]
|
1384
|
-
end
|
1385
|
-
end
|
1386
|
-
|
1387
|
-
#************************************************
|
1388
|
-
# Find the field at every point on regular grid *
|
1389
|
-
#************************************************
|
1390
|
-
#To evaluate field on a regular grid given the field on an irregular grid, need to interpolate. The rubygem
|
1391
|
-
#gsl_extras contains an interpolation routine called ScatterInterp which does exactly this based on a
|
1392
|
-
#'Radial Basis Function' method.
|
1393
|
-
|
1394
|
-
#Have R, Z, and field on an irregular grid in the form of matrices. ScatterInterp only takes in GSL vectors
|
1395
|
-
#so simply convert these matrices to vectors (of size row*col) since the order of the pts don't matter.
|
1396
|
-
x_vec = GSL::Vector.alloc(x.shape[0]*x.shape[1])
|
1397
|
-
z_vec = GSL::Vector.alloc(x.shape[0]*x.shape[1])
|
1398
|
-
field_vec = GSL::Vector.alloc(x.shape[0]*x.shape[1])
|
1399
|
-
for i in 0...x.shape[0]
|
1400
|
-
for j in 0...x.shape[1]
|
1401
|
-
x_vec[x.shape[1]*i + j] = x[i,j]
|
1402
|
-
z_vec[x.shape[1]*i + j] = z[i,j]
|
1403
|
-
field_vec[x.shape[1]*i + j] = field[i,j]
|
1404
|
-
end
|
1405
|
-
end
|
1406
|
-
|
1407
|
-
#Now pass these vectors to ScatterInterp. This creates an object with instance method 'eval' which can be given an x,z coord
|
1408
|
-
#at which to evaluate the interpolated function.
|
1409
|
-
p 'Interpolating'
|
1410
|
-
interp = GSL::ScatterInterp.alloc(:linear, [x_vec, z_vec, field_vec], false, r0=0.1)
|
1411
|
-
p 'Finished interpolating'
|
1412
|
-
for i in 0...x_vec_reg.size
|
1413
|
-
for j in 0...z_vec_reg.size
|
1414
|
-
field_reg[i,j] = interp.eval(x_vec_reg[i], z_vec_reg[j])
|
1415
|
-
end
|
1416
|
-
end
|
1417
|
-
|
1418
|
-
kit = GraphKit.quick_create([x_vec_reg, z_vec_reg, field_reg])
|
1419
|
-
#kit2 = GraphKit.quick_create([x_vec, z_vec, field_vec])
|
1420
|
-
=end
|
1421
|
-
|
1422
|
-
end
|
1423
|
-
|
1424
1188
|
#This section defines a selection of graphs which are written to a latex file when the CR function write_report is called. To add your own, simply copy one a similar looking graph and modify it to your needs.
|
1425
1189
|
# The requirements to use the latex report writing is further specified in CodeRunner.
|
1426
1190
|
def latex_graphs
|