-
Notifications
You must be signed in to change notification settings - Fork 38
Improve Wiggler energy handling to fix #894 #960
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
Improve Wiggler energy handling to fix #894 #960
Conversation
|
@T-Nicholls , I went through the discussion in #894, and I am not so sure what you propose is consistent with what @lfarv had suggested. My understanding is that you shall handle upper case and lower energy arguments in the constructor to avoid any issues. In this case you would only need to add the following line to the wiggler constructor I believe:
and then your super().init() would not complain anymore about having twice Energy...or am I missing something? Furthermore, looking at the passmethod, there are again there several level of prioritization: This is a bit messy in my opinion with to many layers. I would tend to think that we could add gamma to the parameters structure and get rid of atGamma() and atEnergy() using only 1 as the prioritization method. but this is maybe to much for this PR. |
|
Hello @T-Nicholls and @swhite2401. I fully agree with @swhite2401: the single line added to the wiggler constructor is the simplest solution and solves the problem. Such a syntax is used in other constructors. It achieves the usual priorities where the keyword argument has priority over the positional argument. Concerning the
Changing this would need a review of all the integrators, it's another story. |
Ok I did not follow this development, I just came across these functions and was wondering if they were really needed. |
|
Hello @lfarv & @swhite2401 , I chose this way because I didn't want to change the behaviour of the
In summary, we've never supported both If you think it is worthwhile to add this new functionality, then I would be happy to add the line you propose so that both are supported and |
|
Hello @T-Nicholls I see problems in your implementation: by modifying the
So in the end, I would not modify ...,
Energy=energy,
...,line. Instead of creating an
NOTE: this reveals another small bug: in the energy setter of the Lattice property, an |
|
Hello @lfarv I am fine with the solution you propose, so I have implemented it here and I've also fixed the lattice |
| if isinstance( | ||
| elem, (elt.RFCavity, elt.Wiggler) | ||
| ) or elem.PassMethod.endswith("RadPass"): | ||
| if isinstance(elem, elt.RFCavity) or elem.PassMethod.endswith("RadPass"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use black to format the code in AT, maybe this is why this line break was there in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was previously over black's 88 line length limit and was therefore split, but now we are no longer checking wigglers it is only 86 and so can go on one line
| def test_gwig_symplectic_pass(rin, passmethod, func): | ||
| # Parameters copied from one of the Diamond wigglers. | ||
| wiggler = elements.Wiggler('w', 1.15, 0.05, 0.8, 3e9) | ||
| wiggler = elements.Wiggler('w', 1.15, 0.05, 0.8) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you get an error if there energy is not defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Wiggler energy is ignored since the Lattice energy is always used. The 3rd positional argument of the constructor is still accepted for compatibility with the very first implementation of th wiggler. In this PR, no Energy field is created in the Wiggler object, while previously, it was created and later removed by the Lattice constructor (or should have been…).
The only difference is that now a warning is issued while before the energy was silently ignored. This is the reason of the modification of the tests: avoiding this new warning. I don't like too much modifying the tests : it reveals a change of behaviour, and old lattice definitions may now suddenly throw warnings. On the other hand, this warning makes sense, silently ignoring entries is confusing. My preference is to keep this new warning, but if it looks really disturbing, it could be removed…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, now I am lost... so if I understand well energy is now always ignored and instead if the user wants to set manually the energy he should use the keyword argument Energy.
This is a rather significant change of behavior in my opinion that is not reflected in either the warning (that should say please use the keyword argument Energy to set the energy of the wiggler) or the docstring where the positional argument energy is still used.
I do not think that this is backward compatible as script using the positional argument energy will now lead to different results. While the solution I proposed:
energy= kwargs.pop('Energy', energy)
was handling all case.
For me there is now 2 options:
1-either we remove entirely the positional argument energy and user will get an error message, this is the cleaner solution but is not backward compatible (already the case)
2-we handle all case setting priorities as I proposed
I would very much prefer the first option that is simpler and cleaner but it break the rule of maintaining backward compatibility for minor releases... so I would strongly advocate for 2 until the next major release
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, now I am lost... so if I understand well energy is now always ignored and instead if the user wants to set manually the energy he should use the keyword argument Energy.
No, an Energy keyword is ignored as well: in GWigSymplecticPass, an Energy field, if existent, is ignored. The Lattice energy is always used. And there is no change in this PR: GWigSymplecticPass is unchanged.
So there is no difference with your solution: an ignored Energy field or no Energy field is equivalent. In addition, the Lattice constructor removes the Energy field of all elements except cavities and *RadPassMethods. And even in *RadPassMethods, the Element energy is ignored.
I do not think that this is backward compatible as script using the positional argument energy will now lead to different results
No, it's compatible, there will be no change in the results: the 3rd positional argument, or any Energy keyword was already ignored. That's why I think that the new warning is useful. But you are right, the docstring should mention that this argument is kept for compatibility, but ignored.
This is slightly different in Matlab: in old lattices without RingParam element, the element energy is used. If there is a RingParam element, the behaviour is the same as in python. A .mat file created in python has always a RingParam element, so the element Energy fields are not necessary to get the correct behaviour when the file is processed in Matlab.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I did not look all the way down to atEnergy() that in fact always returns the lattice energy...
This is all very interleaved and confusing, we should really think of cleaning this up.
However, I see in the passmethod that 'Energy' is interpreted, so it can be used in case the lattice energy=0.0. Is it possible that this happens if the lattice is defined as a list (allowed in pyAT)?
Shouldn't this be documented? Or should we just completely ignore the 'Energy' attribute and throw an Error if the lattice energy is undefined directly in the passmethod?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
atEnergy/atGamma was introduced in #816 as the standard way to access the energy in all integrators, with the following constraints:
- backward compatibility in Matlab for old lattices without
RingParam, - Matlab and python compatibility for new lattices,
- work for energy ramping
all that in a single line, identical in all integrators except RFCavityPass. For a detailed explanation, see #816.
However, I see in the passmethod that 'Energy' is interpreted, so it can be used in case the lattice energy=0.0
Energy is always interpreted in all integrators, because of Matlab old lattices. But in python, I do not see any particular case for "lattice energy=0.0". 0.0 is used for energy or gamma (except for RFCavityPass again):
#define atEnergy(ringenergy,elemenergy) (ringenergy)
If an error should be thrown for energy==0.0,, it could be added in this python definition of atEnergy.
For lattices as "lists", the energy can be provided with an energy keyword in lattice_track (documented).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I still think this is really not clean and for someone not familiar with AT it is basically impossible to understand the behavior... I guess this is the kind of things we have to live with to maintain backward/matlab compatibility so fine for the moment.
|
In the docstring of |
Energyhas been added to the_BUILD_ATTRIBUTESofWiggler, so it will now be automatically popped and passed as the positional argumentenergywhen loading from lattice filesenergyis still an optional argument when creating aWigglerWigglers will now always have anEnergyattribute, and it will be made the same as theLattice's energyparams_filteris unchangedEnergyattribute on elements (including wigglers) remains unused in Python, as theLattice's energy is always used