Opened 9 years ago

Closed 9 years ago

Last modified 7 years ago

#3503 closed defect (fixed)

Support for Modelica_Synchronous

Reported by: Rüdiger Franke Owned by: Rüdiger Franke
Priority: high Milestone:
Component: Backend Version:
Keywords: Cc: Bernhard Thiele, Lennart Ochel, Maksimov Doe

Description

Meanwhile some clocked features are working (or have been re-activated). But still any model of Modelica_Synchronous fails (besides the reference Examples.SimpleControlledDrive.Continuous).

Can it be that OpenModelica switches off synchronous features if Modelica_Synchronous is loaded?

Shouldn't Modelica_Synchronous be added to the nightly tests?
See:

https://github.com/Modelica/Modelica_Synchronous

Change History (46)

comment:1 by Adrian Pop, 9 years ago

It might be possible that OpenModelica switches off synchronous features when loading Modelica_Synchronous as it has uses(Modelica(version="3.2.1")).
However, I think if you activate +std=3.3 before loading Modelica and Modelica_Synchronous it would stay that way.

comment:2 by Rüdiger Franke, 9 years ago

The problem is related to composed models. The following example works:

model ClockedSource
  parameter Real dt = 0.1;
  Real u = 1;
  Modelica.Blocks.Interfaces.RealOutput ud;
equation
  ud = sample(time*u, Clock(dt));
end ClockedSource;

Invoke:

$ omc +std=3.3 ClockedSource.mo Modelica

The following composed model fails:

model ClockedModel
  ClockedSource cs;
end ClockedModel;

Invoke:

$ omc +std=3.3 ClockedModel.mo ClockedSource.mo Modelica

to get:

Error processing file: ClockedModel.mo
[ClockedSource.mo:6:3-6:33:writable] Error: Failed to instantiate equation 
ud = sample(time * u, Clock(dt));.
Error: Error occurred while flattening model ClockedModel

The same or a similar error shows up for each example from Modelica_Synchronous.

comment:3 by Adrian Pop, 9 years ago

Owner: changed from somebody to Adrian Pop
Status: newaccepted

comment:4 by Adrian Pop, 9 years ago

Cc: Bernhard Thiele added

It seems that Bernhard forgot to add prefixing for Clock expressions.

-PrefixUtil.prefixExp failed on exp: Clock(dt)
-PrefixUtil.prefixExp failed on exp: sample(time * u, Clock(dt))
- InstSection.instEquationCommonWork failed for eqn: ud = sample(time * u, Clock(dt)); in scope: ClockedSource

I added the prefixing now and I'll test it a bit before commit.

comment:5 by Adrian Pop, 9 years ago

Prefixing is now fixed in c5ce437f2bca9d2ae01dfe3da731770de6fefdd2/OMCompiler.

adrpo@ida-liu050 /f/dev/testing
$ ../OpenModelica/build/bin/omc +std=3.3 ClockedModel.mo ClockedSource.mo Modelica
Notification: Laddade paket Complex 3.2.1 med automatik tack vare en uses-annotation.
Notification: Laddade paket ModelicaServices 3.2.1 med automatik tack vare en uses-annotation.

class ClockedModel
  parameter Real cs.dt = 0.1;
  Real cs.u = 1.0;
  Real cs.ud;
equation
  cs.ud = sample(time * cs.u, Clock(cs.dt));
end ClockedModel;

comment:6 by Adrian Pop, 9 years ago

Added the given test for this bug in 4b8cd775272ac0d66dbaec08209347c6c4069ba0/testsuite.

I'll add testing of Modelica_Synchronous in Hudson later today.

comment:7 by Adrian Pop, 9 years ago

I now added Modelica_Synchronous in Hudson.
@rfranke: I guess you want also Modelica_Synchronous_cpp added to test the C++ runtime. Let me know.

comment:8 by Adrian Pop, 9 years ago

We have the first results:
https://test.openmodelica.org/libraries/Modelica_Synchronous/BuildModelRecursive.html
https://test.openmodelica.org/libraries/Modelica_Synchronous_cpp/BuildModelRecursive.html

Most models fail with:

Error: Wrong type or wrong number of arguments to superSample(Clock(factor), resolutionFactor).

So I guess we don't check the superSample function properly. I'll look into it.

comment:9 by Rüdiger Franke, 9 years ago

Besides issues with sub/superSample, there is also a problem with clocks in connectors that are used by about any model. Modelica_Synchronous.Examples.SimpleControlledDrive provides an illustrative example for different synchronous features, starting from the reference model Continuous.

ClockedWithDiscreteTextbookController adds a basic real clock. This leads to:

Error: Illegal connection: component periodicClock.y is not a connector.

comment:10 by Adrian Pop, 9 years ago

@rfanke: yes, I know as I already fixed the superSample and I'm about to fix the connector issues. I'll let you know how it goes.

comment:11 by Adrian Pop, 9 years ago

Fixed subSample/superSample argument checking and allowance to use Clock as connector in ae1a72c/OMCompiler.
I'll restart the library checking for Modelica_Synchronous to see where we're at after Hudson finishes checking my commit.

comment:12 by Adrian Pop, 9 years ago

Cc: Lennart Ochel Maksimov Doe added

10 Models work now (previously only 3):
https://test.openmodelica.org/libraries/Modelica_Synchronous/BuildModelRecursive.html
https://test.openmodelica.org/libraries/Modelica_Synchronous_cpp/BuildModelRecursive.html
As far as I can tell the problems are in the back-end / code generation now, example errors:

  • Error: Partition have different sub-clocks.
  • Error: pre-optimization module clockPartitioning failed.
  • Internal error -- Function SynchronousFeatures.detectEqPatitionCall1 failed

There are still some issues with the front-end (shiftSample argument handling) which I will fix.

comment:13 by Rüdiger Franke, 9 years ago

Great if most things work in the frontend now!

comment:14 by Adrian Pop, 9 years ago

Owner: changed from Adrian Pop to Lennart Ochel
Status: acceptedassigned

I now fixed the remaining front-end things in 9365264/OMCompiler.
Should we open another ticket for the back-end things?

comment:15 by Adrian Pop, 9 years ago

As far as I can tell the back-end can only handle component references in functions hold, sample, subSample, superSample, shiftSample, backSample, noClock. If any of these get a Clock(...) instead the back-end will fail. The call chain goes like this:

detectEqPartition
 detectEqPartitionExp
  detectEqPartitionExp1
   detectEqPartitionCall
    detectEqPartitionCall1

and in detectEqPartitionCall1 the expected expression is a DAE.CREF.

This can be fixed in two ways:

  • if we substitute all the Clock(...) expressions with new generated variables
  • if we handle expressions in these operators instead of component references

What do you think?

in reply to:  14 comment:16 by Lennart Ochel, 9 years ago

Replying to adrpo:

Should we open another ticket for the back-end things?

You can do so and put me on the new ticket or we can just use this one ;-)

in reply to:  15 comment:17 by Lennart Ochel, 9 years ago

Replying to adrpo:

This can be fixed in two ways:

  • if we substitute all the Clock(...) expressions with new generated variables
  • if we handle expressions in these operators instead of component references

What do you think?

I will have a closer look, since I am not sure yet what is better.

in reply to:  15 comment:18 by Maksimov Doe, 9 years ago

Replying to adrpo:

As far as I can tell the back-end can only handle component references in functions hold, sample, subSample, superSample, shiftSample, backSample, noClock. If any of these get a Clock(...) instead the back-end will fail. The call chain goes like this:

detectEqPartition
 detectEqPartitionExp
  detectEqPartitionExp1
   detectEqPartitionCall
    detectEqPartitionCall1

and in detectEqPartitionCall1 the expected expression is a DAE.CREF.

This can be fixed in two ways:

  • if we substitute all the Clock(...) expressions with new generated variables
  • if we handle expressions in these operators instead of component references

What do you think?

This is correct behaviour because all non-trivial arguments of clocked operators should be substituted before in function substituteParitionOpExps.
So it is function substituteParitionOpExps that should be fixed.

Last edited 9 years ago by Maksimov Doe (previous) (diff)

comment:19 by Adrian Pop, 9 years ago

@gossen, thanks for the pointer.
I now fixed some minor typos in 213ddae/OMCompiler and 3e6f284/OMCompiler.

comment:20 by Maksimov Doe, 9 years ago

By the way, what function should be uses to get a value for expression?

in reply to:  20 comment:21 by Adrian Pop, 9 years ago

Replying to gossen:

By the way, what function should be uses to get a value for expression?

You can use Ceval.ceval to evaluate a DAE.Exp, see for example EvaluateParameter.mo.
Why do you need it? Sometimes is good not to evaluate things as then you cannot change them without recompiling in a re-simulation (via -override).

comment:22 by Maksimov Doe, 9 years ago

Clock constructors contain parameter arguments which should be known in clock partitioning phase.
Currently in function SynchronousFeatures.getSubClock we get these parameters using DAE.ICONST pattern.

comment:23 by Adrian Pop, 9 years ago

I played with the clock exp substitution with variables in c7257cc/OMCompiler. Might be good that somebody that knows the code better to check my fix as I'm not sure about it, but more models in Modelica_Synchronous are working now: 25/95 in the C runtime 28/95 in the CPP runtime.

@lochel, let's continue using this ticket as it seems OK, I assigned you to it now.

comment:24 by Adrian Pop, 9 years ago

Component: FrontendBackend

comment:25 by Rüdiger Franke, 9 years ago

First of all I'm happy that basic periodic and inferred clocks are working now!

I'm neither in the details of clock arithmetics (sub/super/shiftSample). Where should this be treated: in the backend or in the runtime? Or some shared treatment, e.g. the backend breaks it down to basic sample times and offsets?

comment:26 by Rüdiger Franke, 9 years ago

Support for embedded continuous equations + solver would be great. See e.g.

Modelica_Synchronous.Examples.System.ControlledMixingUnit

So far the example fails already with Clock instantiation:

[Modelica_Synchronous.ClockSignals: 15:10-15:61]: Wrong type or wrong number of arguments to Clock(Clock(period)).
 (in component periodicClock). 

in reply to:  26 ; comment:27 by Adrian Pop, 9 years ago

Replying to rfranke:

Support for embedded continuous equations + solver would be great. See e.g.

Modelica_Synchronous.Examples.System.ControlledMixingUnit

So far the example fails already with Clock instantiation:

[Modelica_Synchronous.ClockSignals: 15:10-15:61]: Wrong type or wrong number of arguments to Clock(Clock(period)).
 (in component periodicClock). 

This sounds like a front-end issue. I'll have a look.

in reply to:  27 ; comment:28 by Bernhard Thiele, 9 years ago

Replying to adrpo:

This sounds like a front-end issue. I'll have a look.

The example needs clocked discretized continuous-time partition support. This is a rather advanced feature within the synchronous language element extension. I omitted it, since I wanted first to support the basic features.

in reply to:  28 ; comment:29 by Adrian Pop, 9 years ago

Replying to bthiele:

Replying to adrpo:

This sounds like a front-end issue. I'll have a look.

The example needs clocked discretized continuous-time partition support. This is a rather advanced feature within the synchronous language element extension. I omitted it, since I wanted first to support the basic features.

This is true, but at least we should properly support it in the front-end.
As far as I read the Modelica Specification 3.3 section 16.3 Clock Constructors
the Clock(Clock(period)) is not permitted. However, looking into the code we have:

y = Clock(Clock(period), solverMethod=solverMethod);

so it seems we're not handling the name argument solverMethod properly.
I now have a fix for it but there is a problem with the way DAE.SOLVER_CLOCK is defined:

record SOLVER_CLOCK
  Exp c;
  String solverMethod;
end SOLVER_CLOCK;

The problem is that solverMethod in this case is a parameter. We could evaluate it but I guess the idea is to be able to change the solverMethod without recompilation and for that we need to keep it as a parameter all the way to code. So we need to change DAE.SOLVER_CLOCK to:

record SOLVER_CLOCK
  Exp c;
  Exp solverMethod;
end SOLVER_CLOCK;

and I assume all the other ClockKind records needs the same treatment.

So the question is: is it desirable to be able to change Clock parameters without recompilation? If so I'll start changing the compiler to handle the parameters in Clock better.

in reply to:  29 ; comment:30 by Maksimov Doe, 9 years ago

Replying to adrpo:

Replying to bthiele:

Replying to adrpo:

This sounds like a front-end issue. I'll have a look.

The example needs clocked discretized continuous-time partition support. This is a rather advanced feature within the synchronous language element extension. I omitted it, since I wanted first to support the basic features.

This is true, but at least we should properly support it in the front-end.
As far as I read the Modelica Specification 3.3 section 16.3 Clock Constructors
the Clock(Clock(period)) is not permitted. However, looking into the code we have:

y = Clock(Clock(period), solverMethod=solverMethod);

so it seems we're not handling the name argument solverMethod properly.
I now have a fix for it but there is a problem with the way DAE.SOLVER_CLOCK is defined:

record SOLVER_CLOCK
  Exp c;
  String solverMethod;
end SOLVER_CLOCK;

The problem is that solverMethod in this case is a parameter. We could evaluate it but I guess the idea is to be able to change the solverMethod without recompilation and for that we need to keep it as a parameter all the way to code. So we need to change DAE.SOLVER_CLOCK to:

record SOLVER_CLOCK
  Exp c;
  Exp solverMethod;
end SOLVER_CLOCK;

and I assume all the other ClockKind records needs the same treatment.

So the question is: is it desirable to be able to change Clock parameters without recompilation? If so I'll start changing the compiler to handle the parameters in Clock better.

Than we need a rational expressions that would be used in BackendDAE.SUBCLOCK for shift and factor parameters instead of rational constants.

comment:31 by Lennart Ochel, 9 years ago

I tried to fix the floating point exceptions that occur in certain models with the c runtime.

in reply to:  30 ; comment:32 by Bernhard Thiele, 9 years ago

Replying to gossen:

Replying to adrpo:

I now have a fix for it but there is a problem with the way DAE.SOLVER_CLOCK is defined:

record SOLVER_CLOCK
  Exp c;
  String solverMethod;
end SOLVER_CLOCK;

The problem is that solverMethod in this case is a parameter. We could evaluate it but I guess the idea is to be able to change the solverMethod without recompilation and for that we need to keep it as a parameter all the way to code. So we need to change DAE.SOLVER_CLOCK to:

record SOLVER_CLOCK
  Exp c;
  Exp solverMethod;
end SOLVER_CLOCK;

and I assume all the other ClockKind records needs the same treatment.

So the question is: is it desirable to be able to change Clock parameters without recompilation? If so I'll start changing the compiler to handle the parameters in Clock better.

One needs to make some trade-offs. Of course it is convenient to have it as a parameter, however that requires to generate more generic code. My opinion is that one can do without having it as a parameter that can be changed without recompilation and rather one should at least keep the option to generate specialized code, e.g., using inline integration techniques.

There is another issue. Depending on the solver there will be different data-flow constraints. If "ExplicitEuler" is used, the integration only needs the previous value of an input in order to to the integration. The other methods need the "current" value. Hence, scheduling/sorting of the equations within a model that includes a clocked discretized continuous-time partition depends on the chosen solver. That makes it at least very cumbersome to support parameters that can be changed without recompilation. I would not do it.

Than we need a rational expressions that would be used in BackendDAE.SUBCLOCK for shift and factor parameters instead of rational constants.

Also for other parameters we should think on the trade-offs to support changing them without recompilation. It might complicate things a lot and it is better to be more restrictive rather than supporting features that may be error prone to implement and might result in less efficient execution.

in reply to:  32 comment:33 by Maksimov Doe, 9 years ago

Replying to bthiele:

Replying to gossen:

Than we need a rational expressions that would be used in BackendDAE.SUBCLOCK for shift and factor parameters instead of rational constants.

Also for other parameters we should think on the trade-offs to support changing them without recompilation. It might complicate things a lot and it is better to be more restrictive rather than supporting features that may be error prone to implement and might result in less efficient execution.

Well, we already have rational number support in simulation runtime. So subclock's shift and factor parameters can be calculated at compile time as well as at simulation initialization.

in reply to:  29 comment:34 by Rüdiger Franke, 9 years ago

Replying to adrpo:

So the question is: is it desirable to be able to change Clock parameters without recompilation? If so I'll start changing the compiler to handle the parameters in Clock better.

Clock parameters are structural to some extent.

As bthiele outlines, a different solver method leads to different equation systems. The equations can possibly be better optimized if known at compile time, i.e. if the solver method is known. For intance the system solved by an implicit solver might fall apart if known analytically.

This is why I wouldn't consider it overly important to be able to change Clock parameters without recompilation -- it appears more interesting to see code optimizations thanks to inline integration.

comment:35 by Adrian Pop, 9 years ago

Ok. I get the picture.
What I propose is that the front-end doesn't restrict this directly as it is now.
I think we should do the evaluation in the back-end during compilation, that's fine.
At least this way we can change it later if we want to support Clock parameters without recompilation with no need to touch the front-end.

comment:36 by Bernhard Thiele, 9 years ago

I just tried to simulate some of the models that should be working in OMEdit. If executed in OMEdit I get strange errors like (Modelica_Synchronous.IntegerSignals.Sampler.SubSample):

stdout | error | <p>Got number 14.000000, expected: 12.000000<br>

I don't understand why, maybe some default simulation settings in OMEdit are different, but the error message is mysterious to me.

comment:37 by Rüdiger Franke, 9 years ago

This message only shows up with the C runtime -- in an exported FMU as well. You should grep or debug the runtime code.

comment:38 by Rüdiger Franke, 9 years ago

Let's re-activate the ticket. The current OMEdit says "Process crashed" after having issued the error message given in #comment:36 for the C runtime. What is different in the nightly tests, where simulation succeeds for some models?

Moreover, it is really bad that OpenModelica seems to ignore annotation(Evaluate=true). In particular subsample and shift factors disappear during model translation -- because they are stored in rational numbers, but OpenModelica does not evaluate the parameters and leaves the rational numbers with their default values. See e.g.

Modelica_Synchronous.Examples.SimpleControlledDrive.ExactlyClockedWithDiscreteController

The nightly tests report success for this model; but nothing happens during the simulation. Compare load.w with the other SimpleControlledDrive examples.

Last but not least the translation still fails for clocks with solverMethod. See e.g.:

Modelica_Synchronous.Examples.SimpleControlledDrive.ClockedWithDiscretizedContinuousController

If the fronend accepted the model, then someone who knows the backend should be able to replace der(x) with clocked variables and add some simple integration methods like Euler to start with.

The high-end solverMethod implementation would solve the clocked partition to ODE form before adding a solver, e.g. for model inversion. See e.g.:

Modelica_Synchronous.Examples.Systems.ControlledMixingUnit

comment:39 by Adrian Pop, 9 years ago

With changes in PR478 we can now flatten Modelica_Synchronous.Examples.Systems.ControlledMixingUnit and I guess other also.

class Modelica_Synchronous.Examples.Systems.ControlledMixingUnit "Simple example of a mixing unit where a (discretized) nonlinear inverse plant model is used as feedforward controller"
  parameter Real freq(quantity = "Frequency", unit = "Hz") = 0.003333333333333334 "Critical frequency of filter";
  parameter Real c0(unit = "mol/l") = 0.848 "Nominal concentration";
  parameter Real T0(quantity = "ThermodynamicTemperature", unit = "K", displayUnit = "degC", min = 0.0, start = 288.15, nominal = 300.0) = 308.5 "Nominal temperature";
  parameter Real a1_inv = 0.2674;
  parameter Real a21_inv = 1.815;
  parameter Real a22_inv = 0.4682;
  parameter Real b_inv = 1.5476;
  parameter Real k0_inv = 105000000000000.0;
  parameter Real eps = 34.2894;
  parameter Real x10 = 0.42;
  parameter Real x10_inv = 0.6;
  parameter Real x20 = 0.01;
  parameter Real u0 = -0.0224;
  final parameter Real c_start(unit = "mol/l") = c0 * (1.0 - x10);
  final parameter Real c_inv_start(unit = "mol/l") = c0 * (1.0 - x10_inv);
  final parameter Real T_start(quantity = "ThermodynamicTemperature", unit = "K", displayUnit = "degC", min = 0.0, start = 288.15, nominal = 300.0) = T0 * (1.0 + x20);
  final parameter Real c_high_start(unit = "mol/l") = 0.28 * c0;
  final parameter Real T_c_start = T0 * (1.0 + u0);
  parameter Real pro = 1.5 "Deviations of plant to inverse plant parameters";
  final parameter Real a1 = a1_inv * pro;
  final parameter Real a21 = a21_inv * pro;
  final parameter Real a22 = a22_inv * pro;
  final parameter Real b = b_inv * pro;
  final parameter Real k0 = k0_inv * pro;
  Real invMixingUnit.T_c(unit = "K", start = T_c_start, fixed = true) "Cooling temperature";
  Real invMixingUnit.c(unit = "mol/l", start = c_start, fixed = true) "Concentration";
  Real invMixingUnit.T(unit = "K", start = T_start, fixed = true, stateSelect = StateSelect.always) "Temperature in mixing unit";
  parameter Real invMixingUnit.c0(unit = "mol/l") = c0 "Nominal concentration";
  parameter Real invMixingUnit.T0(quantity = "ThermodynamicTemperature", unit = "K", displayUnit = "degC", min = 0.0, start = 288.15, nominal = 300.0) = T0 "Nominal temperature";
  parameter Real invMixingUnit.a1 = a1_inv;
  parameter Real invMixingUnit.a21 = a21_inv;
  parameter Real invMixingUnit.a22 = a22_inv;
  parameter Real invMixingUnit.b = b_inv;
  parameter Real invMixingUnit.k0 = k0_inv;
  parameter Real invMixingUnit.eps = eps;
  Real invMixingUnit.gamma "Reaction speed";
  protected parameter Real invMixingUnit.tau0(quantity = "Time", unit = "s") = 60.0;
  protected parameter Real invMixingUnit.wk0 = invMixingUnit.k0 / invMixingUnit.c0;
  protected parameter Real invMixingUnit.weps = invMixingUnit.eps * invMixingUnit.T0;
  protected parameter Real invMixingUnit.wa11 = invMixingUnit.a1 / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wa12 = invMixingUnit.c0 / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wa13 = invMixingUnit.c0 * invMixingUnit.a1 / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wa21 = invMixingUnit.a21 / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wa22 = invMixingUnit.a22 * invMixingUnit.T0 / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wa23 = invMixingUnit.T0 * (invMixingUnit.a21 - invMixingUnit.b) / invMixingUnit.tau0;
  protected parameter Real invMixingUnit.wb = invMixingUnit.b / invMixingUnit.tau0;
  Real add.u1 "Connector of Real input signal 1";
  Real add.u2 "Connector of Real input signal 2";
  Real add.y "Connector of Real output signal";
  parameter Real add.k1 = 1.0 "Gain of upper input";
  parameter Real add.k2 = 1.0 "Gain of lower input";
  Real inverseBlockConstraints.u1 "Input signal 1 (u1 = u2)";
  Real inverseBlockConstraints.u2 "Input signal 2 (u1 = u2)";
  Real inverseBlockConstraints.y1 "Output signal 1 (y1 = y2)";
  Real inverseBlockConstraints.y2 "Output signal 2 (y2 = y2)";
  Real mixingUnit.T_c(unit = "K") "Cooling temperature";
  Real mixingUnit.c(unit = "mol/l", start = c_start, fixed = true) "Concentration";
  Real mixingUnit.T(unit = "K", start = T_start, fixed = true) "Temperature in mixing unit";
  parameter Real mixingUnit.c0(unit = "mol/l") = c0 "Nominal concentration";
  parameter Real mixingUnit.T0(quantity = "ThermodynamicTemperature", unit = "K", displayUnit = "degC", min = 0.0, start = 288.15, nominal = 300.0) = T0 "Nominal temperature";
  parameter Real mixingUnit.a1 = a1;
  parameter Real mixingUnit.a21 = a21;
  parameter Real mixingUnit.a22 = a22;
  parameter Real mixingUnit.b = b;
  parameter Real mixingUnit.k0 = k0;
  parameter Real mixingUnit.eps = eps;
  Real mixingUnit.gamma "Reaction speed";
  protected parameter Real mixingUnit.tau0(quantity = "Time", unit = "s") = 60.0;
  protected parameter Real mixingUnit.wk0 = mixingUnit.k0 / mixingUnit.c0;
  protected parameter Real mixingUnit.weps = mixingUnit.eps * mixingUnit.T0;
  protected parameter Real mixingUnit.wa11 = mixingUnit.a1 / mixingUnit.tau0;
  protected parameter Real mixingUnit.wa12 = mixingUnit.c0 / mixingUnit.tau0;
  protected parameter Real mixingUnit.wa13 = mixingUnit.c0 * mixingUnit.a1 / mixingUnit.tau0;
  protected parameter Real mixingUnit.wa21 = mixingUnit.a21 / mixingUnit.tau0;
  protected parameter Real mixingUnit.wa22 = mixingUnit.a22 * mixingUnit.T0 / mixingUnit.tau0;
  protected parameter Real mixingUnit.wa23 = mixingUnit.T0 * (mixingUnit.a21 - mixingUnit.b) / mixingUnit.tau0;
  protected parameter Real mixingUnit.wb = mixingUnit.b / mixingUnit.tau0;
  Real feedback.u1;
  Real feedback.u2;
  Real feedback.y;
  parameter Real gain.k(unit = "1", start = 1.0) = 20.0 "Gain value multiplied with input signal";
  Real gain.u "Input signal connector";
  Real gain.y "Output signal connector";
  Real filter.u "Connector of Real input signal";
  Real filter.y "Connector of Real output signal";
  parameter Integer filter.n = 3 "Order of filter";
  parameter Real filter.f(quantity = "Frequency", unit = "Hz", start = 1.0) = freq "Cut-off frequency";
  parameter Boolean filter.normalized = true "= true, if amplitude at f_cut is 3 dB, otherwise unmodified filter";
  Real filter.x[1](start = 0.49, fixed = true) "Filter states";
  Real filter.x[2](start = 0.49, fixed = false) "Filter states";
  Real filter.x[3](start = 0.49, fixed = false) "Filter states";
  protected parameter Real filter.alpha = if filter.normalized then sqrt(-1.0 + 2.0 ^ (1.0 / /*Real*/(filter.n))) else 1.0 "Frequency correction factor for normalized filter";
  protected parameter Real filter.w = 6.283185307179586 * filter.f / filter.alpha;
  parameter Real hold1.y_start = 0.0 "Value of output y before the first tick of the clock associated to input u";
  Real hold1.u(start = hold1.y_start) "Connector of clocked, Real input signal";
  Real hold1.y "Connector of continuous-time, Real output signal";
  Real sample1.u "Connector of continuous-time, Real input signal";
  Real sample1.y "Connector of clocked, Real output signal";
  parameter Boolean periodicClock1.useSolver = true "= true, if solverMethod shall be explicitely defined";
  parameter String periodicClock1.solverMethod = "ExplicitEuler" "Integration method used for discretized continuous-time partitions";
  Clock periodicClock1.y;
  parameter Real periodicClock1.period(quantity = "Time", unit = "s") = 1.0 "Period of clock (defined as Real number)";
  Real step.y "Connector of Real output signal";
  parameter Real step.offset = c_start "Offset of output signal y";
  parameter Real step.startTime(quantity = "Time", unit = "s") = 0.0 "Output y = offset for time < startTime";
  parameter Real step.height = c_high_start - c_start "Height of step";
  Real sample2.u "Connector of continuous-time, Real input signal";
  Real sample2.y "Connector of clocked, Real output signal";
  Clock sample2.clock "Output signal y is associated with this clock input";
equation
  invMixingUnit.gamma = invMixingUnit.c * invMixingUnit.wk0 * exp((-invMixingUnit.weps) / invMixingUnit.T);
  der(invMixingUnit.c) = invMixingUnit.wa13 + (-invMixingUnit.wa12) * invMixingUnit.gamma - invMixingUnit.wa11 * invMixingUnit.c;
  der(invMixingUnit.T) = invMixingUnit.wa22 * invMixingUnit.gamma + invMixingUnit.wa23 + invMixingUnit.wb * invMixingUnit.T_c - invMixingUnit.wa21 * invMixingUnit.T;
  add.y = add.k1 * add.u1 + add.k2 * add.u2;
  inverseBlockConstraints.u1 = inverseBlockConstraints.u2;
  inverseBlockConstraints.y1 = inverseBlockConstraints.y2;
  mixingUnit.gamma = mixingUnit.c * mixingUnit.wk0 * exp((-mixingUnit.weps) / mixingUnit.T);
  der(mixingUnit.c) = mixingUnit.wa13 + (-mixingUnit.wa12) * mixingUnit.gamma - mixingUnit.wa11 * mixingUnit.c;
  der(mixingUnit.T) = mixingUnit.wa22 * mixingUnit.gamma + mixingUnit.wa23 + mixingUnit.wb * mixingUnit.T_c - mixingUnit.wa21 * mixingUnit.T;
  feedback.y = feedback.u1 - feedback.u2;
  gain.y = gain.k * gain.u;
  der(filter.x[1]) = (filter.u - filter.x[1]) * filter.w;
  der(filter.x[2]) = (filter.x[1] - filter.x[2]) * filter.w;
  der(filter.x[3]) = (filter.x[2] - filter.x[3]) * filter.w;
  filter.y = filter.x[3];
  hold1.y = hold(hold1.u);
  sample1.y = sample(sample1.u, Clock());
  periodicClock1.y = Clock(Clock(periodicClock1.period), periodicClock1.solverMethod);
  step.y = step.offset + (if time < step.startTime then 0.0 else step.height);
  sample2.y = sample(sample2.u, sample2.clock);
  feedback.y = gain.u;
  add.u2 = gain.y;
  invMixingUnit.T_c = inverseBlockConstraints.y2;
  invMixingUnit.c = inverseBlockConstraints.u2;
  feedback.u1 = invMixingUnit.T;
  filter.y = inverseBlockConstraints.u1;
  hold1.y = mixingUnit.T_c;
  add.y = hold1.u;
  mixingUnit.T = sample1.u;
  feedback.u2 = sample1.y;
  add.u1 = inverseBlockConstraints.y1;
  sample2.u = step.y;
  filter.u = sample2.y;
  periodicClock1.y = sample2.clock;
end Modelica_Synchronous.Examples.Systems.ControlledMixingUnit;

comment:40 by Rüdiger Franke, 9 years ago

Great. Now it's up to the backend (mostly). The nightly tests report an internal error -- SynchronousFeatures.resolveClocks failure:

Error: pre-optimization module clockPartitioning (simulation) failed.

Unfortunately the error message does not give more details -- the error falls through due to use of match instead of matchcontinue in the function getSubClock. It is most likely the attempt to get a string for the solverMethod (see #3717).

Clock partitioning passes with the runtime argument -d=evalparam. The next failure is then:

Error: Internal error BackendDAEOptimize.partitionIndependentBlocks failed without good error message
Error: No system for the symbolic initialization was generated

comment:41 by Rüdiger Franke, 9 years ago

The error messages have been improved meanwhile.

Commit

https://github.com/OpenModelica/OMCompiler/commit/4d11cc6c536dd69b0d82b7e1750eafba21bb4595

adds initial support for continuous-time equations in clocked partitions. Basic examples are working, such as Modelica_Synchronous.Examples.SimpleControlledDrive.ClockedWithDiscretizedContinuousController.

Unfortunately the solver method only works with -d=evalparam. Meaning that the ball is back on the frontend side (see #3717).

For some other examples the generation of simulation code still fails. See in particular #3741.

comment:42 by Martin Sjölund, 9 years ago

Milestone: 1.9.41.9.5

Milestone pushed to 1.9.5

comment:43 by Martin Sjölund, 9 years ago

Milestone: 1.9.51.10.0

Milestone renamed

comment:44 by Rüdiger Franke, 9 years ago

Owner: changed from Lennart Ochel to Rüdiger Franke

The ticket can be considered solved. #3717 has been solved. Now we simulate 78 of 95 models of Modelica_Synchronous. The results of 56 simulations pass the verification. Also a default clock period has been introduced in #3752.

Remaining issues find in the separate tickets #3770, #3771, 3772.

comment:45 by Rüdiger Franke, 9 years ago

Resolution: fixed
Status: assignedclosed

comment:46 by Martin Sjölund, 7 years ago

Milestone: 1.10.0

Milestone deleted

Note: See TracTickets for help on using tickets.