Open cd155 opened 2 years ago
Right now, in most of the code, we treat such 'dependent variables' as if they were numbers, even though they depend on other variables.
When we introduce vectors (like X), these should be new chunks.
What we don't have is a way to explicitly declare quantities that depend on other quantities (i.e. mathematically these are functions, but we don't necessarily want to treat them that way). We do compute 'dependencies' in some places in the code.
The solution to this isn't quite clear to me right now. I'll need to think about it.
@cd155 in the above you say: "The X here is the dependent variable and its derivatives, it is not just dependent variables. If we have two dependent variables, the X should be two dependent variables and their derivatives. "
I don't think this is true, at least not in the matrix representation of linear systems of odes. X is the list of dependent variables and X' is the first derivative of the dependent variables. If X = [x1, x2], then X' = [x1', x2']. I don't know how it is implemented in Drasil, but if the derivatives and the original variable are mixed that is something we did for our Drasil representation; it isn't connected to the canonical form for X' = AX + B.
@cd155, given that you have the code generation working for the double pendulum example, are there still unanswered questions in this issue, or can we close it?
To take the following as an example,
A * X + B = X'
0 0 1 0 x''' 0 equation 1
0 1 0 0 x'' 0 equation 2
1 0 0 0 x' 0 equation 3
0 -3 sin(t) -8 x t^2 equation 4
This is the format the ODE solvers required to solve the fourth-order ODE.
The original equation is x''''+3x′′−sin(t)x′+8x=t2
The output code is
dy_t[0] = y_t[1];
dy_t[1] = y_t[2];
dy_t[2] = y_t[3];
dy_t[3] = -3.0 * y_t[2] + --Math.sin(K_d) * y_t[1] + -8.0 * y_t[0] + Math.pow(K_p, 2.0);
In the external library, we already assume the dependent variable is a vector. In the above example, the dependent variable is a list, named y_t with length 4. However, if we look a little bit closer, the y_t actually is X which contains x''', x'', x', x. The x is the actual dependent variable, and x', x'', x''' are its derivatives. @smiths
We use the dependent variable as a vector, but it is actually the dependent variable and its derivatives. https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-code/lib/Data/Drasil/ExternalLibraries/ODELibraries.hs#L71
I think the confusion is that when we solve the high-order ode, we start to introduce new dependent variables. In the previous example X = x''', x'', x', x
this can be rewrite as X = x₄,x₃,x₂,x₁. Therefore, if the X = [x₄,x₃,x₂,x₁], X' = [x₄',x₃',x₂',x₁']. The thing is that x''' = x₄, x'' = x₃, x' = x₂, x = x₁. We can get X = [x''', x'', x', x], X' = [x'''',x''',x'',x'].
@cd155, I thought you were describing the canonical form for a system of first order ODEs. From your explanation above, I see that you are discussing the representation of the higher order ODE. As long as it works for capturing the knowledge in Drasil, it is fine with me. My comment was related to the form that numerical solvers will assume for the system of first order ODEs.
What needs to happen to close this issue?
Regard of the canonical form of X' = AX + B.
the equation y'''' + 3y′′ − sin(t)y′ + 8y = t2
can be rewrite into
In this new system of ODEs
x′1 = x2
x′2 = x3
x′3 = x4
x′4 = −8x1 + sin(t)*x2 − 3*x3 + t2
The dependent variables are actually x1, x2, x3, x4 after re-writting. This is the canonical form for X' = AX + B.
The reason I bring up this question is that currently we use the dependent variable that belongs to y'''' + 3y′′ − sin(t)y′ + 8y = t2
in external libraries. Basically, the dependent variable is y
before re-writing into a system of ode. The new system of ODE is the one we want to give to ODE solvers, so I think we shouldn't use the dependent variable y directly from the SRS. Instead, we may want to introduce a new chuck (maybe called dependent variables for ODE solvers). This solution is not quite elegant because the SRS is not responsible to tell the user how to solve the ODE. However, I still think we shouldn't use the y
directly to external libraries.
In the double pendulum example, I introduce a new chuck to handle this situation. As the double pendulum can be rewritten into a system of ODE in four equations, the new chuck is used in external libraries.
Let me know if I am wrong, yeah, this is the part I wasn't so sure. @smiths
I think Dr.Carette's comment lead to something bigger, and I wasn't sure how this could end.
The way I talked "The X here is the dependent variable and its derivatives, it is not just dependent variables. If we have two dependent variables, the X should be two dependent variables and their derivatives." is very misleading.
To take y'''' + 3y′′ − sin(t)y′ + 8y = t2
and the example, the X is x1, x2, x3, x4 after re-writting. The dependent variables are x1, x2, x3, x4. The reason I say that is because there is hidden relationship which
x1=y
x2=y′
x3=y′′
x4=y′′′
Therefore the dependent variables are y, y′, y′′, y′′′. The funny thing is y' is the dependent variable and it is also the first derivative of y. Then I claimed that the X contains with dependent variable y and its derivatives.
Thank you for the clarification @cd155. Yes, the original higher ODE and the derived system of first order ODEs are represented differently. For the SRS level (the "user" level), the higher order ODE, and your matrix equation version of this, is good. We don't want to ask the user to convert the system into a system of first order ODEs if we don't have to. The system of first order ODEs isn't related to the requirements. It isn't what we want to solve, it is part of "how" we solve what we want to solve.
You are correct that we will need something to bridge between the SRS version of the higher order ODE and the external libraries preference for a system of first order ODEs. Ideally this would be automated. It sounds like you wrote code to make this mapping explicit. Is there any way to automate this?
The problem with you writing a chunk to capture the mapping is that every user will need to write this. The information doesn't appear in the SRS and it doesn't appear in any design document. We can make writing the "mapping chunk" part of the instructions for solving ODEs, but generating this mapping would be better.
To generate this "mapping chuck", I think we can give it fixed chuck information. This means every generated code will use this fixed "mapping chuck". For example, the symbol used in generated code will be identical across study cases.
Another thing is this fixed "mapping chuck" will stay in SystemInfomation
because of the way how code is generated. We use this "mapping chuck" in the ODE equation, so we have to put this chuck into SystemInfomation
. Once the chuck is in the SystemInfomation
, it will show up in the SRS (in the symbol map part). We can't just simply remove the fixed "mapping chuck" from SystemInfomation
because we use this definition later in ODE equation. @smiths
@cd155 can you point me to the symbols that are introduced in the SRS by the "mapping chunk"? I'd like to see how much they seem out of place, if at all.
This is the mapping chuck I introduced in the double pendulum example.
the pendDisAngle will eventually be added to SystemInformation
https://github.com/JacquesCarette/Drasil/blob/ba461947c2f1f81c76adce95f05e65edd86b8390/code/drasil-example/dblpendulum/lib/Drasil/DblPendulum/Body.hs#L109
In the Table of Symbols, information for this symbol will show up in this section
(On top of that, some languages don't allow any greek Unicode (θ), so I change to the alphabet.)
Thank you for the information @cd155. The impact to the SRS is small, but it is still strange to introduce a symbol (theta) and never use it. We should talk to @JacquesCarette and @balacij to see if this is necessary. The introduction of a vector of theta values is part of the numerical solution technique, so it doesn't really belong in the SRS.
If we have to keep theta in the SRS for now, we should consider introducing an instance model that shows how it is used. At least then we wouldn't have a symbol in the table of symbols that isn't used.
If we have to, we can leave things as they currently are, but this is another reason why we need to introduce more modularity in Drasil. In particular, it looks like we need to split up SystemInformation
.
So that we also get the meeting discussion noted here. We briefly spoke about this in the meeting today (June 10th, 2022), and I mentioned, approximately: if the symbol here is akin to a temporary variable for a variable swap (e.g., Java: int temp = x; x = y; y = temp;
), then we can generate a symbol for it when we are generating code since it does not matter much to traceability (because there is nothing to trace it to in the SRS).
As @smiths mentioned in the meeting as well, this variable is relevant to the design of the software solution generation (a separate document), not necessarily to the scientific requirements of the solution to the problem at hand.
@balacij Personally, I think the "mapping chuck" is not only a temporary variable.
The reason to create the "mapping chuck" is that there is a gap between the SRS and ODE solvers. The ODE solvers are required to transform original ODE equations into a system in form of X' = AX + B. In order to change original ODE equations to X' = AX + B, we introduced new dependent variables. The "mapping chuck" is newly introduced dependent variables and it is X in the external libraries. Newly introduced dependent variables are different than the original dependent variable. The SRS carries the original dependent variables.
The "mapping chuck" is not original dependent variables, but it is based on original dependent variables. They have a relationship. but the SRS is not responsible to show this relationship.
My rationale to create a "mapping chuck" is that this help to uncover the issue. Originally, we use the original dependent variables in external libraries, this makes sense in first-order ODE since there is no transformation. However, there are two dependent variables in the double pendulum example, theta1 and theta2. Then, we have to unify the theta1 and theta2 into one thing. The "mapping chuck" did this job in this case study.
I feel @smiths idea that we may need to generate a separate document is a way to bridge the gap between ODE solvers and SRS.
@balacij Personally, I think the "mapping chuck" is not only a temporary variable.
Sorry, I didn't mean to imply that it would be a temporary variable. I meant to ask if the variable was merely something we would use as a "means to the end", and if it would be a fairly mechanical, unimportant, but required for implementation, variable.
I agree with everything you say. If the variable is created in a mechanical way, then I think it would be something that we can mechanize, of course. However, I'm not quite sure if there is a generic algorithm we can use to create it -- do you know if this is possible?
There is nothing to sorry about. :smile:
I think ultimately we can let DifferentialModel
handle it. Simply create a fixed "mapping chuck" whenever people create a new DifferentialModel
. Here is what I did in the double pendulum.
This will cause two problems.
DifferentialModel
can't handle non-linear ODE, for example, the double pendulum case study. The ODEs in the double pendulum were created manually.ConstrConcept
, it has extra information in there.(Sorry for not replying earlier)
Once we move to having just theories, linked by refinement, then we can basically make some refinements be visible in the recipe for the SRS, while further refinements would be part of the Design only. Internally, things would all be uniform, and it would be an external choice when we 'assemble' our artifacts that chooses which theory to use and show.
If we have to keep theta in the SRS for now, we should consider introducing an instance model that shows how it is used.
This may be the only way to reasonably proceed on #3259. Based on the discussion on #3533, it seems like this "theta" is the output of DblPend, at least for now (https://github.com/JacquesCarette/Drasil/issues/3533#issuecomment-1637153373). The output requirement is generated from the outputs of the program, which for DblPend is just "theta", and to fill in the source field, the outputs need to be Referable
; the most logical way to do this would be to make it an IM, which would also improve the explanation for how it is obtained. What would an IM for this quantity look like?
This problem hovers me around for a while. How dependent variables should represent in the SRS and code?
The dependent variable in nopcm is the temperature in the water https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-example/swhs/lib/Drasil/SWHS/Unitals.hs#L415-L419
,and the dependent variable in pdcontroller is the output value from the power plant https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-example/pdcontroller/lib/Drasil/PDController/Unitals.hs#L122-L125
As we discussed today, the dependent variable
We also discussed that we should represent the Differential Model in a matrix form. Ax = b the x in there is a column vector it contains dependent variables and their derivatives. For example, in nopcm it is
[tempW, tempW']
. In PDcontroller, it is[y, y', y'']
. I just wonder to know should I think about the whole vector x as the dependent variable vector? I think this thought might be too code-oriented, but I don't know how to interpret the dependent variable correctly in the code.External Libraries
Currently, I think what is implemented in the code is a little bit misleading for the designer to understand what is the dependent variable in the code. As you may know, in order to solve the ode in ode solvers, we have to transfer to the following shape X' = AX + B discussed in this post https://github.com/JacquesCarette/Drasil/issues/2973#issuecomment-1120442094
The X here is the dependent variable and its derivatives, it is not just dependent variables. If we have two dependent variables, the X should be two dependent variables and their derivatives.
Currently, the way we designed the external libraries seem to create a non-exist relationship between (dependent variables) and (X). The X is not just a dependent variable, and I believe we should not use the dependent variable directly in the ODElibraries.hs file. Instead, we should create a dummy variable, it is just a placeholder help to create a well-formatted matrix for ODE solvers.
In the following code, the
depVar
is the dependent variable. I think a better approach is to use a dummy variable. If we have two dependent variables in a system of odes, the dummy variable should be automatically created based on how many dependent variables. (ideally, the dummy variable should be an array in the code)https://github.com/JacquesCarette/Drasil/blob/adfc15f13c7cf81101c1dbab97a6aa61f10a4ec6/code/drasil-code/lib/Data/Drasil/ExternalLibraries/ODELibraries.hs#L68-L79
This non-exist relationship between the dependent variable and X drove me nuts :( somehow until yesterday, we discussed a similar issue on what format for ode output. I hope I explain it clearly, but if not, please let me know.