Opened 6 years ago
Closed 6 years ago
#5127 closed defect (fixed)
[NF] Implement synchronous features in the new front-end
Reported by: | Adrian Pop | Owned by: | Adrian Pop |
---|---|---|---|
Priority: | high | Milestone: | 2.0.0 |
Component: | New Instantiation | Version: | |
Keywords: | Cc: | Rüdiger Franke |
Description
Add support for Clock and Modelica 3.3 synch. features.
Change History (35)
comment:1 by , 6 years ago
Owner: | changed from | to
---|---|
Status: | new → accepted |
comment:2 by , 6 years ago
comment:4 by , 6 years ago
Cc: | added |
---|
comment:6 by , 6 years ago
From the Modelica_Synchronous Hudson tests we have 14/96 models currently simulating.
Many models fail with this error:
[OpenModelica/OMCompiler/build/lib/omlibrary/Modelica_Synchronous 0.92.1/BooleanSignals.mo:60:7-60:26:writable] Error: Type mismatch for positional argument 1 in sample(start=sample.u). The argument has type: Boolean expected type: Real
Other typical issues include
[OpenModelica/OMCompiler/build/lib/omlibrary/Modelica_Synchronous 0.92.1/BooleanSignals.mo:12:7-12:20:writable] Error: Function parameter interval was not given by the function call, and does not have a default value.
and
[OpenModelica/OMCompiler/build/lib/omlibrary/Modelica_Synchronous 0.92.1/IntegerSignals.mo:62:7-62:26:writable] Error: Function argument start=sample1.u in call to sample has variability discrete which is not a parameter expression.
comment:8 by , 6 years ago
PR with interval
, firstTick
and overload of sample
is running now:
https://github.com/OpenModelica/OMCompiler/pull/2665
comment:9 by , 6 years ago
Ouch, seems I broke some stuff +54 & -680 :)
https://libraries.openmodelica.org/branches/history/newInst/2018-09-18%2004:47:02..2018-09-18%2016:00:04.html
I'll see what the problem is.
comment:10 by , 6 years ago
Models with clock variables work better, but all other models using sample()
with old-fashioned discrete variables got broken.
[OpenModelica/OMCompiler/build/lib/omc/NFModelicaBuiltin.mo:544:5-544:28:writable] Error: Function Clock not found in scope sample.
comment:11 by , 6 years ago
Yes. I wanted to overload sample into one with clock and one without clock (the default one) but that is a bit problematic because if you don't have --std=3.3 on, there is no Clock defined and that is exactly what the error message says.
comment:13 by , 6 years ago
Of course. In the current front-end is basically implemented manually. There is a function declared in ModelicaBuiltin.mo but is not used at all as is not overloaded.
I already have a fix for this, will push it in soon.
comment:15 by , 6 years ago
PR https://github.com/OpenModelica/OMCompiler/pull/2666 should (hopefully) fix the failing 680 models.
follow-up: 17 comment:16 by , 6 years ago
Very strange that none of the tests in our testsuite caught this issue.
I'll try to add one so we don't run into this again.
comment:17 by , 6 years ago
Replying to adrpo:
Very strange that none of the tests in our testsuite caught this issue.
I'll try to add one so we don't run into this again.
I guess the testsuite is not using -d=newInst
anywhere, so this kind of things happens quite often.
However, in some cases regressions with NF commits are fine, as long as the model was not already simulating with correct results, so I don't think the strict enforcement of the no-regression rule to accept PRs (that we have for normal commits to master) would be reasonable.
I think manual checking of the latest report is just fine, until we switch to -d=newInst
by default. Then, the standard rules will apply.
In any case, I'm keeping those reports under very close watch :)
comment:18 by , 6 years ago
Of course, my bad, this only happened when -d=newInst is on.
PR: https://github.com/OpenModelica/OpenModelica-testsuite/pull/1037
should test this now.
comment:19 by , 6 years ago
The following example would work for firstTick(u)
. Using firstTick()
:
model m2 input Real[10] u; Real[size(u, 1)] x1(each start = 1); equation when Clock() then x1 = if firstTick() then previous(x1) else previous(x1) + u; end when; end m2;
it produces the error:
[/home/rfranke/OpenModelica/OMCompiler/Compiler/NFFrontEnd/NFCeval.mo: 1447:9-1448:51]: Internal error NFCeval.evalBuiltinCall: unimplemented case for firstTick
comment:20 by , 6 years ago
Did you take the latest sources or the nightly build? The last commit should have fixed this issue.
comment:21 by , 6 years ago
Ok. Now I get:
adrpo33@ida-0030 MINGW64 /c/home/adrpo33/dev/OMTesting/nf $ time ~/dev/OpenModelica/build/bin/omc +d=newInst m2.mo Error processing file: m2.mo [C:/home/adrpo33/dev/OMTesting/nf/m2.mo:6:5-6:64:writable] Error: Internal error NFTyping.evaluateCondition failed to evaluate condition `firstTick()`
It seems it badly wants to evaluate the call and conditions to if equations and expressions.
I disabled the ceval of impure functions and your error went away, but it seems this is something else.
comment:22 by , 6 years ago
I just had updated to the latest version and arrived at the same error. Interestingly it still works for firstTick(u)
, but not for firstTick()
. Independent of the argument passed to firstTick, the result should always be the same Boolean.
comment:23 by , 6 years ago
I will make functions with no arguments that are impure have Variability.CONTINUOUOS to prevent evaluation. That is the actual problem, it thinks firstTick() is constant :)
comment:24 by , 6 years ago
Works now:
adrpo33@ida-0030 MINGW64 /c/home/adrpo33/dev/OMTesting/nf $ time ~/dev/OpenModelica/build/bin/omc +d=newInst,-nfScalarize m2.mo
class m2 input Real[10] u; Real[10] x1; equation when Clock() then x1 = if firstTick() then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]}; end when; end m2;
comment:25 by , 6 years ago
Strange that it does expansion of the else part. I'll have a look on disabling that.
comment:26 by , 6 years ago
Most of the stuff implemented in:
https://github.com/OpenModelica/OMCompiler/pull/2667
Most of Modelica_Synchronous works since this morning:
https://libraries.openmodelica.org/branches/history/newInst/2018-09-19%2003:24:28..2018-09-19%2006:44:44.html
Fix for impure functions firstTick()
is running now:
https://github.com/OpenModelica/OMCompiler/pull/2668
comment:27 by , 6 years ago
Per told me -d=-nfExpandOperations
should disable the expansion of else part and it does:
class m2 input Real[10] u; Real[10] x1; equation when Clock() then x1 = if firstTick() then previous(x1) else previous(x1) + u; end when; end m2;
I will gather all the extra flags we need to disable expansion and scalarization under -nfScalarize
so we don't need to set each flag individually.
comment:28 by , 6 years ago
After PR: https://github.com/OpenModelica/OMCompiler/pull/2669 only -d=-nfScalarize
is needed.
comment:29 by , 6 years ago
This looks better now:
https://libraries.openmodelica.org/branches/newInst/Modelica_Synchronous/Modelica_Synchronous.html
https://libraries.openmodelica.org/branches/newInst/Modelica_Synchronous_cpp/Modelica_Synchronous_cpp.html
but it seems some models that work in the current front-end fail with the NF in the backend, for example:
https://libraries.openmodelica.org/branches/newInst/Modelica_Synchronous/files/Modelica_Synchronous_Modelica_Synchronous.Examples.Elementary.ClockSignals.ShiftSample.err
It dies in clockPartitioning. I guess somebody with back-end knowledge should have a look. I will check the differences when flattening, maybe is still a NF issue.
comment:30 by , 6 years ago
I had a look in the backend. A lot of things work for a simple model. I had to adapt the equation count and moreover disabled detection of strong components, common subexpression elimination, dependency analysis and simcode generation.
The major remaining problem is that all code generation (XML files, variable counts, variable references, start values) assume scalar variables only.
The above example nicely demonstrates the advantage -nfScalarize
. With scalarization the array state equation is evaluated n times, i.e. effort of n*n:
class m2 input Real u[1]; input Real u[2]; input Real u[3]; input Real u[4]; input Real u[5]; input Real u[6]; input Real u[7]; input Real u[8]; input Real u[9]; input Real u[10]; Real x1[1](start = 1.0); Real x1[2](start = 1.0); Real x1[3](start = 1.0); Real x1[4](start = 1.0); Real x1[5](start = 1.0); Real x1[6](start = 1.0); Real x1[7](start = 1.0); Real x1[8](start = 1.0); Real x1[9](start = 1.0); Real x1[10](start = 1.0); equation when Clock() then x1[1] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[1]; x1[2] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[2]; x1[3] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[3]; x1[4] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[4]; x1[5] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[5]; x1[6] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[6]; x1[7] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[7]; x1[8] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[8]; x1[9] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[9]; x1[10] = (if firstTick(u) then previous(x1) else {previous(x1[1]) + u[1], previous(x1[2]) + u[2], previous(x1[3]) + u[3], previous(x1[4]) + u[4], previous(x1[5]) + u[5], previous(x1[6]) + u[6], previous(x1[7]) + u[7], previous(x1[8]) + u[8], previous(x1[9]) + u[9], previous(x1[10]) + u[10]})[10]; end when; end m2;
With -nfScalarize
it is only evaluated once, i.e. effort of n:
class m2 input Real[10] u; Real[10] x1; equation when Clock() then x1 = if firstTick(u) then previous(x1) else previous(x1) + u; end when; end m2;
The start values for x1
are lost though, which is crucial.
comment:31 by , 6 years ago
I fixed the start value for the variable. We only handled scalar types but I now added arrays. The each
qualifier will be lost as we have no way to represent it yet in the DAE.Var
.
// adrpo33@ida-0030 MINGW64 /c/home/adrpo33/dev/OMTesting/nf // $ time ~/dev/OpenModelica/build/bin/omc -d=newInst,-nfScalarize m2.mo class m2 input Real[10] u; Real[10] x1(start = 1.0); equation when Clock() then x1 = if firstTick(u) then previous(x1) else previous(x1) + u; end when; end m2;
comment:33 by , 6 years ago
Looks good! The each
qualifier is not that important anyway. If a scalar start value passes the frontend, then the backend may implicitly assume each
.
comment:34 by , 6 years ago
I noticed that some of the Clock constructors were a bit borked when checking another ticket, e.g. Clock(1, 2)
didn't work. I fixed the definition of Clock()
in NFBuiltinFuncs, but then noticed that they weren't even used since NFBuiltinCall.typeClockCall
did all the argument matching manually. So I rewrote typeClockCall
to use the normal call typing in 7b036fe. The specification is a bit unclear on which arguments are allowed to use named parameters and such things, so I used WWDD (What Would Dymola Do) and allowed all Clock parameters to be both positional and named.
One thing I changed was to remove the check for the Boolean clock that startInterval > 0.0
, partly because the specification doesn't mention that restriction and partly because startInterval
has a default binding of 0.0
which would violate the check.
comment:35 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
Most of the Modelica_Synchronous
models now work with the NF, see report.
I would close this ticket, and possibly open other more specific ones on remaining specific issues.
Maybe we could split this into