2

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:

  • In JModelica I get a warning that “The constant nc does not have a binding expression"
  • In OpenModelica I get an error that “Could not evaluate structural parameter (or constant) .. nc which gives dimensions of array c[MediumBase.nc]. Array dimension must be know at compile time'

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:

  1. To me it looks better to keep nc undefined and then make sure value is set during compilation, while changing a constant during compilation looks questionable, but perhaps (still) allowed in Modelica. IN the Modelica language specification I can see in Appendix A that the requirement of a constant is (only) that it is constant during simulation, i.e. not during compilation. In appendix E8.2 I see that perhaps an initial assignment of nc should be done, but not sure. Would appreciate some comment on this though.
  2. How could it be that with a somewhat larger example compilers of JModelica and OpenModelica give warning and error, respectively?
  3. What the Modelica specification say about what is right here?

If needed I can provide the larger example, but I think that here might be a more general answer.

janpeter
  • 681
  • 8
  • 22

2 Answers2

0

1) In theory i understand what you mean, but the modelica language standard requires every model (besides connectors and partial models) to be valid on their own. This seems to not be relevant for your case since you defined a partial package, the problem here is that you defined an array in the same scope that structurally depends on this variable. Therefore i would strongly recommend to provide a default value that can be checked for.

2) I actually cannot reproduce the problem. With OpenModelica everything runs fine even for nc=10000. Slow but it works (We are working on making array/vector stuff faster in the future). I am working with the nightly build (OpenModelica 1.16.0~dev-102-g5c1a023).

3) See 1). Generally i can just add that you should use the Check Model (Single check mark on green circle top middle) on very component individually to check if everything you do is modelica language conform. You can also use the instantiate button right next to it to look at the flat model that will be generated from your code.

Furthermore i would recommend using the compilation flag -d=newInst (providing you work on one of the newer versions). That uses the new instantiation which is stricter on modelica specification and far more efficient.

kabdelhak
  • 687
  • 3
  • 8
  • 1) What I understand a partial model and package can very well be incomplete since it is not used alone. And my partial package MediumBase essentially make sure that when a Medium is replaced that package really has a parameter nc and when a complete package then is formed the number must be in place. 2) And I am glad that both JModelica and OpenModelica accept the code I posted and confirms somewhat my understanding. 3) But for a larger model, not in terms of nc, but with a few more layers of code then I get compiler warning and error, from JModelican and OpenModelica. Modelica spec say what? – janpeter Feb 25 '20 at 08:47
0

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!

janpeter
  • 681
  • 8
  • 22