Additional derivatives of propagator

Hello,

I am struggling to add integration variables in a numerical propagator (Field version).
I am extending the PythonFieldAdditionalDerivativesProvider and have implemented some functions:

    class MyProvider(PythonFieldAdditionalDerivativesProvider):

        def __init__(self, mu) -> None:
            PythonFieldAdditionalDerivativesProvider.__init__(self)
            self._mu = mu

        def getName(self) -> str:
            return "dummy"

        def init(self, fieldSpacecraftState: FieldSpacecraftState, fieldAbsoluteDate: FieldAbsoluteDate) -> None:
            pass

        def getDimension(self) -> int:
            return 7

        def combinedDerivatives(self, sc: FieldSpacecraftState):
            zero = self._mu.multiply(0.)
            secondary_rates = [zero] * self.getDimension()
            return FieldCombinedDerivatives(secondary_rates, None);
 

and I am trying to use it with my propagator:

coupled_propagator = FieldNumericalPropagator(field, hipparchus_field_integrator)
init_state = FieldSpacecraftState(init_orbit)
init_state.addAdditionalState("dummy", [self._mu.multiply(0.)] * 7)
additional_variables = MyProvider(mu)
coupled_propagator.addAdditionalDerivativesProvider(additional_variables)
coupled_propagator.setInitialState(init_state)

But I’m pretty sure that the propagation never goes inside combinedDerivatives, and I cannot retrieve the final values of the additional variables, as this fails:

coupled_propagator.propagate(tf).getAdditionalState("dummy")

Cheers,
Romain.

Sorry for the double post, but I found why the propagation did not include the extra variables. It is because addAdditionalState for FieldSpacecraftState does not have “void” as signature, it actually returns something (which btw is a bit counterintuitive because of how addAdditionalStateDerivatives works at propagator level). The correct call is thus:

init_state = init_state.addAdditionalState("dummy", [self._mu.multiply(0.)] * 7)

However, I am now getting the following exception:

propagated = coupled_propagator.propagate(tf)
E orekit.JavaError: <super: <class ‘JavaError’>, >
E Java stacktrace:
E java.lang.RuntimeException: AttributeError
E at org.orekit.propagation.integration.PythonFieldAdditionalDerivativesProvider.yield(Native Method)
E at org.orekit.propagation.integration.FieldAbstractIntegratedPropagator$ConvertedSecondaryStateEquations.computeDerivatives(FieldAbstractIntegratedPropagator.java:797)
E at org.hipparchus.ode.FieldExpandableODE.computeDerivatives(FieldExpandableODE.java:143)
E at org.hipparchus.ode.AbstractFieldIntegrator.computeDerivatives(AbstractFieldIntegrator.java:278)
E at org.hipparchus.ode.AbstractFieldIntegrator.initIntegration(AbstractFieldIntegrator.java:229)
E at org.hipparchus.ode.nonstiff.RungeKuttaFieldIntegrator.integrate(RungeKuttaFieldIntegrator.java:122)
E at org.orekit.propagation.integration.FieldAbstractIntegratedPropagator.integrateDynamics(FieldAbstractIntegratedPropagator.java:459)
E at org.orekit.propagation.integration.FieldAbstractIntegratedPropagator.propagate(FieldAbstractIntegratedPropagator.java:416)
E at org.orekit.propagation.integration.FieldAbstractIntegratedPropagator.propagate(FieldAbstractIntegratedPropagator.java:379)

I suspect and fear that the problem comes from the fact that the (Field)AdditionalStateDerivativesProvider has a method called ‘yield’, which is a protected keyword in Python so I cannot name a method like that. Your thoughts @petrus.hyvonen ?

Hi, yes could well be, so as I understand in your code you are missing the yield method in the implemented class, and this is the error you get?

I would suggest we rename the yield extraction point(s) to “yield_”. I will try to get a new build out in short.

Hi Petrus, yes that’s exactly it. Renaming that function for the wrapper and rebuilding it would be very appreciated, thank you. Should I open an issue on gitlab so that this gets traced?

To the Java dev team: in the future please avoid naming methods with Python keywords :sweat_smile:

Hi,
A conda build no 3 should be on the servers in some minutes, that has renamed all yields to yield_

Hi @Serrof, @petrus.hyvonen,

Do we have a list of Python keywords to avoid for methods’ names. So there is “yield” and I remember something about “init” maybe.
This list could be added to the contribution guide and the development guidelines.
Maybe we could also design some SonarQube rules to enforce these restrictions.

1 Like

Hi,

yes there is a list:

In [1]: import keyword

In [2]: keyword.kwlist
Out[2]: 
['False',
 'None',
 'True',
 'and',
 'as',
 'assert',
 'async',
 'await',
 'break',
 'class',
 'continue',
 'def',
 'del',
 'elif',
 'else',
 'except',
 'finally',
 'for',
 'from',
 'global',
 'if',
 'import',
 'in',
 'is',
 'lambda',
 'nonlocal',
 'not',
 'or',
 'pass',
 'raise',
 'return',
 'try',
 'while',
 'with',
 'yield']

init is not on the list, it has successfully been used in many cases.

I don’t think many of these are used but it would be good to automatically check it somehow, will check SonarQube, if you are familiar with it please let me know how to write such rule?

Hi @petrus.hyvonen,

I’m not super familiar with SonarQube but maybe @sdinot could help us on the one.
Sébastien, the idea here would be to forbid the usage of above words for method names in Java.

There’s a Method Name rule that we could use with a properly crafted regular expression I guess.
Some of the names (if, else, for, while etc.) are already forbidden in Java.

Maybe we can just add a Checkstyle rule avoiding the use of these words?

I think we only have to add a new rule in the checkstyle.xml file.

Ah yes that would be a much better idea !

Thank you so much Petrus for the new conda build, it works like a (Py)charm :laughing:

About the forbidden names, I think they only apply to non-private methods.

Cheers,
Romain.

1 Like

@Serrof, @petrus.hyvonen,

I opened an issue on the Java forge so we don’t forget to add the new rule.

1 Like