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