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

[Feature request] ODE solver for complex field elements #39

Closed
jlabroquere opened this Issue Jun 26, 2018 · 6 comments

Comments

Projects
None yet
2 participants
@jlabroquere
Copy link

jlabroquere commented Jun 26, 2018

Hi there,

I am trying to use the FieldOrdinaryDifferentialEquation with Complex type but it seems not possible to use it as the Complex type doesn't implements RealFieldElements.

I do not understand why there is such a limitation of the FODE to only accept RealFieldElement and not FieldElement more generic type. Could you tell me why?

@jlabroquere jlabroquere changed the title [New feature] ODE solver for complex field elements [Feature request] ODE solver for complex field elements Jun 26, 2018

@maisonobe

This comment has been minimized.

Copy link
Contributor

maisonobe commented Jun 26, 2018

Hi,

At least we need to use the absolute value in many places, which is not defined in FieldElements.

I didn't try to move abs upward in the hierarchy and rely only on FieldElements, but if it works, it could
be an interesting change. I suppose a simple search/replace RealFieldElements with FieldElements throughout the ode packages (both library sources and test sources) would show if only abs would need to be moved. Could you try it and report if this works?

@jlabroquere

This comment has been minimized.

Copy link

jlabroquere commented Jun 26, 2018

Okm I am going to give it a go. I'll report the results here.

@jlabroquere

This comment has been minimized.

Copy link

jlabroquere commented Jun 26, 2018

Mmmm, it doesn't seems to be straightforward. I'll have a deeper look at it later on.
So far by doing a simple search and replace, the FieldElement is missing the getReal() method.

By making the Complex type implementing the RealFieldElement to see if intermediate interface could be used, the abs() function gives problem as the return type should be a complex and not a double.

@maisonobe

This comment has been minimized.

Copy link
Contributor

maisonobe commented Jun 27, 2018

Perhaps we could also move getReal() up. Complex implements a getReal() method that returns
the real part. Looking quickly at the use of getReal() in Field ODE, it seems related to either integration
variable (often time), error estimation, and events detection. We could put a limitation in the documentation stating that some operations on these elements WILL be truncated to the behaviour of their getReal() method, so people using Complex will be aware of what they can and can't do.

I guess this limitation would not be too cumbersome. For event detection the semantics
of even is related to real numbers (it is a sign change) and for error estimation the error is mainly
intended to be a magnitude. The remaining problem is that people could not integrate a function
along the imaginary line for example without doing a variable change.

For the abs() function, we could perhaps decide to have both an abs() and absDouble() method in
Complex, where the abs would return a Complex with 0 imaginary part. This would induce the least changes in existing code.

In any case, this change could be done only in a 2.0 release, as it is a breaking change. This is not
a problem as we can do a major release if we want.

@maisonobe

This comment has been minimized.

Copy link
Contributor

maisonobe commented Sep 2, 2018

After some thinking, I think there is a better way to provide complex ODE solving.

The independent variable in ODE equations (call it time, but it can be any other coordinate) is inherently a one dimensional real number. The equations by themselves can be multi-dimensional. RealField-ODE in Hipparchus use the same RealField for both the independent variable and the components of the multi-dimensional state vector. This implies that modifying RealField so Complex are a type of RealField too implies that time becomes a two-dimensional element. Even considering in ODE we simply ignore the imaginary component in the independent variable would in fact not work. Suppose for example that as part of the ODE you compute t * x1, where x1 is one of the Complex component of the state vector. Then the imaginary part of t will be taken into account in the operation, and it will have an effect on the real part of the result, which could end up in the next value for t at the end of the step. Also considering a Complex is a kind of Real is freaking.

I therefore think something different should be done.

I guess you problem is to integrate an ODE where the state is a set of complex numbers (say some electrical properties, with amplitude and phase), but they are integrated with respect to a real variable (say time), i.e. the independent variable and the state variables do not belong to the same types.

Then, a simple and probably elegant solution would be to simply set up a dedicated ComplexOrdinaryDifferentialEquation like that users woul implement to model their ODE problem:

public interface ComplexOrdinaryDifferentialEquation {

    int getDimension();

    default void init(double t0, Complex[] y0, double finalTime) {
        // do nothing by default
    }

    Complex[] computeDerivatives(double t, Complex[] y);

}

and then Hipparchus would provide a converter that would convert this complex representation into the
existing double representation:

public ComplexODEConverter implements OrdinaryDifferentialEquation {
    
    /** Underlying complex order equations set. */
    private final ComplexOrdinaryDifferentialEquation equations;

    /** Simple constructor.
     * Build a converter around a complex order equations set.
     * @param equations complex order equations set to convert
     */
    public ComplexODEConverter( ComplexOrdinaryDifferentialEquation equations) {
        this.equations = equations;
    }

    ... implementation of OrdinaryDifferentialEquation interface ....

}

The converter would simply copy data between n dimension complex arrays and 2n dimensions double arrays. This would be similar to the existing FirstOderConverter for converting second order ODE into first order ODE that Hipparchus can solve.

Would this help you solve your problem? I think I will anyway implement it, as it is probably something useful for other users.

@maisonobe maisonobe self-assigned this Sep 2, 2018

@maisonobe maisonobe closed this in dc8017b Sep 2, 2018

@maisonobe

This comment has been minimized.

Copy link
Contributor

maisonobe commented Sep 2, 2018

I have implemented the converter. It is available in the master branch.
It is slightly more involved than expected. My previous comment above did only address the conversion of the primary equation. There are however other objects to convert: the initial state on input, the final state (and derivatives) on output. It is also possible to have a state split into a primary state associated to the primary equation, plus several secondary states associated to several secondary equations. The converter handles all these elements, so you can use secondary equations if you want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment