From 1af667ea95adf8e5b66960b5117c5c877e348c04 Mon Sep 17 00:00:00 2001 From: lempinen Date: Tue, 22 Nov 2011 13:34:47 +0000 Subject: [PATCH] Support mat-format simulation results git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@23324 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.modelica/META-INF/MANIFEST.MF | 5 +- .../modelica/data/CSVSimulationResult.java | 25 +- .../org/simantics/modelica/data/DataSet.java | 8 +- .../simantics/modelica/data/DoubleMatrix.java | 38 + .../simantics/modelica/data/IntMatrix.java | 49 + .../simantics/modelica/data/Mat4Reader.java | 149 +++ .../modelica/data/MatSimulationResult.java | 43 + .../org/simantics/modelica/data/Matrix.java | 29 + .../modelica/data/SimulationResult.java | 99 +- .../simantics/modelica/data/StringMatrix.java | 41 + .../sysdyn/manager/SysdynDataSet.java | 12 +- .../simantics/sysdyn/manager/SysdynModel.java | 1161 +++++++++-------- .../sysdyn/manager/SysdynResult.java | 56 +- 13 files changed, 1132 insertions(+), 583 deletions(-) create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/DoubleMatrix.java create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/IntMatrix.java create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/Mat4Reader.java create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/MatSimulationResult.java create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/Matrix.java create mode 100644 org.simantics.modelica/src/org/simantics/modelica/data/StringMatrix.java diff --git a/org.simantics.modelica/META-INF/MANIFEST.MF b/org.simantics.modelica/META-INF/MANIFEST.MF index 972e7f90..80e82f4e 100644 --- a/org.simantics.modelica/META-INF/MANIFEST.MF +++ b/org.simantics.modelica/META-INF/MANIFEST.MF @@ -5,9 +5,10 @@ Bundle-SymbolicName: org.simantics.modelica;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: gnu.trove2;bundle-version="2.0.4", - org.simantics.databoard;bundle-version="0.5.2", org.eclipse.osgi;bundle-version="3.6.0", - org.eclipse.core.runtime;bundle-version="3.6.0" + org.eclipse.core.runtime;bundle-version="3.6.0", + org.simantics.history;bundle-version="1.0.0", + org.simantics.databoard;bundle-version="0.6.3" Export-Package: org.simantics.modelica, org.simantics.modelica.data Bundle-Activator: org.simantics.modelica.Activator diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java b/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java index 742beeb3..1c3b1e2f 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/CSVSimulationResult.java @@ -15,11 +15,18 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; - +/** + * class for supporting csv-format simulation results + * @author Teemu Lempinen + * + */ public class CSVSimulationResult extends SimulationResult { HashMap valueMap = new HashMap(); + /** + * Overridden method to support csv-formatted simulation results + */ @Override public void read(InputStream stream) { errors.clear(); @@ -35,28 +42,30 @@ public class CSVSimulationResult extends SimulationResult { // Create lists for receiving values for each variable. Names still with quotes. for(String name : names) { if(!name.isEmpty()) - valueMap.put(name, new DataSet(name, new ArrayList(), new ArrayList())); + valueMap.put(name, new DataSet(name, new double[numberOfTimeSteps], new double[numberOfTimeSteps])); } + int row = 0; // Data sets while((line = getLine(stream)) != null) { if(line.isEmpty()) break; String[] values = line.split(","); - for(int i = 0; i list = errors.get(names[i]); + ArrayList list = errors.get(names[valueIndex]); if(list == null) { list = new ArrayList(); - errors.put(names[i], list); + errors.put(names[valueIndex], list); } - list.add(new TimeValuePair(values[0], values[i])); + list.add(new TimeValuePair(values[0], values[valueIndex])); } } } + row++; } // Add time values for each dataset and add them to variables. diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/DataSet.java b/org.simantics.modelica/src/org/simantics/modelica/data/DataSet.java index 1a1546e2..c1c4bae9 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/DataSet.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/DataSet.java @@ -11,18 +11,16 @@ *******************************************************************************/ package org.simantics.modelica.data; -import java.util.List; - /** * Simulation result for one variable. * @author Hannu Niemistö */ public class DataSet { public String name; - public List times; - public List values; + public double[] times; + public double[] values; - public DataSet(String name, List times, List values) { + public DataSet(String name, double[] times, double[] values) { this.name = name; this.times = times; this.values = values; diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/DoubleMatrix.java b/org.simantics.modelica/src/org/simantics/modelica/data/DoubleMatrix.java new file mode 100644 index 00000000..d8ace791 --- /dev/null +++ b/org.simantics.modelica/src/org/simantics/modelica/data/DoubleMatrix.java @@ -0,0 +1,38 @@ +package org.simantics.modelica.data; + +/** + * Copied from Hannu's DoubleMatrix in org.simantics.modelica.data + * + * To be replaced with the original when SysDyn and Modelica tools + * are synchronized to use the same OpenModelica plugin + * + * @author Teemu Lempinen + * + */ +public class DoubleMatrix extends Matrix { + public final int rows; + public final int columns; + public final double[] data; + + public DoubleMatrix(String name, int rows, int columns) { + super(name); + this.rows = rows; + this.columns = columns; + this.data = new double[rows*columns]; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("double " + name + "(" + rows + "," + columns + ")\n"); + for(int i=0;i 0) + b.append(' '); + b.append(data[i*rows + j]); + } + b.append('\n'); + } + return b.toString(); + } +} diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/IntMatrix.java b/org.simantics.modelica/src/org/simantics/modelica/data/IntMatrix.java new file mode 100644 index 00000000..6f3d6d4e --- /dev/null +++ b/org.simantics.modelica/src/org/simantics/modelica/data/IntMatrix.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.modelica.data; + +/** + * Copied from Hannu's IntMatrix in org.simantics.modelica.data + * + * To be replaced with the original when SysDyn and Modelica tools + * are synchronized to use the same OpenModelica plugin + * + * @author Teemu Lempinen + * + */ +public class IntMatrix extends Matrix { + public final int rows; + public final int columns; + public final int[] data; + + public IntMatrix(String name, int rows, int columns) { + super(name); + this.rows = rows; + this.columns = columns; + this.data = new int[rows*columns]; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("int " + name + "(" + rows + "," + columns + ")\n"); + for(int i=0;i 0) + b.append(' '); + b.append(data[i*rows + j]); + } + b.append('\n'); + } + return b.toString(); + } +} diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/Mat4Reader.java b/org.simantics.modelica/src/org/simantics/modelica/data/Mat4Reader.java new file mode 100644 index 00000000..0d896368 --- /dev/null +++ b/org.simantics.modelica/src/org/simantics/modelica/data/Mat4Reader.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.modelica.data; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * Copied from Hannu's Mat4Reader in org.simantics.modelica.data + * + * To be replaced with the original when SysDyn and Modelica tools + * are synchronized to use the same OpenModelica plugin + * + * @author Teemu Lempinen + * + */ +public class Mat4Reader { + + InputStream in; + + public Mat4Reader(InputStream in) { + this.in = in; + } + + private final int getInt() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + int ch3 = in.read(); + int ch4 = in.read(); + return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24)); + } + + private final long getLong() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + int ch3 = in.read(); + int ch4 = in.read(); + int ch5 = in.read(); + int ch6 = in.read(); + int ch7 = in.read(); + int ch8 = in.read(); + return ((((long)ch1) << 0) + (((long)ch2) << 8) + (((long)ch3) << 16) + (((long)ch4) << 24) + + (((long)ch5) << 32) + (((long)ch6) << 40) + (((long)ch7) << 48) + (((long)ch8) << 56)); + } + + private final double getDouble() throws IOException { + return Double.longBitsToDouble(getLong()); + } + + private String getString(int length) throws IOException { + byte[] buffer = new byte[length]; + int pos = 0; + while(pos < length) + pos += in.read(buffer, pos, length-pos); + return new String(buffer, "UTF-8"); + } + + public Matrix readMatrix() throws IOException { + int type = getInt(); + int rows = getInt(); + int columns = getInt(); + int imagf = getInt(); + int namlen = getInt(); + + String name = getString(namlen-1); + in.read(); + + if(imagf > 0) + throw new IOException("Imaginary part of the matrix is not supported (matrix " + name + ")."); + + switch(type) { + case 0: { + DoubleMatrix matrix = new DoubleMatrix(name, rows, columns); + int size = rows*columns; + double[] data = matrix.data; + for(int i=0;i read(InputStream in) throws IOException { + Mat4Reader reader = new Mat4Reader(in); + reader.readMatrix(); // Header + StringMatrix names = (StringMatrix)reader.readMatrix(); // Variable names + reader.readMatrix(); // Variable descriptions + IntMatrix info = (IntMatrix)reader.readMatrix(); // Data info + if(info.rows != 4 || info.columns != names.rows ) + throw new IOException("Invalid result data."); + int[] infoData = info.data; + /*for(int i=0;i result = new HashMap(); + double[] valueData = values.data; + int rows = values.rows; + //System.out.println("cols="+values.columns+", rows=" +values.rows+ ", data.length="+valueData.length); + for(int i=0;i 0 ? sc-1 : 1-sc; + //System.out.println("i=" + i + ", sc=" + sc + ", c=" + c); + for(int j=0;j valueMap = null; + try { + valueMap = Mat4Reader.read(stream); + } catch (IOException e) { + e.printStackTrace(); + return; + } + + DataSet ds; + double[] times = valueMap.get("time"); + for(String key : valueMap.keySet()) { + ds = new DataSet(key, times, valueMap.get(key)); + variables.add(ds); + } + } +} diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/Matrix.java b/org.simantics.modelica/src/org/simantics/modelica/data/Matrix.java new file mode 100644 index 00000000..1e68c1b6 --- /dev/null +++ b/org.simantics.modelica/src/org/simantics/modelica/data/Matrix.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.modelica.data; + +/** + * Copied from Hannu's Matrix in org.simantics.modelica.data + * + * To be replaced with the original when SysDyn and Modelica tools + * are synchronized to use the same OpenModelica plugin + * + * @author Teemu Lempinen + * + */ +public abstract class Matrix { + public final String name; + + public Matrix(String name) { + this.name = name; + } +} diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java b/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java index a7068a38..3d379ca4 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java @@ -14,8 +14,10 @@ package org.simantics.modelica.data; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; +import java.io.LineNumberReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -38,13 +40,21 @@ import org.xml.sax.SAXException; /** * Class that reads OpenModelica result files. + * + * SimulationResult class reads plt-files. Extended classes read other types. + * + * Will be replaced with a common OpenModelica plugin * @author Hannu Niemistö */ public class SimulationResult { List variables = new ArrayList(); List initials = new ArrayList(); - + protected int numberOfTimeSteps = 0; + + /** + * Private class used in displaying errors + */ class TimeValuePair { public String time; public String value; @@ -57,6 +67,11 @@ public class SimulationResult { HashMap> errors = new HashMap>(); + /** + * Get the next line in the plt-file + * @param stream plt-file input stream + * @return next line in the stream + */ static String getLine(InputStream stream) { if(stream == null) return null; @@ -82,6 +97,14 @@ public class SimulationResult { } + /** + * Read parameters that are located in the inits-file to the simulation result. + * Supports both txt and xml type inits. + * + * @param file inits-file + * @throws FileNotFoundException + * @throws IOException + */ public void readInits(File file) throws FileNotFoundException, IOException { if(file.getName().endsWith("txt")) { @@ -93,6 +116,11 @@ public class SimulationResult { } } + /** + * Read xml inits + * + * @param file xml-formatted inits file + */ public void readInitsXML(String file) { Document doc; try { @@ -101,20 +129,20 @@ public class SimulationResult { XPath xpath = XPathFactory.newInstance().newXPath(); - List times = new ArrayList(2); + double[] times = new double[2]; Node node; // Find start time node = (Node)xpath.evaluate ("//fmiModelDescription/DefaultExperiment/@startTime", doc, XPathConstants.NODE); - times.add(Double.parseDouble(node.getNodeValue())); + times[0] = Double.parseDouble(node.getNodeValue()); // Find end time node = (Node)xpath.evaluate ("//fmiModelDescription/DefaultExperiment/@stopTime", doc, XPathConstants.NODE); - times.add(Double.parseDouble(node.getNodeValue())); + times[1] = Double.parseDouble(node.getNodeValue()); NodeList nodes; // Find parameters and constants @@ -124,7 +152,7 @@ public class SimulationResult { XPathConstants.NODESET); // make the change. There should be only one node. - List values; + double[] values; NodeList children; for (int idx = 0; idx < nodes.getLength(); idx++) { Node n = nodes.item(idx); @@ -133,9 +161,7 @@ public class SimulationResult { Node child = children.item(i); if(child.getNodeName().equals("Real")) { Double d = Double.parseDouble(child.getAttributes().getNamedItem("start").getNodeValue()); - values = new ArrayList(2); - values.add(d); - values.add(d); + values = new double[] {d,d}; initials.add( new DataSet(n.getAttributes().getNamedItem("name").getNodeValue(), times , @@ -157,6 +183,10 @@ public class SimulationResult { } } + /** + * Read txt inits + * @param stream txt-formatted init file + */ public void readInitsTXT(InputStream stream) { HashMap mappedInitials = new HashMap(); while(true) { @@ -182,14 +212,11 @@ public class SimulationResult { double startTime = mappedInitials.get("start value"); double stopTime = mappedInitials.get("stop value"); - List times = new ArrayList(2); - times.add(startTime); - times.add(stopTime); + double[] times = new double[] {startTime, stopTime}; for(String key : mappedInitials.keySet()) { - List values = new ArrayList(2); - values.add(mappedInitials.get(key)); - values.add(mappedInitials.get(key)); + double d = mappedInitials.get(key); + double[] values = new double[] {d, d}; initials.add(new DataSet(key, times , values)); } } @@ -197,12 +224,33 @@ public class SimulationResult { final static Pattern p1 = Pattern.compile("DataSet: ([^ ]*)"); + /** + * Read result file + * + * @param file result file + * @throws FileNotFoundException + * @throws IOException + */ public void read(File file) throws FileNotFoundException, IOException { + // First check the number of time steps + FileReader fr = new FileReader(file); + LineNumberReader lnr = new LineNumberReader(fr); + lnr.skip(Long.MAX_VALUE); + numberOfTimeSteps = lnr.getLineNumber() - 1; // minus the first row, which is for names + lnr.close(); + fr.close(); + InputStream is = new FileInputStream(file); read(is); is.close(); } + + /** + * Read result file. The basic implementation supports + * plt-formatted results. Overridden to support other formats. + * @param stream FileInputStream for the result file + */ public void read(InputStream stream) { while(true) { String line = getLine(stream); @@ -219,8 +267,9 @@ public class SimulationResult { return; String name = matcher.group(1); - List times = new ArrayList(); - List values = new ArrayList(); + double[] dtimes = new double[numberOfTimeSteps]; + double[] dvalues = new double[numberOfTimeSteps]; + int i = 0; while(true) { String line = getLine(stream); if(line == null) @@ -228,14 +277,18 @@ public class SimulationResult { if(line.isEmpty()) break; String[] nn = line.split(", ", 2); - times.add(Double.parseDouble(nn[0])); - values.add(Double.parseDouble(nn[1])); + dtimes[i] = Double.parseDouble(nn[0]); + dvalues[i] = Double.parseDouble(nn[1]); + i++; } - variables.add(new DataSet(name, times, values)); + variables.add(new DataSet(name, dtimes, dvalues)); } } + /** + * Filter result set + */ public void filter() { ArrayList newVariables = new ArrayList(); for(DataSet dataSet : variables) { @@ -245,10 +298,18 @@ public class SimulationResult { variables = newVariables; } + /** + * Get datasets for the variables in this result + * @return variable datasets + */ public List getVariableDataSets() { return variables; } + /** + * Get datasets for the initial values in this simulation + * @return initial value datasets + */ public List getInitialValueDataSets() { return initials; } diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/StringMatrix.java b/org.simantics.modelica/src/org/simantics/modelica/data/StringMatrix.java new file mode 100644 index 00000000..8cfbea02 --- /dev/null +++ b/org.simantics.modelica/src/org/simantics/modelica/data/StringMatrix.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.modelica.data; + +/** + * Copied from Hannu's StringMatrix in org.simantics.modelica.data + * + * To be replaced with the original when SysDyn and Modelica tools + * are synchronized to use the same OpenModelica plugin + * + * @author Teemu Lempinen + * + */ +public class StringMatrix extends Matrix { + public final int rows; + public final String[] data; + + public StringMatrix(String name, int rows) { + super(name); + this.rows = rows; + this.data = new String[rows]; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("char " + name + "(" + rows + ")\n"); + for(String row : data) + b.append(row + "\n"); + return b.toString(); + } +} diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynDataSet.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynDataSet.java index 431f5eb5..89e53db5 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynDataSet.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynDataSet.java @@ -11,15 +11,19 @@ *******************************************************************************/ package org.simantics.sysdyn.manager; -import java.util.List; - import org.simantics.modelica.data.DataSet; +/** + * Extension for the basic Modelica result {@link DataSet} containing also an optional result name. + * + * @author Teemu Lempinen + * + */ public class SysdynDataSet extends DataSet { - public String result; + public String result; // Name of the result file if this is not the result of the current simulation - public SysdynDataSet(String name, String result, List times, List values) { + public SysdynDataSet(String name, String result, double[] times, double[] values) { super(name, times, values); this.result = result; } 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 0a857906..25bff4f8 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -32,16 +32,17 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; -import org.simantics.db.common.request.ReadRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; import org.simantics.db.exception.ServiceException; +import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.modelica.IModelicaMonitor; import org.simantics.modelica.ModelicaException; import org.simantics.modelica.ModelicaManager; import org.simantics.modelica.SimulationLocation; import org.simantics.modelica.data.CSVSimulationResult; +import org.simantics.modelica.data.MatSimulationResult; import org.simantics.modelica.data.SimulationResult; import org.simantics.objmap.IMapping; import org.simantics.objmap.IMappingListener; @@ -70,553 +71,639 @@ import org.simantics.sysdyn.representation.expressions.ParameterExpression; /** * Maintains a Java representation of system dynamic model. - * @author Hannu Niemistö + * @author Hannu Niemistö */ public class SysdynModel implements IMappingListener, IModel { - private Session session; + private Session session; - private IMapping mapping; + private IMapping mapping; - private Resource configurationResource; - private Resource modelResource; - - private Configuration configuration; + private Resource configurationResource; + private Resource modelResource; - private Set modules = new HashSet(); + private Configuration configuration; - private Process process; - private boolean canceled; - private SimulationResult result; - private SysdynResult sysdynResult; + private Set modules = new HashSet(); + + private Process process; + private boolean canceled; + private SimulationResult result; + private SysdynResult sysdynResult; + + private CopyOnWriteArrayList modificationListeners = + new CopyOnWriteArrayList(); + private CopyOnWriteArrayList resultListeners = + new CopyOnWriteArrayList(); - private CopyOnWriteArrayList modificationListeners = - new CopyOnWriteArrayList(); - private CopyOnWriteArrayList resultListeners = - new CopyOnWriteArrayList(); - protected THashSet variableValueSubscriptions = new THashSet(); protected volatile VariableValueSubscription[] variableValueSubscriptionsSnapshot = null; - @SuppressWarnings("rawtypes") - private Map services = new HashMap(); - - private String previousModelStructure; - private HashMap previousImportantInits = new HashMap(); - - private File simulationDir; - - void readModules(ReadGraph graph, Resource configResource, Set result) throws DatabaseException { - - if(!result.add(configResource)) return; - - Layer0 l0 = Layer0.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - StructuralResource2 str = StructuralResource2.getInstance(graph); - - for(Resource part : graph.getObjects(configResource, l0.ConsistsOf)) { - if(graph.isInstanceOf(part, sr.Module)) { - Resource type = graph.getPossibleType(part, sr.Module); - Resource config = graph.getPossibleObject(type, str.IsDefinedBy); - readModules(graph, config, result); - } - } - - } - - Set readModules(ReadGraph graph, Resource configResource) throws DatabaseException { - HashSet result = new HashSet(); - readModules(graph, configResource, result); - return result; - } - - private void createMapping(ReadGraph g) throws DatabaseException { - SysdynSchema schema = new SysdynSchema(g); - mapping = Mappings.createWithListening(schema); - mapping.addMappingListener(SysdynModel.this); - configuration = (Configuration)mapping.map(g, configurationResource); - for(Resource config : readModules(g, configurationResource)) { - modules.add((Configuration)mapping.map(g, config)); - } -// System.out.println("Loaded model with " + modules.size() + " modules."); - } - - public SysdynModel(ReadGraph g, Resource configurationResource) { - this.session = g.getSession(); - this.configurationResource = configurationResource; - - try { - createMapping(g); - } catch(DatabaseException e) { - e.printStackTrace(); - } - sysdynResult = new SysdynResult(); - sysdynResult.setResult(new SimulationResult()); - - previousModelStructure = ""; - } - - - /* - * some dummy(?) stuff for experiments - */ - public SysdynModel(Resource modelResource) { - this.modelResource = modelResource; - } - - public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor, final Experiment experiment) throws IOException { - canceled = false; - progressMonitor.subTask("Write modelica classes"); - - // Write Modelica files - ModelicaWriter writer = new ModelicaWriter(); - try { - for(Configuration c : modules) { - writer.write(c); - } - } catch (Exception e) { - setExperimentStopped(experiment); - - - monitor.showConsole(); - - monitor.message("Error when writing Modelica code."); - return; - } - - progressMonitor.worked(1); - - progressMonitor.subTask("Write initial files"); - String modelText = writer.toString(); - HashMap inits = getInits(configuration, ""); - Model model = configuration.getModel(); - Double startTime = model.getStartTime(); - Double stopTime = model.getStopTime(); - Double numberOfIntervals = model.getOutputInterval(); - inits.put("start value", startTime.toString()); - inits.put("stop value", stopTime.toString()); - String outputFormat = "\"csv\""; - inits.put("outputFormat", outputFormat); - if(numberOfIntervals != null) { - inits.put("step value", numberOfIntervals.toString()); - } else { - inits.put("step value", "" + (stopTime - startTime) / 500); - } - String method = "\"" + model.getSolver() + "\""; - inits.put("method", method); - if(model.getTolerance() != null) - inits.put("tolerance", model.getTolerance().toString()); - - StringBuilder functionscript = new StringBuilder(); - for(String path : FunctionUtils.getLibraryPathsForModelica(this)) { - System.out.println("loadFile(\"" + path + "\");\n"); - functionscript.append("loadFile(\"" + path + "\");\n"); - } - - final SimulationLocation simulationLocation = ModelicaManager.createInputFiles( - getSimulationDir(), - configuration.getName(), - modelText, - inits, - functionscript.toString()); - - - progressMonitor.worked(1); - - - if (!simulationLocation.exeFile.isFile() || hasStructureChanged(modelText, inits)) { - progressMonitor.subTask("Build model"); - previousModelStructure = modelText; - System.out.println("== Modelica == "); + @SuppressWarnings("rawtypes") + private Map services = new HashMap(); + + private String previousModelStructure; + private HashMap previousImportantInits = new HashMap(); + + private File simulationDir; + + /** + * Recursively read all module configurations that are used in + * configResource and its components children + * + * @param graph ReadGraph + * @param configResource Configuration + * @param result set containing all encountered configurations + * @throws DatabaseException + */ + void readModules(ReadGraph graph, Resource configResource, Set result) throws DatabaseException { + + // if result does not contain this resource, add it to the result + if(!result.add(configResource)) return; + + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 str = StructuralResource2.getInstance(graph); + + for(Resource part : graph.getObjects(configResource, l0.ConsistsOf)) { + if(graph.isInstanceOf(part, sr.Module)) { + Resource type = graph.getPossibleType(part, sr.Module); + Resource config = graph.getPossibleObject(type, str.IsDefinedBy); + // Recursively readModules + readModules(graph, config, result); + } + } + + } + + /** + * Get all modules that have been used in configResource and its children + * @param graph ReadGraph + * @param configResource Configuration + * @return All modules (configuration resources) that have been used in configResource + * @throws DatabaseException + */ + Set readModules(ReadGraph graph, Resource configResource) throws DatabaseException { + HashSet result = new HashSet(); + readModules(graph, configResource, result); + return result; + } + + /** + * Create an ObjMapping + * @param g ReadGraph + * @throws DatabaseException + */ + private void createMapping(ReadGraph g) throws DatabaseException { + SysdynSchema schema = new SysdynSchema(g); + mapping = Mappings.createWithListening(schema); + mapping.addMappingListener(SysdynModel.this); + configuration = (Configuration)mapping.map(g, configurationResource); + for(Resource config : readModules(g, configurationResource)) { + modules.add((Configuration)mapping.map(g, config)); + } + } + + /** + * New Sysdyn model + * @param g ReadGraph + * @param configurationResource Configration resource of the model + */ + public SysdynModel(ReadGraph g, Resource configurationResource) { + this.session = g.getSession(); + this.configurationResource = configurationResource; + + try { + createMapping(g); + } catch(DatabaseException e) { + e.printStackTrace(); + } + + // initialize results + sysdynResult = new SysdynResult(); + sysdynResult.setResult(new SimulationResult()); + + previousModelStructure = ""; + } + + + /* + * a dummy(?) call for experiments + */ + public SysdynModel(Resource modelResource) { + this.modelResource = modelResource; + } + + /** + * Simulate this model + * @param monitor IModelicaMonitor + * @param progressMonitor IProgressMonitor + * @param experiment SysdynExperiment + * @throws IOException + */ + public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor, final Experiment experiment) throws IOException { + canceled = false; + progressMonitor.subTask("Write modelica classes"); + + // Write Modelica files + ModelicaWriter writer = new ModelicaWriter(); + try { + // Write all configurations once + for(Configuration c : modules) { + writer.write(c); + } + } catch (Exception e) { + // Stop experiment and show console + setExperimentStopped(experiment); + monitor.showConsole(); + monitor.message("Error when writing Modelica code."); + return; + } + String modelText = writer.toString(); + progressMonitor.worked(1); + + // Write initial files and add init-parameters + progressMonitor.subTask("Write initial files"); + HashMap inits = getInits(configuration, ""); + Model model = configuration.getModel(); + Double startTime = model.getStartTime(); + Double stopTime = model.getStopTime(); + Double numberOfIntervals = model.getOutputInterval(); + inits.put("start value", startTime.toString()); + inits.put("stop value", stopTime.toString()); + String outputFormat = "\"mat\""; + inits.put("outputFormat", outputFormat); + if(numberOfIntervals != null) { + inits.put("step value", numberOfIntervals.toString()); + } else { + inits.put("step value", "" + (stopTime - startTime) / 500); + } + String method = "\"" + model.getSolver() + "\""; + inits.put("method", method); + if(model.getTolerance() != null) + inits.put("tolerance", model.getTolerance().toString()); + + // add loadFile script to load all related functions and function libraries + StringBuilder functionscript = new StringBuilder(); + for(String path : FunctionUtils.getLibraryPathsForModelica(this)) { + functionscript.append("loadFile(\"" + path + "\");\n"); + } + + // Create simulation files + final SimulationLocation simulationLocation = ModelicaManager.createInputFiles( + getSimulationDir(), + configuration.getName(), + modelText, + inits, + functionscript.toString()); + + + progressMonitor.worked(1); + + // Build the model and store previous model structure and inits that affect the building + // If there is no exe file OR the model structure has not changed, no need to build + if (!simulationLocation.exeFile.isFile() || hasStructureChanged(modelText, inits)) { + progressMonitor.subTask("Build model"); + previousModelStructure = modelText; +// System.out.println("== Modelica == "); // System.out.println(writer.toString()); - System.out.println("== Modelica ends == "); - - try { - simulationLocation.exeFile.delete(); - ModelicaManager.buildModel(simulationLocation, monitor); - previousImportantInits.clear(); - previousImportantInits.put("start value", startTime.toString()); - previousImportantInits.put("stop value", stopTime.toString()); - previousImportantInits.put("method", method); - previousImportantInits.put("outputFormat", outputFormat); - } catch (ModelicaException e) { - if(e.getMessage() != null) - monitor.message(e.getMessage()); - monitor.showConsole(); - canceled = true; - previousModelStructure = ""; - } - } - - progressMonitor.worked(1); - - if(simulationLocation != null && !canceled) { - progressMonitor.subTask("Simulate model"); - process = ModelicaManager.runModelica( - simulationLocation, - monitor, - inits - ); - ModelicaManager.printProcessOutput(process, monitor); - - Thread resultThread = new Thread() { - @Override - public void run() { - try { - process.waitFor(); - - if(!canceled) { - progressMonitor.worked(1); - progressMonitor.subTask("Read results"); - result = new CSVSimulationResult(); - result.read(simulationLocation.outputFile); - result.readInits(simulationLocation.initFile); - result.filter(); - sysdynResult.setResult(result); - progressMonitor.worked(1); - resultChanged(); - - setExperimentStopped(experiment); - - String errorString = result.getResultReadErrors(); - if(errorString != null && !errorString.isEmpty()) - monitor.message(errorString); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }; - resultThread.run(); - } - if(canceled) - setExperimentStopped(experiment); - process = null; - } - - private void setExperimentStopped(Experiment experiment) { - if(experiment instanceof SysdynExperiment) { - SysdynExperiment e = (SysdynExperiment)experiment; - if(e.getState() != ExperimentState.DISPOSED) - e.simulate(false); - } - } - - private boolean hasStructureChanged(String modelText, Map inits) { - - - BufferedReader current = new BufferedReader( - new StringReader(modelText)); - BufferedReader previous = new BufferedReader( - new StringReader(previousModelStructure)); - - String c, p; - try { - c = current.readLine(); - p = previous.readLine(); - - while (c != null && p != null) { - if(!c.equals(p)) { - if(c.contains("parameter") && p.contains("parameter")) { - int i = c.indexOf("="); - if(!c.substring(0, i).equals(p.substring(0, i))) { - // different parameter definition - return true; - } - } else { - // other than a line containing parameters differs - return true; - } - } - c = current.readLine(); - p = previous.readLine(); - } - - if((c == null && p != null) || (c != null && p == null)) { - // different lengths - return true; - } - - } catch(IOException e) { - //e.printStackTrace(); - return true; - } - - for(String key : previousImportantInits.keySet()) { - if(!inits.containsKey(key) || !previousImportantInits.get(key).equals(inits.get(key))) - return true; - } - return false; - } - - public void cancelSimulation() { - canceled = true; - if(process != null) { - process.destroy(); - } - } - - public synchronized boolean update(ReadGraph graph) throws DatabaseException { - if(mapping.isDomainModified()) { - mapping.updateRange(graph); - Set configs = readModules(graph, configurationResource); - for(Resource config : configs) { - if(!modules.contains(config)) - modules.add((Configuration)mapping.map(graph, config)); - } - - HashSet toBeRemoved = null; - for(Configuration module : modules) { - if(!configs.contains(mapping.inverseGet(module))) { - if(toBeRemoved == null) - toBeRemoved = new HashSet(); - toBeRemoved.add(module); - } - } - if(toBeRemoved != null) - modules.removeAll(toBeRemoved); - return true; - } - else - return false; - } - - public synchronized boolean update() throws DatabaseException { - if(mapping.isDomainModified()) { - session.syncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - mapping.updateRange(graph); - Set configs = readModules(graph, configurationResource); - for(Resource config : configs) { - if(!modules.contains(config)) - modules.add((Configuration)mapping.map(graph, config)); - } - - HashSet toBeRemoved = null; - for(Configuration module : modules) { - if(!configs.contains(mapping.inverseGet(module))) { - if(toBeRemoved == null) - toBeRemoved = new HashSet(); - toBeRemoved.add(module); - } - } - if(toBeRemoved != null) - modules.removeAll(toBeRemoved); - } - }); - return true; - } - else - return false; - } - - public SimulationResult getSimulationResult() { - return result; - } - - public SysdynResult getSysdynResult() { - return sysdynResult; - } - - public void addResultListener(Runnable listener) { - synchronized(resultListeners) { - resultListeners.add(listener); - } - } - - public void removeResultListener(Runnable listener) { - synchronized(resultListeners) { - resultListeners.remove(listener); - } - } - - public void resultChanged() { - synchronized(resultListeners) { - for(Runnable listener : resultListeners) { - listener.run(); - } - } - - updateSubscriptions(); - } - - public void addModificationListener(Runnable listener) { - synchronized(modificationListeners) { - modificationListeners.add(listener); - } - } - - public void removeModificationListener(Runnable listener) { - synchronized(modificationListeners) { - modificationListeners.remove(listener); - } - } - - @Override - public void domainModified() { - synchronized(modificationListeners) { - for(Runnable listener : modificationListeners) - listener.run(); - } - } - - @Override - public void rangeModified() { - } - - public Configuration getConfiguration() { - return configuration; - } - - public Resource getConfigurationResource() { - return configurationResource; - } - - public IMapping getMapping() { - return mapping; - } - - public synchronized IElement getElement(Resource resource) { - return (IElement)mapping.get(resource); - } - - public T getService(Class clazz) { - synchronized(services) { - return clazz.cast(services.get(clazz)); - } - } - - public void addService(Class clazz, T service) { - synchronized(services) { - services.put(clazz, service); - } - } - - @Override - public IExperiment loadExperiment(ReadGraph g, Resource experiment, IExperimentActivationListener listener) { - - // Not good. IModel pushes only modelResource and it is assumed that - // SysdynModel is based on configuration - if(configurationResource == null && modelResource != null) { - SimulationResource simu = SimulationResource.getInstance(g); - try { - configurationResource = g.getPossibleObject(modelResource, simu.HasConfiguration); - } catch (ManyObjectsForFunctionalRelationException e) { - e.printStackTrace(); - } catch (ServiceException e) { - e.printStackTrace(); - } - } - - - try { - - SysdynResource sr = SysdynResource.getInstance(g); - IDynamicExperiment exp; - if(g.isInstanceOf(experiment, sr.PlaybackExperiment)) { - exp = new SysdynPlaybackExperiment(experiment, modelResource); - ((SysdynPlaybackExperiment)exp).init(g); - } else if(g.isInstanceOf(experiment, sr.BasicExperiment)) { - exp = new SysdynExperiment(experiment, modelResource); - ((SysdynExperiment)exp).init(g); - } else { - return null; - } - - ExperimentRuns.createRun(g.getSession(), experiment, exp, listener, null); - if(listener != null) - listener.onExperimentActivated(exp); - return exp; - } catch(Exception e) { - if(listener != null) - listener.onFailure(e); - return null; - } - } - - public Collection getActiveResults(ReadGraph graph) { - ArrayList results = new ArrayList(); - - try { - Layer0 l0 = Layer0.getInstance(graph); - SysdynResource sr = SysdynResource.getInstance(graph); - SimulationResource SIMU = SimulationResource.getInstance(graph); - Resource model = graph.getSingleObject(configurationResource, SIMU.IsConfigurationOf); - Collection experiments = graph.getObjects(model, l0.ConsistsOf); - for(Resource experiment : experiments) { - Collection experimentResults = graph.getObjects(experiment, sr.HasResult); - for(Resource result : experimentResults) { - if(graph.hasStatement(result, SIMU.IsActive)) { - SysdynResult sysdynResult = new SysdynResult( - (String) graph.getPossibleRelatedValue(result, l0.HasLabel), - (String) graph.getPossibleRelatedValue(result, sr.HasResultFile)); - results.add(sysdynResult); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - if(getSysdynResult() != null) - results.add(0, getSysdynResult() ); - - - - return results; - } - - private HashMap getInits(Configuration configuration, String prefix) { - HashMap inits = new HashMap(); - for (IElement element : configuration.getElements()) { - if (element instanceof Module) { - Module module = (Module) element; - Configuration conf = module.getType().getConfiguration(); - inits.putAll(getInits(conf, prefix + module.getName() + ".")); - } else if (element instanceof IndependentVariable) { - IndependentVariable variable = (IndependentVariable) element; - //FIXME: more general solution? - IExpression expression = variable.getExpressions().getExpressions().get(0); - if (expression instanceof ParameterExpression) { - Double value = ((ParameterExpression)expression).getValue(); - if(value != null) - inits.put(prefix + variable.getName(), "" + value); - } - } - } - return inits; - } - - public File getSimulationDir() { - if(simulationDir == null) { - File modelsDir = Activator.getBundleContext().getDataFile("models"); - String configName = configuration.getName(); - List files = Arrays.asList(modelsDir.list()); - if (files.contains(configName)) { - int i = 2; - while (files.contains(configName + "_" + i)){ - i++; - } - configName += "_" + i; - } - - simulationDir = Activator.getBundleContext().getDataFile("models/" + configName); - if (!simulationDir.exists()) { - simulationDir.mkdir(); - } - } - return simulationDir; - } - - - - - +// System.out.println("== Modelica ends == "); + + try { + simulationLocation.exeFile.delete(); + ModelicaManager.buildModel(simulationLocation, monitor); + previousImportantInits.clear(); + previousImportantInits.put("start value", startTime.toString()); + previousImportantInits.put("stop value", stopTime.toString()); + previousImportantInits.put("method", method); + previousImportantInits.put("outputFormat", outputFormat); + } catch (ModelicaException e) { + if(e.getMessage() != null) + monitor.message(e.getMessage()); + monitor.showConsole(); + canceled = true; + previousModelStructure = ""; + } + } + + progressMonitor.worked(1); + + if(simulationLocation != null && !canceled) { + // Simulate the model + progressMonitor.subTask("Simulate model"); + process = ModelicaManager.runModelica( + simulationLocation, + monitor, + inits + ); + ModelicaManager.printProcessOutput(process, monitor); + + Thread resultThread = new Thread() { + @Override + public void run() { + try { + process.waitFor(); + + if(!canceled) { + // Get and store results + progressMonitor.worked(1); + progressMonitor.subTask("Read results"); + if(simulationLocation.outputFile.getName().endsWith(".csv")) + result = new CSVSimulationResult(); + else if(simulationLocation.outputFile.getName().endsWith(".plt")) + result = new SimulationResult(); + else + result = new MatSimulationResult(); // The latest format + result.read(simulationLocation.outputFile); + result.readInits(simulationLocation.initFile); + result.filter(); + sysdynResult.setResult(result); + progressMonitor.worked(1); + resultChanged(); + + setExperimentStopped(experiment); + + String errorString = result.getResultReadErrors(); + if(errorString != null && !errorString.isEmpty()) + monitor.message(errorString); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }; + resultThread.run(); + } + if(canceled) + setExperimentStopped(experiment); + process = null; + } + + /** + * Stop an experiment + * + * @param experiment Experiment to be stopped + */ + private void setExperimentStopped(Experiment experiment) { + if(experiment instanceof SysdynExperiment) { + SysdynExperiment e = (SysdynExperiment)experiment; + if(e.getState() != ExperimentState.DISPOSED) + e.simulate(false); + } + } + + /** + * Method that compares given modelText and inits to previous model and inits + * @param modelText Textual representation of a model (Modelica code) + * @param inits map of init parameters + * @return true if the model has changed, false otherwise + */ + private boolean hasStructureChanged(String modelText, Map inits) { + + // Compare inits first because it is faster + for(String key : previousImportantInits.keySet()) { + if(!inits.containsKey(key) || !previousImportantInits.get(key).equals(inits.get(key))) + return true; + } + + // Then compare the actual model structure + BufferedReader current = new BufferedReader( + new StringReader(modelText)); + BufferedReader previous = new BufferedReader( + new StringReader(previousModelStructure)); + + String c, p; + try { + // Read both current and previous model texts at the same time + c = current.readLine(); + p = previous.readLine(); + + 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")) { + /* + * The line is a parameter definition. + * In this case only what is before '=' matters + * + * parameter Real Var = 1; + * is structurally same as + * parameter Real Var = 2; + */ + int i = c.indexOf("="); + if(!c.substring(0, i).equals(p.substring(0, i))) { + // different parameter definition + return true; + } + } else { + // other than a line containing parameters differs + return true; + } + } + c = current.readLine(); + p = previous.readLine(); + } + + if((c == null && p != null) || (c != null && p == null)) { + // different lengths + return true; + } + + } catch(IOException e) { + // Something went wrong in the comparison, it is safer to say that the structure has changed + return true; + } + return false; + } + + /** + * Cancel a possible ongoing simulation + */ + public void cancelSimulation() { + canceled = true; + if(process != null) { + process.destroy(); + } + } + + /** + * Update mapping. + * + * Use this if inside a transaction. + * + * @param graph ReadGraph + * @return has the range been modified + * @throws DatabaseException + */ + public synchronized boolean update(ReadGraph graph) throws DatabaseException { + if(mapping.isDomainModified()) { + mapping.updateRange(graph); + + // Remove all unnecessary module configurations from modules + Set configs = readModules(graph, configurationResource); + for(Resource config : configs) { + if(!modules.contains(config)) + modules.add((Configuration)mapping.map(graph, config)); + } + + HashSet toBeRemoved = null; + for(Configuration module : modules) { + if(!configs.contains(mapping.inverseGet(module))) { + if(toBeRemoved == null) + toBeRemoved = new HashSet(); + toBeRemoved.add(module); + } + } + if(toBeRemoved != null) + modules.removeAll(toBeRemoved); + return true; + } + else + return false; + } + + /** + * Update mapping. + * + * Use only if not inside a transaction + * @return has range been updated + * @throws DatabaseException + */ + public boolean update() throws DatabaseException { + return session.syncRequest(new Read() { + @Override + public Boolean perform(ReadGraph graph) throws DatabaseException { + return update(graph); + } + }); + } + + public SimulationResult getSimulationResult() { + return result; + } + + public SysdynResult getSysdynResult() { + return sysdynResult; + } + + public void addResultListener(Runnable listener) { + synchronized(resultListeners) { + resultListeners.add(listener); + } + } + + public void removeResultListener(Runnable listener) { + synchronized(resultListeners) { + resultListeners.remove(listener); + } + } + + /** + * Fires an update to all result listeners and subscriptions + * after results have changed + */ + public void resultChanged() { + synchronized(resultListeners) { + for(Runnable listener : resultListeners) { + listener.run(); + } + } + + updateSubscriptions(); + } + + public void addModificationListener(Runnable listener) { + synchronized(modificationListeners) { + modificationListeners.add(listener); + } + } + + public void removeModificationListener(Runnable listener) { + synchronized(modificationListeners) { + modificationListeners.remove(listener); + } + } + + /** + * Fires all modification listeners after a change in the domain + */ + @Override + public void domainModified() { + synchronized(modificationListeners) { + for(Runnable listener : modificationListeners) + listener.run(); + } + } + + @Override + public void rangeModified() { + } + + public Configuration getConfiguration() { + return configuration; + } + + public Resource getConfigurationResource() { + return configurationResource; + } + + public IMapping getMapping() { + return mapping; + } + + public synchronized IElement getElement(Resource resource) { + return (IElement)mapping.get(resource); + } + + public T getService(Class clazz) { + synchronized(services) { + return clazz.cast(services.get(clazz)); + } + } + + public void addService(Class clazz, T service) { + synchronized(services) { + services.put(clazz, service); + } + } + + @Override + public IExperiment loadExperiment(ReadGraph g, Resource experiment, IExperimentActivationListener listener) { + + // Make sure that configurationResource exists + if(configurationResource == null && modelResource != null) { + SimulationResource simu = SimulationResource.getInstance(g); + try { + configurationResource = g.getPossibleObject(modelResource, simu.HasConfiguration); + } catch (ManyObjectsForFunctionalRelationException e) { + e.printStackTrace(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } + + + try { + // Create a new experiment based on the experiment resource type + SysdynResource sr = SysdynResource.getInstance(g); + IDynamicExperiment exp; + if(g.isInstanceOf(experiment, sr.PlaybackExperiment)) { + exp = new SysdynPlaybackExperiment(experiment, modelResource); + } else if(g.isInstanceOf(experiment, sr.BasicExperiment)) { + exp = new SysdynExperiment(experiment, modelResource); + } else { + return null; + } + + ((SysdynExperiment)exp).init(g); + + ExperimentRuns.createRun(g.getSession(), experiment, exp, listener, null); + if(listener != null) + listener.onExperimentActivated(exp); + return exp; + } catch(Exception e) { + if(listener != null) + listener.onFailure(e); + return null; + } + } + + /** + * Get all active results for this model including the current result and + * all saved results that are active + * @param graph ReadGraph + * @return all active SysdynResults + */ + public Collection getActiveResults(ReadGraph graph) { + ArrayList results = new ArrayList(); + + try { + // Find all active saved results + Layer0 l0 = Layer0.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + SimulationResource SIMU = SimulationResource.getInstance(graph); + Resource model = graph.getSingleObject(configurationResource, SIMU.IsConfigurationOf); + Collection experiments = graph.getObjects(model, l0.ConsistsOf); + for(Resource experiment : experiments) { + Collection experimentResults = graph.getObjects(experiment, sr.HasResult); + for(Resource result : experimentResults) { + if(graph.hasStatement(result, SIMU.IsActive)) { + SysdynResult sysdynResult = new SysdynResult( + (String) graph.getPossibleRelatedValue(result, l0.HasLabel), + (String) graph.getPossibleRelatedValue(result, sr.HasResultFile)); + results.add(sysdynResult); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + // Add the current result if there is one + if(getSysdynResult() != null) + results.add(0, getSysdynResult() ); + + return results; + } + + /** + * Get all parameters for Configuration + * + * @param configuration Configuration + * @param prefix String prefix of configuration in this model (Module1.Module2...) + * @return + */ + private HashMap getInits(Configuration configuration, String prefix) { + HashMap inits = new HashMap(); + for (IElement element : configuration.getElements()) { + if (element instanceof Module) { + Module module = (Module) element; + Configuration conf = module.getType().getConfiguration(); + inits.putAll(getInits(conf, prefix + module.getName() + ".")); + } else if (element instanceof IndependentVariable) { + IndependentVariable variable = (IndependentVariable) element; + //FIXME: more general solution for finding out if the variable is a parameter + IExpression expression = variable.getExpressions().getExpressions().get(0); + if (expression instanceof ParameterExpression) { + Double value = ((ParameterExpression)expression).getValue(); + if(value != null) + inits.put(prefix + variable.getName(), "" + value); + } + } + } + return inits; + } + + /** + * Get a simulation directory for this model + * @return File directory + */ + public File getSimulationDir() { + if(simulationDir == null) { + File modelsDir = Activator.getBundleContext().getDataFile("models"); + String configName = configuration.getName(); + List files = Arrays.asList(modelsDir.list()); + if (files.contains(configName)) { + int i = 2; + while (files.contains(configName + "_" + i)){ + i++; + } + configName += "_" + i; + } + + simulationDir = Activator.getBundleContext().getDataFile("models/" + configName); + if (!simulationDir.exists()) { + simulationDir.mkdir(); + } + } + return simulationDir; + } + + /** * Copy from AprosExperiment * @param subscription @@ -629,7 +716,7 @@ public class SysdynModel implements IMappingListener, IModel { variableValueSubscriptionsSnapshot = null; } } - + /** * Copy from AprosExperiment * @param subscription diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java index 3b41feda..9fbacbb3 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java @@ -14,7 +14,6 @@ package org.simantics.sysdyn.manager; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.TreeMap; @@ -44,15 +43,27 @@ import org.simantics.databoard.type.Datatype; import org.simantics.modelica.data.DataSet; import org.simantics.modelica.data.SimulationResult; +/** + * Class for containing the accessor for a sysdyn simulation result + * @author Teemu Lempinen + * + */ public class SysdynResult { RecordAccessor accessor; String resultName; + /** + * Create an empty result + */ public SysdynResult() { } + /** + * Create a sysdynresult accessor using a {@link SimulationResult} + * @param result + */ public SysdynResult(SimulationResult result) { if(result != null) setResult(result); @@ -76,10 +87,18 @@ public class SysdynResult { } } + /** + * Get the {@link RecordAccessor} of this result + * @return {@link RecordAccessor} for this result + */ public Accessor getAccessor() { return accessor; } + /** + * Create a {@link RecordAccessor} for this result based on a {@link SimulationResult} + * @param result {@link SimulationResult} + */ public void setResult(SimulationResult result) { try { // Create Memory Historian @@ -114,6 +133,12 @@ public class SysdynResult { } } + /** + * Create a recording for a variable to this result's {@link RecordAccessor} + * @param ds {@link DataSet} for the variable + * @return {@link Recording} + * @throws BindingException + */ @SuppressWarnings("unchecked") Recording createRecording(DataSet ds) throws BindingException { RecordBinding recordingBinding = (RecordBinding) Bindings.getBindingUnchecked( Recording.class ); @@ -125,15 +150,20 @@ public class SysdynResult { TreeMap segment = new TreeMap(); recording.segments = new TreeMap[] { segment }; - int length = ds.values.size(); + int length = ds.values.length; for (int i=0; i labels; public @Arguments({TreeMap.class, Double.class, Double.class}) TreeMap[] segments; } + /** + * Get dataset for a named variable + * @param variable The name of the variable + * @return {@link SysdynDataSet} + */ public SysdynDataSet getDataSet(String variable) { if(accessor != null) { try { @@ -184,11 +224,11 @@ public class SysdynResult { ma.getAll(Bindings.DOUBLE, Bindings.DOUBLE, times, values); - List times_ = new ArrayList(size); - List values_ = new ArrayList(size); + double[] times_ = new double[size]; + double[] values_ = new double[size]; for (int i=0; i