import org.simantics.objmap.annotations.RelatedValue;\r
import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.sysdyn.manager.SysdynModel;\r
-import org.simantics.sysdyn.representation.IndependentVariable;\r
-import org.simantics.sysdyn.representation.Variability;\r
+import org.simantics.sysdyn.modelica.ModelicaWriter;\r
import org.simantics.sysdyn.representation.utils.FormatUtils;\r
import org.simantics.sysdyn.representation.utils.IndexUtils;\r
import org.simantics.sysdyn.representation.utils.UnitUtils;\r
@GraphType(SysdynResource.URIs.DelayExpression)\r
public class DelayExpression extends Expression {\r
\r
- @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue)\r
- private String initialValue;\r
-\r
- @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime)\r
- private String delayTime;\r
-\r
- @RelatedValue(SysdynResource.URIs.DelayExpression_order)\r
- private Integer order;\r
-\r
- @RelatedValue(SysdynResource.URIs.DelayExpression_expression)\r
- private String equation;\r
-\r
- @Override\r
- public String getDeclarationAddition() {\r
- String delayTime = FormatUtils.replaceWhitespace(this.delayTime);\r
- delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime);\r
- String initialValue = FormatUtils.replaceWhitespace(this.initialValue);\r
- initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue);\r
- Variability delayTimeVariability = Variability.getVariability((IndependentVariable)parent, delayTime);\r
- Variability initialVariability = Variability.CONTINUOUS;\r
- if(initialValue != null && initialValue.length() > 0) {\r
- /*\r
- * By default, initial value variability is continuous.\r
- * If initial value has been set, it can be some other. \r
- */\r
- initialVariability = Variability.getVariability(parent, initialValue);\r
- }\r
-\r
-\r
- StringBuilder declaration = new StringBuilder();\r
-\r
- String range = parent.getRange();\r
-\r
- // Delay declaration\r
- declaration.append(" " + parent.getModelicaName() + "_delayClass " + parent.getModelicaName() + "_delayClass_instance");\r
-\r
- // Change enumeration sizes from the delay class. Supports overridden enumerations in modules.\r
- if(range.length() > 0 || !initialVariability.equals(Variability.CONTINUOUS) || !delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
- declaration.append("(");\r
-\r
- boolean started = false;\r
- if(range.length() > 0) {\r
- started = true;\r
- String[] ranges = range.substring(1, range.length() - 1).split(",");\r
- for(int i = 0; i < ranges.length; i++ ) {\r
- String r = ranges[i];\r
- declaration.append(r.replace(".size", "size") + " = " + r);\r
- if(i < ranges.length - 1) {\r
- declaration.append(", ");\r
- }\r
- }\r
- }\r
-\r
- // If initial value is not continuous, it is set in the module declaration\r
- if(!initialVariability.equals(Variability.CONTINUOUS)) {\r
- if(started)\r
- declaration.append(", ");\r
- started = true;\r
- declaration.append("initialValue = " + initialValue);\r
- }\r
-\r
- // If delay time is not continuous, it is set in the module declaration \r
- if(!delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
- if(started)\r
- declaration.append(", ");\r
- declaration.append("delayTime = " + delayTime);\r
- }\r
-\r
- declaration.append(")");\r
- }\r
- declaration.append(";\n");\r
-\r
- // Write the delay class\r
- declaration.append(getDelayClass(range, order));\r
- return declaration.toString();\r
- }\r
-\r
- /**\r
- * Creates a class that is used to implement the delay. Class contains\r
- * a basic delay structure with "stocks and flows". The number of \r
- * stocks and flows is determined by the order of the delay\r
- * \r
- * @param variable The variable for which the delay is created\r
- * @param range Array range\r
- * @param n Order of the delay\r
- * @return\r
- */\r
- private String getDelayClass(String range, int n) {\r
- StringBuilder sb = new StringBuilder();\r
-\r
- sb.append("class " + parent.getModelicaName() + "_delayClass\n");\r
-\r
- // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable\r
- if(range.length() > 0) {\r
- range = range.replaceAll(".size", "size");\r
- for(String r : range.substring(1, range.length() - 1).split(",")) {\r
- sb.append("\t parameter Integer " + r + ";\n");\r
- }\r
- }\r
-\r
- String delayTime = FormatUtils.replaceWhitespace(this.delayTime);\r
- String dt = FormatUtils.formatExpressionForModelica(parent,delayTime);\r
- Variability delayTimeVariability = Variability.getVariability(parent, dt);\r
- if(!delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
- // Auxiliary variable\r
- sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " DL = delayTime/" + n + ";\n");\r
- // Delay time\r
- sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " delayTime;\n");\r
- } else {\r
- // Continuous auxiliary variable\r
- sb.append("\tReal" + range + " DL;\n");\r
- // Continuous delay time\r
- sb.append("\tReal" + range + " delayTime;\n");\r
- }\r
-\r
-\r
- // Get initial value variability\r
- Variability initialValueVariability = Variability.CONTINUOUS;\r
- String initEquation = FormatUtils.replaceWhitespace(this.initialValue);\r
- initEquation = FormatUtils.formatExpressionForModelica(parent, initEquation);\r
- if(initialValue != null && initialValue.length() > 0) {\r
- initialValueVariability = Variability.getVariability(parent, initEquation);\r
- }\r
-\r
- // Declare initial value (continuous or other)\r
- String ivv = !initialValueVariability.equals(Variability.CONTINUOUS) ? initialValueVariability.getText() + " " : "";\r
- sb.append("\t" + ivv + "Real" + range + " initialValue;\n");\r
-\r
- // First valve\r
- sb.append("\tReal" + range + " delay0;\n");\r
-\r
- // Stocks and valves. Valves are the delayed values of the variable\r
- for(int i = 1; i <= n; i++) {\r
- if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS))\r
- // Continuous initial value or delay time\r
- sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n");\r
- else\r
- // initial value and delay time are not continuous\r
- sb.append("\tReal" + range + " LV" + i + \r
- "(" + (range.length() > 0 ? "each " : "") + "fixed=true, start=initialValue " + (range.isEmpty() ? "*" : ".*") + " DL);\n");\r
- sb.append("\tReal" + range + " delay" + i + ";\n");\r
- }\r
-\r
- // If initial value or delay time are continuous, use initial equation block\r
- if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
- sb.append("initial equation\n");\r
-\r
- // Each stock gets the same initial value\r
- for(int i = 1; i <= n; i++)\r
- sb.append("\tLV" + i +" = DL " + (range.isEmpty() ? "*" : ".*") + " initialValue;\n");\r
- }\r
-\r
- // Equation block\r
- sb.append("equation\n");\r
-\r
- if(delayTimeVariability.equals(Variability.CONTINUOUS))\r
- sb.append("\tDL = delayTime/" + n + ";\n");\r
-\r
- // Valves and stocks\r
- for(int i = 1; i <= n; i++) {\r
- sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n");\r
- sb.append("\tdelay" + i + " = LV" + i + " " + (range.isEmpty() ? "/" : "./") + "DL;\n");\r
- }\r
-\r
- sb.append("end " + parent.getModelicaName() + "_delayClass;\n");\r
- return sb.toString();\r
- }\r
-\r
- @Override\r
- public String getEquation() {\r
- StringBuilder sb = new StringBuilder();\r
-\r
- String equation = FormatUtils.replaceWhitespace(this.equation);\r
- equation = FormatUtils.formatExpressionForModelica(parent, equation);\r
- String delayTime = FormatUtils.replaceWhitespace(this.delayTime);\r
- delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime);\r
- String initialValue = FormatUtils.replaceWhitespace(this.initialValue);\r
- initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue);\r
-\r
- // First "valve" in the delay\r
- sb.append(" " + parent.getModelicaName() + "_delayClass_instance.delay0 = " + equation + ";\n");\r
-\r
- // Delay time (if continuous)\r
- Variability delayTimeVariability = Variability.getVariability(parent, delayTime);\r
- if(delayTimeVariability.equals(Variability.CONTINUOUS)) {\r
- sb.append(" " + parent.getModelicaName() + "_delayClass_instance.delayTime = " + delayTime + ";\n");\r
- }\r
-\r
- // Initial value\r
- if(initialValue == null || initialValue.length() == 0) {\r
- // No initial value set, use delay0 (the first "valve")\r
- sb.append(" " + parent.getModelicaName() + "_delayClass_instance.initialValue = " + parent.getModelicaName() + "_delayClass_instance.delay0;\n");\r
- } else {\r
- // Continuous initial value\r
- Variability initialVariability = Variability.getVariability(parent, initialValue);\r
- if(initialVariability.equals(Variability.CONTINUOUS)) {\r
- sb.append(" " + parent.getModelicaName() + "_delayClass_instance.initialValue = " + initialValue + ";\n");\r
- }\r
- }\r
-\r
- // The value of the actual variable\r
- String range = IndexUtils.rangeToIndexes(parent, this.getArrayRange());\r
- sb.append(" " + parent.getModelicaName() + (range.equals("[:]") ? "" : range) + " = " + parent.getModelicaName() + "_delayClass_instance.delay" + order + ";\n");\r
- return sb.toString();\r
- }\r
-\r
- @Override\r
- public String getExpression() {\r
- return "This + is + not + a + parameter + at + any + time";\r
- }\r
-\r
- @Override\r
- public String getModelicaExpression() {\r
- return getExpression();\r
- }\r
-\r
- @Override\r
- public String validateUnits(ReadGraph graph, SysdynModel model) {\r
- if(parent.getUnit() == null)\r
- return "Unit not defined for " + parent.getName();\r
- \r
- String result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), equation);\r
- if(result == null)\r
- result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialValue);\r
- if(result == null)\r
- result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), UnitUtils.getTimeUnit(graph, model), delayTime);\r
- \r
- return result;\r
- }\r
+ @RelatedValue(SysdynResource.URIs.DelayExpression_initialValue)\r
+ private String initialValue;\r
+\r
+ @RelatedValue(SysdynResource.URIs.DelayExpression_delayTime)\r
+ private String delayTime;\r
+\r
+ @RelatedValue(SysdynResource.URIs.DelayExpression_order)\r
+ private Integer order;\r
+\r
+ @RelatedValue(SysdynResource.URIs.DelayExpression_expression)\r
+ private String equation;\r
+\r
+ @Override\r
+ public String getDeclarationAddition() {\r
+ // instantiate the correct delay class for this expression\r
+ return "\t" + ModelicaWriter.getDelayName(order) + " " + instance() + ";\n";\r
+ }\r
+\r
+ @Override\r
+ public String getEquation() {\r
+ StringBuilder sb = new StringBuilder();\r
+\r
+ String equation = FormatUtils.replaceWhitespace(this.equation);\r
+ equation = FormatUtils.formatExpressionForModelica(parent, equation);\r
+ String delayTime = FormatUtils.replaceWhitespace(this.delayTime);\r
+ delayTime = FormatUtils.formatExpressionForModelica(parent, delayTime);\r
+ String initialValue = FormatUtils.replaceWhitespace(this.initialValue);\r
+ initialValue = FormatUtils.formatExpressionForModelica(parent, initialValue);\r
+\r
+ sb.append("\t" + instance() + "." + ModelicaWriter.getDelayValve(0) + " = " + equation + ";\n");\r
+\r
+ sb.append("\t" + instance() + "." + ModelicaWriter.DELAY_TIME + " = " + delayTime + ";\n");\r
+\r
+ sb.append("\t" + instance() + "." + ModelicaWriter.DELAY_INITIAL + " = ");\r
+ if (initialValue != null && !initialValue.isEmpty()) {\r
+ sb.append(initialValue);\r
+ } \r
+ else {\r
+ // if an initial value is not set, use the value of the first valve\r
+ sb.append(instance() + "." + ModelicaWriter.getDelayValve(0));\r
+ }\r
+ sb.append(";\n");\r
+\r
+ // set the value of the variable\r
+ String range = IndexUtils.rangeToIndexes(parent, getArrayRange());\r
+ // TODO: this variable name thing here (and in other expressions) is a hack and should be fixed\r
+ sb.append("\t" + parent.getModelicaName() + (range.equals("[:]") ? "" : range) + " = " + \r
+ instance() + "." + ModelicaWriter.getDelayValve(order) + ";\n");\r
+ \r
+ return sb.toString();\r
+ }\r
+\r
+ @Override\r
+ public String getExpression() {\r
+ return "This + is + not + a + parameter + at + any + time";\r
+ }\r
+\r
+ @Override\r
+ public String getModelicaExpression() {\r
+ return getExpression();\r
+ }\r
+\r
+ @Override\r
+ public String validateUnits(ReadGraph graph, SysdynModel model) {\r
+ if(parent.getUnit() == null)\r
+ return "Unit not defined for " + parent.getName();\r
+\r
+ String result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), equation);\r
+ if(result == null)\r
+ result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), parent.getUnit(), initialValue);\r
+ if(result == null)\r
+ result = UnitUtils.matchUnits(graph, model, parent.getParentConfiguration(), UnitUtils.getTimeUnit(graph, model), delayTime);\r
+\r
+ return result;\r
+ }\r
+\r
+ public int getOrder() {\r
+ return order;\r
+ }\r
+\r
+ private String instance() {\r
+ // construct an identifier for this expression based on the array \r
+ // indices if necessary\r
+ String identifier;\r
+ if (getArrayRange() != null && !getArrayRange().isEmpty()) {\r
+ identifier = IndexUtils.rangeToIndexes(parent, getArrayRange()).replaceAll("[\\[\\]{},]", "_");\r
+ }\r
+ else {\r
+ identifier = "_";\r
+ }\r
+ return parent.getModelicaName() + identifier + "instance";\r
+ }\r
\r
}\r
\r
public class RepresentationUtils {\r
\r
-\r
/**\r
* Returns true, if there is an active experiment and the active experiment\r
* is a game experiment\r
* @return\r
*/\r
public static boolean isPartOfGameExperiment(Variable variable) {\r
- Configuration conf = variable.getParentConfiguration();\r
- if(conf != null)\r
- return conf.isGameConfiguration();\r
- else\r
- return false;\r
+ Configuration conf = variable.getParentConfiguration();\r
+ if(conf != null)\r
+ return conf.isGameConfiguration();\r
+ else\r
+ return false;\r
}\r
- \r
+\r
/**\r
- * Find out if a module is part of a game configuration. (This means that the module is a \r
- * part of a game experiment)\r
- * @param variable\r
- * @return\r
- */\r
- public static boolean isPartOfGameExperiment(Module module) {\r
- Configuration conf = module.getParentConfiguration();\r
- if(conf != null)\r
- return conf.isGameConfiguration();\r
- else\r
- return false;\r
- }\r
+ * Find out if a module is part of a game configuration. (This means that the module is a \r
+ * part of a game experiment)\r
+ * @param variable\r
+ * @return\r
+ */\r
+ public static boolean isPartOfGameExperiment(Module module) {\r
+ Configuration conf = module.getParentConfiguration();\r
+ if(conf != null)\r
+ return conf.isGameConfiguration();\r
+ else\r
+ return false;\r
+ }\r
\r
\r
/**\r
if(v.getName().equals(variable.getName())) {\r
return null;// Reference to self.\r
} else {\r
- if(Variability.PARAMETER.equals(Variability.getVariability(v, false, null))) {\r
- return v;\r
- } else {\r
- return null;\r
- }\r
- \r
- /*\r
+ if(Variability.PARAMETER.equals(Variability.getVariability(v, false, null))) {\r
+ return v;\r
+ } else {\r
+ return null;\r
+ }\r
+\r
+ /*\r
if(v.getExpressions() == null || v.getExpressions().getExpressions().size() > 1)\r
return null;\r
- \r
+\r
IExpression e = v.getExpressions().getExpressions().get(0);\r
- \r
+\r
if(e instanceof ParameterExpression)\r
return v;\r
*/\r
\r
\r
public static Variable getVariable(Configuration configuration, String name) {\r
- Configuration conf = configuration;\r
- // This function seems to be used with both whitespaced and\r
- // underscored versions of the variable name.\r
- String whitespacedName = name.replace('_', ' ');\r
- String[] components = whitespacedName.split("\\.");\r
- \r
- for(String component : components) {\r
- \r
- Configuration newConf = null;\r
- \r
- for(IElement element : conf.getElements()) {\r
- if(element instanceof Variable) {\r
- Variable variable = (Variable) element;\r
- if(variable.getName().equals(component)) {\r
- return variable;\r
- }\r
- } else if(element instanceof Module) {\r
- Module m = (Module)element;\r
- if(m.getName().equals(component)) {\r
- newConf = m.getType().getConfiguration();\r
- }\r
- }\r
- }\r
- \r
- // If variable or configuration has not been found, return null\r
- if(newConf == null)\r
- return null;\r
- }\r
- \r
- return null;\r
+ Configuration conf = configuration;\r
+ // This function seems to be used with both whitespaced and\r
+ // underscored versions of the variable name.\r
+ String whitespacedName = name.replace('_', ' ');\r
+ String[] components = whitespacedName.split("\\.");\r
+\r
+ for(String component : components) {\r
+\r
+ Configuration newConf = null;\r
+\r
+ for(IElement element : conf.getElements()) {\r
+ if(element instanceof Variable) {\r
+ Variable variable = (Variable) element;\r
+ if(variable.getName().equals(component)) {\r
+ return variable;\r
+ }\r
+ } else if(element instanceof Module) {\r
+ Module m = (Module)element;\r
+ if(m.getName().equals(component)) {\r
+ newConf = m.getType().getConfiguration();\r
+ }\r
+ }\r
+ }\r
+\r
+ // If variable or configuration has not been found, return null\r
+ if(newConf == null)\r
+ return null;\r
+ }\r
+\r
+ return null;\r
}\r
\r
}\r