I work with finding a good way to divide code in two parts: a general library and and application code, The examples I work with usually contain liquids and I want to make the general library independent of the number of components in the liquid. The idea is that the application code set the liquid medium used and then import equipment from the general library and adapt these equipment to the actual medium.
The example below is a very concise example that illustrate one way to do this division of code. Here I let value nc of number of components be undefined in the partial package MediumBase. Later when the EquipmentLib is adapted to the actual Medium then nc get a value. This is what I mean with “delay” setting of structural parameter. The code works well in both JModelica and OpenModelica.
package DEMO_v30
// Author: Jan Peter Axelsson
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
partial package MediumBase
constant Integer nc "Number of components";
replaceable type Concentration = Real[nc] "Component conc";
end MediumBase;
package Medium3
extends MediumBase (nc=3);
end Medium3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package EquipmentLib
replaceable package Medium = MediumBase // formal parameter - EquipmentLib
constrainedby MediumBase;
model ReactorType
parameter Medium.Concentration c_0 = ones(Medium.nc) "Initial component conc";
Medium.Concentration c (start=c_0, each fixed=true) "Component conc";
equation
for i in 1:Medium.nc loop
der(c[i]) = -c[i];
end for;
end ReactorType;
end EquipmentLib;
// ---------------------------------------------------------------------------------------------
// Adaptation of package Equipment to Medium3
// ---------------------------------------------------------------------------------------------
package Equipment
import DEMO_v30.EquipmentLib;
extends EquipmentLib(redeclare package Medium=Medium3);
end Equipment;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Equipment.ReactorType reactor;
end Test;
end DEMO_v30;
In slightly larger examples with the same code structure I get some problems though:
The message does not make sense to me since nc is known at compile time, at the level of where EquipmentLib is adapted. This problem can actually be resolved by givning nc in MediumBase a “dummy” value nc=1 in Medium Base, and then that nc get changed during compilation to the value provided when EquipmentLib is adapted.
So my questions are:
If needed I can provide the larger example, but I think that here might be a more general answer.
I have now got confirmed that my posted code is indeed sound and for a partial package (or model) you can define variables that has no values or vectors with undetermined size, provided they at compilation time are completely defined. The more complex code with similar structure that gave problem I mentioned, is now also solved. The code works on both JModelica 2.14 and OpenModelica 1.16 nightly build ...b48. Interestingly the code does not work on version 1.15 or earlier. Thanks to my contact at Modelon, Markus Olsson!