1 /*******************************************************************************
\r
2 * Copyright (c) 2010, 2012 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.io.StringReader;
\r
15 import java.util.ArrayList;
\r
16 import java.util.Set;
\r
18 import org.simantics.db.ReadGraph;
\r
19 import org.simantics.objmap.annotations.GraphType;
\r
20 import org.simantics.objmap.annotations.RelatedValue;
\r
21 import org.simantics.sysdyn.SysdynResource;
\r
22 import org.simantics.sysdyn.expressionParser.ExpressionParser;
\r
23 import org.simantics.sysdyn.expressionParser.ParseException;
\r
24 import org.simantics.sysdyn.manager.SysdynModel;
\r
25 import org.simantics.sysdyn.representation.Book;
\r
26 import org.simantics.sysdyn.representation.Enumeration;
\r
27 import org.simantics.sysdyn.representation.IElement;
\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 import org.simantics.sysdyn.representation.utils.UnitUtils;
\r
36 * Class representing a stock expression in a variable
\r
38 * @author Teemu Lempinen
\r
41 @GraphType(SysdynResource.URIs.StockExpression)
\r
42 public class StockExpression extends Expression {
\r
44 @RelatedValue(SysdynResource.URIs.StockExpression_initialEquation)
\r
45 private String initialEquation;
\r
48 public String getExpression() {
\r
49 return initialEquation;
\r
54 public String getEquation() {
\r
56 // Build range e.g. Stock[2,3]
\r
57 String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());
\r
59 // Stock equation is always der(Stock)
\r
60 StringBuilder b = new StringBuilder();
\r
62 .append(parent.getName() + range)
\r
65 // Stock equation is formed automatically using incoming and outgoing flows (actually the nearest valves in those flows)
\r
66 ArrayList<Valve> incoming = ((Stock)parent).getIncomingValves();
\r
67 ArrayList<Valve> outgoing = ((Stock)parent).getOutgoingValves();
\r
68 if(incoming.isEmpty() && outgoing.isEmpty()) {
\r
69 // No connections, add 0 for each array index if any.
\r
70 ArrayList<Enumeration> enumerations = parent.getArrayIndexes();
\r
71 if(enumerations == null || enumerations.isEmpty()) {
\r
74 b.append(" zeros(");
\r
75 for(int i = 0; i < enumerations.size(); i++) {
\r
76 b.append(enumerations.get(i).getName() + ".size");
\r
77 if(i != enumerations.size() - 1)
\r
84 // incoming valves add and outgoing valves reduce the stock
\r
85 for(Valve valve : outgoing)
\r
86 b.append("\n - ").append(valve.getName() + range);
\r
87 for(Valve valve : incoming)
\r
88 b.append("\n + ").append(valve.getName() + range);
\r
91 return b.toString();
\r
95 * Check whether to use fixed=true and start=... in Modelica code
\r
98 private boolean useStartValue() {
\r
99 // If no variables are used in the equation, start value is used
\r
101 // First the equation is formatted and parsed
\r
102 String equation = FormatUtils.formatExpressionForModelica(parent, initialEquation);
\r
103 ExpressionParser parser = new ExpressionParser(new StringReader(equation));
\r
106 if(parser.getReferences().isEmpty()) {
\r
107 // if equation did not contain any references, start value is used
\r
110 // Check if references are references to sheets.
\r
111 // Sheet references are allowed, since sheets contain only constants
\r
112 boolean found = false;
\r
113 Set<String> references = parser.getReferences().keySet();
\r
115 // Go through each reference
\r
116 for(String reference : references) {
\r
117 // We only need the first element to know that it is a Sheet (SheetName.CellOrRange)
\r
118 reference = reference.split("\\.")[0];
\r
120 for(IElement element : parent.getParentConfiguration().getElements()) {
\r
121 if(element instanceof Book) {
\r
122 for(Sheet sheet : ((Book)element).getSheets()) {
\r
123 if(reference.equals(sheet.getName())) {
\r
133 // If there was no sheet for this reference name, return false
\r
138 } catch (ParseException e) {
\r
139 e.printStackTrace();
\r
145 public String getInitialEquation() {
\r
146 // if start value is used, no initial equation is returned
\r
147 if(useStartValue())
\r
149 // format the initial equation for modelica execution
\r
150 String equation = FormatUtils.formatExpressionForModelica(parent, initialEquation, false);
\r
151 String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());
\r
154 return " " + parent.getName() + range + " = " + equation + ";\n";
\r
159 * Return Double representation of the initial equation for given variable
\r
162 * @return Double representing the initial equation or null if initial equation is not a double
\r
164 public Double getStartValue() {
\r
165 Double value = null;
\r
166 ArrayList<IExpression> expressions = parent.getExpressions();
\r
167 if(expressions.size() == 1) {
\r
168 IExpression e = expressions.get(0);
\r
169 if(e.getInitialEquation() == null) {
\r
171 value = Double.parseDouble(initialEquation);
\r
172 } catch(NumberFormatException e1) {
\r
182 public String validateUnits(ReadGraph graph, SysdynModel model) {
\r
183 String result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialEquation);
\r
184 if(result == null) {
\r
185 String integralEquation = getEquation();
\r
186 if(integralEquation.contains("="))
\r
187 result = UnitUtils.matchUnits(
\r
190 parent.getParentConfiguration(),
\r
192 "(" + integralEquation.substring(integralEquation.indexOf("=") + 1, integralEquation.lastIndexOf(";")) +") * time");
\r