JacquesCarette / Drasil

Generate all the things (focusing on research software)
https://jacquescarette.github.io/Drasil
BSD 2-Clause "Simplified" License
142 stars 26 forks source link

The output format of solved ODEs #2975

Open cd155 opened 2 years ago

cd155 commented 2 years ago

Things get interested in how much effort we would like to output the ODE results.

We don't have any control over what kind of structure the solver gives us. It would be a fair assumption to assume that solver gives us some kind of list structure, but it is not always the default list structure in the language. For solving the ODEs in IVP, we will have one/more initial values. The ODE solver will solve ODEs, but the result they have usually exclude the initial values. Therefore, we have concat/append two objects.

For example in python, the Scipy solver use numpy.array structure to output each iteration. A possible way is to convert from numpy.array to list, because the initial object is a list (default list object), and then we start to append on it.

If we want a super clear and super well-formatted structure, it will make things more complicated when we try to deal with converting one type of object into another type of object via the current design of external libraries. The design language of external libraries may need to improve to get the desired result, but personally, I feel we don't have much gain since it mainly deals with formatting.

Another idea is that people would like to plot a graph, which visualizes the ODE results. Again, it requires an improved design language of external libraries.

smiths commented 2 years ago

Discussed during https://github.com/JacquesCarette/Drasil/issues/2971

smiths commented 2 years ago

@cd155, please reopen if you have additional questions.

cd155 commented 2 years ago

For the record, here is the link to the example of the manual version of generated code. This might give some inspiration on what's the choice we want to provide.

https://github.com/smiths/caseStudies/tree/master/CaseStudies/noPCM/src

smiths commented 2 years ago

@cd155, as we discussed, you should have a look at the ODE solver libraries that we use in our examples to see what output options they offer. In particular, do they have the option of outputting a "function" for the ODE solution, as described by @JacquesCarette. The function uses splines so that it is continuous.

cd155 commented 2 years ago

In nopcm example, the dependent variable is tempW, temperature changes in the water. It is declared as a vector of rationale in the SRS.

https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-example/swhs/lib/Drasil/SWHS/Unitals.hs#L415-L419

In pdcontroller example, the dependent variable is opProcessVariable, the output value from the power plant. It is declared as a vector of rationale in the SRS.

https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-example/pdcontroller/lib/Drasil/PDController/Unitals.hs#L122-L125

These two declarations eventually make the GOOL create a function to return a vector in each language

In order to add a choice to return a different type of object, I think we have to somehow change the declaration because the definition of external libraries has no control on what type to return.

@JacquesCarette is there a type better fit for this situation? Maybe Function? Is there a more polymorphic type?

JacquesCarette commented 2 years ago

Note that it should be Real, not Rational. That seems to also be a hack.

I agree that we need to change the declaration as a way to fix this. Right now, we don't use Function very much, i.e. we cheat and use the value of the expression as if all its components variables were known. So here it should just be Real. It can become a vector when the appropriate design decision is made at the implementation stage.

cd155 commented 2 years ago

In the Drasil framework, we have options to generate modularized software. The modularized software contains a controller module, an input module, a calculation module and an output module. In all case studies, the ODE will output modularized software in this design pattern.

Spec 1

Currently, the specification for the calculation is

Screen Shot 2022-09-19 at 4 46 25 PM

Given necessary input values, in this case numbers, the calculation module will output a list of numbers. For example in Double Pendulum, the inputs are m1, m2, L1, L2. The output is the list of θ1. This specification seems not to work quite well in Double Pendulum. We want to output both θ1 and θ2.

Spec 2

Another specification is what we discovered in the C# OSLO library. The OSLO library can output an infinite list of numbers.

https://github.com/JacquesCarette/Drasil/blob/21904c715546944d36e75a4ca91c710d92e98149/code/stable/dblpendulum/src/csharp/Calculations.cs#L28-L29

The Ode.RK547M will return an infinite list of SolPoint. If we are interested in a partial solution, we can use SolveFromToStep. The partial solution is based on the start time, end time, and time step. This gives us an option to output an infinite list of numbers. Here is the proposed specification

Screen Shot 2022-09-19 at 5 05 59 PM

The inputs remain the same, but the output is different than the previous specification

Spec 3

We discuss that the ODE is a function and investigate outputting the ODE as a function. Here is the idea that the ODE can return the value of the dependent variable for any value of the independent variable. Basically, giving the independent variable, often time, the function will output dependent variables.

Screen Shot 2022-09-19 at 5 16 25 PM

The inputs still remain the same, but the Calculation module output a function. The first R is the independent variable, and R^k is the dependent variables.

smiths commented 2 years ago

I'm not sure how we fit it into Drasil, but I prefer the third specification option. The output is a function. If we did try to do this, would we need dependent types, since n and k will vary between different problems? Although not mentioned here the ODE is also usually going to have other parameters to make the function. The number of parameters will also depend on the specific ODE in question.

JacquesCarette commented 2 years ago

The "generic" type of such a function would need dependent types (as it would depend on parameters $n$ and $k$), but any given instance would have $n$ and $k$ fixed, so that the types could be expanded out to something known. Still, not being forced to expand out the types would be even better.

Furthermore, in a staged setting, we can fake a lot of dependent types, by associating compile-time values to quoted code values. In other words, we know at compile time what the dimension is, even though the code we're going to generate doesn't have that information in its types.