Open cd155 opened 2 years ago
Discussed during https://github.com/JacquesCarette/Drasil/issues/2971
@cd155, please reopen if you have additional questions.
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
@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.
In nopcm example, the dependent variable is tempW, temperature changes in the water. It is declared as a vector of rationale in the SRS.
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.
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?
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.
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.
Currently, the specification for the calculation is
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
.
Another specification is what we discovered in the C# OSLO library. The OSLO library can output an infinite list of numbers.
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
The inputs remain the same, but the output is different than the previous specification
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.
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.
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.
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.
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 fromnumpy.array
tolist
, 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.