]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
59121d641c4449d50a9c6e58d46cd1885d071c21
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.sysdyn.representation.expressions;\r
13 \r
14 import org.simantics.db.ReadGraph;\r
15 import org.simantics.objmap.annotations.GraphType;\r
16 import org.simantics.objmap.annotations.RelatedValue;\r
17 import org.simantics.sysdyn.SysdynResource;\r
18 import org.simantics.sysdyn.manager.SysdynModel;\r
19 import org.simantics.sysdyn.representation.IndependentVariable;\r
20 import org.simantics.sysdyn.representation.Variability;\r
21 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
22 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
23 import org.simantics.sysdyn.representation.utils.UnitUtils;\r
24 \r
25 /**\r
26  * Representation of a delay expression. The order of the \r
27  * delay can be 1-n.\r
28  * \r
29  * Delay with n = 3:\r
30  * \r
31  * DELAY3=LV3/DL\r
32  * LV3=INTEG(RT2-DELAY3,DL*input)\r
33  * RT2=LV2/DL\r
34  * LV2=INTEG(RT1-RT2,LV3)\r
35  * RT1=LV1/DL\r
36  * LV1=INTEG(input-RT1,LV3)\r
37  * DL=delay time/3\r
38  * \r
39  * DELAY3I=LV3/DL\r
40  * LV3=INTEG(RT2-DELAY3I,initial value*DL) \r
41  * RT2=LV2/DL\r
42  * LV2=INTEG(RT1-RT2,LV3)\r
43  * RT1=LV1/DL\r
44  * LV1=INTEG(input-RT1,LV3)\r
45  * DL=delay time/3\r
46  * \r
47  * @author Teemu Lempinen\r
48  *\r
49  */\r
50 @GraphType(SysdynResource.URIs.DelayExpression)\r
51 public class DelayExpression extends Expression {\r
52 \r
53     @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue)\r
54     private String initialValue;\r
55 \r
56     @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime)\r
57     private String delayTime;\r
58 \r
59     @RelatedValue(SysdynResource.URIs.DelayExpression_order)\r
60     private Integer order;\r
61 \r
62     @RelatedValue(SysdynResource.URIs.DelayExpression_expression)\r
63     private String equation;\r
64 \r
65     @Override\r
66     public String getDeclarationAddition() {\r
67 \r
68         String delayTime = FormatUtils.formatExpressionForModelica(parent, this.delayTime);\r
69         String initialValue = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
70         Variability delayTimeVariability = Variability.getVariability((IndependentVariable)parent, delayTime);\r
71         Variability initialVariability = Variability.CONTINUOUS;\r
72         if(initialValue != null && initialValue.length() > 0) {\r
73             /*\r
74              *  By default, initial value variability is continuous.\r
75              *  If initial value has been set, it can be some other. \r
76              */\r
77             initialVariability = Variability.getVariability(parent, initialValue);\r
78         }\r
79 \r
80 \r
81         StringBuilder declaration = new StringBuilder();\r
82 \r
83         String range = parent.getRange();\r
84 \r
85         // Delay declaration\r
86         declaration.append("    " + parent.getName() + "_delayClass " + parent.getName() + "_delayClass_instance");\r
87 \r
88         // Change enumeration sizes from the delay class. Supports overridden enumerations in modules.\r
89         if(range.length() > 0 || !initialVariability.equals(Variability.CONTINUOUS) || !delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
90             declaration.append("(");\r
91 \r
92             boolean started = false;\r
93             if(range.length() > 0) {\r
94                 started = true;\r
95                 String[] ranges = range.substring(1, range.length() - 1).split(",");\r
96                 for(int i = 0; i < ranges.length; i++ ) {\r
97                     String r = ranges[i];\r
98                     declaration.append(r.replace(".size", "size") + " = " + r);\r
99                     if(i < ranges.length - 1) {\r
100                         declaration.append(", ");\r
101                     }\r
102                 }\r
103             }\r
104 \r
105             // If initial value is not continuous, it is set in the module declaration\r
106             if(!initialVariability.equals(Variability.CONTINUOUS)) {\r
107                 if(started)\r
108                     declaration.append(", ");\r
109                 started = true;\r
110                 declaration.append("initialValue = " + initialValue);\r
111             }\r
112 \r
113             // If delay time is not continuous, it is set in the module declaration \r
114             if(!delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
115                 if(started)\r
116                     declaration.append(", ");\r
117                 declaration.append("delayTime = " + delayTime);\r
118             }\r
119 \r
120             declaration.append(")");\r
121         }\r
122         declaration.append(";\n");\r
123 \r
124         // Write the delay class\r
125         declaration.append(getDelayClass(range, order));\r
126         return declaration.toString();\r
127     }\r
128 \r
129     /**\r
130      * Creates a class that is used to implement the delay. Class contains\r
131      * a basic delay structure with "stocks and flows". The number of \r
132      * stocks and flows is determined by the order of the delay\r
133      * \r
134      * @param variable The variable for which the delay is created\r
135      * @param range Array range\r
136      * @param n Order of the delay\r
137      * @return\r
138      */\r
139     private String getDelayClass(String range, int n) {\r
140         StringBuilder sb = new StringBuilder();\r
141 \r
142         sb.append("class " + parent.getName() + "_delayClass\n");\r
143 \r
144         // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable\r
145         if(range.length() > 0) {\r
146             range = range.replaceAll(".size", "size");\r
147             for(String r : range.substring(1, range.length() - 1).split(",")) {\r
148                 sb.append("\t parameter Integer " + r + ";\n");\r
149             }\r
150         }\r
151 \r
152         String dt = FormatUtils.formatExpressionForModelica(parent,delayTime);\r
153         Variability delayTimeVariability = Variability.getVariability(parent, dt);\r
154         if(!delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
155             // Auxiliary variable\r
156             sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " DL = delayTime/" + n + ";\n");\r
157             // Delay time\r
158             sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " delayTime;\n");\r
159         } else {\r
160             // Continuous auxiliary variable\r
161             sb.append("\tReal" + range + " DL;\n");\r
162             // Continuous delay time\r
163             sb.append("\tReal" + range + " delayTime;\n");\r
164         }\r
165 \r
166 \r
167         // Get initial value variability\r
168         Variability initialValueVariability = Variability.CONTINUOUS;\r
169         String initEquation = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
170         if(initialValue != null && initialValue.length() > 0) {\r
171             initialValueVariability = Variability.getVariability(parent, initEquation);\r
172         }\r
173 \r
174         // Declare initial value (continuous or other)\r
175         String ivv = !initialValueVariability.equals(Variability.CONTINUOUS) ? initialValueVariability.getText() + " " : "";\r
176         sb.append("\t" + ivv + "Real" + range + " initialValue;\n");\r
177 \r
178         // First valve\r
179         sb.append("\tReal" + range + " delay0;\n");\r
180 \r
181         // Stocks and valves. Valves are the delayed values of the variable\r
182         for(int i = 1; i <= n; i++) {\r
183             if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS))\r
184                 // Continuous initial value or delay time\r
185                 sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n");\r
186             else\r
187                 // initial value and delay time are not continuous\r
188                 sb.append("\tReal" + range + " LV" + i + \r
189                         "(" + (range.length() > 0 ? "each " : "") + "fixed=true, start=initialValue " + (range.isEmpty() ? "*" : ".*") + " DL);\n");\r
190             sb.append("\tReal" + range + " delay" + i + ";\n");\r
191         }\r
192 \r
193         // If initial value or delay time are continuous, use initial equation block\r
194         if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
195             sb.append("initial equation\n");\r
196 \r
197             // Each stock gets the same initial value\r
198             for(int i = 1; i <= n; i++)\r
199                 sb.append("\tLV" + i +" = DL " + (range.isEmpty() ? "*" : ".*") + " initialValue;\n");\r
200         }\r
201 \r
202         // Equation block\r
203         sb.append("equation\n");\r
204 \r
205         if(delayTimeVariability.equals(Variability.CONTINUOUS))\r
206             sb.append("\tDL = delayTime/" + n + ";\n");\r
207 \r
208         // Valves and stocks\r
209         for(int i = 1; i <= n; i++) {\r
210             sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n");\r
211             sb.append("\tdelay" + i + " = LV" + i + " " + (range.isEmpty() ? "/" : "./") + "DL;\n");\r
212         }\r
213 \r
214         sb.append("end " + parent.getName() + "_delayClass;\n");\r
215         return sb.toString();\r
216     }\r
217 \r
218     @Override\r
219     public String getEquation() {\r
220         StringBuilder sb = new StringBuilder();\r
221 \r
222         String equation = FormatUtils.formatExpressionForModelica(parent, this.equation);\r
223         String delayTime = FormatUtils.formatExpressionForModelica(parent, this.delayTime);\r
224         String initialValue = FormatUtils.formatExpressionForModelica(parent, this.initialValue);\r
225 \r
226         // First "valve" in the delay\r
227         sb.append("    " + parent.getName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
228 \r
229         // Delay time (if continuous)\r
230         Variability delayTimeVariability = Variability.getVariability(parent, delayTime);\r
231         if(delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
232             sb.append("    " + parent.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
233         }\r
234 \r
235         // Initial value\r
236         if(initialValue == null || initialValue.length() == 0) {\r
237             // No initial value set, use delay0 (the first "valve")\r
238             sb.append("    " + parent.getName() + "_delayClass_instance.initialValue = " + parent.getName() + "_delayClass_instance.delay0;\n");\r
239         } else {\r
240             // Continuous initial value\r
241             Variability initialVariability = Variability.getVariability(parent, initialValue);\r
242             if(initialVariability.equals(Variability.CONTINUOUS)) {\r
243                 sb.append("    " + parent.getName() + "_delayClass_instance.initialValue = " + initialValue + ";\n");\r
244             }\r
245         }\r
246 \r
247         // The value of the actual variable\r
248         String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
249         sb.append("    " + parent.getName() + (range.equals("[:]") ? "" : range) + " = " + parent.getName() + "_delayClass_instance.delay" + order + ";\n");\r
250         return sb.toString();\r
251     }\r
252 \r
253     @Override\r
254     public String getExpression() {\r
255         return "This + is + not + a + parameter + at + any + time";\r
256     }\r
257 \r
258     \r
259     @Override\r
260     public String validateUnits(ReadGraph graph, SysdynModel model) {\r
261         if(parent.getUnit() == null)\r
262             return "Unit not defined for " + parent.getName();\r
263         \r
264         String result =  UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), equation);\r
265         if(result == null)\r
266             result =  UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialValue);\r
267         if(result == null)\r
268             result =  UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), UnitUtils.getTimeUnit(graph, model), delayTime);\r
269         \r
270         return result;\r
271     }\r
272 \r
273 }\r