[Bug] Embedded failures break local balance
Describe the bug
Several components (Pipes, all heat exchangers) can be declared as faulty, giving access to some failure modes (fouling, water_level_rise, etc.)
But currently, those failure modes are used in the model as :
if not faulty then
fouling = 0;
end if;
Which means that in a faulty=true model, each failure variable should be declared as a connector input, right ? How can we take that into account ?
Additional context
I tried to define a fouling class, with only one connector input, fouling, and extend this class in Pipe for instance but it did not solve the local balance issue...
To be checked by issue author
- [x] I checked that this issue is not a duplicate
- [x] I added the appropriate labels to my issues
- [x] I added the appropriate assignees to my issue
- [x] I linked the related issues in the description of my issue
@pepmts it is not clear to me what you mean by "failure mode". Is fouling an integer variable (0: OK, 1: faulty, 2: irreparably broken) or is is a Real parameter?
If it is a Real parameter, this can be done by giving a default binding to it:
model HeatExchanger
Real fouling = 0;
...
If you use the model as it is, fouling = 0. However, you can make it faulty by changing the binding equation when instantiating
HeatExchanger hex(fouling = 0.1);
fouling is a real variable, but we want to be able to define inputs in faulty models, that are assigned to this "failure variable". For instance :
model SimplePlant
... // no faulty parameters, variables, etc. involved, okay with binding equation ✔️
end SimplePlant
And then :
model SimplePlant_faulty
extends SimplePlant(
heat_exchanger(faulty=true, fouling=Failure_fouling) // okay with binding equation ?
input Real Failure_fouling;
equation
Failure_fouling = time*10; // for instance
end SimplePlant
fouling is a real variable, but we want to be able to define inputs in faulty models, that are assigned to this "failure variable".
The only way I see to have well-balanced models with inputs having default values is not to have them as inputs, but as regular variables with default binding equations, that can be changed upon instantiation or inheritance.
So
model HeatExchanger
Real fouling = 0;
...
end HeatExchanger;
model SimplePlant
HeatExchanger hex;
... // no faults, default binding applies
end SimplePlant;
model SimplePlant_faulty
extends SimplePlant(
hex(fouling=Failure_fouling);
Real Failure_fouling;
equation
Failure_fouling = time*10; // for instance
end SimplePlant
BTW, if you write the equation for Failure_fouling inside the model, then Failure_fouling needs to to be a plain Real variable, not input Real, otherwise the SimplePlant_faulty model won't be balanced.
BTW, if you write the equation for Failure_fouling inside the model, then Failure_fouling needs to to be a plain Real variable, not input Real, otherwise the SimplePlant_faulty model won't be balanced.
Agreed, I made a wrong example. So you would say that this is not balanced ? :
model SimplePlant_faulty
extends SimplePlant(
hex(fouling=Failure_fouling);
input Real Failure_fouling;
equation
// No binding equation on Failure_fouling
end SimplePlant
It works great for me, with both your case (which is what we do in our unit tests) and mine, which is what we do in our methodology, so it seems fine to me !
Agreed, I made a wrong example. So you would say that this is not balanced ? :
model SimplePlant_faulty extends SimplePlant( hex(fouling=Failure_fouling); input Real Failure_fouling; equation // No binding equation on Failure_fouling end SimplePlant
This looks balanced to me.
SimplePlant is balanced, thanks to the default binding fouling = 0.
SimplePlant_fouling adds one variable Failure_fouling and one equation because of the input prefix. The binding in hex doesn't change the number of equations, because it replaces an existing one. So it is balance, but it requires you to instantiate it and give a binding equation to its input (see
The only question is if you want to use input Real or rather a connector input. According to the rules for balanced models in Section 4.7 of the Modelica specification, if you use input Real then you are expected to provide the extra equation as a binding equation:
Definition 4.2. Local equation size. The local equation size of a model or block class is the sum of the following numbers: ... The number of (top level) public input variables that neither are connectors nor have binding equations. [I.e., top-level inputs are treated as known variables. This represents the number of binding equations that will be provided when the class is used.]
If you use a connector Input, you can do it with a connect, or with an extra equation in the system where the model is instantiated
BTW, if I understand correctly, you could define the heat exchanger model as
model HeatExchanger
input Real fouling = 0;
...
end HeatExchanger;
by using input Real instead of just Real, to make it clearer that you are possibly expected to change this binding when instantiating the class.
Note that in this case, according to the balanced model rules, this top level input is not considered as an extra equation when checking for the balancedness of HeatExchanger, because it has a binding equation. So the HeatExchanger model is still balanced, despite adding the input prefix. Extra equations are assumed in the counting only for "(top level) public input variables that neither are connectors nor have binding equations."
I hope I haven't managed to get you more confused 😅
Okay ! It is clear now, no problem 😄, I am glad to know that we can use this internal failures that are quite important to us and do it with properly balanced models.
About input/connector input, I think we would define input in the top level SimplePlant_faulty model, with binding equation provided by our software, and connector input in the hex model, as it is an internal model.