[Modelica]operator, operator function, operator recordクラスのサンプル

# はじめに
本記事は[Modelicaのチートシート](https://qiita.com/UedaShigenori/items/6430b8d2e42882b82631)のoperator, operator function, operator recordクラスの解説記事になります。

# Modelica言語のoperator, operator function, operator recordクラス

Modelica言語では、operator, operator function, operator recordクラスを使用すれば、"+"や"-"などの基本的なオペレータに対してユーザーが定義した演算を実行させる事が出来ます。また、独自のオペレータを使用し、型に応じて自動的に処理を切り替えることが出来るようになります。
C++でいう多重定義やオーバーロードという機能だと思います。
自分で定義した処理を実行させたいだけならfunctionクラスを使用すれば良い、と思いますがfunctionだと入力と出力が定義された因果的なモデルしか作成できません。
オーバーロードを使用することでModelicaの非因果モデリングの恩恵を受けることが出来ます。

## operator, operator function, operator recordクラスの意味

operator functionは独自定義したいオペレータの宣言と内部の処理を定義します。

operator recordは処理を行う対象となる型を定義します。

operatorはオペレータの宣言と、そのオペレータに対する引数の型違いのoperator functionをpackageのようにまとめる機能です。ポリモーフィズムという機能だと思います。本記事内の使用例では使用しませんでした。時間があるときにサンプルを追加します。

## 使用例：時間の分と秒の計算

### 作業環境  

Windows10

OpenModelica1.14.1

### 前提
ここでは、operator record, operator functionクラスを使って時間の分(minute)と秒(second)の和をModelicaで実行出来るようにしてみましょう。
operatorクラスは使用しません。



以下が実装の仕様らしきものです。

* minuteとsecondの二つの変数を持つ型(operator record)を用意する

* secondの和の結果、secondが60秒以上となる毎にminuteが1だけ繰り上がる

処理としては60進法の計算を実装することとなります。



以下のような簡単な計算が出来るようになれば嬉しいです。

* 例1.  分と秒の和
  ```1分10秒 + 3分40秒 = ?```
  答え：4分50秒
  
* 例2.  繰り上がり有り
  ```1分40秒 + 3分40秒 = ?```
  答え：5分20秒

* 例3. 非因果計算
  ```? + 3分10秒 = 4分20秒```
  答え：1分10秒
  

特に例3はModelicaっぽい非因果な方程式であり、オーバーロードを使わずにfunctionクラスだけを使用しても計算は出来無いかも知れません。
(functionクラス内の未知数が連立方程式を解かないで導出出来るなら解けるかも知れません)



### 実装

まずは「minuteとsecondの二つの変数を持つ型(operator record)を用意する」を実装してみましょう。

```Time.mo
operator record Time
  Real minute;
  Real second;
end Time;
```



次に、minuteとsecondでそれぞれ足され、secondが60以上の時はminuteに1繰り上がるように"+"オペレータを定義しましょう。
"+"オペレータの定義をoperator functionを使って上記のTime.mo内に書き込みます。

```Time.mo
operator record Time
  Real minute;
  Real second;
  
  //"+"オペレータの定義
  operator function '+'  //+や-などのオペレータはシングルクオテーションマークで囲むこと
  　import Time;
  　input Time c1;
  　input Time c2;
  　output Time c3;
　algorithm
  　c3 := Time(c1.minute + c2.minute+div(c1.second + c2.second,60), mod(c1.second + c2.second,60));
　end '+';

end Time;
```

ここでポイントは以下の行です。

```
c3 := Time(c1.minute + c2.minute+div(c1.second + c2.second,60), mod(c1.second + c2.second,60));
```

Time型の和を上記のように定義しています。

divオペレータは、div(変数x, 変数y)のときx÷yの整数部だけを返します。

modオペレータは、mod(変数x, 変数y)のときx÷yの剰余だけを返します。

あとは実際に上記の演算を行うサンプルを作成しましょう。



### 例1. 分と秒の和

以下の計算を実施してみましょう。

```1分10秒 + 3分40秒 = ?```

答え：4分50秒

サンプルコード

```Example1.mo
model Example1
  import Time;
  Time a;
  Time b;
  Time c;
  
equation
  //1分10秒を定義
  a.minute = 1;
  a.second = 10.0;

  //3分40秒を定義
  b.minute = 3;
  b.second = 40.0;

  //1分10秒 + 3分40秒 = ?
  a + b = c;

end Example1;
```

結果
OpenModelicaの結果表示です。
minitueに4, secondに50が入っていることが分かります。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244254/ce7c50dc-91fb-27fd-8f2a-9c0a31845326.png)


### 例2. 繰り上がり有り

以下の計算を実施してみましょう。

```1分40秒 + 3分40秒 = ?```

答え：5分20秒

サンプルコード

```Example2.mo
model Example2
  import Time;
  Time a;
  Time b;
  Time c;
  
equation
  a.minute = 1;
  a.second = 40.0;
  b.minute = 3;
  b.second = 40.0;
  a + b = c;

end Example2;
```

結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244254/27ca937a-c14f-4c2b-3f36-b7d1552842c1.png)


### 例3. 非因果計算

以下の計算を実施してみましょう。

```? + 3分10秒 = 4分20秒```

答え：1分10秒



サンプルコード


```Example3.mo
model Example3
  import Time;
  Time a;
  Time b;
  Time c;
  
equation
  b.minute = 3;
  b.second = 10.0;
  c.minute = 4;
  c.second = 20.0;
  a + b = c;
  
end Example3;
```

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244254/30381270-729e-2a77-ab29-78fd69af13ba.png)

### 感想
オーバーロードの実装方法の確認のため使用例を作成したため、-や×は定義しておらず時間の計算としては不完全です。
またあまりメリットが分かりづらいかも知れません。
マイナーな機能についてとりあえず実装方法を確認した程度にご理解頂ければと思います。  

# まとめ

operator function, operator recordクラスの使い方を、簡単な例題を通して確認してみました。
オーバーロードを使用することで簡単に独自の型に対して非因果計算が実行出来ました。
上手く定義すればOpenFOAMのように偏微分方程式の数値計算にも使えるかも知れません。


# Reference

* Modelica Specification 3.4

https://modelica.org/documents/ModelicaSpec34.pdf