Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fill out more of the EFIT mapping to MDS+ #255

Merged
merged 40 commits into from
Aug 12, 2023
Merged

Conversation

torrinba
Copy link
Collaborator

This may not be 100% complete, but should be pretty close.

This may not be 100% complete, but should be pretty close.
@torrinba torrinba requested a review from AreWeDreaming June 29, 2023 20:44
@torrinba torrinba self-assigned this Jun 29, 2023
@torrinba
Copy link
Collaborator Author

torrinba commented Jun 29, 2023

I am leaving it up to you to test this out @AreWeDreaming

There several areas that need more attention still

  1. constraints.pressure.:.position.psi needs to have an absolute value applied (some additional logic could expand the applicability further)
  2. constraints.pf_current needs to have e-coils, f-coils, and a-coils appended (I just put slashes for now so this is most likely why the regression build fails)
  3. constraints.mse_polarisation_angle needs to have an atan applied
  4. constraints.chi_squared_total is an OMAS extension that is not yet part of IMAS (up to you whether it should be included now or not)
  5. constraints.j_tor needs to be converted to OMAS units (some additional logic could expand the applicability of the position.psi as well)

torrinba added 4 commits June 29, 2023 16:23
Changes will be made in EFIT to make these usable
This includes nearly all of the additional EFIT variables in MDS+
that I know how to mapp to IMAS.
There were other name changes I had missed.

This takes care of everything that comes out of EFIT now.
@AreWeDreaming
Copy link
Collaborator

  • constraints.pressure.:.position.psi needs to have an absolute value applied (some additional logic could expand the applicability further)
  • constraints.pf_current needs to have e-coils, f-coils, and a-coils appended (I just put slashes for now so this is most likely why the regression build fails)
  • constraints.mse_polarisation_angle needs to have an atan applied
  • constraints.chi_squared_total is an OMAS extension that is not yet part of IMAS (up to you whether it should be included now or not)
  • constraints.j_tor needs to be converted to OMAS units (some additional logic could expand the applicability of the position.psi as well)

I think I got this covered in my next commit (not yet pushed because it needs to be tested)

@torrinba
Copy link
Collaborator Author

I also forgot that the constraints.j_tor will need to be added as an OMAS extension until the new IMAS version gets released and updated. Hopefully you resolved this already, but if not I can help with that

@AreWeDreaming
Copy link
Collaborator

After some modifications of OMAS I got most of the fields to load, but the following do not have data for my test case 17408219 created with CAKE. Notably I didn't test all of these but rather these are the ones I get MDS+ exception for. The first one ZSEPS is kinda weird because RSEP is set correctly.

equilibrium.time_slice.:.boundary.x_point.:.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZSEPS','\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZSEPS',0)
equilibrium.time_slice.:.boundary_separatrix.closest_wall_point.distance: data(\{EFIT_tree}::TOP.RESULTS.AEQDSK.DSEP)/100.
equilibrium.time_slice.:.boundary_separatrix.geometric_axis.z: data(\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZOUT)/100.
equilibrium.time_slice.:.boundary_separatrix.strike_point.1.r: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSID/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.RVSID/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.1.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSID/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZVSID/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.2.r: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOD/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.RVSOD/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.2.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOD/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZVSOD/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.3.r: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSIU/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.RVSIU/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.3.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSIU/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZVSIU/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.4.r: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOU/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.RVSOU/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.strike_point.4.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOU/100.','\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZVSOU/100.',-0.89)
equilibrium.time_slice.:.boundary_separatrix.x_point.:.z: py2tdi(nan_where,'\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZSEPS','\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZSEPS',0)
equilibrium.time_slice.:.constraints.bpol_probe.:.measured_error_upper: data(\{EFIT_tree}::TOP.MEASUREMENTS.SIGMPI)
equilibrium.time_slice.:.constraints.diamagnetic_flux.chi_squared: data(\{EFIT_tree}::TOP.MEASUREMENTS.CHIDFLUX)
equilibrium.time_slice.:.constraints.diamagnetic_flux.weight: data(\{EFIT_tree}::TOP.MEASUREMENTS.FWTDIA)
equilibrium.time_slice.:.constraints.flux_loop.:.chi_squared: data(\{EFIT_tree}::TOP.MEASUREMENTS.SAISI)
equilibrium.time_slice.:.constraints.flux_loop.:.measured_error_upper: data(\{EFIT_tree}::TOP.MEASUREMENTS.SIGSIL)
equilibrium.time_slice.:.constraints.ip.chi_squared: data(\{EFIT_tree}::TOP.MEASUREMENTS.CHIPASMA)
equilibrium.time_slice.:.constraints.ip.measured_error_upper: data(\{EFIT_tree}::TOP.MEASUREMENTS.SIGPASMA)
equilibrium.time_slice.:.constraints.ip.weight: data(\{EFIT_tree}::TOP.MEASUREMENTS.FWTPASMA)
equilibrium.time_slice.:.constraints.j_tor.:.measured: data(\{EFIT_tree}::TOP.MEASUREMENTS.VZEROJ)*data(\{EFIT_tree}::TOP.RESULTS.GEQDSK.CPASMA)/(data(\{EFIT_tree}::TOP.RESULTS.AEQDSK.AREA)/10000.)
equilibrium.time_slice.:.constraints.j_tor.:.position.psi: py2tdi(efit_psi_to_psi,'\{EFIT_tree}::TOP.MEASUREMENTS.SIZEROJ','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY')
equilibrium.time_slice.:.constraints.pf_current.:.chi_squared: py2tdi(stack_outer,'\{EFIT_tree}::TOP.MEASUREMENTS.CHIECC','\{EFIT_tree}::TOP.MEASUREMENTS.CHIFCC')
equilibrium.time_slice.:.constraints.pf_current.:.measured: py2tdi(stack_outer,'\{EFIT_tree}::TOP.MEASUREMENTS.ECCURT','\{EFIT_tree}::TOP.MEASUREMENTS.FCCURT','\{EFIT_tree}::TOP.MEASUREMENTS.ACCURT')
equilibrium.time_slice.:.constraints.pf_current.:.measured_error_upper: py2tdi(stack_outer,'\{EFIT_tree}::TOP.MEASUREMENTS.SIGECC','\{EFIT_tree}::TOP.MEASUREMENTS.SIGFCC')
equilibrium.time_slice.:.constraints.pf_current.:.reconstructed: py2tdi(stack_outer,'\{EFIT_tree}::TOP.MEASUREMENTS.CECURR','\{EFIT_tree}::TOP.MEASUREMENTS.CCBRSP')
equilibrium.time_slice.:.constraints.pf_current.:.weight: py2tdi(stack_outer,'\{EFIT_tree}::TOP.MEASUREMENTS.FWTEC','\{EFIT_tree}::TOP.MEASUREMENTS.FWTFC')
equilibrium.time_slice.:.constraints.pressure.:.position.psi: py2tdi(efit_psi_to_psi,'\{EFIT_tree}::TOP.MEASUREMENTS.RPRESS','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY')

@AreWeDreaming
Copy link
Collaborator

@bechtt Could you take a look at this list and note any fields that should be set by a standard EFIT run but aren't. If none of these are expected to be set then that's fine, we'll add them on CAKE side of things.

@AreWeDreaming
Copy link
Collaborator

@orso82 Any idea why the following TDI expression would cause trouble:

"equilibrium.time_slice.:.convergence.iterations_n": {
    "eval2TDI": "py2tdi(nan_max_where,'size(\\{EFIT_tree}::TOP.MEASUREMENTS.CERROR)','\\{EFIT_tree}::TOP.MEASUREMENTS.CERROR',0)",
    "treename": "{EFIT_tree}"
 }

with

def nan_max_where(a, b, n):
    import numpy as np

    a = a.data()
    b = b.data()
    a[b == n] = np.NaN
    return np.nanmax(a)

MDS+ just returns an error with no info on what's actually wrong.

@torrinba
Copy link
Collaborator Author

torrinba commented Jul 18, 2023

After some modifications of OMAS I got most of the fields to load, but the following do not have data for my test case 17408219 created with CAKE. Notably I didn't test all of these but rather these are the ones I get MDS+ exception for. The first one ZSEPS is kinda weird because RSEP is set correctly.

Most of the issues from MEASUREMENTS were missing or conflicting names between what was setup in MDS+ for rtEFIT and the offline version of EFIT. I fixed the EFIT outputs to match, but you will have to rerun the case to see that.

The AEQDSK failures are harder to diagnose. It's possible there are are problems with efitloader. That's the only reason I can think RSEPS would be set but not ZSEPS (which I see in other cases as well)

omas/omas_core.py Outdated Show resolved Hide resolved
@torrinba
Copy link
Collaborator Author

torrinba commented Jul 20, 2023

Here are the fields that are still broken

equilibrium.time_slice.:.boundary_separatrix.closest_wall_point.distance: data(\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZEPLIM)/100.
equilibrium.time_slice.:.constraints.j_tor.:.position.psi: py2tdi(efit_psi_to_psi,'\{EFIT_tree}::TOP.MEASUREMENTS.SIZEROJ','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY')
equilibrium.time_slice.:.constraints.pf_current.:.measured: py2tdi(stack_outer_3,'\{EFIT_tree}::TOP.MEASUREMENTS.ECCURT','\{EFIT_tree}::TOP.MEASUREMENTS.FCCURT','\{EFIT_tree}::TOP.MEASUREMENTS.ACCURT')
equilibrium.time_slice.:.constraints.pressure.:.position.psi: py2tdi(efit_psi_to_psi,'\{EFIT_tree}::TOP.MEASUREMENTS.RPRESS','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG','\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY')

I fixed the first and third. I can confirm the quantities in the second and fourth are in MDS+ so I expect the problem is with the TDI (possibly the dimensions)

@AreWeDreaming
Copy link
Collaborator

I'll retest.

I fixed the first and third. I can confirm the quantities in the second and fourth are in MDS+ so I expect the problem is with the TDI (possibly the dimensions)
My favorite kinda error.

@AreWeDreaming
Copy link
Collaborator

There is no more broken fields now for @bechtt's test case.

@AreWeDreaming AreWeDreaming requested a review from orso82 July 20, 2023 20:38
@AreWeDreaming
Copy link
Collaborator

@orso82 If you could take a look at my changes to OMAS machine it would be much appreciated. The main change is that you can now load all available mappings by using a wildcard in the location.

@torrinba
Copy link
Collaborator Author

@AreWeDreaming do you understand why regression is failing? It passed prior to 02fef13

@AreWeDreaming
Copy link
Collaborator

I'll have to run the regression tests locally. The error before was related to OMFIT things, now it doesn't seem to give us any information at all. The lines that were changed in the hash you pointed out don't exist anymore...

@orso82
Copy link
Member

orso82 commented Jul 20, 2023

Looks good to me

I am happy to see that someone else other than me was able to generate the updated IMAS JSON data dictionary files! 👍

@smithsp
Copy link
Member

smithsp commented Jul 27, 2023

I may have merged https://github.com/gafusion/OMFIT-source/pull/6708 prematurely, since this one is not passing regressions. It was passing regression on the OMFIT side...

@smithsp
Copy link
Member

smithsp commented Jul 27, 2023

If I run make test on my own computer, I get

======================================================================
ERROR: test_omas_dynamic_machine (test_omas_examples.TestOmasExamples)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/smithsp/omas/omas/omas_core.py", line 1303, in __getitem__
    value = self.dynamic.__getitem__(location)
  File "/Users/smithsp/omas/omas/omas_machine.py", line 984, in __getitem__
    return self.cache[o2u(key)][key]
  File "/Users/smithsp/omas/omas/omas_core.py", line 1324, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  File "/Users/smithsp/omas/omas/omas_core.py", line 1324, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  File "/Users/smithsp/omas/omas/omas_core.py", line 1324, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  [Previous line repeated 3 more times]
  File "/Users/smithsp/omas/omas/omas_core.py", line 1314, in __getitem__
    self.__setitem__(key[0], self.same_init_ods())
  File "/Users/smithsp/omas/omas/omas_core.py", line 872, in __setitem__
    raise ValueError('`%s` has no data' % location)
ValueError: `pf_active.coil.2.element.6.geometry.geometry_type` has no data

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/smithsp/omas/omas/tests/test_omas_examples.py", line 143, in test_omas_dynamic_machine
    from omas.examples import omas_dynamic_machine
  File "/Users/smithsp/omas/omas/examples/omas_dynamic_machine.py", line 30, in <module>
    ods.plot_overlay(wall=True, magnetics=True, pf_active=True)
  File "/Users/smithsp/omas/omas/omas_plot.py", line 2443, in overlay
    overlay_function(ods, ax, **overlay_kw)
  File "/Users/smithsp/omas/omas/omas_plot.py", line 2748, in pf_active_overlay
    ods['pf_active.coil'][c]['element'][e]['geometry.geometry_type'], 'pf_active', ods.imas_version
  File "/Users/smithsp/omas/omas/omas_core.py", line 1324, in __getitem__
    return value.__getitem__(key[1:], cocos_and_coords)
  File "/Users/smithsp/omas/omas/omas_core.py", line 1305, in __getitem__
    raise OmasDynamicException(f'Error dynamic fetching of `{location}` for {self.dynamic.kw}: {repr(_excp)}')
omas.omas_core.OmasDynamicException: Error dynamic fetching of `pf_active.coil.2.element.6.geometry.geometry_type` for {'machine': 'd3d', 'pulse': 168830, 'options': {'EFIT_tree': 'EFIT02'}, 'branch': '', 'user_machine_mappings': None}: ValueError('`pf_active.coil.2.element.6.geometry.geometry_type` has no data')

----------------------------------------------------------------------
Ran 42 tests in 17.585s

Note that this does not seem to be the same problem as reported in the automatic tests.

@torrinba
Copy link
Collaborator Author

Thanks for helping test this @smithsp. We didn't make changes to any of the DIII-D machine mappings and I don't see any changes to the IMAS schema for pf_active so I don't understand why you are seeing that error
pf_active

From what I can tell _common.py only sets the geometry properties for element 0, which could be related, but when I run make test on Iris I can't reproduce the issue. Instead it seemed like the only problem was that COCOs needed to be updated (last commit). Hopefully that resolves everything and this merge can go forward!

@AreWeDreaming
Copy link
Collaborator

This shouldn't be merged yet. I just implemented the changes we do have into omas-viewer and this is what the equilibrium plot looks like:
image

I'll try and figure out what went wrong. I think psi is just a transposition error, but I do not understand what's going on with

equilibrium.time_slice.:.constraints.pressure.:.position.psi

@AreWeDreaming
Copy link
Collaborator

Much better:
image

torrinba and others added 2 commits July 29, 2023 16:45
@smithsp
Copy link
Member

smithsp commented Jul 31, 2023

Need to check omas_from_imas.

@AreWeDreaming
Copy link
Collaborator

Midway of testing omas_from_imas I realized how incredibly unrelated that is to this PR. I did it anyways and found no problems.
Looking for someone that could test _efit.json for non-DIII-D machine. Looped in @jmcclena to test something NSTX related.

@torrinba
Copy link
Collaborator Author

torrinba commented Aug 2, 2023

Midway of testing omas_from_imas I realized how incredibly unrelated that is to this PR. I did it anyways and found no problems.

It is related to the orientation of the flux matrix loaded into OMAS from the MDS+ machine mapping. There is an issue with the g-file to OMAS conversion being resolved in this PR https://github.com/gafusion/OMFIT-source/pull/6684

I'm surprised, but happy to hear that the orientation in MDS+ must be different

omas/machine_mappings/_efit.json Outdated Show resolved Hide resolved
omas/machine_mappings/_efit.json Outdated Show resolved Hide resolved
@torrinba
Copy link
Collaborator Author

@orso82 or @smithsp could you merge this if you approve? Neither Severin or I have permission to, but both agree it is ready

@AreWeDreaming AreWeDreaming merged commit 47ae79c into master Aug 12, 2023
@AreWeDreaming AreWeDreaming deleted the EFIT_mdsplus_mapping branch August 12, 2023 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants