modelicaopenmodelicajmodelica

Extending packages and access to the content


I continue work on understanding how to best divide code in library and application. In a few previous posts I have worked with a toy example DEMO_xx library with application dxx_app7. Below is a slightly updated version to cover the question here. I have included the possibility to add a sensor to the harvest tank.

Now I want to understand how to in application code bring in information from the application Medium7 that is extended from the library Medium2 and use that fully in a new component model in the application.

What I understand is that if you import a package that is extended from another package you only get what is the “latest” package and NOT what is built up from through extensions and what is aggregated total Medium7 information.

This fact is illustrated in the example by changing the constant SensorX.component from C that works to A or B that does not work.

However, if I make a local instance of Medium7 THEN I get the complete information of Medium7. I can do that in SensorX as marked Question 1 - alt 2. I can also do this choice of substrate to measure out in the configuration of the system and marked Question 1 alt 3. This is more readable code I think.

  1. But how do I make all of the content of Medium7 available locally? Must I define locally a new constant for every constant I need as I show here with sensorX.component? Generally you may want to in a model have access to various properties of the medium and that is convenient to put in the package Medium

  2. Also I wish I could import a connector LiquidCon adapted for Medium7 instead of writing that code once again in package Sensor7. Import as suggested does not work. Is there another way? I have only tested the code in JModelica 2.4 and it might be a bug?

Would appreciate some input on these two questions. / Jan Peter

Below the application code d12_app7 that is of interest for the questions and then the associated library DEMO_v12. I have marked up with comments changes of code for the two questions and as the code stands it is for question 1 alt 1.

    encapsulated package d12_app7 

    //  ---------------------------------------------------------------------------------------------
    //     Interfaces  
    //  ---------------------------------------------------------------------------------------------

        import Modelica.Blocks.Interfaces.RealInput;
        import Modelica.Blocks.Interfaces.RealOutput;

        package Medium7
            import M2 = DEMO_v12.Medium2;
            extends M2
                (name = "Seven components"                      "Medium name", 
                nc = 7                                          "Number of substances",
                mw = cat(1,M2.mw,{30,40,50,60,70})              "Substance weight",
                redeclare type Concentration = Real[nc]         "Substance conc");
            constant Integer C = 3                              "Substance index";
            constant Integer D = 4                              "Substance index";  
            constant Integer E = 5                              "Substance index";  
            constant Integer F = 6                              "Substance index";  
            constant Integer G = 7                              "Substance index";  
        end Medium7;

    //  ---------------------------------------------------------------------------------------------
    //     New sensor introduced in this application for measurement of substance A 
    //  ---------------------------------------------------------------------------------------------

        package Sensor7
            connector LiquidCon
                Medium7.Concentration c                         "Substance conc";
                flow Real F (unit="m3/s")                       "Flow rate";
            end LiquidCon;

            model SensorX
    //          import d12_app7.Equipment7.LiquidCon;                 // Question 2
                import d12_app7.Medium7.*;                            // Question 1 - alt 1
                constant Integer component = C;                       // Question 1 - alt 1  
    //          constant Integer component = d12_app7.Medium7.A;      // Question 1 - alt 2
                LiquidCon probe;
                RealOutput out;
            equation
                probe.F = 0;
                out = probe.c[component];
            end SensorX;    
        end Sensor7;

    //  ---------------------------------------------------------------------------------------------
    //     Adaptation of library DEMO_v12 to Medium7  
    //  ---------------------------------------------------------------------------------------------

        package Equipment7
            import DEMO_v12.Equipment;
            extends Equipment(redeclare package Medium=Medium7);
        end Equipment7;

    //  ---------------------------------------------------------------------------------------------       
    //     Examples of systems 
    //  ---------------------------------------------------------------------------------------------

        import DEMO_v12.Control;

        model Test
            Equipment7.Medium medium;        // Instance not necessary but helpful for user interface
            Equipment7.PumpType pump;
            Equipment7.FeedtankType feedtank;
            Equipment7.HarvesttankType harvesttank;
            Sensor7.SensorX sensor;                             // Question 1 alt 1 and 2
    //      Sensor7.SensorX sensor(component = medium.A);       // Question 1 alt 3    
            Control.FixValueType Fsp(val=0.2);
        equation
            connect(feedtank.outlet, pump.inlet);
            connect(pump.outlet, harvesttank.inlet);
            connect(Fsp.out, pump.Fsp);
            connect(sensor.probe, harvesttank.port);
        end Test;

    end d12_app7;

And finally the library code DEMO_v12

    package DEMO_v12

    //  ---------------------------------------------------------------------------------------------
    //     Interfaces  
    //  ---------------------------------------------------------------------------------------------

        import Modelica.Blocks.Interfaces.RealInput;
        import Modelica.Blocks.Interfaces.RealOutput;

        package Medium2
            replaceable constant String name = "Two components"    "Medium name";
            replaceable constant Integer nc = 2                    "Number of substances";
            replaceable type Concentration = Real[nc]              "Substance conc";
            replaceable constant Real[nc] mw = {10, 20}            "Substance weight";  
            constant Integer A = 1                                 "Substance index";
            constant Integer B = 2                                 "Substance index";   
        end Medium2;

        package Medium3 
            import M2 = DEMO_v12.Medium2;
            extends M2
                (name="Three components"                           "Medium name",
                 nc=3                                              "Number of substances",
                 mw = cat(1,M2.mw,{30})                            "Substance weight",
                 redeclare type Concentration = Real[nc]           "Substance conc");
            constant Integer C = 3                                 "Substance index";   
        end Medium3;

    //  ---------------------------------------------------------------------------------------------
    //     Equipment dependent on the medium  
    //  ---------------------------------------------------------------------------------------------

        package Equipment
            replaceable package Medium
            end Medium;

            connector LiquidCon
                Medium.Concentration c                             "Substance conc";
                flow Real F (unit="m3/s")                          "Flow rate";
            end LiquidCon;

            model PumpType
                LiquidCon inlet, outlet;                                                     
                RealInput Fsp;
            equation
                inlet.F = Fsp;                                         
                connect(outlet, inlet);                          
            end PumpType;

            model FeedtankType
                LiquidCon outlet;                                  
                constant Integer medium_nc = size(outlet.c,1);
                parameter Real[medium_nc] c_in (each unit="kg/m3") 
                                = {1.0*k for k in 1:medium_nc}     "Feed inlet conc";                        
                parameter Real V_0 (unit="m3") = 100               "Initial feed volume";
                Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
            equation    
                for i in 1:medium_nc loop
                    outlet.c[i] = c_in[i];
                end for;
                der(V) = outlet.F;               
            end FeedtankType;

            model HarvesttankType
                LiquidCon inlet, port;                                   
                constant Integer medium_nc = size(inlet.c,1);
                parameter Real V_0 (unit="m3") = 1.0   "Initial harvest liquid volume";
                parameter Real[medium_nc] m_0 
                      (each unit="kg/m3") = zeros(medium_nc)       "Initial substance mass";
                Real[medium_nc] c                                  "Substance conc";
                Real[medium_nc] m 
                      (start=m_0, each fixed=true)                 "Substance mass";
                Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
            equation
                for i in 1:medium_nc loop
                    der(m[i]) = inlet.c[i]*inlet.F;
                    c[i] = m[i]/V;
                    port.c[i] = c[i];
                end for;
                der(V) = inlet.F;               
            end HarvesttankType;
        end Equipment;

    //  ---------------------------------------------------------------------------------------------   
    //     Control 
    //  ---------------------------------------------------------------------------------------------

        package Control
            block FixValueType
                RealOutput out;
                parameter Real val=0;
            equation
                out = val;
            end FixValueType;
        end Control;

    //  ---------------------------------------------------------------------------------------------
    //     Examples of systems 
    //  ---------------------------------------------------------------------------------------------

    //  package Equipment3 = Equipment(redeclare package Medium=Medium3);   // Just shorter version

        package Equipment3
            import DEMO_v12.Equipment;
            extends Equipment(redeclare package Medium=Medium3);
        end Equipment3;

        model Test
            Equipment3.Medium medium;
            Equipment3.FeedtankType feedtank;
            Equipment3.HarvesttankType harvesttank;
            Equipment3.PumpType pump;
            Control.FixValueType Fsp(val=0.2);
        equation
            connect(feedtank.outlet, pump.inlet);
            connect(pump.outlet, harvesttank.inlet);
            connect(Fsp.out, pump.Fsp);
        end Test;

    end DEMO_v12;

Solution

  • Thank you Adeel! The Dymola error log made me do the following changes to the code:

    1. DEMO_v20 here I eliminated the instantiation of medium - forgot it see 3) above
    2. DEMO_v20 here I now get the size of the models from Medium.nc instead of through the connector and size of c.
    3. D20_app7 here I now in the procedure of adaptation of package Equipment, first import, and then extend and adapt to Medium7.

    The updated code DEMO_v22 and d22_app7 now works with both JModelica and OpenModelica. Would be good to have it tested in Dymola too 🙂

    Updated code DEMO_v22.mo

        package DEMO_v22
    
            // Here I have put together a small demo-library to illustrate questions
            // around structuring handling of medium. The key structures are taken
            // from MSL fluid, I think it is fair to say.
    
        //  ---------------------------------------------------------------------------------------------
        //     Interfaces  
        //  ---------------------------------------------------------------------------------------------
    
            import Modelica.Blocks.Interfaces.RealInput;
            import Modelica.Blocks.Interfaces.RealOutput;
    
            partial package MediumBase
                constant String name                                   "Medium name";
                constant Integer nc                                    "Number of substances";
                replaceable type Concentration = Real[nc]              "Substance conc";        
            end MediumBase;
    
            package Medium2 
                extends MediumBase
                    (name="Two components",
                     nc=2);
                constant Real[nc] mw = {10, 20}                        "Substance weight";  
                constant Integer A = 1                                 "Substance index";
                constant Integer B = 2                                 "Substance index";   
            end Medium2;
    
            package Medium3 
                import M2 = DEMO_v22.Medium2;
                extends M2
                    (name="Three components"                           "Medium name",
                     nc=3                                              "Number of substances",
                     mw = cat(1,M2.mw,{30})                            "Substance weight");
                constant Integer C = 3                                 "Substance index";   
            end Medium3;
    
        //  ---------------------------------------------------------------------------------------------
        //     Equipment dependent on the medium  
        //  ---------------------------------------------------------------------------------------------
    
            package Equipment
                replaceable package Medium = MediumBase 
                    constrainedby MediumBase;
    
                connector LiquidCon
                    Medium.Concentration c                             "Substance conc";
                    flow Real F (unit="m3/s")                          "Flow rate";
                end LiquidCon;
    
                model PumpType
                    LiquidCon inlet, outlet;                                                     
                    RealInput Fsp;
                equation
                    inlet.F = Fsp;                                         
                    connect(outlet, inlet);                          
                end PumpType;
    
                model FeedtankType
                    LiquidCon outlet;                                  
                    parameter Real[Medium.nc] c_in (each unit="kg/m3") 
                                    = {1.0*k for k in 1:Medium.nc}     "Feed inlet conc";                        
                    parameter Real V_0 (unit="m3") = 100               "Initial feed volume";
                    Real V(start=V_0, fixed=true, unit="m3")           "Feed volume";
                equation    
                    for i in 1:Medium.nc loop
                        outlet.c[i] = c_in[i];
                    end for;
                    der(V) = outlet.F;               
                end FeedtankType;
    
                model HarvesttankType
                    LiquidCon inlet, port;
                    parameter Real V_0 (unit="m3") = 1.0   "Initial harvest liquid volume";
                    parameter Real[Medium.nc] m_0 
                          (each unit="kg/m3") = zeros(Medium.nc)       "Initial substance mass";
                    Real[Medium.nc] c                                  "Substance conc";
                    Real[Medium.nc] m 
                          (start=m_0, each fixed=true)                 "Substance mass";
                    Real V(start=V_0, fixed=true, unit="m3")           "Harvest liquid volume";
                equation
                    for i in 1:Medium.nc loop
                        der(m[i]) = inlet.c[i]*inlet.F;
                        c[i] = m[i]/V;
                        port.c[i] = c[i];
                    end for;
                    der(V) = inlet.F;               
                end HarvesttankType;
            end Equipment;
    
        //  ---------------------------------------------------------------------------------------------   
        //     Control 
        //  ---------------------------------------------------------------------------------------------
    
            package Control
                block FixValueType
                    RealOutput out;
                    parameter Real val=0;
                equation
                    out = val;
                end FixValueType;
            end Control;
    
        //  ---------------------------------------------------------------------------------------------
        //     Adaptation of package Equipment to Medium3 
        //  ---------------------------------------------------------------------------------------------
    
            package Equipment3
                extends DEMO_v22.Equipment(redeclare package Medium=Medium3);
            end Equipment3;
    
        //  ---------------------------------------------------------------------------------------------
        //     Examples of systems 
        //  ---------------------------------------------------------------------------------------------
    
            model Test
                package medium = DEMO_v22.Medium3;                     // Not accessible in FMU though
                constant String name = medium.name;                    // But name here is now accessible
                Equipment3.FeedtankType feedtank;
                Equipment3.HarvesttankType harvesttank;
                Equipment3.PumpType pump;
                Control.FixValueType Fsp(val=0.2);
            equation
                connect(feedtank.outlet, pump.inlet);
                connect(pump.outlet, harvesttank.inlet);
                connect(Fsp.out, pump.Fsp);
            end Test;
    
        end DEMO_v22;
    

    and updated application code d22_app7.mo

        encapsulated package d22_app7 
    
            // Here I put together an application for 7 substances - print 8 pt
            // and import code from the library DEMO.
    
        //  ---------------------------------------------------------------------------------------------
        //     Interfaces  
        //  ---------------------------------------------------------------------------------------------
    
            import Modelica.Blocks.Interfaces.RealInput;
            import Modelica.Blocks.Interfaces.RealOutput;
    
            package Medium7
                import M2 = DEMO_v22.Medium2;
                extends M2
                    (name = "Seven components"                            "Medium name", 
                    nc = 7                                                "Number of substances",
                    mw = cat(1,M2.mw,{30,40,50,60,70})                    "Substance weight");
                constant Integer C = 3                                    "Substance index";
                constant Integer D = 4                                    "Substance index";    
                constant Integer E = 5                                    "Substance index";    
                constant Integer F = 6                                    "Substance index";    
                constant Integer G = 7                                    "Substance index";    
            end Medium7;
    
        //  ---------------------------------------------------------------------------------------------
        //     Adaptation of library DEMO_v22 to Medium7 and including a new model SensorX 
        //  ---------------------------------------------------------------------------------------------
    
            package Equipment7
                import DEMO_v22.Equipment;
                extends Equipment(redeclare package Medium=Medium7);
                model SensorX
                    LiquidCon probe;
                    RealOutput out;
                    constant Integer component                            "Component measured";         
                equation
                    probe.F = 0;
                    out = probe.c[component];
                end SensorX;            
            end Equipment7;
    
        //  ---------------------------------------------------------------------------------------------       
        //     Examples of systems 
        //  ---------------------------------------------------------------------------------------------
    
            import DEMO_v22.Control;
    
            model Test
                package medium = Medium7;                                // Not accessible in FMU though
                constant String name = medium.name;                      // But name here is accessible
                Equipment7.PumpType pump;
                Equipment7.FeedtankType feedtank;
                Equipment7.HarvesttankType harvesttank;
                Equipment7.SensorX sensor(component = medium.G);               
                Control.FixValueType Fsp(val=0.2);
            equation
                connect(feedtank.outlet, pump.inlet);
                connect(pump.outlet, harvesttank.inlet);
                connect(Fsp.out, pump.Fsp);
                connect(sensor.probe, harvesttank.port);
            end Test;
    
        end d22_app7;