Message Boards Message Boards

GROUPS:

Can one have custom "operator records" in WSM?

Posted 11 days ago
196 Views
|
7 Replies
|
3 Total Likes
|

Inspired by this answer to my question on stack overflow I was curious about overloading the class operator to have an operator record. From the Modelica specs for Version 3.2.2 (Chapter 14) I take it that operator records are available in the language since 2013.

Can one have a class operator in WSM?

Edit: I edited the title to make my question more precise: I am interested in defining my own operator records.

Update: I have cross-posted this question now on Mathematica Stack Exchange (181939).

7 Replies

Yes, Complex (complex numbers) from the Modelica Standard Library is implemented using operator record. It's used in for example Modelica.ComplexBlocks.Examples.TestConversionBlock.

But that does not answer my question: Can I have my own custom operator record? I cannot find the class operator in the documentation; and afaik operator records are not extensible - I have to build my own for something like the answer I posted above.

UPDATE:

I tried to input the following example (cf. stack overflow above) into WSM 4.3 and will not validate successfully.

Error: Only classes of type 'operator record' may contain elements of type 'operator function'; '==' was found in a class that has restriction 'operator record'.

operator record Time
  Integer s "Second";

  encapsulated operator 'constructor'
    import Time;

    function from_s
      input Integer s "Seconds";
      output Time t(s=s);
    algorithm 
    end from_s;

    function from_d
      input Integer d "Days";
      output Time t(s=d*24*3600);
    algorithm 
    end from_d;
  end 'constructor';

  encapsulated operator 'String' "Convert Time to string"
    import Time;

    function formated
      input Time t;
      input String format = "s" annotation(choices(choice="s" "seconds", choice="d" "days"));
      output String str;

    algorithm 
      if format == "d" then
        str :=String(t.s/24/3600);
      else
        str :=String(t.s);
      end if;
    end formated;
  end 'String';

  encapsulated operator function '==' "Compare time records"
    import Time;
    input Time t1;
    input Time t2;
    output Boolean result "= t1 == t2";
  algorithm 
    result := t1.s == t2.s;
  end '==';

end Time;

Sorry for not being clear enough, but my point was that Complex uses operator records and Complex is just another Modelica library so of course you can have your own operator records.

I don't know what you have tried, but the Time package works as far as I can see in 4.3.

A note about the documentation, it only attempts to cover the usage of the product and not the Modelica language it self. I'm not saying that's a good thing, but it explains why you wont find any information about operator records in the documentation. The best places for documentation regarding the language in product are ModelicaReference (you need to load it first it's part of MSL) or Modelica By Example.

Thank you, Otto, for making this more explicit. Albeit, the System Modeler does not allow to create a class called "operator"? I simply chose another one and edited it in Modelica text mode.

Is there a way to make the operator record that I posted work out in System Modeler? (the error message I got when creating it is quite confusing; shouldn't it work out according to ModelicaReference?)

Best, Guido

PS: Modelica By Example really is excellent and it got me going with WSM much easier than Peter Fritzon who is better once you are beyond "baby steps".

Oh I totally missed that you cannot create them from the new class dialog, I see how that can be confusing.

I don't understand why it doesn't work for you. If I paste in the code you posted (in 4.3) and simulate the following model I get the expected result. I have a hard time believing that this could be a platform issue, but what platform are you on?

model TestTime
  Time d1 = Time(d=1);
  Time d2 = Time(d=2);
equation
  Modelica.Utilities.Streams.print(String(d1, format="s"));
  Modelica.Utilities.Streams.print(String(d2, format="s"));
end TestTime;

I am on Windows 10 Pro (64 Bit) Version 10.0.17134 Build 17134

I tried this again:

package TestingTime "Testing Operator Record"

operator record Time
  Integer s "Second";

  encapsulated operator 'constructor'
    import Time;

    function from_s
      input Integer s "Seconds";
      output Time t(s=s);
    algorithm 
    end from_s;

    function from_d
      input Integer d "Days";
      output Time t(s=d*24*3600);
    algorithm 
    end from_d;
  end 'constructor';

  encapsulated operator 'String' "Convert Time to string"
    import Time;

    function formated
      input Time t;
      input String format = "s" annotation(choices(choice="s" "seconds", choice="d" "days"));
      output String str;

    algorithm 
      if format == "d" then
        str :=String(t.s/24/3600);
      else
        str :=String(t.s);
      end if;
    end formated;
  end 'String';

  encapsulated operator function '==' "Compare time records"
    import Time;
    input Time t1;
    input Time t2;
    output Boolean result "= t1 == t2";
  algorithm 
    result := t1.s == t2.s;
  end '==';

end Time;

model TestTime
  Time d1 = Time(d=1);
  Time d2 = Time(d=2);
equation
  Modelica.Utilities.Streams.print(String(d1, format="s"));
  Modelica.Utilities.Streams.print(String(d2, format="s"));
end TestTime;

//dropping annotations for readability...

end TestingTime;

And validating this package leads to:

Error: Error occurred while flattening model TestingTime.TestTime

Error: [<interactive>:0:0-0:0] Only classes of type 'operator record' may contain elements of type 'operator function'; '==' was found in a class that has restriction 'operator record'.

Error: [<interactive>:41:5-41:18] Class Time not found in scope TestingTime.Time.'=='.

Error: [<interactive>:26:7-26:19] Class Time not found in scope TestingTime.Time.'String'.formated.

Error: [<interactive>:17:7-17:33] Class Time not found in scope TestingTime.Time.'constructor'.from_d.

Error: [<interactive>:11:7-11:25] Class Time not found in scope TestingTime.Time.'constructor'.from_s.

Error: Error occurred while flattening model TestingTime.Time

Error: [<interactive>:0:0-0:0] Only classes of type 'operator record' may contain elements of type 'operator function'; '==' was found in a class that has restriction 'operator record'.

Error: [<interactive>:41:5-41:18] Class Time not found in scope TestingTime.Time.'=='.

Error: [<interactive>:26:7-26:19] Class Time not found in scope TestingTime.Time.'String'.formated.

Error: [<interactive>:17:7-17:33] Class Time not found in scope TestingTime.Time.'constructor'.from_d.

Error: [<interactive>:11:7-11:25] Class Time not found in scope TestingTime.Time.'constructor'.from_s.

Check failed for model: TestingTime.Time.

Check failed for model: TestingTime.TestTime.

Validation of package TestingTime completed with errors.

The error message is bit misleading, the actual error is

Error: [<interactive>:41:5-41:18] Class Time not found in scope TestingTime.Time.'=='.

The other one is just a weird error that follows from proceeding without knowing what class Time is.

I belive this is correct behaviour, the example uses encapsulated which basically means stop normal lookup rules and look everything up in the global scope. Now when you put Time in a package TestingTime there is no Time in the global scope. You would have to change all import Time to import TestingTime.Time and then the example works.

I pasted in your original code and there Time is a top-level name that's why it worked for me.

I hope that explains it.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract