Opened 4 years ago

Last modified 4 years ago

#6260 reopened defect

Error "Following variable is discrete, but does not appear on the LHS of a when-statement"

Reported by: marianne.saugier@… Owned by: Per Östlund
Priority: high Milestone: NeedsInput
Component: Frontend Version: 1.16.0
Keywords: error, discrete variable, when statement Cc:

Description

I get the error "Following variable is discrete, but does not appear on the LHS of a when-statement" for a discrete variable connected to another discrete variable that is in a when statement. Is that normal?

Example:

connect(tapChanger.tap, transformer.tap); error with new front end
(transformer.tap is not in the LHS of a when-statement, but tapChanger.tap is, so I would have expected the error to disappear when writing the connect statement.

when time >0 then
transformer.tap.value = tapChanger.tap.value; no error
end when;

Attachments (1)

TestDiscreteBlocks.mo (957 bytes ) - added by Francesco Casella 4 years ago.

Download all attachments as: .zip

Change History (16)

comment:1 by Francesco Casella, 4 years ago

@marianne, if you could attach the test case it would be great, because then we can reproduce your problem and analyze it better.

I assume you are using models from PowerGrids extending TapChangerPhaseShifterLogicCommon. There, tap is not a connector in the first place, so I guess that's the main problem, you can't really use non-connector in a connect statement. Do I miss something?

in reply to:  1 comment:2 by Per Östlund, 4 years ago

Replying to casella:

I assume you are using models from PowerGrids extending TapChangerPhaseShifterLogicCommon. There, tap is not a connector in the first place, so I guess that's the main problem, you can't really use non-connector in a connect statement. Do I miss something?

No, it has to be something else since tap is a simple Integer in that class, so e.g. transformer.tap.value would not be legal in that case. Besides, the new frontend does not allow connecting non-connectors, and that error would trigger much earlier than the "unassigned discrete" one.

Anyway, like the error message says all discrete Real variables must be assigned in a when-equation. Connect-equations do not count since they're not allowed inside when anyway (connections must be possible to handle at compile time).

comment:3 by marianne.saugier@…, 4 years ago

Thanks for your answers.

I am using Dynawo Modelica library.
I am trying to update the library to be compatible with recent OM version and with the new front end. I am currently working on a local branch but I can let you know when the dev is ready if you want to try by yourselves.
Here are more information on the models:

model Transformer
Connector.ZPin tap;
equation the tap is determined and regulated by the tapChanger, so no equation on tap here.
end Transformer;

model TapChanger
Connector.ZPin tap;
equation
when ... then
tap.value = ... ; the tap is inside a when statement here.
end when;
end TapChanger;

connector ZPin
discrete Real value; Connector for propagating discrete values (and events)
end ZPin;

And now I am trying to build a model with transformer and tapChanger and wanted to write:
connect(tapChanger.tap, transformer.tap);

You know the rest!
I would have expected it to work. Is it normal that it doesn't?
How would you do then?
Thanks!

in reply to:  3 ; comment:4 by Francesco Casella, 4 years ago

Replying to marianne.saugier@…:

Thanks for your answers.

I am using Dynawo Modelica library.

It would be best to have this library in our testsuite, so we can monitor it and also do regression testing. Is it available on a public git repo?

model Transformer
Connector.ZPin tap;
equation the tap is determined and regulated by the tapChanger, so no equation on tap here.
end Transformer;

model TapChanger
Connector.ZPin tap;
equation
when ... then
tap.value = ... ; the tap is inside a when statement here.
end when;
end TapChanger;

connector ZPin
discrete Real value; Connector for propagating discrete values (and events)
end ZPin;

And now I am trying to build a model with transformer and tapChanger and wanted to write:
connect(tapChanger.tap, transformer.tap);

You know the rest!
I would have expected it to work. Is it normal that it doesn't?

I'm not aware of any restriction about connector variables being barred to be discrete variables. In fact, that's what happens with all discrete blocks. It would be best to have a MWE we could run ourselves.

@perost, any comment?

in reply to:  4 comment:5 by Per Östlund, 4 years ago

Replying to casella:

I'm not aware of any restriction about connector variables being barred to be discrete variables. In fact, that's what happens with all discrete blocks. It would be best to have a MWE we could run ourselves.

@perost, any comment?

There's nothing in the specification about discrete variables in connectors, but I'm not sure what the implications of it are. I've never seen it used, and I can't find any such use in the MSL either.

However, the issue here is that tap.value in Transformer is never assigned in a when-equation. As I mentioned you can't do that with a connect-equation, you need to do something similiar to what's done in TapChanger.

comment:6 by Per Östlund, 4 years ago

Resolution: invalid
Status: newclosed

I'm closing this since it's a model issue and not a compiler isssue, but feel free to continue using this ticket for discussion anyway.

in reply to:  6 comment:7 by Francesco Casella, 4 years ago

Replying to perost:

I'm closing this since it's a model issue and not a compiler isssue, but feel free to continue using this ticket for discussion anyway.

Agreed.

@marianne, consider the attached example, that I think is relevant for you. The sampler block generates the discrete output by assigning the connector variable y inside a when statement. That variable is then passed via a connection to the variable u of the transferFunction block. However, if you check the definition of the interfaces, the connector variables themselves are not declared explicitly as discrete.

I don't know the definizion of your ZPin connector, but I guess you should do something similar your library.

by Francesco Casella, 4 years ago

Attachment: TestDiscreteBlocks.mo added

comment:8 by marianne.saugier@…, 4 years ago

Thanks for the remarks.

The thing is, the tap variable is an input for the transformer model, meaning that the transformer model doesn't know how the variable tap will move. Only the tap changer can say how the tap will evolve. That's why the equations are in the tap changer model and not in the transformer model. How can we say that the tap variable of the tap changer is controlling the tap variable of the transformer if not in a connect statement or an equality?

Shound't the tap variable of the transformer appear in the same equations than the tap variable of the tap changer if they are connected together?

From what I understand from our discussion so far, is that it is impossible to propagate the behavior of discrete variables between different models, and impossible to have a model with discrete input variables set by discrete output variables of other models, but maybe I miss something...

comment:9 by Francesco Casella, 4 years ago

You just use non-discrete connectors. They will automatically get discrete status based on the equations. That's what happens in the attached example. As you can see there, there is indeed transfer of discrete variables between blocks through input/output connectors, which are however themselves not discrete.

comment:10 by franco.ferrucci@…, 4 years ago

Hi there,
I'm trying to simulate a basic example from Peter Fritzson's book "Principles of Object-Oriented Modeling and Simulation with Modelica 3.3", page 382, and I get the same error mentioned in this ticket: "Following variable is discrete, but does not appear on the LHS of a when-statement:x"

This is the model:


model BasicClockedSynchronous

extends Modelica.Icons.Example;
Clock clk "A clock variable";
discrete Real x "Clocked discrete-time variable";
Real y "Unclocked discrete-time variable";

equation

clk = Clock(0.2);
x = sample(time, clk);
y = hold(x) + 1;

end BasicClockedSynchronous;


The model does not check under OMEdit 1.16, 1.17-dev and 1.18-dev.

However, if I remove the "discrete" qualifier, the model checks and simulates correctly.

Note: in Dymola 2021, the model check and compile without the need of removing the "discrete" qualifier.

comment:11 by Francesco Casella, 4 years ago

Cc: adrien.guironnet@… florentine.rosiere@… francesco.casella@… removed
Resolution: invalid
Status: closedreopened

@franco, I checked Chapter 16 of the Modelica Specification. As I understand, discrete and clocked variables have a different variability. Discrete variables change at discrete event, but they are well defined (and remain constant) in-between. Clocked variables exist only at clock events, and are not defined elsewhere; if you want to use them together with continuous or discrete variables, you need to use the sample() and hold() operators.

That said, clocked variables are either explicitly declared as such, or they can be inferred to be clocked because they show up in clocked equations. In all examples of the Specification, this happens with continuous time Real variables. However, as clocked variables can also be Boolean, Integer and String (which are discrete by definition), there is no reason why they couldn't be discrete Real as well.

Summing up, I don't see the point of declaring x as discrete, since it will automatically get its clocked discrete-time status from the equation x = sample(time,clk). But it shouldn't be illegal.

@perost, do you agree? Can we make sure discrete variables are also accepted for clock inference?

Last edited 4 years ago by Francesco Casella (previous) (diff)

in reply to:  11 ; comment:12 by Per Östlund, 4 years ago

Replying to casella:

@perost, do you agree? Can we make sure discrete variables are also accepted for clock inference?

I'm not very familiar with the synchronous bits, but I don't think it's something that's trivial to change at least. It would probably be a good idea to get this clarified in the specification.

in reply to:  12 ; comment:13 by Francesco Casella, 4 years ago

Replying to perost:

Replying to casella:

@perost, do you agree? Can we make sure discrete variables are also accepted for clock inference?

I'm not very familiar with the synchronous bits, but I don't think it's something that's trivial to change at least. It would probably be a good idea to get this clarified in the specification.

I checked what OpenModelica says when flattening this model:

[1] 17:25:19 Translation Error
[BasicClockedSynchronous: 5:5-5:53]: 
Following variable is discrete, but does not appear on the LHS of a when-statement: ‘x‘.

This is because of the rule in Section 4.4.4: "If a Real variable is declared with the prefix discrete it must in a simulation model be assigned in a when-clause, either by an assignment or an equation."

However, since x shows up in an equation with a sample() operator, it becomes a clocked variable, as it would if it were just a Real variable. So I guess the rule should not apply.

On the other hand, I understand the clock partitioning is performed much later by the backend, right? So, either this is illegal, or we should check for the discrete variable assignment in the backend, after the clock partitioning step.

@perost, is this what we should discuss with the MAP-LANG group?

in reply to:  13 comment:14 by Per Östlund, 4 years ago

Replying to casella:

Replying to perost:

Replying to casella:

@perost, do you agree? Can we make sure discrete variables are also accepted for clock inference?

I'm not very familiar with the synchronous bits, but I don't think it's something that's trivial to change at least. It would probably be a good idea to get this clarified in the specification.

I checked what OpenModelica says when flattening this model:

[1] 17:25:19 Translation Error
[BasicClockedSynchronous: 5:5-5:53]: 
Following variable is discrete, but does not appear on the LHS of a when-statement: ‘x‘.

This is because of the rule in Section 4.4.4: "If a Real variable is declared with the prefix discrete it must in a simulation model be assigned in a when-clause, either by an assignment or an equation."

However, since x shows up in an equation with a sample() operator, it becomes a clocked variable, as it would if it were just a Real variable. So I guess the rule should not apply.

The rule only says "declared with the prefix discrete" though, so as it's currently written it doesn't matter if the variable also happens to be clocked. Also, if being clocked means it's no longer discrete I think it should be an error to declare a clocked variable as discrete. If it has some actual meaning it needs to be clarified in the specification.

On the other hand, I understand the clock partitioning is performed much later by the backend, right? So, either this is illegal, or we should check for the discrete variable assignment in the backend, after the clock partitioning step.

Yes, the frontend doesn't really care about clocks much.

Note: See TracTickets for help on using tickets.