1

I try to make a parametrised library. I works fine using packages and connectors as parameters.

Using a model as a parameter is also possible. However, if the model is used in the library to build new models using extend, then it is not allowed, what I understand.

I wonder if the library contains a model with inner/outer style of connector, is it then allowed to let the inner model to be a parameter of the library?

Below a simple example to illustrate the problem. TEST is the library and Fish3b is an application. When I run the Example in the library TEST it all works, but when I have a separate application file it does not.

The error text is: cannot find class declaration for AquariumType running JModelica 2.4

package TEST

   model FishType1
       outer Real T;
       Real health;
   equation
       health = 30-T;
   end FishType1;

   model FishType2
       outer Real T;
       Real health;
   equation
       health = 32-T;
   end FishType2;

   package Equipment
       model AquariumType
           replaceable model FishType
           end FishType;       
           FishType fish;
           inner Real T;
       equation
          T = 29;
       end AquariumType;
   end Equipment;

   // Adapt AquariumType model to actual fish
   model Aquarium
       import TEST.Equipment.AquariumType;
       extends AquariumType(redeclare model FishType=FishType2);
   end Aquarium;

   // Example
   model Example
       Aquarium aquarium;
   end Example;

end TEST;

And below an example of application code that import from library above - and here is some error I think.

   encapsulated package Fish3b

       model FishType3
           outer Real T;
           Real health;
       equation
           health = 34-T;
       end FishType3;

       // Adapt package Equipment with AquariumType model to actual fish
       package Equipment3 
           import TEST.Equipment;
           extends Equipment.AquariumType(redeclare model   FishType=FishType3);
       end Equipment3;

       // Example
       model Example
           import Fish3b.Equipment3;
           Equipment3.AquariumType aquarium;
       end Example;

   end Fish3b;
janpeter
  • 681
  • 8
  • 22
  • This is not an [SSCCE][1] since the namespace `Library` in the application code cannot be resolved. [1]: http://sscce.org/ – tbeu Mar 13 '19 at 06:54
  • Sorry, there was a late change of the term "library" to "equipment" in the code when I posted it. I want to use the word library more generally in the post, so the library-file is the TEST and the package Equipment is the part in the library I want parametrise using the model FishType. And the corrected code do have the problem said I the the text. – janpeter Mar 13 '19 at 07:05
  • 1
    The Modelica class of Fish3b.Equipment3 (package) and its base class TEST.Equipment.AquariumType (model) are not compatible, since a package must not extend from a model. – tbeu Mar 13 '19 at 07:08

3 Answers3

2

Thanks “tbeu” for the comment!

I have modified the code so that package Equipment is not extended from a model. The updated code below also represent my underlying “true” problem much better. And it all works. Thanks!

The updated library file TEST2.mo:

   package TEST2

       model FishType1
           outer Real T;
           Real health;
       equation
           health = 30-T;
       end FishType1;

       model FishType2
           outer Real T;
           Real health;
       equation
           health = 32-T;
       end FishType2;

       package Equipment
           replaceable model FishType
           end FishType;

           constant Integer dummy = 1;

           model AquariumType
               FishType fish;
               inner Real T;
           equation
               T = 29;
           end AquariumType;
       end Equipment;

       // Adapt package Equipment to the actual fish
       package Equipment1
           import TEST2.Equipment;
           extends Equipment(redeclare model FishType=FishType1);
       end Equipment1;

       // Example
       model Example
           Equipment1.AquariumType aquarium;
       end Example;

    end TEST2;

And the application code T2_Fish3 that now uses the above library TEST2:

   encapsulated package T2_Fish3

       model FishType3
           outer Real T;
           Real health;
       equation
           health = 34-T;
       end FishType3;

       // Adapt package Equipment to the actual fish
       package Equipment3
           import TEST2.Equipment;
           extends Equipment(redeclare model FishType=FishType3);
       end Equipment3;

       // Example
       model Example
           Equipment3.AquariumType aquarium;
       end Example;

   end T2_Fish3;
janpeter
  • 681
  • 8
  • 22
1

The answer from janpeter works.

Another alternative that avoids introducing models called "FishType1", "FishType3" etc is to use "redeclare model extends" as follows (the Test2 can be unchanged or same change for Equipment1), but it uses more advanced constructs.

encapsulated package T2_Fish3

       // Adapt package Equipment to the actual fish
       package Equipment3
           import TEST2.Equipment;
           extends Equipment;

           redeclare model extends FishType
            outer Real T;
            Real health;
           equation 
             health = 32-T;
           end FishType;
       end Equipment3;

       // Example
       model Example
           Equipment3.AquariumType aquarium;
       end Example;

end T2_Fish3;

Additionally it would be possible to move the common "outer Real T" to the base-model FishType leading to:

package TEST2

    package Equipment
        replaceable model FishType
          outer Real T;
        end FishType;

        constant Integer dummy = 1;

        model AquariumType
            FishType fish;
            inner Real T;
        equation 
            T = 29;
        end AquariumType;
    end Equipment;

    // Adapt package Equipment to the actual fish
    package Equipment1
      import TEST2.Equipment;

      extends Equipment;
      redeclare model extends FishType
        Real health;
      equation 
        health = 30 - T;
      end FishType;
    end Equipment1;

    // Example
    model Example
        Equipment1.AquariumType aquarium;
    end Example;

end TEST2;

and

encapsulated package T2_Fish3

       // Adapt package Equipment to the actual fish
       package Equipment3
           import TEST2.Equipment;
           extends Equipment;

           redeclare model extends FishType
            Real health;
           equation 
             health = 32-T;
           end FishType;
       end Equipment3;

       // Example
       model Example
           Equipment3.AquariumType aquarium;
       end Example;

end T2_Fish3;
Hans Olsson
  • 11,123
  • 15
  • 38
  • It is always good to see alternative solutions! Interesting that we can "redeclare model extend” and avoid updating the name of the actual model. I think it will be very useful. I think in your package TEST2 I think you should have partial model FishType for your base model and not replaceable, right? Also in your application code T2_Fish3 you declare “outer Real T” not needed since declared in the partial base model. But perhaps good to have for readability. – janpeter Mar 14 '19 at 10:31
  • Yes, the FishType should be both replaceable and partial. I agree that it is possible to miss inherited declarations, but I normally think that it is still not good practice to repeat the declarations. – Hans Olsson Mar 14 '19 at 10:56
  • I thought that extend from a replaceable model is more or less forbidden!? Have got that comment recently from OpenModelica community. In their new OM compiler 2.0-beta test you get that kind of errors but not in current 1.13 or 1.14 and JModelica has little problem and gives no errors or warnings and simulations seems ok. The Modelica def 6.2.1 is also not that clear to me. Fritzons write about in section 4.15 in his book 2nd ed 2015. – janpeter Mar 14 '19 at 11:47
  • It's legal in this case. The idea of forbidding extend from a not-yet-known model is to avoid the new base-model elements breaking things. That does not occur in this case since the base-model is known. For more information see section 7.3.1. – Hans Olsson Mar 14 '19 at 17:57
  • Understand you have a “nice” application code writing that do a redeclaration of FishType that do extend from the known FishType and is “safe”. In your example replaceable could be just exchange to partial and redeclare omitted…., I even tried it in JModelica (too forgiving?), may not pass Dymola compiler? I try to figure out a case in this example where it "pays off” to have the base class replaceable as you have, but cannot see that easily? I understand 7.3.1 is an important exception to 6.2.1 and mentioned on the last line. Looks as “rules” to ensure correctness on a “higher" level. – janpeter Mar 15 '19 at 10:23
0

Updated the code with input from Hans Olsson before, but slightly different with the corrections suggested above. And I manage to avoid “extend from a replaceable model”, but I am not too sure how critical that is, see my previous comment.

Also, I think I would like to keep the clear identity of the different fishes, and also declare them outside package Equipment.

    package TEST3

        partial model FishBase
            outer Real T;
        end FishBase;

        model FishType1
            extends FishBase;
            Real health;
        equation
            health = 30 - T;
        end FishType1;

        model FishType2
            extends FishBase;
            Real health;
        equation
            health = 32 - T;
        end FishType2;  

        package Equipment
            replaceable model FishType
            end FishType;

            constant Integer dummy = 1;

            model AquariumType
                FishType fish;
                inner Real T;
            equation
                T = 29;
            end AquariumType;
        end Equipment;

        // Adapt package Equipment to the actual fish
        package Equipment3
            import TEST3.Equipment;
            extends Equipment;
            redeclare model FishType=FishType2;
        end Equipment3;

        // Example
        model Example
            Equipment3.AquariumType aquarium;
        end Example;

    end TEST3;

And an example of application code:

    encapsulated package T3_Fish3

        model FishType3
            import TEST3.FishBase;
            extends FishBase;
            Real health;
        equation
            health = 34-T;
        end FishType3;

        // Adapt package Equipment to the actual fish
        package Equipment3
            import TEST3.Equipment;
            extends Equipment(redeclare model FishType=FishType3);
        end Equipment3;

        // Example
        model Example
            Equipment3.AquariumType aquarium;
        end Example;

    end T3_Fish3;
janpeter
  • 681
  • 8
  • 22