gafusion / omas

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

Coordinate interpolation always uses coordinate from source 0 #134

Closed bclyons12 closed 3 years ago

bclyons12 commented 3 years ago

If the different sources in ods.core_sources have different lengths, there are issues with coordinate interpolation. It looks like all the sources look to core_sources.source[0].profiles_1d[0].grid.rho_tor_norm to know if they should interpolate and then it's not done right. I made an example here: /fusion/projects/omfit-results/lyonsbc/projects/ods_source-coord-interp-fail.zip The ODS has two sources. 0 has length 201 and 1 has length 51. If I try to interpolate on core_sources.source[1].profiles_1d[0].grid.rho_tor_norm, nothing happens. If I try on core_sources.source[0].profiles_1d[0].grid.rho_tor_norm, the source 0 interpolation works properly, but then 1 throws an error. Script is in Command box 1, results are below. Note that there's a bug in the exception statement, but that's not the problem. The code for the exception is

if len(ods_coordinates.__getitem__(coordinate, None)) != len(value):
    raise Exception(
        'coordsio %s.shape=%s does not match %s.shape=%s'
        % (coordinate, output_coordinates.__getitem__(coordinate, False).shape, location, value.shape)
    )

The output_coordinates in the Exception should be ods_coordinates, I think.

Original ODS source lengths
0:  201
1:  51

Interpolate Source 1 rho to 101
Should give 201 & 101, but Source 1 does not interpolate
0:  201
1:  51

Interpolate Source 0 rho to 101
Should give 101 & 51, but Source 1 throws error
0:  101
Error in "OMFIT command box #1" at line  22
    print('1: ', len(ods['core_sources.source[1].profiles_1d[0].grid.volume']))
  [Previous line repeated 3 more times]

Exception: coordsio core_sources.source.0.profiles_1d.0.grid.rho_tor_norm.shape=(101,) does not match core_sources.source.0.profiles_1d.0.grid.volume.shape=(51,)

Press <F6> to see full error report...

Traceback (most recent call last):
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/classes/OMFITx.py", line 4068, in manage_user_errors
    tmp=command(**kw)
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/utils_tk.py", line 1060, in GlobLoc_tk
    return py.run(_relLoc=self.namespace, _OMFITscriptsDict=False, _OMFITconsoleDict=True, noGUI=None)
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/classes/omfit_python.py", line 1082, in run
    result = self.__run__(**kw)
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/classes/omfit_python.py", line 931, in __run__
    self, userDict=kw, inputDict=_relLoc, persistentDict=OMFITconsoleDict, runDict={}, prerun=prerun, postrun=postrun
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/classes/omfit_python.py", line 129, in f_locked
    return f(*args, **kw)
  File "/fusion/projects/omfit-results/lyonsbc/OMFIT-source/omfit/classes/omfit_python.py", line 362, in execGlobLoc
    exec(compile(execString, filename, "exec"), GlobLoc)
  File "/local-scratch/lyonsbc/OMFIT/OMFIT_2020-10-26_18_37_01_292295/project/OMFIT command box #1", line 22, in <module>
    print('1: ', len(ods['core_sources.source[1].profiles_1d[0].grid.volume']))
  File "/fusion/projects/omfit-results/lyonsbc/omas/omas/omas_core.py", line 1152, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  File "/fusion/projects/omfit-results/lyonsbc/omas/omas/omas_core.py", line 1152, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  File "/fusion/projects/omfit-results/lyonsbc/omas/omas/omas_core.py", line 1152, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  [Previous line repeated 3 more times]
  File "/fusion/projects/omfit-results/lyonsbc/omas/omas/omas_core.py", line 1215, in __getitem__
    % (coordinate, output_coordinates.__getitem__(coordinate, False).shape, location, value.shape)
Exception: coordsio core_sources.source.0.profiles_1d.0.grid.rho_tor_norm.shape=(101,) does not match core_sources.source.0.profiles_1d.0.grid.volume.shape=(51,)
orso82 commented 3 years ago

@bclyons12 the issue here is not with the interpolation logic, but rather with how the ODS was filled with data.

The issue is that somehow your ODS core_sources.source.1.profiles_1d.0.grid and core_sources.source.0.profiles_1d.0.grid had the same .location attribute, which was was set to core_sources.source.0.profiles_1d.0.grid.

I can think of ways that this could happen, but those ways would be quite convoluted.

I could make OMAS more robust to this kind of situations, but I would first like to know how did you get the ODS that was saved in that project...

bclyons12 commented 3 years ago

I got it through running STEP: CHEF (with FREYA) --> ONETWO (external sources) --> EFIT.

bclyons12 commented 3 years ago

N.B.: That had 11 sources and only the last one had a different grid size. I deleted 2-10 to make the one in the project with just two sources.

bclyons12 commented 3 years ago

@orso82 It's after the ONETWO step, maybe from the merged work by you and @TimSlendebroek ? I ran this:

ods = OMFIT['STEP_4']['STATE'][2]
for s in ods['core_sources']['source']:
    print('%2d'%s, ods['core_sources']['source'][s]['profiles_1d'][0]['grid'].location)

and got

0 core_sources.source.0.profiles_1d.0.grid
 1 core_sources.source.1.profiles_1d.0.grid
 2 core_sources.source.2.profiles_1d.0.grid
 3 core_sources.source.3.profiles_1d.0.grid
 4 core_sources.source.6.profiles_1d.0.grid
 5 core_sources.source.7.profiles_1d.0.grid
 6 core_sources.source.8.profiles_1d.0.grid
 7 core_sources.source.11.profiles_1d.0.grid
 8 core_sources.source.12.profiles_1d.0.grid
 9 core_sources.source.14.profiles_1d.0.grid
10 core_sources.source.16.profiles_1d.0.grid
11 core_sources.source.0.profiles_1d.0.grid

All sorts of messed up.

TimSlendebroek commented 3 years ago

I think if you run ONETWO (external sources) it copies the core_sources odd over from the previous STATE. What do the core_sources in your previous STEP step look like?

bclyons12 commented 3 years ago

@orso82 @TimSlendebroek Looks like there are two problems in ONETWO_step.py. First, calling del on a source does not change the source number of the grid: https://github.com/gafusion/OMFIT-source/blob/e394ea9fea181453eda7517ed956fe68b65c1ef8/modules/STEP/STEPS/ONETWO_step.py#L225

Second, adding an existing source keeps that source's original number for the grid: https://github.com/gafusion/OMFIT-source/blob/e394ea9fea181453eda7517ed956fe68b65c1ef8/modules/STEP/STEPS/ONETWO_step.py#L229

Example: take any ODS with multiple sources. I had one with 16, so I deleted source 13 and then readded it to sources. Here's the code:

ods = OMFIT['ods_12_mod'] = copy.deepcopy(OMFIT['ods_12'])
print('Original')
for s in ods['core_sources']['source']:
    print('%2d'%s, 
          ods['core_sources']['source'][s]['profiles_1d'][0]['grid'].location)
src = copy.deepcopy(ods['core_sources']['source'][13])
print()
print('13 deleted')
del ods['core_sources']['source'][13]
for s in ods['core_sources']['source']:
    print('%2d'%s, 
          ods['core_sources']['source'][s]['profiles_1d'][0]['grid'].location)
print()
print('13 readded')
ods['core_sources']['source']['+'] = src
for s in ods['core_sources']['source']:
    print('%2d'%s, 
          ods['core_sources']['source'][s]['profiles_1d'][0]['grid'].location)

and the result

Original
 0 core_sources.source.0.profiles_1d.0.grid
 1 core_sources.source.1.profiles_1d.0.grid
 2 core_sources.source.2.profiles_1d.0.grid
 3 core_sources.source.3.profiles_1d.0.grid
 4 core_sources.source.4.profiles_1d.0.grid
 5 core_sources.source.5.profiles_1d.0.grid
 6 core_sources.source.6.profiles_1d.0.grid
 7 core_sources.source.7.profiles_1d.0.grid
 8 core_sources.source.8.profiles_1d.0.grid
 9 core_sources.source.9.profiles_1d.0.grid
10 core_sources.source.10.profiles_1d.0.grid
11 core_sources.source.11.profiles_1d.0.grid
12 core_sources.source.12.profiles_1d.0.grid
13 core_sources.source.13.profiles_1d.0.grid
14 core_sources.source.14.profiles_1d.0.grid
15 core_sources.source.15.profiles_1d.0.grid
16 core_sources.source.16.profiles_1d.0.grid

13 deleted
 0 core_sources.source.0.profiles_1d.0.grid
 1 core_sources.source.1.profiles_1d.0.grid
 2 core_sources.source.2.profiles_1d.0.grid
 3 core_sources.source.3.profiles_1d.0.grid
 4 core_sources.source.4.profiles_1d.0.grid
 5 core_sources.source.5.profiles_1d.0.grid
 6 core_sources.source.6.profiles_1d.0.grid
 7 core_sources.source.7.profiles_1d.0.grid
 8 core_sources.source.8.profiles_1d.0.grid
 9 core_sources.source.9.profiles_1d.0.grid
10 core_sources.source.10.profiles_1d.0.grid
11 core_sources.source.11.profiles_1d.0.grid
12 core_sources.source.12.profiles_1d.0.grid
13 core_sources.source.14.profiles_1d.0.grid
14 core_sources.source.15.profiles_1d.0.grid
15 core_sources.source.16.profiles_1d.0.grid

13 readded
 0 core_sources.source.0.profiles_1d.0.grid
 1 core_sources.source.1.profiles_1d.0.grid
 2 core_sources.source.2.profiles_1d.0.grid
 3 core_sources.source.3.profiles_1d.0.grid
 4 core_sources.source.4.profiles_1d.0.grid
 5 core_sources.source.5.profiles_1d.0.grid
 6 core_sources.source.6.profiles_1d.0.grid
 7 core_sources.source.7.profiles_1d.0.grid
 8 core_sources.source.8.profiles_1d.0.grid
 9 core_sources.source.9.profiles_1d.0.grid
10 core_sources.source.10.profiles_1d.0.grid
11 core_sources.source.11.profiles_1d.0.grid
12 core_sources.source.12.profiles_1d.0.grid
13 core_sources.source.14.profiles_1d.0.grid
14 core_sources.source.15.profiles_1d.0.grid
15 core_sources.source.16.profiles_1d.0.grid
16 core_sources.source.13.profiles_1d.0.grid
orso82 commented 3 years ago

@bclyons12 great investigative work! 👍

you can solve issue (2) by doing: onetwo_ods['core_sources.source']['+'] = copy.deepcopy(source)

while I have do handle issue (1) on the OMAS side

bclyons12 commented 3 years ago

@orso82 copy.deepcopy(source) doesn't seem to make a difference. That's done in my example script above.

orso82 commented 3 years ago

good point, for the time being, try:

onetwo_ods['core_sources.source']['+'] = ODS()
onetwo_ods['core_sources.source'][-1].update(source)

I have to fix this within OMAS...

bclyons12 commented 3 years ago

Just making @jmcclena aware in the meantime. I'm just going to interpolate them all onto the same grid for now to avoid this issue. The references will still be wrong, but the values will be the same so it won't know any difference.