2012-06-13 152 views
3

剛開始使用Modelica並無法理解其工作原理。Modelica執行順序

在模型的下面'方法'中,第二行使用qInflow和qOutflow來評估der(h),但他們還沒有收到數值! (他們沒有在方法的'數據'中定義)?代碼執行的順序是什麼。

equation 
assert(minV >= 0, "minV must be greater or equal to zero"); 
der(h)=(qInflow - qOutflow)/area; 
qInflow=if time > 150 then 3*flowLevel else flowLevel; 
qOutflow=Functions.LimitValue(minV, maxV, -flowGain*outCtr); 
error=ref - h; 
der(x)=error/T; 
outCtr=K*(error + x); 
end FlatTank;  

http://www.mathcore.com/resources/documents/ie_tank_system.pdf

回答

5

當來自使用命令式語義的語言和系統時,這是一個可以理解的混亂點。但是Modelica不能這樣工作。

使用Modelica時,重要的是要明白equation部分包含方程式,而不是分配。考慮這一點,如果我給你以下方程

x + y = 3; 
x + 2*y = 5; 

如果你明白這是一個數學問題,你就可以判斷x必須爲1和y的值必須爲2的值換句話說,你必須解決一個聯立方程組。你會注意到這些方程的左邊是而不是變量(一般來說),它們是表達式。公式只是一種關係,它將左側的一個表達式與右側的另一個表達式等同起來。此外,這種關係是總是是真的,所以訂單是無關緊要的。

這與具有命令語義的命令式編程語言完全不同。但它也非常強大,因爲你可以說明這些關係(線性方程組,方程組,非線性方程組,隱式方程等),編譯器將找出最有效的方法來解決它們。

回到您的示例中,當您查看問題中的代碼時,您正在將這些方程式解釋爲賦值語句。這個概念被強化了,因爲它們恰好在左邊有變量。但他們真的是方程式。在基於方程式的系統中,您不必擔心給定的變量是否已被分配到以前。相反,要求只是對於每個變量都存在(某處)方程,並且沒有額外的方程。換句話說,你應該有與未知數相同數量的變量,方程組有一個獨特的解決方案。這就是Modelica所要求的一切。

現在,Modelica支持您習慣的命令式語義。但是它們只能在特殊情況下使用,因爲它們限制了數學行爲的解釋,以至於它干擾了允許Modelica編譯器生成真正快速代碼的符號操作。所以它不僅僅是一個風格問題。如果可能的話,您應該使用方程式,Modelica中的算法只能用作最後的手段。

最後一個註釋。有些人可能想知道:「你是否告訴我這些方程將被放入一個巨大的方程組中,並通過矩陣求逆或Newton-Raphson或其他方法求解?爲什麼使它變得如此複雜,以至於它可以很容易地解決!」但它不會被解爲一個巨大的方程組。如果它可以作爲一組簡單的作業解決,它將。這是將應用的不同符號操作技術之一(其中很多)。事實上,這是Modelica的一個關鍵點......您不需要擔心優化解決方案的方法,該工具會照顧到這一點。更重要的是,如果你以一種同時系統的方式連接組件,你也不必擔心。 Modelica工具可以爲您處理這種「代數循環」,他們將優化它以找到計算效率最高的公式,並且不依賴於您爲這些案例重新制定模型。

這是否幫助?

+0

沒錯!我繼續介紹基於組件的示例,並且它更有意義。非常感謝作者的指導! – Matt

+0

太好了。很高興幫助。來自* an *作者「的小修正(有許多Modelica規範的作者,除此之外,Modelica還有其他一些書籍) –

1

你不會知道在Modelica的模型公式的執行順序,直到你運行它的Modelica工具(你可以重新排序源模型中的任何方程,得到相同的結果)。然後該命令僅適用於您使用此設置的此工具。

這是由OpenModelica編譯器選擇的順序(OMC + S + simCodeTarget =轉儲model.mo):

error = ref - h;
outCtr = K * (error + x);
der(x) = DIVISION(error, T, #SHARED_LITERAL_2(String#);
qOutflow = LimitValue(minV, maxV, (-flowGain) * outCtr);
qInflow = if time > 150.0 then 3.0 * flowLevel else flowLevel;
der(h) = DIVISION(qInflow - qOutflow, area, #SHARED_LITERAL_3(String#);

這個例子有點無聊,因爲沒有方程式的左右兩邊發生了變化(如果沒有選擇h作爲狀態變量等,h = error - ref將是可行的)。