gafusion / omas

Ordered Multidimensional Array Structure
http://gafusion.github.io/omas
MIT License
30 stars 15 forks source link

Trouble accessing `langmuir_probes.embedded.:.time` #124

Closed eldond closed 3 years ago

eldond commented 3 years ago

Langmuir probes are allowed to have independent timing for different probes. That is, they use langmuir_probes.embedded.:.time, not langmuir_probes.embedded.time. Accessing langmuir_probes.embedded.:.time SOMETIMES works, and it seems that some padding with NaNs can be done to account for missing times. However, it doesn't work for varying array lengths, which are allowed in IMAS and make sense on the basis of how LPs work. It would be useful if times = ods['langmuir_probes.embedded.:.time'] would return a NaN padded 2D array for an ODS with varying lengths of time arrays, uneven time-bases, and missing time information for some probes (it's normal and useful to record probe physical R-Z coordinates even when they're off and have no data or time).

Here are commands for filling in sample data in an ODS that won't work with times = ods['langmuir_probes.embedded.:.time'].

ods['langmuir_probes.embedded.0.name'] = '1'
ods['langmuir_probes.embedded.0.position.r'] = 1.235
ods['langmuir_probes.embedded.0.position.z'] = -0.952
ods['langmuir_probes.embedded.0.position.phi'] = 0.0
ods['langmuir_probes.embedded.1.name'] = '2'
ods['langmuir_probes.embedded.1.position.r'] = 1.3
ods['langmuir_probes.embedded.1.position.z'] = -0.99
ods['langmuir_probes.embedded.1.position.phi'] = 0.0
ods['langmuir_probes.embedded.2.name'] = '3'
ods['langmuir_probes.embedded.2.position.r'] = 1.332
ods['langmuir_probes.embedded.2.position.z'] = -1.023
ods['langmuir_probes.embedded.2.position.phi'] = 0.0
ods['langmuir_probes.embedded.3.name'] = '4'
ods['langmuir_probes.embedded.3.position.r'] = 1.36
ods['langmuir_probes.embedded.3.position.z'] = -1.0295
ods['langmuir_probes.embedded.3.position.phi'] = 0.0
ods['langmuir_probes.embedded.4.name'] = '5'
ods['langmuir_probes.embedded.4.position.r'] = 1.381
ods['langmuir_probes.embedded.4.position.z'] = -1.032
ods['langmuir_probes.embedded.4.position.phi'] = 0.0
ods['langmuir_probes.embedded.5.name'] = '6'
ods['langmuir_probes.embedded.5.position.r'] = 1.41
ods['langmuir_probes.embedded.5.position.z'] = -1.035
ods['langmuir_probes.embedded.5.position.phi'] = 0.0

add_data = True
if add_data:
    t = ods['langmuir_probes.embedded.0.time'] = np.arange(0.5, 5.72, 0.001)
    dt = t[1] - t[0]
    poly_part = 0.0056 + (t / 5.2) * 1.2 + ((t - 2.3) / 2.4) ** 2 * 0.223 - ((t - 4.15) / 3.5) ** 2 * 0.45
    sine_part = np.sin(t / (dt * 3)) * 0.4 + np.cos(t / (dt * 10)) * 0.231 - np.sin(t / 0.234) * 0.054
    ods['langmuir_probes.embedded.0.saturation_current_ion.data'] = poly_part + sine_part
    t1 = ods['langmuir_probes.embedded.1.time'] = np.arange(0.5, 5.54, 0.001)
    ods['langmuir_probes.embedded.1.saturation_current_ion.data'] = (
        -0.001893 + (t1 / 4.9) * 0.867 + ((t1 - 2.7) / 2.35) ** 2 * 0.52 - ((t1 - 3.9) / 3.4) ** 2 * 0.654
    )
    ods['langmuir_probes.embedded.2.time'] = t
    ods['langmuir_probes.embedded.2.potential_plasma.data'] = 0.041 + 0.042 * t - 3.297e-3 * t ** 2
    ods['langmuir_probes.embedded.2.potential_floating.data'] = 0.001 + 0.023 * t - 4.121e-6 * t ** 2
    ods['langmuir_probes.embedded.2.t_e.data'] = 11.23 + 2.356 * cos(t / 0.789)
    ods['langmuir_probes.embedded.2.n_e.data'] = 10.9 + 35.6 / ods['langmuir_probes.embedded.2.t_e.data']

    ods['langmuir_probes.embedded.3.time'] = t
    ods['langmuir_probes.embedded.3.saturation_current_ion.data'] = (
        ods['langmuir_probes.embedded.0.saturation_current_ion.data'] * 0.326
    )
    ods['langmuir_probes.embedded.4.time'] = t
    ods['langmuir_probes.embedded.4.saturation_current_ion.data'] = (
        ods['langmuir_probes.embedded.0.saturation_current_ion.data'] * 0.12233
    )
    # Probe index 5 doesn't get any data; it's blank on purpose to make sure that
    # functions are robust to empty probes mixed in with data-having probes.
eldond commented 3 years ago

Okay, I gave a specific example, but it happens when combining any arrays with different lengths. That is, if I define a different number of X-points for different time-slices in equilibrium, I can't combine them:

xr = ods['equilibrium.time_slice.:.boundary.x_point.:.r']
xz = ods['equilibrium.time_slice.:.boundary.x_point.:.z']

The above sample only works if all the slices that have any X-points defined have the same number of X-points. Some slices are allowed to have totally missing X-point data and they get filled in with NaNs, which is very convenient.