]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
085754f4a86b6b60647c2d9a6d9d829c1bf3896d
[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 java.io.StringReader;\r
15 import java.util.ArrayList;\r
16 import java.util.Set;\r
17 \r
18 import org.simantics.objmap.annotations.GraphType;\r
19 import org.simantics.objmap.annotations.RelatedValue;\r
20 import org.simantics.sysdyn.SysdynResource;\r
21 import org.simantics.sysdyn.expressionParser.ExpressionParser;\r
22 import org.simantics.sysdyn.expressionParser.ParseException;\r
23 import org.simantics.sysdyn.representation.ArrayIndexes;\r
24 import org.simantics.sysdyn.representation.Book;\r
25 import org.simantics.sysdyn.representation.Enumeration;\r
26 import org.simantics.sysdyn.representation.IElement;\r
27 import org.simantics.sysdyn.representation.IndependentVariable;\r
28 import org.simantics.sysdyn.representation.Sheet;\r
29 import org.simantics.sysdyn.representation.Stock;\r
30 import org.simantics.sysdyn.representation.Valve;\r
31 import org.simantics.sysdyn.representation.utils.FormatUtils;\r
32 import org.simantics.sysdyn.representation.utils.IndexUtils;\r
33 \r
34 /**\r
35  * Class representing a stock expression in a variable\r
36  * \r
37  * @author Teemu Lempinen\r
38  *\r
39  */\r
40 @GraphType(SysdynResource.URIs.StockExpression)\r
41 public class StockExpression extends Expression {\r
42 \r
43     @RelatedValue(SysdynResource.URIs.StockExpression_initialEquation)\r
44     private String initialEquation;\r
45 \r
46     @Override\r
47     public String getExpression(IndependentVariable variable) {\r
48         return initialEquation;\r
49     }\r
50     \r
51 \r
52     @Override\r
53     public String getEquation(IndependentVariable variable) {\r
54         \r
55         // Build range e.g. Stock[2,3]\r
56         String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
57         \r
58         // Stock equation is always der(Stock)\r
59         StringBuilder b = new StringBuilder();\r
60         b.append("    der(")\r
61         .append(variable.getName() + range)\r
62         .append(") =");\r
63         \r
64         // Stock equation is formed automatically using incoming and outgoing flows (actually the nearest valves in those flows)\r
65         ArrayList<Valve> incoming = ((Stock)variable).getIncomingValves();\r
66         ArrayList<Valve> outgoing = ((Stock)variable).getOutgoingValves();\r
67         if(incoming.isEmpty() && outgoing.isEmpty()) {\r
68             // No connections, add 0 for each array index if any.\r
69             ArrayIndexes ai = variable.getArrayIndexes();\r
70             ArrayList<Enumeration> enumerations = null;\r
71             if(ai != null) \r
72                 enumerations = ai.getEnumerations();\r
73             \r
74             if(ai == null || enumerations == null || enumerations.isEmpty()) {\r
75                 b.append(" 0.0");\r
76             } else {\r
77                 b.append(" zeros(");\r
78                 for(int i = 0; i < enumerations.size(); i++) {\r
79                     b.append(enumerations.get(i).getEnumerationIndexes().size());\r
80                     if(i != enumerations.size() - 1)\r
81                         b.append(", ");\r
82                 }\r
83                 b.append(")");\r
84             }\r
85 \r
86         } else {\r
87             // incoming valves add and outgoing valves reduce the stock\r
88             for(Valve valve : outgoing)\r
89                 b.append("\n        - ").append(valve.getName() + range);\r
90             for(Valve valve : incoming)\r
91                 b.append("\n        + ").append(valve.getName() + range);\r
92         }\r
93         b.append(";\n");\r
94         return b.toString();\r
95     }\r
96     \r
97     /** \r
98      * Check whether to use fixed=true and start=... in Modelica code\r
99      * @return\r
100      */\r
101     private boolean useStartValue(IndependentVariable variable) {\r
102         // If no variables are used in the equation, start value is used\r
103         \r
104         // First the equation is formatted and parsed\r
105         String equation = FormatUtils.formatExpressionForModelica(variable, initialEquation);\r
106         ExpressionParser parser = new ExpressionParser(new StringReader(equation));\r
107         try {\r
108             parser.expr();\r
109             if(parser.getReferences().isEmpty()) {\r
110                 // if equation did not contain any references, start value is used\r
111                 return true;\r
112             } else {\r
113                 // Check if references are references to sheets. \r
114                 // Sheet references are allowed, since sheets contain only constants\r
115                 boolean found = false;\r
116                 Set<String> references = parser.getReferences().keySet();\r
117                 \r
118                 // Go through each reference\r
119                 for(String reference : references) {\r
120                     // We only need the first element to know that it is a Sheet (SheetName.CellOrRange)\r
121                     reference = reference.split("\\.")[0]; \r
122                     found = false;\r
123                     for(IElement element : variable.getParentConfiguration().getElements()) {\r
124                         if(element instanceof Book) {\r
125                             for(Sheet sheet : ((Book)element).getSheets()) {\r
126                                 if(reference.equals(sheet.getName())) {\r
127                                     found = true;\r
128                                     break;\r
129                                 }\r
130                             }\r
131                         }\r
132                         if(found)\r
133                             break;\r
134                     }\r
135                     \r
136                     // If there was no sheet for this reference name, return false\r
137                     if(!found)\r
138                         return false;\r
139                 }\r
140             }\r
141         } catch (ParseException e) {\r
142         }\r
143         return true;\r
144     }\r
145 \r
146     @Override\r
147     public String getInitialEquation(IndependentVariable variable) {\r
148         // if start value is used, no initial equation is returned\r
149         if(useStartValue(variable))\r
150             return null;\r
151         // format the initial equation for modelica execution \r
152         String equation = FormatUtils.formatExpressionForModelica(variable, initialEquation);\r
153         String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange());\r
154         if(range == null)\r
155                 range = "";\r
156         return "    " + variable.getName() + range + " = " + equation + ";\n";\r
157     }\r
158     \r
159     \r
160     /**\r
161      * Return Double representation of the initial equation for given variable\r
162      * \r
163      * @param variable\r
164      * @return Double representing the initial equation or null if initial equation is not a double\r
165      */\r
166     public Double getStartValue(IndependentVariable variable) {\r
167         Double value = null;\r
168         ArrayList<IExpression> expressions = variable.getExpressions().getExpressions();\r
169         if(expressions.size() == 1) {\r
170                 IExpression e = expressions.get(0);\r
171             if(e.getInitialEquation(variable) == null) {\r
172                 try {\r
173                     value = Double.parseDouble(initialEquation);\r
174                 } catch(NumberFormatException e1) {\r
175                     \r
176                 }\r
177             }\r
178         }\r
179         return value;\r
180     }\r
181 \r
182 \r
183 }\r