gs2crmod 0.11.78 → 0.11.79
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.
- 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
|