I have recently started using Modelica (OpenModelica) as a modeling tool and I am facing a problem regarding the use of inner/outer functionalities. I am trying to create an environment model containing values for ambient temperature and pressure, so that other models can use this values. I have tried to do so with inner and outer keywords but I keep receiving the following warning:
No corresponding 'inner' declaration found for component .Real component.T0 declared as 'outer '. The existing 'inner' components are: .Real ambient.T0; defined in scope: Test.Ambient. Check if you have not misspelled the 'outer' component name. Please declare an 'inner' component with the same name in the top scope. Continuing flattening by only considering the 'outer' component declaration.
Below these lines you can see a simplification of the code I am trying.
The three models below these lines are contained in a package named Test.
The model for ambient in which a temperature T0 is defined as inner:
within Test;
model Ambient
inner Real T0;
equation
T0 = 300;
end Ambient;
The model of a component that tries to call T0 via outer operator:
within Test;
model Component
Real T;
outer Real T0;
parameter Real k = 2;
equation
T = k * time + T0;
end Component;
Both models ambient and component are dragged and dropped in the combined model:
within Test;
model System
Test.Ambient ambient annotation(
Placement(visible = true, transformation(origin = {-30, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Test.Component component annotation(
Placement(visible = true, transformation(origin = {30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
end System;
When running System I get the aforementioned warning. Also, there is one variable more than equations (which makes sense since it is not being able to connect Component.T0 with Ambient T0)
Your use-case seems pretty similar to what is done in Modelica.Mechanics.MultiBody
and Modelica.Fluid
. In both cases, there is a class that contains all the "global" properties of the system, called world
or system
respectively.
Therefore your class Ambient
should defined to be an inner
class. This is then accessed by an outer
statement to re-use values from it. What would be possible when using your code, is to access T0
from models within Ambient
. Judging from your example code this is not what you want...
Applying the technique used in the MSL to your example, would result in the following code:
package Test
model Ambient
inner Real T0;
equation
T0 = 300;
annotation(defaultComponentPrefixes="inner");
end Ambient;
model Component
Real T;
Real T0 = ambient.T0;
parameter Real k = 2;
protected
outer Test.Ambient ambient;
equation
T = k * time + T0;
end Component;
model System
inner Test.Ambient ambient;
Test.Component component;
end System;
end Test;
Some comments:
protected
part of the model, just to prevent to have the same variables multiple times in the result.defaultComponentPrefixes
annotation ensures, that the model has the prefix inner
in case a graphical instance is created (as it is shown in the model System
).