From 8cbb4d899d33d6ed8ccb72788d515c66b417a31a Mon Sep 17 00:00:00 2001 From: lempinen Date: Thu, 23 Feb 2012 12:26:42 +0000 Subject: [PATCH] Automatic parameter declarations for all variables. Variability is not calculated from one module to another: the variability of input variables is set manually. (refs #2056) git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@24277 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../ui/modelica/SysdynModelicaEditor.java | 17 +- .../ui/properties/InputVariableTab.java | 77 +++++- .../ui/trend/chart/element/ChartNode.java | 12 +- org.simantics.sysdyn/META-INF/MANIFEST.MF | 2 + .../expressionParser/ExpressionParser.jj | 6 +- .../simantics/sysdyn/manager/SysdynModel.java | 15 +- .../sysdyn/modelica/ModelicaWriter.java | 225 ++++++++++++------ .../sysdyn/representation/Configuration.java | 22 +- .../sysdyn/representation/Entity.java | 25 ++ .../sysdyn/representation/Function.java | 78 ++++++ .../representation/FunctionLibrary.java | 78 ++++++ .../representation/IndependentVariable.java | 191 +++++++++------ .../sysdyn/representation/Input.java | 47 +++- .../sysdyn/representation/LibraryDummy.java | 29 ++- .../sysdyn/representation/Model.java | 123 +++++++++- .../sysdyn/representation/Module.java | 174 +++++++++++--- .../sysdyn/representation/ModuleType.java | 15 +- .../representation/SharedFunctionLibrary.java | 26 ++ .../sysdyn/representation/Stock.java | 110 ++++++--- .../sysdyn/representation/SysdynSchema.java | 6 +- .../sysdyn/representation/Variability.java | 180 ++++++++++++++ .../sysdyn/representation/Variable.java | 40 +++- .../annotations/BuiltinFunctions.java | 31 +++ .../annotations/BuiltinFunctionsAccessor.java | 57 +++++ .../annotations/BuiltinFunctionsFactory.java | 36 +++ .../expressions/ConstantExpression.java | 17 +- .../expressions/DelayExpression.java | 189 ++++++++++----- .../expressions/Expression.java | 21 +- .../expressions/IExpression.java | 40 +++- .../expressions/NormalExpression.java | 40 +--- .../expressions/ParameterExpression.java | 50 ++-- .../expressions/StockExpression.java | 59 +---- .../expressions/WithLookupExpression.java | 45 +--- 33 files changed, 1604 insertions(+), 479 deletions(-) create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Entity.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Function.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/FunctionLibrary.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SharedFunctionLibrary.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variability.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctions.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsAccessor.java create mode 100644 org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsFactory.java diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java index c5a2ed34..b6fcb97b 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -44,7 +44,12 @@ import org.simantics.sysdyn.representation.ModuleType; import org.simantics.ui.SimanticsUI; import org.simantics.ui.workbench.ResourceEditorInput; - +/** + * Text editor for displaying Modelica code + * + * @author Teemu Lempinen + * + */ public class SysdynModelicaEditor extends TextEditor { AnnotationModel annotationModel = new AnnotationModel(); @@ -80,16 +85,12 @@ public class SysdynModelicaEditor extends TextEditor { try { Configuration configuration = LoadRepresentation.loadConfiguration(SimanticsUI.getSession(), ((ResourceEditorInput)element).getResource()); - ModelicaWriter writer = new ModelicaWriter(); HashSet configurations = new HashSet(); configurations.add(configuration); getConfigurations(configuration, configurations); - - for(Configuration c : configurations) - writer.write(c); - - return new Document(writer.toString()); + + return new Document(ModelicaWriter.write(configurations)); } catch (DatabaseException e) { e.printStackTrace(); throw new CoreException(STATUS_ERROR); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java index a3d6b187..e55f2acd 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -12,6 +12,9 @@ package org.simantics.sysdyn.ui.properties; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; @@ -19,8 +22,15 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbenchSite; import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.TrackedCombo; import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl; +import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; import org.simantics.db.management.ISessionContext; import org.simantics.layer0.Layer0; import org.simantics.sysdyn.SysdynResource; @@ -29,6 +39,7 @@ import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactor import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier; import org.simantics.sysdyn.ui.properties.widgets.factories.VariableNamePropertyModifier; import org.simantics.sysdyn.ui.properties.widgets.factories.VariableNameValidator; +import org.simantics.utils.datastructures.Pair; import org.simantics.utils.ui.validators.DoubleValidator; /** @@ -53,7 +64,7 @@ public class InputVariableTab extends LabelPropertyTabContributor { GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); Composite defaultValueComposite = new Composite(composite, SWT.NONE); - GridDataFactory.fillDefaults().grab(false, true).applyTo(defaultValueComposite); + GridDataFactory.fillDefaults().grab(false, false).applyTo(defaultValueComposite); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(defaultValueComposite); Label label = new Label(defaultValueComposite, SWT.NULL); @@ -65,6 +76,68 @@ public class InputVariableTab extends LabelPropertyTabContributor { defaultValue.setInputValidator(new DoubleValidator()); GridDataFactory.fillDefaults().grab(true, false).applyTo(defaultValue.getWidget()); + Composite variabilityComposite = new Composite(composite, SWT.NONE); + GridDataFactory.fillDefaults().grab(false, true).applyTo(variabilityComposite); + GridLayoutFactory.fillDefaults().numColumns(2).applyTo(variabilityComposite); + + label = new Label(variabilityComposite, SWT.NULL); + label.setText("Variability:"); + + TrackedCombo variability = new TrackedCombo(variabilityComposite, support, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); + GridDataFactory.fillDefaults().grab(true, false).applyTo(variability.getWidget()); + setVariabilityFactories(variability); + new IsOutputWidget(composite, support, SWT.NULL); } + + /** + * set item, selection and modify properties for variability combo + * @param variability + */ + private void setVariabilityFactories(TrackedCombo variability) { + variability.setItemFactory(new ReadFactoryImpl>() { + + @Override + public Map perform(ReadGraph graph, final Resource input) throws DatabaseException { + Map map = new HashMap(); + map.put("continuous", "continuous"); + map.put("parameter", "parameter"); + map.put("constant", "constant"); + return map; + } + }); + + variability.setSelectionFactory(new ReadFactoryImpl() { + + public Object getIdentity(Object inputContents) { + return new Pair>(inputContents, getClass()); + } + + @Override + public String perform(ReadGraph graph, final Resource input) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + String variability = graph.getPossibleRelatedValue(input, sr.Variable_variability); + if(variability == null || variability.isEmpty()) + return "continuous"; + else + return variability; + } + }); + + variability.addModifyListener(new ComboModifyListenerImpl() { + + @Override + public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + String variability = text; + if(text.equals("continuous")) + variability = ""; + + if(variability != null) { + graph.claimLiteral(input, sr.Variable_variability, variability); + } + } + + }); + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/element/ChartNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/element/ChartNode.java index f0460938..c1c0d437 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/element/ChartNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/chart/element/ChartNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 Association for Decentralized Information Management in + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -28,6 +28,7 @@ import org.simantics.scenegraph.ISelectionPainterNode; import org.simantics.scenegraph.g2d.events.EventTypes; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; import org.simantics.scenegraph.swing.ComponentNode; import org.simantics.scenegraph.utils.GeometryUtils; @@ -256,6 +257,15 @@ public class ChartNode extends ComponentNode implements ISelectionPainte setBounds(bounds); } + @Override + protected boolean mouseDragged(MouseDragBegin e) { + if(dragging) { + return true; // Eat event for faster resize + } else { + return false; + } + } + @Override protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) { if(dragging) { diff --git a/org.simantics.sysdyn/META-INF/MANIFEST.MF b/org.simantics.sysdyn/META-INF/MANIFEST.MF index c83f7bdb..a7e2ceea 100644 --- a/org.simantics.sysdyn/META-INF/MANIFEST.MF +++ b/org.simantics.sysdyn/META-INF/MANIFEST.MF @@ -34,6 +34,8 @@ Export-Package: org.simantics.sysdyn, org.simantics.sysdyn.modelParser, org.simantics.sysdyn.modelica, org.simantics.sysdyn.representation, + org.simantics.sysdyn.representation.expressions, + org.simantics.sysdyn.representation.utils, org.simantics.sysdyn.representation.visitors, org.simantics.sysdyn.simulation, org.simantics.sysdyn.tableParser diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj b/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj index df82b2c8..bc00a188 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/expressionParser/ExpressionParser.jj @@ -263,7 +263,11 @@ void component_reference(String prevToken) : { void function_call_args() : { } { - "(" ( function_arguments() )? ")" + "(" ( function_arguments() )? ")" { if(functionCall != null) { + if(!functionCallReferences.containsKey(functionCall)) + functionCallReferences.put(functionCall, new ArrayList()); + } + } } void function_arguments() : { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java index 2bb5a165..20583a7b 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -198,7 +198,9 @@ public class SysdynModel implements IMappingListener, IModel { Layer0 l0 = Layer0.getInstance(graph); SysdynResource sr = SysdynResource.getInstance(graph); SimulationResource SIMU = SimulationResource.getInstance(graph); - Resource model = graph.getSingleObject(getConfigurationResource(), SIMU.IsConfigurationOf); + Resource model = graph.getPossibleObject(getConfigurationResource(), SIMU.IsConfigurationOf); + if(model == null) + return null; Collection experiments = graph.syncRequest(new ObjectsWithType(model, l0.ConsistsOf, sr.Experiment)); for(Resource experiment : experiments) { Collection experimentResults = graph.getObjects(experiment, sr.Experiment_result); @@ -263,12 +265,10 @@ public class SysdynModel implements IMappingListener, IModel { progressMonitor.subTask("Write modelica classes"); // Write Modelica files - ModelicaWriter writer = new ModelicaWriter(); + String modelText = null; try { // Write all configurations once - for(Configuration c : modules) { - writer.write(c); - } + modelText = ModelicaWriter.write(modules); } catch (Exception e) { // Stop experiment and show console setExperimentStopped(experiment); @@ -276,7 +276,6 @@ public class SysdynModel implements IMappingListener, IModel { monitor.message("Error when writing Modelica code."); return; } - String modelText = writer.toString(); progressMonitor.worked(1); // Write initial files and add init-parameters @@ -443,7 +442,9 @@ public class SysdynModel implements IMappingListener, IModel { while (c != null && p != null) { // if the lines are the same, no need for further examination if(!c.equals(p)) { - if(c.contains("parameter") && p.contains("parameter")) { + if( + c.contains("parameter") && c.contains("/* Actual value read from init file */") && + p.contains("parameter") && p.contains("/* Actual value read from init file */")) { /* * The line is a parameter definition. * In this case only what is before '=' matters diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java index c9cecaf0..53ac48bd 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 Association for Decentralized Information Management in + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -12,6 +12,7 @@ package org.simantics.sysdyn.modelica; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import org.simantics.sysdyn.representation.Book; @@ -26,27 +27,45 @@ import org.simantics.sysdyn.representation.ModuleType; import org.simantics.sysdyn.representation.Stock; import org.simantics.sysdyn.representation.Variable; +/** + * ModelicaWriter writes Sysdyn model representations (objmap) into Modelica code. + * + * @author Teemu Lempinen + * + */ public class ModelicaWriter { - StringBuilder b = new StringBuilder(); - String app; - boolean enumerationsWritten = false; - - public void write(Configuration conf) { - - if(!enumerationsWritten) { - b.append("partial class Enumeration_class\n"); - b.append(" parameter Integer size;\n"); - b.append(" parameter Integer elements[:];\n"); - b.append("end Enumeration_class;\n\n"); - enumerationsWritten = true; - } - - writeConfiguration(conf); + /** + * Write a collection of configurations into a single Modelica code + * + * @param Configurations Configurations, one main configuration and possible modules + * @return Complete Modelica code of a model + */ + public static String write(Collection configurations) { + StringBuilder b = new StringBuilder(); + + // Super class for enumerations + b.append("partial class Enumeration_class\n"); + b.append(" parameter Integer size;\n"); + b.append(" parameter Integer elements[:];\n"); + b.append("end Enumeration_class;\n\n"); + + for(Configuration conf : configurations) + writeConfiguration(conf, b); + + return b.toString(); } - private void writeConfiguration(Configuration configuration) { + /** + * Write a single configuration to a given string builder + * + * @param configuration Model or module configuration + * @param b String builder + */ + private static void writeConfiguration(Configuration configuration, StringBuilder b) { + String app; + // Lists for storing different configuration elements ArrayList variables = new ArrayList(); ArrayList inputs = new ArrayList(); ArrayList modules = new ArrayList(); @@ -60,41 +79,56 @@ public class ModelicaWriter { // Initialize lists for(IElement element : configuration.getElements()) { if(element instanceof IndependentVariable) { + // Normal variable variables.add((IndependentVariable)element); if(element instanceof Stock) + // Stock stocks.add((Stock)element); } else if (element instanceof Module) { + // Module Module m = (Module)element; modules.add(m); moduleInputs.put(m.getName(), new ArrayList()); for(IElement e : m.getType().getConfiguration().getElements()) + // Inputs inside the module if(e instanceof Input && !((Input)e).isHeadOfDependency()) { moduleInputs.get(m.getName()).add((Input)e); } } else if (element instanceof Input) { + // Input variables inputs.add((Input)element); } else if (element instanceof Enumeration) { + // Enumerations enumerations.add((Enumeration)element); } else if (element instanceof Dependency) { Dependency dependency = (Dependency)element; if(dependency.getHead() instanceof Module) { + // References given to child modules outputDependencies.add(dependency); } else if(dependency.getTail() instanceof Module){ + // References from child modules inputDependencies.add(dependency); } } else if (element instanceof Book) { + // Spreadsheet book book = (Book)element; } } + + // Setup input references. (Input, String reference to another variable) + HashMap inputReferences = new HashMap(); + setupInputReferences(inputReferences, inputDependencies); + + // If the configuration is model configuration, use model name. Otherwise, use configuration name. ModuleType mt = configuration.getModuleType(); String className = mt != null ? (mt.getName().replace(" ", "")) : (configuration.getName().replace(" ", "")); b.append("class ").append(className).append('\n'); b.append("// Variable definitions\n"); for(IndependentVariable variable : variables) { - app = variable.getDeclaration(); - if (app != null) b.append(app); + app = variable.getDeclaration(); + if (app != null) b.append(app); } if(!modules.isEmpty()) { @@ -104,20 +138,17 @@ public class ModelicaWriter { } } - if(!inputs.isEmpty()) { - b.append("// Input definitions\n"); - for(Input i : inputs) { - b.append(i.getDeclaration()); - } - } - + + // Input definitions + inputDefinitions(b, configuration, inputs, inputReferences); + if(!enumerations.isEmpty()) { b.append("// Enumeration definitions\n"); for(Enumeration e : enumerations) { b.append(e.getDeclaration()); } } - + if(book != null) { b.append("// Spreadsheet definition\n"); b.append(book.markBook()); @@ -125,64 +156,44 @@ public class ModelicaWriter { boolean initialEquations = false; for(Stock stock : stocks) { - app = stock.getInitialEquation(); - if (app != null) { - if(initialEquations == false) { - initialEquations = true; - b.append("// Initial Equations\n"); - b.append("initial equation\n"); - } - b.append(app); - } + app = stock.getInitialEquation(); + if (app != null) { + if(initialEquations == false) { + initialEquations = true; + b.append("// Initial Equations\n"); + b.append("initial equation\n"); + } + b.append(app); + } } b.append("equation\n"); b.append("// Equations\n"); for(IndependentVariable variable : variables) { - app = variable.getEquation(); - if (app != null) b.append(app); - } - - - b.append("// Inputs\n"); - for(Dependency dependency : inputDependencies) { - Input variable = (Input)dependency.getHead(); - Module module = (Module)dependency.getTail(); - Variable reference = (Variable)dependency.refersTo(); - if(reference != null && reference.getName() != null) - b.append(" " + variable.getName() + " = " + module.getName() + "." + reference.getName() + ";\n"); - else - b.append(" " + variable.getName() + " = " + variable.getDefaultInputValue() + ";\n"); - - if(configuration.getModel() != null) { - // Root configuration - inputs.remove(variable); - } + app = variable.getEquation(); + if (app != null) b.append(app); } - // Set root configuration input defaults - if(configuration.getModel() != null) { - for(Input i : inputs) { - b.append(" " + i.getName() + " = " + i.getDefaultInputValue() + ";\n"); - } - } - + // Continous input references + continuousInputReferences(b, inputReferences); + b.append("// Outputs\n"); for(Dependency dependency : outputDependencies) { Variable variable = (Variable)dependency.getTail(); Module module = (Module)dependency.getHead(); Input reference = (Input)dependency.refersTo(); - if(reference != null) { - b.append(" " + module.getName() + "." + reference.getName() + " = " + variable.getName() + ";\n"); - moduleInputs.get(module.getName()).remove(reference); + if(reference != null && (reference.getVariability() == null || reference.getVariability().isEmpty())) { + b.append(" " + module.getName() + "." + reference.getName() + " = " + variable.getName() + ";\n"); + moduleInputs.get(module.getName()).remove(reference); } } b.append("// Default values for inputs in modules\n"); for(String moduleLabel : moduleInputs.keySet()) { for(Input input : moduleInputs.get(moduleLabel)) { - b.append(" " + moduleLabel + "." + input.getName() + " = " + input.getDefaultInputValue(moduleLabel) + ";\n"); + if(input.getVariability() == null || input.getVariability().isEmpty()) + b.append(" " + moduleLabel + "." + input.getName() + " = " + input.getDefaultInputValue(moduleLabel) + ";\n"); } } @@ -195,14 +206,86 @@ public class ModelicaWriter { b.replace(s, s + book.markBook().length(), book.getBook()); } } + + /** + * Define continuous input references + * @param b String builder + * @param inputReferences Input references + */ + private static void continuousInputReferences(StringBuilder b, HashMap inputReferences) { + b.append("// Inputs\n"); + for(Input i : inputReferences.keySet()) { + if(i.getVariability() == null || i.getVariability().isEmpty()) { + // Define only continuous variables here + b.append(" " + i.getName() + " = " + inputReferences.get(i)); + } + } + } - public String escape(String name) { - return name.replace(' ', '_'); + /** + * Setup input references for all inputs that are defined in child modules + * + * @param inputReferences Map containing the references + * @param inputDependencies List of input dependencies + */ + private static void setupInputReferences(HashMap inputReferences, ArrayList inputDependencies) { + for(Dependency dependency : inputDependencies) { + Input input = (Input)dependency.getHead(); + Module module = (Module)dependency.getTail(); + Variable reference = (Variable)dependency.refersTo(); + String expression; + // If reference exists, use reference name. Otherwise, use default value. + if(reference != null && reference.getName() != null) + expression = module.getName() + "." + reference.getName() + ";\n"; + + else + expression = input.getDefaultInputValue() + ";\n"; + + inputReferences.put(input, expression); + } } - @Override - public String toString() { - return b.toString(); + /** + * Build input definitions + * + * @param b String builder + * @param configuration Module configuration + * @param inputs All inputs of this module + * @param inputReferences + */ + private static void inputDefinitions(StringBuilder b, Configuration configuration, ArrayList inputs, HashMap inputReferences) { + if(inputs.isEmpty()) + return; + + b.append("// Input definitions\n"); + for(Input i : inputs) { + if(i.getVariability() != null && !i.getVariability().isEmpty()) { + // Input is NOT continuous + if(inputReferences.containsKey(i)) { + // Input is defined in a child module + String declaration = i.getDeclaration(); + declaration = declaration.substring(0, declaration.length() - 2); // remove ";\n" from the end + b.append(declaration + " = " + inputReferences.get(i)); + } else { + // Input is not defined in a child module, use default value + b.append(i.getDeclarationWithValue()); + } + } else if(configuration.getModel() != null && !i.isHeadOfDependency()) { + /* + * Input is in the top of the hierarchy, + * and it does not get value from anywhere else. + * => Declare it wit its default value + */ + b.append(i.getDeclarationWithValue()); + } else { + // Continuous => Parent module takes care of declaring a value for the input + b.append(i.getDeclaration()); + } + } + } + + public String escape(String name) { + return name.replace(' ', '_'); } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java index 02279551..f13b4044 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,7 +22,12 @@ import org.simantics.simulation.ontology.SimulationResource; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; - +/** + * Representation of a model or module configuration + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.Configuration) public class Configuration { @@ -32,18 +37,28 @@ public class Configuration { @RelatedValue(Layer0.URIs.HasLabel) private String label; + /** + * Not null if configuration of a module + */ @RelatedElement(StructuralResource2.URIs.Defines) private ModuleType moduleType; + /** + * Not null if is configuration of a model + */ @RelatedElement(SimulationResource.URIs.IsConfigurationOf) private Model model; - + @RelatedElements( value = Layer0.URIs.ConsistsOf, composition = true) private ArrayList elements = new ArrayList(); + /** + * Get all elements of this configuration. Also all sheets from books are included. + * @return + */ public ArrayList getElements() { ArrayList elements = new ArrayList(); elements.addAll(this.elements); @@ -71,5 +86,4 @@ public class Configuration { return model; } - } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Entity.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Entity.java new file mode 100644 index 00000000..433848f6 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Entity.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation; + +import org.simantics.layer0.Layer0; +import org.simantics.objmap.annotations.GraphType; + +/** + * Dummy class representing any entity. + * @author Teemu Lempinen + * + */ +@GraphType(Layer0.URIs.Entity) +public class Entity { + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Function.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Function.java new file mode 100644 index 00000000..59243839 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Function.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedValue; +import org.simantics.objmap.annotations.UpdateMethod; +import org.simantics.sysdyn.SysdynResource; + +/** + * Representation of a function + * + * @author Teemu Lempinen + * + */ +@GraphType(SysdynResource.URIs.SysdynModelicaFunction) +public class Function { + + @RelatedValue(Layer0.URIs.HasName) + private String name; + + @RelatedValue(SysdynResource.URIs.SysdynModelicaFunction_modelicaFunctionCode) + private String code; + + private boolean hasTimeReference = false; + + public String getCode() { + return + "function " + name + "\n" + + code + + "end " + name + ";\n"; + } + + public String getName() { + return name; + } + + /** + * Keep track if the function contains references to time. If there is a reference to time, + * the variables calling this function cannot be parameters or constants. + * + * @param g ReadGraph + * @param r Function resource + * @return + * @throws DatabaseException + */ + @UpdateMethod + public boolean update(ReadGraph g, Resource r) throws DatabaseException { + String code = g.getPossibleRelatedValue(r, SysdynResource.getInstance(g).SysdynModelicaFunction_modelicaFunctionCode); + String[] elements = code.split("[\\+\\-\\*\\/\\(\\)\\[\\]\\{\\}=;\\s]"); + hasTimeReference = false; + for(String element : elements) { + if("time".equals(element)) { + hasTimeReference = true; + break; + } + } + return true; + } + + public boolean hasTimeReference() { + return hasTimeReference; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/FunctionLibrary.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/FunctionLibrary.java new file mode 100644 index 00000000..5300a34e --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/FunctionLibrary.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation; + +import java.util.ArrayList; + + +import org.simantics.layer0.Layer0; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedElements; +import org.simantics.objmap.annotations.RelatedValue; +import org.simantics.sysdyn.SysdynResource; +/** + * Representation of a function library + * + * @author Teemu Lempinen + * + */ +@GraphType(SysdynResource.URIs.SysdynModelicaFunctionLibrary) +public class FunctionLibrary { + + @RelatedValue(Layer0.URIs.HasName) + private String name; + + @RelatedElements( + value = Layer0.URIs.ConsistsOf, + composition = true) + private ArrayList elements = new ArrayList(); + + /** + * Get all functions inside this library. (sub-libraries excluded) + * @return + */ + public ArrayList getFunctions() { + ArrayList functions = new ArrayList(); + if(elements != null) { + for(Object element : elements) { + if(element instanceof Function) + functions.add((Function)element); + } + } + return functions; + } + + /** + * Get all function libraries included in this library + * @return All function libraries included in this library + */ + public ArrayList getLibraries() { + ArrayList libraries = new ArrayList(); + if(elements != null) { + for(Object element : elements) { + if(element instanceof FunctionLibrary) + libraries.add((FunctionLibrary)element); + } + } + return libraries; + } + + /** + * Get the name of this library + * @return The name of this library + */ + public String getName() { + return name; + } + + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java index fa6b9f59..945f9d78 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/IndependentVariable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -12,84 +12,135 @@ package org.simantics.sysdyn.representation; import java.util.ArrayList; +import java.util.Iterator; import org.simantics.sysdyn.representation.expressions.IExpression; -import org.simantics.sysdyn.representation.expressions.ParameterExpression; +/** + * Representation of an independent variable + * + * @author Teemu Lempinen + * + */ public abstract class IndependentVariable extends Variable { - + + /** + * Get the declaration of this variable + * @return Declaration of this variable + */ public String getDeclaration() { - ArrayList expressions = this.expressions.getExpressions(); - return expressions.get(0).getDeclaration(this); - - /* - ArrayList expressions = this.expressions.getExpressions(); - ArrayIndexes ai = this.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - if(enumerations == null || enumerations.size() < 1) { - // NOT an array variable, get declaration from the only expression. - if(expressions.get(0) == null) - return null; - else - return expressions.get(0).getDeclaration(this); - } else { - // ARRAY variable. Create declaration according to the type, name and indexes - //TODO: check if all of them are parameters -> form a parameter - StringBuilder sb = new StringBuilder(); - sb.append(" "); - sb.append(this.getType()); - sb.append(" "); - sb.append(this.getName()); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName()); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("];\n"); - return sb.toString(); - } - */ + Variability variability = Variability.getVariability(this); + + // [variability] type name[range] + StringBuilder sb = new StringBuilder(); + sb.append(" "); + sb.append(variability.getText().isEmpty() ? "" : variability.getText() + " "); + sb.append(getType() + " "); + sb.append(getName()); + sb.append(getRange()); + + // [= expression] + if(variability == Variability.PARAMETER || variability == Variability.CONSTANT) { + // parameters and constants are guaranteed to have only one expression + sb.append(" = " + getExpressions().getExpressions().get(0).getExpression(this)); + } + + // ;\n + sb.append(";\n"); + + // Possible additions to expressions. e.g. helper classes and variables + String addition; + for(IExpression e : getExpressions().getExpressions()) { + addition = e.getDeclarationAddition(this); + if(addition != null) + sb.append(addition); + } + + return sb.toString(); + } + + /** + * Get the range of this variable, if it is an array variable. + *

+ * Format: [EnumerationName.size (, Enumeration2Name.size)*] + * @return Range of this variable, if it is an array variable. Empty string otherwise. + */ + public String getRange() { + ArrayIndexes ai = getArrayIndexes(); + ArrayList enumerations = null; + if(ai != null) + enumerations = ai.getEnumerations(); + + String range = ""; + if(enumerations != null && enumerations.size() > 0) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + Iterator iterator = enumerations.iterator(); + while(iterator.hasNext()) { + sb.append(iterator.next().getName() + ".size"); + if(iterator.hasNext()) { + sb.append(", "); + } + } + sb.append("]"); + range = sb.toString(); + } + return range; } - + + /** + * Get all initial equations or null, if there are no initial equations. + * @return Initial equations as string or null. + */ public String getInitialEquation() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - for(IExpression expression : expressions.getExpressions()) { - String initialEquation = expression.getInitialEquation(this); - if(initialEquation != null) - sb.append(initialEquation); - } - String result = sb.toString(); - return result.length() > 0 ? result : null; + for(IExpression expression : expressions.getExpressions()) { + String initialEquation = expression.getInitialEquation(this); + if(initialEquation != null) + sb.append(initialEquation); + } + String result = sb.toString(); + return result.length() > 0 ? result : null; } - + + /** + * Get the equation of this variable for equation block. Null is returned if this variable is not continuous. + * @return Equation or null + */ public String getEquation() { - ArrayList expressions = this.expressions.getExpressions(); - ArrayIndexes ai = this.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - IExpression firstExpression = expressions.get(0); - if(enumerations == null || enumerations.size() < 1) { - // NOT an array variable, get equation from the only expression. - if(firstExpression == null || firstExpression instanceof ParameterExpression) - return null; - else - return firstExpression.getEquation(this); - } else { - // ARRAY variable. Create all equations for the variable - //TODO: check that it has not been a parameter - StringBuilder sb = new StringBuilder(); - for(IExpression expression : expressions) { - sb.append(expression.getEquation(this)); - } - return sb.toString(); - } - + Variability variability = Variability.getVariability(this); + if(variability == Variability.CONTINUOUS) { + return getVariableEquation(); + } else { + return null; + } + + } + + /** + * Combines all possible equations for this variable. Array variables can have multiple equations. + * @return equations or null + */ + protected String getVariableEquation() { + ArrayList expressions = this.expressions.getExpressions(); + ArrayIndexes ai = this.getArrayIndexes(); + ArrayList enumerations = null; + if(ai != null) + enumerations = ai.getEnumerations(); + IExpression firstExpression = expressions.get(0); + if(enumerations == null || enumerations.size() < 1) { + if(firstExpression == null) + return null; + else + return firstExpression.getEquation(this); + } else { + // ARRAY variable. Create all equations for the variable + StringBuilder sb = new StringBuilder(); + for(IExpression expression : expressions) { + sb.append(expression.getEquation(this)); + } + return sb.toString(); + } } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Input.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Input.java index 96f3a5c4..f3e10ac9 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Input.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Input.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -21,6 +21,12 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; +/** + * Representation of an input variable + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.Input) public class Input extends Variable { @@ -29,13 +35,20 @@ public class Input extends Variable { @RelatedElements(SysdynResource.URIs.Variable_isHeadOf) private List isHeadOf; - - @Override public void accept(IElementVisitorVoid v) { v.visit(this); } + /** + * Get the default value for this input. Default values may be set in either + * inside input's own module or in its parent module. If the value is set in a + * parent module, give input module's instance name as inModule. + * + * @param inModule The name of the instance in which this variable is. + * Can be null, if default value is set inside the variable's own module. + * @return Default input value. + */ public String getDefaultInputValue(String inModule) { if( getArrayIndexes() == null || getArrayIndexes().getEnumerations().isEmpty()) { return defaultInputValue.toString(); @@ -47,7 +60,7 @@ public class Input extends Variable { Iterator i = getArrayIndexes().getEnumerations().iterator(); while(i.hasNext()) { Enumeration e = i.next(); - sb.append((!inModule.isEmpty() && inModule != null ? inModule + "." : "") + e.getName() + ".size"); + sb.append((inModule != null && !inModule.isEmpty() ? inModule + "." : "") + e.getName() + ".size"); if(i.hasNext()) sb.append(", "); } @@ -56,14 +69,37 @@ public class Input extends Variable { } } + /** + * Get the default value for this input inside it's own module. + * @return Default value + */ public String getDefaultInputValue() { return getDefaultInputValue(null); } + /** + * Is there a connection to this input variable from a module. (i.e. does this input variable possibly get its value from a child module) + * @return + */ public boolean isHeadOfDependency() { return !isHeadOf.isEmpty(); } + /** + * Get the declaration of this input variable with its default value + * @return declaration of this input variable with its default value + */ + public String getDeclarationWithValue() { + String declaration = getDeclaration(); + declaration = declaration.substring(0, declaration.length() - 2); // remove ";\n" + declaration += " = " + getDefaultInputValue() + ";\n"; + return declaration; + } + + /** + * Get the declaration of this input variable without a default value + * @return declaration of this input variable without a default value + */ public String getDeclaration() { ArrayIndexes ai = getArrayIndexes(); ArrayList enumerations = null; @@ -85,6 +121,7 @@ public class Input extends Variable { range = sb.toString(); } - return " " + getType() + " " + getName() + range + ";\n"; + boolean continuous = variability == null || variability.isEmpty(); + return " " + (continuous ? "" : variability + " ") + getType() + " " + getName() + range + ";\n"; } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/LibraryDummy.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/LibraryDummy.java index 9e0c59b1..6abe502c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/LibraryDummy.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/LibraryDummy.java @@ -1,16 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ package org.simantics.sysdyn.representation; import org.simantics.layer0.Layer0; import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; - +/** + * A dummy variable representing any possible library + * @author Teemu Lempinen + * + */ @GraphType(Layer0.URIs.Library) public class LibraryDummy implements IElement { + + @RelatedValue(Layer0.URIs.HasName) + private String name; @Override public void accept(IElementVisitorVoid v) { v.visit(this); } + + /** + * Name of the library + * @return Name of the library + */ + public String getName() { + return name; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Model.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Model.java index d2d5da2d..371241e9 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Model.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Model.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,46 +11,155 @@ *******************************************************************************/ package org.simantics.sysdyn.representation; +import java.util.ArrayList; +import java.util.HashMap; + +import org.simantics.layer0.Layer0; import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedElements; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.representation.annotations.BuiltinFunctions; +/** + * Representation of a system dynamics model + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.SysdynModel) public class Model { @RelatedValue(SysdynResource.URIs.SysdynModel_startTime) private Double startTime = 0.0; - + @RelatedValue(SysdynResource.URIs.SysdynModel_stopTime) private Double stopTime = 10.0; - + @RelatedValue(SysdynResource.URIs.SysdynModel_outputInterval) private Double outputInterval; - + @RelatedValue(SysdynResource.URIs.SysdynModel_tolerance) private Double tolerance; - + @RelatedValue(SysdynResource.URIs.SysdynModel_solver) private String solver; + @RelatedElements( + value = Layer0.URIs.ConsistsOf, + composition = true) + private ArrayList consistsOf = new ArrayList(); + + @RelatedElements( + value = Layer0.URIs.IsLinkedTo, + composition = true) + private ArrayList linkedTo = new ArrayList(); + + + @BuiltinFunctions + private FunctionLibrary builtins; + + /** + * + * @return Simulation start time + */ public Double getStartTime() { return startTime; } + /** + * + * @return Simulation end time + */ public Double getStopTime() { return stopTime; } - + + /** + * Result output interval + * @return + */ public Double getOutputInterval() { - return outputInterval; + return outputInterval; } + /** + * + * @return Tolerance for simulation engine + */ public Double getTolerance() { return tolerance; } + /** + * + * @return Solver name + */ public String getSolver() { return solver; } + + /** + * Get all functions that are linked to this model: built-in functions, model's own functions and shared function libraries + * @return all functions liked to this model + */ + public HashMap getFunctions() { + HashMap functions = new HashMap(); + if(consistsOf != null ) { + for(Object o : consistsOf) { + if(o instanceof Function) { + Function f = (Function) o; + functions.put(f.getName(), f); + } else if (o instanceof FunctionLibrary) { + addFunctions("", (FunctionLibrary)o, functions); + } + } + } + + if(linkedTo != null) { + for(Object o : linkedTo) { + if(o instanceof SharedFunctionLibrary) { + SharedFunctionLibrary fl = (SharedFunctionLibrary)o; + addFunctions(fl.getName(), fl, functions); + } + } + } + + if(builtins != null) + addBuiltinFunctions(builtins, functions); + + return functions; + } + /** + * Add built-in functions to functions map. Built-in functions do not have any library path. + * @param library Built-in function library + * @param functions Function map containing all functions + */ + private void addBuiltinFunctions(FunctionLibrary library, HashMap functions) { + for(Function f : library.getFunctions()) + functions.put(f.getName(), f); + for(FunctionLibrary fl : library.getLibraries()) + addBuiltinFunctions(fl, functions); + } + + /** + * Add functions from a library to a library map + * @param path Path to the library + * @param library Function library + * @param functions Function map containing all functions + */ + private void addFunctions(String path, FunctionLibrary library, HashMap functions) { + for(Function f : library.getFunctions()) + functions.put(path + (path.isEmpty() ? "" : ".") + f.getName(), f); + for(FunctionLibrary fl : library.getLibraries()) + addFunctions((path.isEmpty() ? "" : path + ".") + fl.getName(), fl, functions); + } + + /** + * + * @return Built-in functions library + */ + public FunctionLibrary getBuiltins() { + return builtins; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Module.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Module.java index c5ece68c..415fdc05 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Module.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Module.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,7 +22,13 @@ import org.simantics.objmap.annotations.RelatedElements; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; +import org.simantics.utils.datastructures.Pair; +/** + * Representation of a module instance + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.Module) public class Module implements IElement { @@ -34,7 +40,7 @@ public class Module implements IElement { @RelatedElement(Layer0.URIs.InstanceOf) private ModuleType type; - + @RelatedElements(SysdynResource.URIs.Module_redeclaration) private List redeclarations; @@ -46,63 +52,155 @@ public class Module implements IElement { public String getName() { return name; } - + public ModuleType getType() { - return type; + return type; } - + /** - * Returns the declaration of a module with possible redeclared enumerations - * - * parameter Integer Enum__size = Enum.size; - * parameter Integer Enum__elements[:] = Enum.elements; - * ModuleType ModuleType1(Enum.size = Enum__size, Enum.elements = Enum__elements); + * Returns the declaration of a module with possible redeclared enumerations and parameter assignments + * + *

+ * Enumeration redeclaration: + * parameter Integer Enum__size = Enum.size;
+ * parameter Integer Enum__elements[:] = Enum.elements;
+ * ModuleType ModuleType1(Enum.size = Enum__size, Enum.elements = Enum__elements);
* + *

* Temporary parameter variables are needed to avoid name conflicts when redeclaring an * enumeration with the same name. * * @return Declaration of a module instance */ public String getDeclaration() { - - StringBuilder redeclarations = new StringBuilder(); - if(!getRedeclarations().isEmpty()) { - redeclarations.append("("); - Iterator i = getRedeclarations().iterator(); - while(i.hasNext()) { - Redeclaration rd = i.next(); - redeclarations.append(rd.getRedeclaration()); - if(i.hasNext()) - redeclarations.append(","); - } - redeclarations.append(")"); - } - - - StringBuilder sb = new StringBuilder(); - sb.append(" "); - sb.append(getType().getName()); - sb.append(" "); - sb.append(getName()); - sb.append(redeclarations.toString()); - sb.append(";\n"); - return sb.toString(); + + + String enumerationRedeclarations = getEnumerationRedeclarations(); + Pair inputRedeclarations = getInputRedeclarations(); + + StringBuilder redeclarations = new StringBuilder(); + + if(!enumerationRedeclarations.isEmpty() || !inputRedeclarations.first.isEmpty()) { + redeclarations.append("("); + redeclarations.append(enumerationRedeclarations); + + String ir = inputRedeclarations.first; + if(enumerationRedeclarations.isEmpty() && !inputRedeclarations.first.isEmpty()) + // remove first ", " if no enumeration redeclarations + ir = inputRedeclarations.first.substring(2); + redeclarations.append(ir); + + redeclarations.append(")"); + } + + StringBuilder sb = new StringBuilder(); + + // Possible reference variables + if(inputRedeclarations.second != null && !inputRedeclarations.second.isEmpty()) { + sb.append(inputRedeclarations.second); + } + + sb.append(" "); + sb.append(getType().getName()); + sb.append(" "); + sb.append(getName()); + sb.append(redeclarations.toString()); // possible redeclarations + sb.append(";\n"); + return sb.toString(); + } + + /** + * Get possible enumeration redeclarations. + * @return enumeration redeclarations or empty string + */ + private String getEnumerationRedeclarations() { + StringBuilder redeclarations = new StringBuilder(); + if(!getRedeclarations().isEmpty()) { + + Iterator i = getRedeclarations().iterator(); + while(i.hasNext()) { + Redeclaration rd = i.next(); + redeclarations.append(rd.getRedeclaration()); + if(i.hasNext()) + redeclarations.append(","); + } + } + return redeclarations.toString(); + } + + /** + * Get possible input redeclarations + * @return input redeclarations or empty string + */ + private Pair getInputRedeclarations() { + StringBuilder declarations = new StringBuilder(); + StringBuilder references = new StringBuilder(); + + for(IElement element : parentConfiguration.getElements()) { + if (element instanceof Dependency) { + Dependency dependency = (Dependency)element; + if(dependency.getHead().equals(this)){ + Input reference = (Input)dependency.refersTo(); + Variable outputVariable = (Variable)dependency.getTail(); + String name = outputVariable.getName(); + + Module module = (Module)dependency.getHead(); + + if(reference != null && reference.getName() != null) { + if(reference.getVariability() == null || reference.getVariability().isEmpty()) + continue; // Only parameters and constants are redeclared + + for(IElement e : module.getType().getConfiguration().getElements()) { + if(e instanceof Variable) { + Variable v = (Variable)e; + + if(v.getName() != null && outputVariable.getName().equals(v.getName())) { + /* + * The target module contains a variable with the same name. Need to + * avoid Module(variable = variable) situations + */ + String declaration; + if(outputVariable instanceof Input) + declaration = ((Input)outputVariable).getDeclaration(); + else + declaration = ((IndependentVariable)outputVariable).getDeclaration(); + + if(declaration.contains("=")) + declaration = declaration.substring(0, declaration.indexOf("=") - 1); // Break to "=" + else + declaration = declaration.substring(0, declaration.length() - 2); // Remove ending ";\n" + + name = outputVariable.getName() + "_reference"; + declaration = declaration.replace(outputVariable.getName(), name); + declaration += " = " + outputVariable.getName() + " /* Reference value to avoid name conflicts in module instantiation */ ;\n"; + references.append(declaration); + break; + } + } + } + + declarations.append(", " + reference.getName() + " = " + name); + } + } + } + } + return new Pair(declarations.toString(), references.toString()); } public Configuration getParentConfiguration() { return this.parentConfiguration; } - + /** * Return the list of the defined redeclarations for this module instance. * * @return List of the defined redeclarations or an empty list if redeclarations have not been set */ public List getRedeclarations() { - if(redeclarations == null) { - redeclarations = new ArrayList(); - } - return redeclarations; + if(redeclarations == null) { + redeclarations = new ArrayList(); + } + return redeclarations; } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/ModuleType.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/ModuleType.java index 148018c7..5b57d2b4 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/ModuleType.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/ModuleType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -18,6 +18,12 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; +/** + * Representation of a module type + * + * @author Teemu Lempinen + * + */ @GraphType(StructuralResource2.URIs.ComponentType) public class ModuleType implements IElement { @@ -26,6 +32,9 @@ public class ModuleType implements IElement { @RelatedElement(StructuralResource2.URIs.IsDefinedBy) private Configuration configuration; + + @RelatedElement(Layer0.URIs.PartOf) + protected Object parent; public String getName() { return name; @@ -38,5 +47,9 @@ public class ModuleType implements IElement { @Override public void accept(IElementVisitorVoid v) { } + + public Object getParent() { + return parent; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SharedFunctionLibrary.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SharedFunctionLibrary.java new file mode 100644 index 00000000..357f9d09 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SharedFunctionLibrary.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation; + +import org.simantics.objmap.annotations.GraphType; +import org.simantics.sysdyn.SysdynResource; + +/** + * Representation of a shared function library. See {@link FunctionLibrary} + * + * @author Teemu Lempinen + * + */ +@GraphType(SysdynResource.URIs.SharedFunctionOntology) +public class SharedFunctionLibrary extends FunctionLibrary { + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java index ec92d298..9dde7e4f 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Stock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,50 +16,106 @@ import java.util.ArrayList; import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedElements; import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.representation.expressions.StockExpression; import org.simantics.sysdyn.representation.visitors.IElementVisitorVoid; +/** + * Representation of a Stock variable + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.Stock) public class Stock extends IndependentVariable { @RelatedElements( value = SysdynResource.URIs.Variable_isHeadOf, composition = true) - private ArrayList incomingConnections = new ArrayList(); - + private ArrayList incomingConnections = new ArrayList(); + @RelatedElements( value = SysdynResource.URIs.Variable_isTailOf, composition = true) - private ArrayList outgoingConnections = new ArrayList(); - + private ArrayList outgoingConnections = new ArrayList(); + @Override public void accept(IElementVisitorVoid v) { v.visit(this); } - public ArrayList getIncomingValves() { - ArrayList valves = new ArrayList(); - for(IElement element : incomingConnections) { - if(element instanceof Flow) { - Flow flow = (Flow)element; - valves.add((Valve)flow.getTail()); - } - } - return valves; - } - - public ArrayList getOutgoingValves() { - ArrayList valves = new ArrayList(); - for(IElement element : outgoingConnections) { - if(element instanceof Flow) { - Flow flow = (Flow)element; - valves.add((Valve)flow.getHead()); - } - } - return valves; - } - + @Override + public String getInitialEquation() { + if (Variability.getVariability(this) == Variability.CONTINUOUS) { + return super.getInitialEquation(); + } else { + return null; + } + } + @Override + public String getDeclaration() { + + ArrayIndexes ai = getArrayIndexes(); + + String each = ""; + // each is required when a single value is used for all dimensions e.g. Stock[30](each start = 0) + if (Variability.getVariability(this) == Variability.CONTINUOUS) { + // start parameter is not used, everything needs to be fixed=false + if(ai != null && !ai.getEnumerations().isEmpty()) + each = "each"; + return " " + getType() + " " + getName() + getRange() + "(" + each + " fixed=false);\n"; + } else { + // Start parameter is used. Parameter guarantees that there is only one expression. + StockExpression e = (StockExpression)getExpressions().getExpressions().get(0); + String initialEquation = e.getExpression(this); + + if(ai != null && !ai.getEnumerations().isEmpty()) + each = "each"; + + + return " " + + getType() + + " " + + getName() + + getRange() + + "(" + + (e.getStartValue(this) != null ? each : "") + + " start=" + + initialEquation + + ", " + + each + + " fixed=true);\n"; + } + } + + public String getEquation() { + return getVariableEquation(); + } + + + public ArrayList getIncomingValves() { + ArrayList valves = new ArrayList(); + for(IElement element : incomingConnections) { + if(element instanceof Flow) { + Flow flow = (Flow)element; + valves.add((Valve)flow.getTail()); + } + } + return valves; + } + + public ArrayList getOutgoingValves() { + ArrayList valves = new ArrayList(); + for(IElement element : outgoingConnections) { + if(element instanceof Flow) { + Flow flow = (Flow)element; + valves.add((Valve)flow.getHead()); + } + } + return valves; + } + + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SysdynSchema.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SysdynSchema.java index aadf2a0f..0621f830 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SysdynSchema.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/SysdynSchema.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -56,6 +56,10 @@ public class SysdynSchema extends SimpleSchema { addLinkType(MappingSchemas.fromAnnotations(g, Sheet.class)); addLinkType(MappingSchemas.fromAnnotations(g, DiagramContainerDummy.class)); addLinkType(MappingSchemas.fromAnnotations(g, DelayExpression.class)); + addLinkType(MappingSchemas.fromAnnotations(g, FunctionLibrary.class)); + addLinkType(MappingSchemas.fromAnnotations(g, SharedFunctionLibrary.class)); + addLinkType(MappingSchemas.fromAnnotations(g, Function.class)); + addLinkType(MappingSchemas.fromAnnotations(g, Entity.class)); } catch (DatabaseException e) { e.printStackTrace(); } catch (InstantiationException e) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variability.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variability.java new file mode 100644 index 00000000..db9d4ab9 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variability.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; + +import org.simantics.sysdyn.expressionParser.ExpressionParser; +import org.simantics.sysdyn.expressionParser.ParseException; +import org.simantics.sysdyn.representation.utils.FormatUtils; + +/** + * Variability of a variable in system dynamics models. + * + * @author Teemu Lempinen + * + */ +public enum Variability { + + PARAMETER("parameter"), + CONSTANT("constant"), + CONTINUOUS(""); + + private String text; + + Variability(String text) { + this.text = text; + } + + public String getText() { + return this.text; + } + + /** + * Convert a textual representation to a Variability object. + * + * @param text Variability as text (parameter / constant / continuous) + * @return Variability or null + */ + public static Variability fromString(String text) { + if (text != null) { + for (Variability v : Variability.values()) { + if (text.equalsIgnoreCase(v.text)) { + return v; + } + } + } + return null; + } + + /** + * Check if reference in a configuration is a parameter. + * @param configuration Configuration + * @param reference String reference to a variable + * @return is the reference a parameter + */ + private static boolean isParameter(Configuration configuration, String reference) { + // Check if references are references to sheets. + // Sheet references are allowed, since sheets contain only constants + + // We only need the first element to know that it is a Sheet (SheetName.CellOrRange) + String r = reference.split("\\.")[0]; + for(IElement element : configuration.getElements()) { + if(element instanceof Module) { + Module m = (Module)element; + if(r.equals(m.getName())) { + if(!reference.contains(".")) { + // The reference contains only modules, implementation feature for the expression parser + return true; + } + Configuration moduleConfiguration = m.getType().getConfiguration(); + return isParameter(moduleConfiguration, reference.substring(reference.indexOf(".") + 1)); + } + } else if(element instanceof Book) { + for(Sheet sheet : ((Book)element).getSheets()) { + if(r.equals(sheet.getName())) { + return true; + } + } + } else if(element instanceof IndependentVariable && !(element instanceof Stock)) { + IndependentVariable v = (IndependentVariable)element; + if(r.equals(v.getName())) { + return getVariability(v) != Variability.CONTINUOUS; + } + } else if(element instanceof Input) { + Input i = (Input)element; + if(r.equals(i.getName())) { + return i.getVariability() != null && !i.getVariability().equals(Variability.CONTINUOUS.getText()); + } + + + } + } + // If there was no sheet for this reference name, return false + return false; + } + + static public Variability getVariability(IndependentVariable variable) { + ArrayList expressions = variable.getExpressions().getExpressions(); + + if(expressions.size() != 1) + return Variability.CONTINUOUS; // Cannot handle multiple expressions as parameters + + org.simantics.sysdyn.representation.expressions.IExpression ie = expressions.get(0); + + String expression = ie.getExpression(variable); + + return getVariability(variable, expression); + } + + /** + * Get the variability of an expression in a variable. Variables may have multiple expressions. + * + * @param variable Variable + * @param expression Expression + * @return Variability of the expression + */ + static public Variability getVariability(IndependentVariable variable, String expression) { + + // If no variables are used in the equation, start value is used + + HashMap functions = new HashMap(); + if(variable.getParentConfiguration() != null) { + Configuration conf = variable.getParentConfiguration(); + Model model = null; + if(conf.getModuleType() != null) { + ModuleType moduleType = conf.getModuleType(); + if (moduleType.getParent() instanceof Model) { + model = (Model) moduleType.getParent(); + } + } else { + model = conf.getModel(); + } + + if(model != null) + functions = model.getFunctions(); + } + + // First the equation is formatted and parsed + String equation = FormatUtils.formatExpressionForModelica(variable, expression); + ExpressionParser parser = new ExpressionParser(new StringReader(equation)); + try { + parser.expr(); + if(parser.getReferences().isEmpty() && parser.getFunctionCallReferences().isEmpty()) { + // if equation did not contain any references, start value is used + return Variability.PARAMETER; + } else { + Set references = parser.getReferences().keySet(); + // Go through each reference + for(String reference : references) { + if(!isParameter(variable.getParentConfiguration(), reference)) { + return Variability.CONTINUOUS; + } + } + + for(String function : parser.getFunctionCallReferences().keySet()) { + if(functions.containsKey(function) && functions.get(function).hasTimeReference()) + return Variability.CONTINUOUS; + } + + // All found variables were sheets or non-continuous + return Variability.PARAMETER; + } + } catch (ParseException e) { + } + + return Variability.CONTINUOUS; + } + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variable.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variable.java index f8d5a943..1f1e1fc5 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variable.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Variable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -17,6 +17,11 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.expressions.Expressions; +/** + * Abstract class for representing a variable in system dynamics models + * @author Teemu Lempinen + * + */ public abstract class Variable implements IElement { @RelatedValue(SysdynResource.URIs.Variable_type) @@ -34,11 +39,29 @@ public abstract class Variable implements IElement { @RelatedElement(SysdynResource.URIs.Variable_expressions) protected Expressions expressions; - + @RelatedValue(SysdynResource.URIs.Variable_variability) + protected String variability; + + /** + * Return the variability of this variable (Used in practice only with Input variables) + * @return Variability + */ + public String getVariability() { + return variability; + } + + /** + * + * @return The name of this variable + */ public String getName() { return this.name; } + /** + * + * @return Parent configuration of this variable (or null if something is wrong) + */ public Configuration getParentConfiguration() { if(parent instanceof Configuration) { return (Configuration)parent; @@ -49,15 +72,28 @@ public abstract class Variable implements IElement { } } + /** + * + * @return The type of this variable (Real / Boolean / ...) + */ public String getType() { return this.type; } + /** + * + * @return Array indexes for this variable + */ public ArrayIndexes getArrayIndexes() { return this.arrayIndexes; } + /** + * + * @return Expressions of this variable + */ public Expressions getExpressions() { return this.expressions; } + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctions.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctions.java new file mode 100644 index 00000000..173db2c2 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctions.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.simantics.objmap.annotations.meta.HasFieldRuleFactory; + +/** + * BuiltinFunctions -annotation returns the built-in functions function library + * @author Teemu Lempinen + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@HasFieldRuleFactory(BuiltinFunctionsFactory.class) +public @interface BuiltinFunctions { +} + diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsAccessor.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsAccessor.java new file mode 100644 index 00000000..c010706c --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsAccessor.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ + +package org.simantics.sysdyn.representation.annotations; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.PossibleObjectWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.objmap.MappingException; +import org.simantics.objmap.rules.domain.IDomainAccessor; +import org.simantics.sysdyn.SysdynResource; + +/** + * Accesses the built-in functions in Sysdyn ontology + * + * @author Teemu Lempinen + */ +public class BuiltinFunctionsAccessor implements IDomainAccessor { + + + public BuiltinFunctionsAccessor() { + } + + @Override + public Resource get(ReadGraph graph, Resource element) throws MappingException { + SysdynResource sr = SysdynResource.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + Resource builtinFunctions = null; + try { + Resource sysdyn = graph.getResource("http://www.simantics.org/Sysdyn-1.1"); + builtinFunctions = graph.syncRequest(new PossibleObjectWithType(sysdyn, l0.ConsistsOf, sr.SysdynModelicaFunctionLibrary)); + } catch (DatabaseException e) { + throw new MappingException(e); + } + return builtinFunctions; + } + + @Override + public boolean set(WriteGraph g, Resource element, Resource value) + throws MappingException { + // Built-in functions should not be set programmatically + return true; + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsFactory.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsFactory.java new file mode 100644 index 00000000..f6800db4 --- /dev/null +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/annotations/BuiltinFunctionsFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2007, 2012 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.representation.annotations; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; + +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.ResourceNotFoundException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.exception.ValidationException; +import org.simantics.objmap.IMappingRule; +import org.simantics.objmap.rules.MappedElementRule; +import org.simantics.objmap.rules.factory.IFieldRuleFactory; +import org.simantics.objmap.rules.range.FieldAccessor; + +public class BuiltinFunctionsFactory implements IFieldRuleFactory { + + @Override + public IMappingRule create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException { + return new MappedElementRule( + new BuiltinFunctionsAccessor(), + new FieldAccessor(field) + ); + } + +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ConstantExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ConstantExpression.java index c134bd6c..5490f308 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ConstantExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ConstantExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,6 +16,12 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.IndependentVariable; +/** + * Represents a constant expression + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.ConstantExpression) public class ConstantExpression extends Expression { @@ -23,10 +29,7 @@ public class ConstantExpression extends Expression { private String equation; @Override - public String getDeclaration(IndependentVariable variable) { - StringBuilder b = new StringBuilder(); - b.append(" constant " + variable.getType() + " " + variable.getName()); - b.append(" = " + equation + ";\n"); - return b.toString(); } - + public String getExpression(IndependentVariable variable) { + return equation; + } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java index b8c969b2..1c63ec0d 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/DelayExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,15 +11,11 @@ *******************************************************************************/ package org.simantics.sysdyn.representation.expressions; -import java.util.ArrayList; -import java.util.Iterator; - import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; -import org.simantics.sysdyn.representation.ArrayIndexes; -import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.sysdyn.representation.Variability; import org.simantics.sysdyn.representation.Variable; import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; @@ -65,50 +61,64 @@ public class DelayExpression extends Expression { private String equation; @Override - public String getDeclaration(IndependentVariable variable) { - - // Calculate range for the variable - ArrayIndexes ai = variable.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - - String range = ""; - if(enumerations != null && enumerations.size() > 0) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName() + ".size"); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - range = sb.toString(); + public String getDeclarationAddition(IndependentVariable variable) { + + String delayTime = FormatUtils.formatExpressionForModelica(variable, this.delayTime); + String initialValue = FormatUtils.formatExpressionForModelica(variable, this.initialValue); + Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, delayTime); + Variability initialVariability = Variability.CONTINUOUS; + if(initialValue != null && initialValue.length() > 0) { + /* + * By default, initial value variability is continuous. + * If initial value has been set, it can be some other. + */ + initialVariability = Variability.getVariability(variable, initialValue); } - - /* Build the declaration */ + + StringBuilder declaration = new StringBuilder(); - // Variable declaration - declaration.append(" " + variable.getType() + " " + variable.getName() + range + ";\n"); + + String range = variable.getRange(); + // Delay declaration declaration.append(" " + variable.getName() + "_delayClass " + variable.getName() + "_delayClass_instance"); + // Change enumeration sizes from the delay class. Supports overridden enumerations in modules. - if(range.length() > 0) { + if(range.length() > 0 || !initialVariability.equals(Variability.CONTINUOUS) || !delayTimeVariability.equals(Variability.CONTINUOUS)) { declaration.append("("); - String[] ranges = range.substring(1, range.length() - 1).split(","); - for(int i = 0; i < ranges.length; i++ ) { - String r = ranges[i]; - declaration.append(r.replace(".size", "size") + " = " + r); - if(i < ranges.length - 1) { - declaration.append(", "); + + boolean started = false; + if(range.length() > 0) { + started = true; + String[] ranges = range.substring(1, range.length() - 1).split(","); + for(int i = 0; i < ranges.length; i++ ) { + String r = ranges[i]; + declaration.append(r.replace(".size", "size") + " = " + r); + if(i < ranges.length - 1) { + declaration.append(", "); + } } } + + // If initial value is not continuous, it is set in the module declaration + if(!initialVariability.equals(Variability.CONTINUOUS)) { + if(started) + declaration.append(", "); + started = true; + declaration.append("initialValue = " + initialValue); + } + + // If delay time is not continuous, it is set in the module declaration + if(!delayTimeVariability.equals(Variability.CONTINUOUS)) { + if(started) + declaration.append(", "); + declaration.append("delayTime = " + delayTime); + } + declaration.append(")"); } declaration.append(";\n"); - + // Write the delay class declaration.append(getDelayClass(variable, range, order)); return declaration.toString(); @@ -128,11 +138,6 @@ public class DelayExpression extends Expression { StringBuilder sb = new StringBuilder(); sb.append("class " + variable.getName() + "_delayClass\n"); - - // Auxiliary variable - sb.append("\tReal DL;\n"); - // Delay time - sb.append("\tReal delayTime;\n"); // Enumeration sizes as parameters. Sizes correspond the enumeration sizes of variable if(range.length() > 0) { @@ -142,38 +147,66 @@ public class DelayExpression extends Expression { } } - if(initialValue == null || initialValue.length() == 0) - // Use "random" number as initial value, if initial value is not set - sb.append("\tReal" + range + " initialValue = " + (range.length() > 0 ? "fill(-137543," + range.substring(1, range.length() - 1) + ")" : -137543) + ";\n"); - else - // Initial value - sb.append("\tReal" + range + " initialValue = " + FormatUtils.formatExpressionForModelica(variable, this.initialValue) + ";\n"); - + String dt = FormatUtils.formatExpressionForModelica(variable,delayTime); + Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, dt); + if(!delayTimeVariability.equals(Variability.CONTINUOUS)) { + // Auxiliary variable + sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " DL = delayTime/" + n + ";\n"); + // Delay time + sb.append("\t" + delayTimeVariability.getText() + " Real" + range + " delayTime;\n"); + } else { + // Continuous auxiliary variable + sb.append("\tReal" + range + " DL;\n"); + // Continuous delay time + sb.append("\tReal" + range + " delayTime;\n"); + } + + + // Get initial value variability + Variability initialValueVariability = Variability.CONTINUOUS; + String initEquation = FormatUtils.formatExpressionForModelica(variable, this.initialValue); + if(initialValue != null && initialValue.length() > 0) { + initialValueVariability = Variability.getVariability((IndependentVariable)variable, initEquation); + } + + // Declare initial value (continuous or other) + String ivv = !initialValueVariability.equals(Variability.CONTINUOUS) ? initialValueVariability.getText() + " " : ""; + sb.append("\t" + ivv + "Real" + range + " initialValue;\n"); + // First valve sb.append("\tReal" + range + " delay0;\n"); // Stocks and valves. Valves are the delayed values of the variable for(int i = 1; i <= n; i++) { - sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n"); + if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) + // Continuous initial value or delay time + sb.append("\tReal" + range + " LV" + i + "(" + (range.length() > 0 ? "each " : "") + "fixed=false);\n"); + else + // initial value and delay time are not continuous + sb.append("\tReal" + range + " LV" + i + + "(" + (range.length() > 0 ? "each " : "") + "fixed=true, start=initialValue " + (range.isEmpty() ? "*" : ".*") + " DL);\n"); sb.append("\tReal" + range + " delay" + i + ";\n"); } - sb.append("initial equation\n"); - - // "Generic" structure selection. If the "random" number is not used in initial value, use delay0 as initial value - // Each stock gets the same initial value - for(int i = 1; i <= n; i++) - sb.append("\tLV" + i +" = DL * " + - (range.length() > 0 ? "(if max(initialValue) < -137543 or max(initialValue) > -137543 then initialValue else delay0)" : - "(if initialValue < -137543 or initialValue > -137543 then initialValue else delay0)") + ";\n"); + // If initial value or delay time are continuous, use initial equation block + if(initialValueVariability.equals(Variability.CONTINUOUS) || delayTimeVariability.equals(Variability.CONTINUOUS)) { + sb.append("initial equation\n"); + + // Each stock gets the same initial value + for(int i = 1; i <= n; i++) + sb.append("\tLV" + i +" = DL " + (range.isEmpty() ? "*" : ".*") + " initialValue;\n"); + } + // Equation block sb.append("equation\n"); - sb.append("\tDL = delayTime/" + n + ";\n"); + + if(delayTimeVariability.equals(Variability.CONTINUOUS)) + sb.append("\tDL = delayTime/" + n + ";\n"); // Valves and stocks for(int i = 1; i <= n; i++) { sb.append("\tder(LV" + i + ") = - delay" + i + " + delay" + (i - 1) + ";\n"); - sb.append("\tdelay" + i + " = LV" + i + "/DL;\n"); + sb.append("\tdelay" + i + " = LV" + i + " " + (range.isEmpty() ? "/" : "./") + "DL;\n"); } sb.append("end " + variable.getName() + "_delayClass;\n"); @@ -182,19 +215,43 @@ public class DelayExpression extends Expression { @Override public String getEquation(IndependentVariable variable) { + StringBuilder sb = new StringBuilder(); + String equation = FormatUtils.formatExpressionForModelica(variable, this.equation); String delayTime = FormatUtils.formatExpressionForModelica(variable, this.delayTime); + String initialValue = FormatUtils.formatExpressionForModelica(variable, this.initialValue); - // Set delay properties - StringBuilder sb = new StringBuilder(); - sb.append(" " + variable.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n"); + // First "valve" in the delay sb.append(" " + variable.getName() + "_delayClass_instance.delay0 = " + equation + ";\n"); - // Use the delay in the value of variable + // Delay time (if continuous) + Variability delayTimeVariability = Variability.getVariability((IndependentVariable)variable, delayTime); + if(delayTimeVariability.equals(Variability.CONTINUOUS)) { + sb.append(" " + variable.getName() + "_delayClass_instance.delayTime = " + delayTime + ";\n"); + } + + // Initial value + if(initialValue == null || initialValue.length() == 0) { + // No initial value set, use delay0 (the first "valve") + sb.append(" " + variable.getName() + "_delayClass_instance.initialValue = " + variable.getName() + "_delayClass_instance.delay0;\n"); + } else { + // Continuous initial value + Variability initialVariability = Variability.getVariability(variable, initialValue); + if(initialVariability.equals(Variability.CONTINUOUS)) { + sb.append(" " + variable.getName() + "_delayClass_instance.initialValue = " + initialValue + ";\n"); + } + } + + // The value of the actual variable String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange()); sb.append(" " + variable.getName() + (range.equals("[:]") ? "" : range) + " = " + variable.getName() + "_delayClass_instance.delay" + order + ";\n"); return sb.toString(); } + @Override + public String getExpression(IndependentVariable variable) { + return "This + is + not + a + parameter + at + any + time"; + } + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/Expression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/Expression.java index e500115f..1d9d77fa 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/Expression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/Expression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,23 +15,34 @@ import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.IndependentVariable; +/** + * Abstract class for any expression + * + * @author Teemu Lempinen + * + */ public abstract class Expression implements IExpression { @RelatedValue(SysdynResource.URIs.Expression_arrayRange) private String range; - + @Override - public String getDeclaration(IndependentVariable variable) { + public String getEquation(IndependentVariable variable) { return null; } @Override - public String getEquation(IndependentVariable variable) { + public String getInitialEquation(IndependentVariable variable) { + return null; + } + + @Override + public String getDeclarationAddition(IndependentVariable variable) { return null; } @Override - public String getInitialEquation(IndependentVariable variable) { + public String getExpression(IndependentVariable variable) { return null; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java index 54431347..c3f7ae77 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/IExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -13,11 +13,47 @@ package org.simantics.sysdyn.representation.expressions; import org.simantics.sysdyn.representation.IndependentVariable; +/** + * Interface for all expressions in System Dynamics models + * + * @author Teemu Lempinen + * + */ public interface IExpression { - String getDeclaration(IndependentVariable variable); + /** + * Get any possible additions to variable declaration. + * + * @param variable Declared independent variable + * @return additions or null + */ + String getDeclarationAddition(IndependentVariable variable); + + /** + * Initial value for this variable and expression + * @param variable IndependentVariable + * @return initial value or null + */ String getInitialEquation(IndependentVariable variable); + + /** + * Get the actual equation of this expression + * @param variable IndependentVariable + * @return equation or null + */ String getEquation(IndependentVariable variable); + + /** + * Get the range of this expression + * @return Range or null if not multidimensional + */ String getArrayRange(); + + /** + * Get the plain (possibly unformatted) expression from this expression. (type variable = EXPRESSION ;\n) + * @param variable + * @return + */ + String getExpression(IndependentVariable variable); } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java index 360ad577..a0501b47 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/NormalExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,48 +11,28 @@ *******************************************************************************/ package org.simantics.sysdyn.representation.expressions; -import java.util.ArrayList; -import java.util.Iterator; - import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; -import org.simantics.sysdyn.representation.ArrayIndexes; -import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; +/** + * Representation of a normal (auxiliary) expression + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.NormalExpression) public class NormalExpression extends Expression { @RelatedValue(SysdynResource.URIs.Expression_equation) private String equation; - + @Override - public String getDeclaration(IndependentVariable variable) { - - ArrayIndexes ai = variable.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - - String range = ""; - if(enumerations != null && enumerations.size() > 0) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName() + ".size"); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - range = sb.toString(); - } - - return " " + variable.getType() + " " + variable.getName() + range + ";\n"; + public String getExpression(IndependentVariable variable) { + return equation; } @Override diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java index 90ca0c5b..874de79a 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/ParameterExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,17 +11,18 @@ *******************************************************************************/ package org.simantics.sysdyn.representation.expressions; -import java.util.ArrayList; -import java.util.Iterator; - import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; -import org.simantics.sysdyn.representation.ArrayIndexes; -import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.utils.IndexUtils; +/** + * Representation of a parameter expression + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.ParameterExpression) public class ParameterExpression extends Expression { @@ -29,38 +30,15 @@ public class ParameterExpression extends Expression { private String equation; @Override - public String getDeclaration(IndependentVariable variable) { - // FIXME: Still needs to manually confirm that really is parameter - ArrayIndexes ai = variable.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - - boolean parameter = true; - String range = ""; - if(enumerations != null && enumerations.size() > 0) { - parameter = false; - StringBuilder sb = new StringBuilder(); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName() + ".size"); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - range = sb.toString(); - } - - StringBuilder sb = new StringBuilder(); - sb.append(" " + (parameter ? "parameter " : "") + variable.getType() + " " + variable.getName() + range); - if(parameter) - sb.append(" = " + getValue() + " /* Actual value read from init file */"); - sb.append(";\n"); - return sb.toString(); + public String getExpression(IndependentVariable variable) { + return equation + " /* Actual value read from init file */"; } + @Override + public String getDeclarationAddition(IndependentVariable variable) { + return ""; + } + /** * Used when the expression is a part of an array variable. Then it is like a normal auxiliary. diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java index 6c30e6ba..085754f4 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/StockExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -13,7 +13,6 @@ package org.simantics.sysdyn.representation.expressions; import java.io.StringReader; import java.util.ArrayList; -import java.util.Iterator; import java.util.Set; import org.simantics.objmap.annotations.GraphType; @@ -45,58 +44,10 @@ public class StockExpression extends Expression { private String initialEquation; @Override - public String getDeclaration(IndependentVariable variable) { - - // See if the start parameter is used Stock(start = x, fixed = y) - String value = null; - if(useStartValue(variable)) - value = FormatUtils.formatExpressionForModelica(variable, initialEquation); - - - // Build the enumeration indexes, if there are enumerations. Stock[enumIndexes, enum2Indexes, ...] - ArrayIndexes ai = variable.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - - String range = ""; - if(enumerations != null && enumerations.size() > 0) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName() + ".size"); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - range = sb.toString(); - } - - String each = ""; - // each is required when a single value is used for all dimensions e.g. Stock[30](each start = 0) - if (value == null) { - // start parameter is not used, everything needs to be fixed=false - if(ai != null && !ai.getEnumerations().isEmpty()) - each = "each"; - return " " + variable.getType() + " " + variable.getName() + range + "(" + each + " fixed=false);\n"; - } else { - // start parameter is used - - if(getStartValue(variable) != null) { - // a single number is used as the initial equation -> (each start, each fixed) if there are dimensions - if(ai != null && !ai.getEnumerations().isEmpty()) - each = "each"; - return " " + variable.getType() + " " + variable.getName() + range + "(" + each+ " start=" + value + ", " + each + " fixed=true);\n"; - } else { - // a function or array constructor {.., .., ..} is used as the initial equation -> (start, each fixed) if there are dimensions - if(ai != null && !ai.getEnumerations().isEmpty()) - each = "each"; - return " " + variable.getType() + " " + variable.getName() + range + "(start=" + value + ", " + each + " fixed=true);\n"; - } - } + public String getExpression(IndependentVariable variable) { + return initialEquation; } + @Override public String getEquation(IndependentVariable variable) { @@ -212,7 +163,7 @@ public class StockExpression extends Expression { * @param variable * @return Double representing the initial equation or null if initial equation is not a double */ - private Double getStartValue(IndependentVariable variable) { + public Double getStartValue(IndependentVariable variable) { Double value = null; ArrayList expressions = variable.getExpressions().getExpressions(); if(expressions.size() == 1) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java index ed99a236..15e34766 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,19 +11,19 @@ *******************************************************************************/ package org.simantics.sysdyn.representation.expressions; -import java.util.ArrayList; -import java.util.Iterator; - import org.simantics.objmap.annotations.GraphType; import org.simantics.objmap.annotations.RelatedValue; import org.simantics.sysdyn.SysdynResource; -import org.simantics.sysdyn.representation.ArrayIndexes; -import org.simantics.sysdyn.representation.Enumeration; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; - +/** + * Representation of a withlookup expression + * + * @author Teemu Lempinen + * + */ @GraphType(SysdynResource.URIs.WithLookupExpression) public class WithLookupExpression extends Expression { @@ -32,32 +32,6 @@ public class WithLookupExpression extends Expression { @RelatedValue(SysdynResource.URIs.WithLookupExpression_expression) private String equation; - @Override - public String getDeclaration(IndependentVariable variable) { - ArrayIndexes ai = variable.getArrayIndexes(); - ArrayList enumerations = null; - if(ai != null) - enumerations = ai.getEnumerations(); - - String range = ""; - if(enumerations != null && enumerations.size() > 0) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - Iterator iterator = enumerations.iterator(); - while(iterator.hasNext()) { - sb.append(iterator.next().getName() + ".size"); - if(iterator.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - range = sb.toString(); - } - - return " " + variable.getType() + " " + variable.getName() + range + ";\n"; - - } - @Override public String getEquation(IndependentVariable variable) { String equation = FormatUtils.formatExpressionForModelica(variable, this.equation); @@ -66,5 +40,10 @@ public class WithLookupExpression extends Expression { return " " + variable.getName() + (range.equals("[:]") ? "" : range) + " = interpolate(" + equation + ", " + lookupTable + ");\n"; } + + @Override + public String getExpression(IndependentVariable variable) { + return "interpolate(" + equation + ", " + lookupTable + ")"; + } } -- 2.47.1