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.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
28 * Representation of a delay expression. The order of the
\r
34 * LV3=INTEG(RT2-DELAY3,DL*input)
\r
36 * LV2=INTEG(RT1-RT2,LV3)
\r
38 * LV1=INTEG(input-RT1,LV3)
\r
42 * LV3=INTEG(RT2-DELAY3I,initial value*DL)
\r
44 * LV2=INTEG(RT1-RT2,LV3)
\r
46 * LV1=INTEG(input-RT1,LV3)
\r
49 * @author Teemu Lempinen
\r
52 @GraphType(SysdynResource.URIs.DelayExpression)
\r
53 public class DelayExpression extends Expression {
\r
55 @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue)
\r
56 private String initialValue;
\r
58 @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime)
\r
59 private String delayTime;
\r
61 @RelatedValue(SysdynResource.URIs.DelayExpression_order)
\r
62 private Integer order;
\r
64 @RelatedValue(SysdynResource.URIs.DelayExpression_expression)
\r
65 private String equation;
\r
68 public String getDeclaration(IndependentVariable variable) {
\r
70 // Calculate range for the variable
\r
71 ArrayIndexes ai = variable.getArrayIndexes();
\r
72 ArrayList<Enumeration> enumerations = null;
\r
74 enumerations = ai.getEnumerations();
\r
77 if(enumerations != null && enumerations.size() > 0) {
\r
78 StringBuilder sb = new StringBuilder();
\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
88 range = sb.toString();
\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
108 declaration.append(")");
\r
110 declaration.append(";\n");
\r
112 // Write the delay class
\r
113 declaration.append(getDelayClass(variable, range, order));
\r
114 return declaration.toString();
\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
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
127 private String getDelayClass(Variable variable, String range, int n) {
\r
128 StringBuilder sb = new StringBuilder();
\r
130 sb.append("class " + variable.getName() + "_delayClass\n");
\r
132 // Auxiliary variable
\r
133 sb.append("\tReal DL;\n");
\r
135 sb.append("\tReal delayTime;\n");
\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
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
150 sb.append("\tReal" + range + " initialValue = " + FormatUtils.formatExpressionForModelica(variable, this.initialValue) + ";\n");
\r
153 sb.append("\tReal" + range + " delay0;\n");
\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
161 sb.append("initial equation\n");
\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
170 sb.append("equation\n");
\r
171 sb.append("\tDL = delayTime/" + n + ";\n");
\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
179 sb.append("end " + variable.getName() + "_delayClass;\n");
\r
180 return sb.toString();
\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
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
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