1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.representation.expressions;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Iterator;
\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
27 * Representation of a delay expression. The order of the
\r
33 * LV3=INTEG(RT2-DELAY3,DL*input)
\r
35 * LV2=INTEG(RT1-RT2,LV3)
\r
37 * LV1=INTEG(input-RT1,LV3)
\r
41 * LV3=INTEG(RT2-DELAY3I,initial value*DL)
\r
43 * LV2=INTEG(RT1-RT2,LV3)
\r
45 * LV1=INTEG(input-RT1,LV3)
\r
48 * @author Teemu Lempinen
\r
51 @GraphType("http://www.simantics.org/Sysdyn-1.1/DelayExpression")
\r
52 public class DelayExpression extends Expression {
\r
54 @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/initialValue")
\r
55 private String initialValue;
\r
57 @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/delayTime")
\r
58 private String delayTime;
\r
60 @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/order")
\r
61 private Integer order;
\r
63 @RelatedValue("http://www.simantics.org/Sysdyn-1.1/DelayExpression/expression")
\r
64 private String equation;
\r
67 public String getDeclaration(IndependentVariable variable) {
\r
69 // Calculate range for the variable
\r
70 ArrayIndexes ai = variable.getArrayIndexes();
\r
71 ArrayList<Enumeration> enumerations = null;
\r
73 enumerations = ai.getEnumerations();
\r
76 if(enumerations != null && enumerations.size() > 0) {
\r
77 StringBuilder sb = new StringBuilder();
\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
87 range = sb.toString();
\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
107 declaration.append(")");
\r
109 declaration.append(";\n");
\r
111 // Write the delay class
\r
112 declaration.append(getDelayClass(variable, range, order));
\r
113 return declaration.toString();
\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
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
126 private String getDelayClass(Variable variable, String range, int n) {
\r
127 StringBuilder sb = new StringBuilder();
\r
129 sb.append("class " + variable.getName() + "_delayClass\n");
\r
131 // Auxiliary variable
\r
132 sb.append("\tReal DL;\n");
\r
134 sb.append("\tReal delayTime;\n");
\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
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
149 sb.append("\tReal" + range + " initialValue = " + FormatUtils.formatExpressionForModelica(variable, this.initialValue) + ";\n");
\r
152 sb.append("\tReal" + range + " delay0;\n");
\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
160 sb.append("initial equation\n");
\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
169 sb.append("equation\n");
\r
170 sb.append("\tDL = delayTime/" + n + ";\n");
\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
178 sb.append("end " + variable.getName() + "_delayClass;\n");
\r
179 return sb.toString();
\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
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
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