1

I work with understanding how parametrized packages in a library can be adapted to external application code, i.e. I like to keep library code and application code very separate.

In my example here I have two parameters of my package Equipment, a connector LCon and also a model CType. The connector affect all models in the Equipment package. The model CType only affects one model RType in the Equipment (and have a closer inner-outer relation) to that model.

When I adapt the package Equipment to the application requirement of LCon2 and CTyp2 I can do that in one sweep as below.

   code1

   package Equipment2
          import BR5i.Equipment;
          extends Equipment(redeclare connector LCon=LCon2,
                      redeclare model CType=CType2);
   end Equipment2;    

However, I think the code (in the long run) is more readable if I divide these two adaptations to two different parts. I try the code below, but does not work. Error text: Cannot find class declaration for RType - when I run it in JModelica.

   code2

   package Equipment2
       import BR5i.Equipment;
       extends Equipment(redeclare connector LCon=LCon2);
   end Equipment2;

   model BRType2        
       import BR5i.Equipment2.RType;
       extends RType(redeclare model CType=CType2);
   end BRType2;

(And for code 2 the library was modified so the parameter CType was moved Equipment level down to the individual model RType where CType should serve as a parameter. And in the end I want BRType2 for code 2 correspond to Equipment2.RType from code 1).

I wonder if it is at all possible to make changes in several steps like this, i.e. first RType get a new connector LCon2 and then in the next step RType now imported from Equipment2 shall get CType replaced to CType2?

I understand that the code should not be seen as a sequence of "assignment statements", but rather parallel. In my eyes the logic of the "equations" in code 2 should make it possible to get a correct BRType2.

janpeter
  • 681
  • 8
  • 22

5 Answers5

2

Your "code2" would result in BRType2 not having CType modified. A redeclare does not mean "change package A to look like this", but rather "this should be like package A, but with these changes". So to get the result you want, you should do something like:

package Equipment2
    import BR5i.Equipment;
    extends Equipment(redeclare connector LCon=LCon2);
end Equipment2;

model BRType2
    // Equipment2 has the change in LCon, so extend RType from there instead
    import Equipment2.RType;
    extends RType(redeclare model CType=CType2);
end BRType2;

Also note that this approach will not give the expected results if Equipment contains any instances of or other references to Rtype, as they would refer to the unchanged RType, not to BRType2.

Why you get the error about not finding RType, I can't say. It could plausibly be a bug, but I'd first check to see if you have written the path to it correctly.

  • Yes, I was blind to my typo error and should of course in code 2 be import Equipment2.Rtype in order to change CType for the adapted RType with LCon2. Actually I had the same typo in my "real" code, but is till does not work in JModelica. Error is: "Cannot find class declaration for RType". There is no instances or other references to RType in Equipment, what I understand. – janpeter Mar 28 '19 at 14:53
  • Also error "Cannot find class declaration for CType" and then errors of the same kind related to the LCon2. I suspect some very basic error... – janpeter Mar 28 '19 at 15:02
  • I just tested the original code (with your correction) in OpenModelica 1.13.2 and does work there, so seems to be a JModelica problem. – janpeter Mar 28 '19 at 15:55
  • What lines are the errors reported on, the imports or the extends? Also, could you make a self-contained example that shows the problem? – Jesper Mattsson Mar 29 '19 at 11:33
  • The error list starts with the extends in model BRType2. I have a self-contained example but the code is too long to publish here. Need to think about it. – janpeter Mar 29 '19 at 12:07
1

On request I here supply a small self-contained example, about 150 lines. I decided to re-use my toy-example used in a couple of other posts recently and now add on what is needed to exemplify the problem discussed here. It means I use different names of things compared to what is written above, but the structure of the problem is exactly the same.

The toy-example describe pumping of a medium from one vessel to another and is made general so that we can easily change medium and the equipment of pumps and tanks are automatically updated. Originally the medium contain two substances. With a separate short application code we define a medium with more components and update the package Equipment by redeclaring the connector LiquidCon and then system setup is simply re-used.

Now I add on an inner model to the harvest that describe some reaction between the substances. Originally we have a reaction model NoReaction that leave the substances in the harvest tank without any reaction. Another reaction model is Reaction 3 that shows degradation of substance 3.

The problem I want to highlight is that if we first adapt the equipment with a connector for say three substances. And then in a second round change the reaction model of the adapted equipment3 to a reaction model Reaction3, then JModelica compiler gives error message, while OpenModelica does not and produce simulation resultat that are ok. This is marked Alternative 2 in the code.

Alternative 1. On other hand if the two very different re-declrations are done at the same time, i.e. both changed connector LiquidCon and model ReactionType then it works in both JModelica and OpenModelica.

Below self-contained code and the example Test now is Alternative 2 and generates error in JModelica 2.4 but works in OpenModelica. Not clear to me what to expect from the Modelica def itself.

    package DEMO_v14

        // 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.

        // Author: Jan Peter Axelsson

    //  ---------------------------------------------------------------------------------------------
    //     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_v14.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;

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

        model Reaction3
            constant Integer nc = 3;
            outer Real[nc] c;
            outer Real[nc] q;           
        equation
            q[1] = 0;
            q[2] = 0;
            q[3] =-c[3];
        end Reaction3;      

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

        package Equipment
            replaceable connector LiquidCon
            end LiquidCon;

    //      replaceable model ReactionType                         // Alternative 1
    //      end ReactionType;

            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
                // Connection to reaction
                replaceable model ReactionType                     // Alternative 2 
                end ReactionType;

                ReactionType reaction;
                inner Real[medium_nc] c                            "Substance conc";
                inner Real[medium_nc] q                            "Reaction rate";     

                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] 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 + q[i];
                    c[i] = m[i]/V;
                    port.c[i] = c[i];
                end for;
                der(V) = inlet.F;               
            end HarvesttankType;

            model NoReaction
                constant Integer nc = Medium.nc;
                outer Real[nc] c;
                outer Real[nc] q;           
            equation
                for i in 1:nc loop
                    q[i] = 0;
                end for;
            end NoReaction;     

        end Equipment;

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

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

    //  ---------------------------------------------------------------------------------------------
    //  Adaptation of library for the actual culture and media
    //  ---------------------------------------------------------------------------------------------

    //  package Equipment3                                                     // Alternative  1
    //      import DEMO_v14.Equipment;
    //      extends Equipment(redeclare connector LiquidCon=LiquidCon3,
    //                        redeclare model ReactionType=Reaction3);
    //  end Equipment3;

        package Equipment3                                                     // Alternative 2
            import DEMO_v14.Equipment;
            extends Equipment(redeclare connector LiquidCon=LiquidCon3);
        end Equipment3;

        model HarvesttankType3
            import DEMO_v14.Equipment3.HarvesttankType;
            extends HarvesttankType(redeclare model ReactionType=Reaction3);
        end HarvesttankType3;

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

        model Test
            Medium3 medium;
            Equipment3.FeedtankType feedtank;
    //      Equipment3.HarvesttankType harvesttank;                            // Alternative 1 
            HarvesttankType3 harvesttank;                                      // Alternative 2
            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_v14;
janpeter
  • 681
  • 8
  • 22
1

I have not had time to analyze your problem in Detail, but I would like to point out here that if some code is accepted in one tool, but not accepted in the other, it does not necessarily mean the bug is in the tool that does not accept the code. Modelica semantics got quite a bit stricter over time to make Modelica safer to use, and easier to be portable across tools. Since the OpenModelica kernel is one of the oldest ones around, it is known to accept a lot of code that is actually not (anymore in many cases) legal Modelica in the latest versions.

Sorry, I don't have the time to analyze this in depth from the Modelica semantics legality point of view. I am in any case convinced that you can achieve what you want to achieve with certainly legal Modelica. Two remarks on modeling practices: It is unsafe, and should be avoided, to have an empty class (connector in your case) as a replaceable class since it can be replaced with anything, which is inherently unsafe. I also think that you can achieve what you want to achieve with a variable length vector in the connector, the connector itself does not need to be replaceable.

All the best, /Hubertus

Hubertus
  • 187
  • 3
0

I buy the idea that to make a library package parametrized in a safe way you make the flexibility as “small” as you can. You can in the package have a constant integer nc that you give the number Medium3.nc at the time when you adapt the package. And then the connector LiquidCon is defined inside the package Equipment and have a declaration of concentration vector as Real [nc] c; Other information about the Medium than nc can be brought to the application Test on configuration level rather than as adaptation of the package Equipment, and not discussed in this example but in other related posts. In this way the package adaptation process would be as “safe” as you can.

The other adaptation that involves introducing a ReactionType to HarvesttankType (that is now adapted to the actual nc) needs to be very flexible for this library package to be of any interest. What we require from the ReactionType is to have the interface: outer Real(nc] c, q; and that we can describe in a partial model and use the constrainedby construction, to bring some safety.

See code DEMO_v17_alt1 and d17_alt1_app7 below.

However, I would prefer to write the code as alt2 and keep ReactionType etc defined for HarvesttankType only and not for the whole Equipment package. That would need to allow for a two-step procedure of adaptation of the library. First level adapt the Equipment to the number of medium components. Second level adapt the now adapted HarvesttankType to the ReactionType. This is not possible in JModelica, but actually in OpenModelica.

So only alt1 works in JModelica 2.4 while both alt1 and alt2 works in OpenModelica 1.13.2 (and 1.14 beta). What does the current Modelica definition say?

The library code DEMO_v17_alt1:

    package DEMO_v17_alt1

        // 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;

        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_v17_alt1.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;

        model Reaction3
            constant Integer nc = 3;
            outer Real[nc] c;
            outer Real[nc] q;           
        equation
            q[1] = 0;
            q[2] = 0;
            q[3] =-c[3];
        end Reaction3;      

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

        package Equipment

            constant Integer nc;

            connector LiquidCon
                Real[nc] c                                         "Substance conc";
                flow Real F (unit="m3/s")                          "Flow rate";
            end LiquidCon;              

            replaceable model ReactionType = NoReaction            // Alternative 1
                constrainedby ReactionTypeInterface;               

            partial model ReactionTypeInterface                    // Alternative 1
                outer Real[nc] c, q;
            end ReactionTypeInterface;

            model NoReaction                                       // Alternative 1
                extends ReactionTypeInterface;          
            equation
                for i in 1:nc loop
                    q[i] = 0;
                end for;
            end NoReaction;             

            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
                // Connection to reaction
                // replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface;   // Alternative 2

                ReactionType reaction;
                inner Real[medium_nc] c                            "Substance conc";
                inner Real[medium_nc] q                            "Reaction rate";     

                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] 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 + q[i];
                    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 library DEMO_v17_alt1 to Medium3 and Reaction3
    //  ---------------------------------------------------------------------------------------------

        package Equipment3                                         // Alternative 1
            import DEMO_v17_alt1.Equipment;
            extends Equipment(nc=Medium3.nc,
                              redeclare model ReactionType=Reaction3);
        end Equipment3;

    //  package Equipment3                                         // Alternative 2
    //      import DEMO_v17_alt2.Equipment;
    //      extends Equipment(nc=3);
    //  end Equipment3;

    //  model HarvesttankType3
    //      import DEMO_v17_alt2.Equipment3.HarvesttankType;
    //      extends HarvesttankType(redeclare model ReactionType=Reaction3);
    //  end HarvesttankType3;

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

        model Test
            Medium3 medium;
            Equipment3.FeedtankType feedtank;
            Equipment3.HarvesttankType harvesttank;                // Alternative 1 
    //      HarvesttankType3 harvesttank;                          // Alternative 2
            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_v17_alt1;

and the application code d17_alt1_app7

    encapsulated package d17_alt1_app7 


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

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

        package Medium7
            import M2 = DEMO_v17_alt1.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;

        model Reaction7
            constant Integer nc = 7;
            outer Real[nc] c;
            outer Real[nc] q;           
        equation
            q[1] = 0;
            q[2] = 0;
            q[3] = 0;
            q[4] = 0;       
            q[5] = 0;               
            q[6] = 0;       
            q[7] =-c[7];
        end Reaction7;  

    //  ---------------------------------------------------------------------------------------------
    //     Adaptation of library DEMO_v17_alt1 to Medium7 and Reaction7  
    //  ---------------------------------------------------------------------------------------------

        package Equipment7
            import DEMO_v17_alt1.Equipment;
            extends Equipment(nc=Medium7.nc,
                              redeclare model ReactionType=Reaction7);
        end Equipment7;

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

        import DEMO_v17_alt1.Control;

        model Test
            Medium7 medium;                 // Instance not necessary but helpful for user interface
            Equipment7.PumpType pump;
            Equipment7.FeedtankType feedtank;
            Equipment7.HarvesttankType harvesttank;
            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 d17_alt1_app7;
janpeter
  • 681
  • 8
  • 22
0

I have recently got some help on the subject from both people related to Modelon and to OpenModelica and I am grateful for that. Below updated files of the library and the application. The presented code does work in JModelica and OpenModelica and now also in Dymola.

A couple of comments to the code errors that are corrected.

  1. In the model Test I have the habit to make an instance of the Medium of interest. It is actually not allowed (and not very meaningful either) to make an instance of a package like this in Modelica, although current versions of JModelica and OpenModelica support it. The reason I do this instance of the package Medium is two-fold:

    1. I need generally in Test (but not in this example) have access to information in the medium package to make the configuration. For example if I connect a sensor to the harvest tank and that sensor is of gernal type then I need to specify what substance I want to measure and that is best done using the mnemonics for substance position in the state vector store in the package medium. I can of course import the mnemonics I need for the configuration, one by one, but shorter and even more readable to just use the medium package.

    2. From the FMU it is good to be able to access the information in the medium package. This package may contain not only mnemonics but also various facts about the medium that we want to make use of when designing a tailer-made user interface for the FMU and interactive simulation. This is what I do in Python using JModelica. This works actually fine as it is now with JModelica and PyFMI but what I have learned is forbidden in Modelica.

  2. In several places I transmit the number of components in the medium nc to the different equipment models. And I do this transmission of nc somewhat in-directly using the connector and “measure" the size of the vector. This is not OK to do like this in Modelica at compilation time.Also this works in both JModelica and OpenModelica currently, but not in Dymola. I resolve this by introducing a local constant in the general package Equipment that is unspecified, but given the appropriate number later when the package is adapted to the medium that should be used. Then it get the value medium.nc

These modification make the code more generally accepted I hope, and at least works for JModelica, OpenModelica and Dymola. However, I am not too happy with the solutions since it do not address the my uderlying user-requirements as described above.

Also, with this “solution”, the “alternative 2” - adaptation of the library in two (or more steps) is not relevant - which after all was the key question in the post. I will try to re-formulate this question with a smaller example in a new post later on.

Below the library DEMO_v18_alt1 and then after that the application d18_alt1_app7

    package DEMO_v18_alt1

        // 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;

        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_v18_alt1.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;

        model Reaction3
            constant Integer nc = 3;
            outer Real[nc] c;
            outer Real[nc] q;           
        equation
            q[1] = 0;
            q[2] = 0;
            q[3] =-c[3];
        end Reaction3;      

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

        package Equipment

            constant Integer nc;

            connector LiquidCon
                Real[nc] c                                         "Substance conc";
                flow Real F (unit="m3/s")                          "Flow rate";
            end LiquidCon;              

            replaceable model ReactionType = NoReaction            // Alternative 1
                constrainedby ReactionTypeInterface;               

            partial model ReactionTypeInterface                    // Alternative 1
                outer Real[nc] c, q;
            end ReactionTypeInterface;

            model NoReaction                                       // Alternative 1
                extends ReactionTypeInterface;          
            equation
                for i in 1:nc loop
                    q[i] = 0;
                end for;
            end NoReaction;             

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

            model FeedtankType
                LiquidCon outlet;                                  
                parameter Real[nc] c_in (each unit="kg/m3") 
                                = {1.0*k for k in 1: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:nc loop
                    outlet.c[i] = c_in[i];
                end for;
                der(V) = outlet.F;               
            end FeedtankType;

            model HarvesttankType
                // Connection to reaction
                // replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface;   // Alternative 2

                ReactionType reaction;
                inner Real[nc] c                            "Substance conc";
                inner Real[nc] q                            "Reaction rate";        

                LiquidCon inlet, port;                                   
                parameter Real V_0 (unit="m3") = 1.0   "Initial harvest liquid volume";
                parameter Real[nc] m_0 
                      (each unit="kg/m3") = zeros(nc)       "Initial substance mass";
                Real[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:nc loop
                    der(m[i]) = inlet.c[i]*inlet.F + q[i];
                    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 library for the actual culture and media
    //  ---------------------------------------------------------------------------------------------

        package Equipment3                                         // Alternative 1
            import DEMO_v18_alt1.Equipment;
            extends Equipment(nc=Medium3.nc,
                              redeclare model ReactionType=Reaction3);
        end Equipment3;

    //  package Equipment3                                         // Alternative 2
    //      import DEMO_v18_alt2.Equipment;
    //      extends Equipment(nc=Medium3.nc);
    //  end Equipment3;

    //  model HarvesttankType3
    //      import DEMO_v18_alt2.Equipment3.HarvesttankType;
    //      extends HarvesttankType(redeclare model ReactionType=Reaction3);
    //  end HarvesttankType3;

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

        model Test
            package medium = DEMO_v18_alt1.Medium3;                // Not accessible in FMU though
            Equipment3.FeedtankType feedtank;
            Equipment3.HarvesttankType harvesttank;                // Alternative 1 
    //      HarvesttankType3 harvesttank;                          // Alternative 2
            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_v18_alt1;

and here the application code

    encapsulated package d18_alt1_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_v18_alt1.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;

        model Reaction7
            constant Integer nc = 7;
            outer Real[nc] c;
            outer Real[nc] q;           
        equation
            q[1] = 0;
            q[2] = 0;
            q[3] = 0;
            q[4] = 0;       
            q[5] = 0;               
            q[6] = 0;       
            q[7] =-c[7];
        end Reaction7;  

    //  ---------------------------------------------------------------------------------------------
    //     Adaptation of library DEMO_v18_alt1 to Medium7 and Reaction7  
    //  ---------------------------------------------------------------------------------------------

        package Equipment7
            import DEMO_v18_alt1.Equipment;
            extends Equipment(nc=Medium7.nc,
                              redeclare model ReactionType=Reaction7);
        end Equipment7;

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

        import DEMO_v18_alt1.Control;

        model Test
            package medium = d18_alt1_app7.Medium7;                // Not accessible in FMU though
            Equipment7.PumpType pump;
            Equipment7.FeedtankType feedtank;
            Equipment7.HarvesttankType harvesttank;
            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 d18_alt1_app7;
janpeter
  • 681
  • 8
  • 22