]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
852ea14cf14a5ed1a2d99c4f70990e02141239c0
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010 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 java.util.ArrayList;\r
15 import java.util.Iterator;\r
16 \r
17 import org.simantics.objmap.annotations.GraphType;\r
18 import org.simantics.objmap.annotations.RelatedValue;\r
19 import org.simantics.sysdyn.representation.ArrayIndexes;\r
20 import org.simantics.sysdyn.representation.Enumeration;\r
21 import org.simantics.sysdyn.representation.IndependentVariable;\r
22 import org.simantics.sysdyn.representation.Variable;\r
23 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
24 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
25 \r
26 /**\r
27  * Representation of a delay expression. The order of the \r
28  * delay can be 1-n.\r
29  * \r
30  * Delay with n = 3:\r
31  * \r
32  * DELAY3=LV3/DL\r
33  * LV3=INTEG(RT2-DELAY3,DL*input)\r
34  * RT2=LV2/DL\r
35  * LV2=INTEG(RT1-RT2,LV3)\r
36  * RT1=LV1/DL\r
37  * LV1=INTEG(input-RT1,LV3)\r
38  * DL=delay time/3\r
39  * \r
40  * DELAY3I=LV3/DL\r
41  * LV3=INTEG(RT2-DELAY3I,initial value*DL) \r
42  * RT2=LV2/DL\r
43  * LV2=INTEG(RT1-RT2,LV3)\r
44  * RT1=LV1/DL\r
45  * LV1=INTEG(input-RT1,LV3)\r
46  * DL=delay time/3\r
47  * \r
48  * @author Teemu Lempinen\r
49  *\r
50  */\r
51 @GraphType("http://www.simantics.org/Sysdyn-1.1/DelayExpression")\r
52 public class DelayExpression extends Expression {\r
53 \r
54     @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/initialValue")\r
55     private String initialValue;\r
56 \r
57     @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/delayTime")\r
58     private String delayTime;\r
59 \r
60     @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/order")\r
61     private Integer order;\r
62 \r
63     @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/expression")\r
64     private String equation;\r
65 \r
66     @Override\r
67     public String getDeclaration(IndependentVariable variable) {\r
68 \r
69         // Calculate range for the variable\r
70         ArrayIndexes ai = variable.getArrayIndexes();\r
71         ArrayList<Enumeration> enumerations = null;\r
72         if(ai != null) \r
73             enumerations = ai.getEnumerations();\r
74 \r
75         String range = "";\r
76         if(enumerations != null && enumerations.size() > 0) {\r
77             StringBuilder sb = new StringBuilder();\r
78             sb.append("[");\r
79             Iterator<Enumeration> iterator = enumerations.iterator();\r
80             while(iterator.hasNext()) {\r
81                 sb.append(iterator.next().getName() + ".size");\r
82                 if(iterator.hasNext()) {\r
83                     sb.append(", ");\r
84                 }\r
85             }\r
86             sb.append("]");\r
87             range = sb.toString();\r
88         }\r
89         \r
90         /* Build the declaration */\r
91         StringBuilder declaration = new StringBuilder();\r
92         // Variable declaration\r
93         declaration.append("    " + variable.getType() + " " + variable.getName() + range + ";\n");\r
94         // Delay declaration\r
95         declaration.append("    " + variable.getName() + "_delayClass " + variable.getName() + "_delayClass_instance");\r
96         // Change enumeration sizes from the delay class. Supports overridden enumerations in modules.\r
97         if(range.length() > 0) {\r
98             declaration.append("(");\r
99             String[] ranges = range.substring(1, range.length() - 1).split(",");\r
100             for(int i = 0; i < ranges.length; i++ ) {\r
101                 String r = ranges[i];\r
102                 declaration.append(r.replace(".size", "size") + " = " + r);\r
103                 if(i < ranges.length - 1) {\r
104                     declaration.append(", ");\r
105                 }\r
106             }\r
107             declaration.append(")");\r
108         }\r
109         declaration.append(";\n");\r
110         \r
111         // Write the delay class\r
112         declaration.append(getDelayClass(variable, range, order));\r
113         return declaration.toString();\r
114     }\r
115 \r
116     /**\r
117      * Creates a class that is used to implement the delay. Class contains\r
118      * a basic delay structure with "stocks and flows". The number of \r
119      * stocks and flows is determined by the order of the delay\r
120      * \r
121      * @param variable The variable for which the delay is created\r
122      * @param range Array range\r
123      * @param n Order of the delay\r
124      * @return\r
125      */\r
126     private String getDelayClass(Variable variable, String range, int n) {\r
127         StringBuilder sb = new StringBuilder();\r
128 \r
129         sb.append("class " + variable.getName() + "_delayClass\n");\r
130         \r
131         // Auxiliary variable\r
132         sb.append("\tReal DL;\n");\r
133         // Delay time\r
134         sb.append("\tReal delayTime;\n");\r
135 \r
136         // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable\r
137         if(range.length() > 0) {\r
138             range = range.replaceAll(".size", "size");\r
139             for(String r : range.substring(1, range.length() - 1).split(",")) {\r
140                 sb.append("\t parameter Integer " + r + ";\n");\r
141             }\r
142         }\r
143 \r
144         if(initialValue == null || initialValue.length() == 0)\r
145             // Use "random" number as initial value, if initial value is not set\r
146             sb.append("\tReal" + range + " initialValue = " + (range.length() > 0 ? "fill(-137543," + range.substring(1, range.length() - 1) + ")" : -137543) + ";\n");\r
147         else\r
148             // Initial value\r
149             sb.append("\tReal" + range + " initialValue = " + FormatUtils.formatExpressionForModelica(variable, this.initialValue) + ";\n");\r
150         \r
151         // First valve\r
152         sb.append("\tReal" + range + " delay0;\n");\r
153 \r
154         // Stocks and valves. Valves are the delayed values of the variable\r
155         for(int i = 1; i <= n; i++) {\r
156             sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n");\r
157             sb.append("\tReal" + range + " delay" + i + ";\n");\r
158         }\r
159 \r
160         sb.append("initial equation\n");\r
161         \r
162         // "Generic" structure selection. If the "random" number is not used in initial value, use delay0 as initial value\r
163         // Each stock gets the same initial value\r
164         for(int i = 1; i <= n; i++)\r
165             sb.append("\tLV" + i +" = DL * " + \r
166                     (range.length() > 0 ? "(if max(initialValue) < -137543 or max(initialValue) > -137543 then initialValue else delay0)" :\r
167                             "(if initialValue < -137543 or initialValue > -137543 then initialValue else delay0)") + ";\n");\r
168 \r
169         sb.append("equation\n");\r
170         sb.append("\tDL = delayTime/" + n + ";\n");\r
171 \r
172         // Valves and stocks\r
173         for(int i = 1; i <= n; i++) {\r
174             sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n");\r
175             sb.append("\tdelay" + i + " = LV" + i + "/DL;\n");\r
176         }\r
177 \r
178         sb.append("end " + variable.getName() + "_delayClass;\n");\r
179         return sb.toString();\r
180     }\r
181 \r
182     @Override\r
183     public String getEquation(IndependentVariable variable) {\r
184         String equation = FormatUtils.formatExpressionForModelica(variable, this.equation);\r
185         String delayTime = FormatUtils.formatExpressionForModelica(variable, this.delayTime);\r
186 \r
187         // Set delay properties\r
188         StringBuilder sb = new StringBuilder();\r
189         sb.append("    " + variable.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
190         sb.append("    " + variable.getName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
191 \r
192         // Use the delay in the value of variable\r
193         String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
194         sb.append("    " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + variable.getName() + "_delayClass_instance.delay" + order + ";\n");\r
195         return sb.toString();\r
196     }\r
197 \r
198 \r
199 }\r