From 76207bac5b11d8338909de34b0304a3d1c984324 Mon Sep 17 00:00:00 2001 From: miettinen Date: Fri, 7 Dec 2012 12:12:13 +0000 Subject: [PATCH] * Optimized simulation result read: The result file is indexed after running the simulation; only the 'time' variable and parameters are read straight after the simulation. (refs #3709) * Fixing a bug of output interval rounding up instead of rounding to the nearest. git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@26510 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../modelica/data/MatSimulationResult.java | 11 +++ .../modelica/data/SimulationResult.java | 75 +++++++++++++++-- .../modelica/reader/MatFileReader.java | 84 +++++++++++++++---- .../sysdyn/manager/SysdynExperiment.java | 30 +++---- .../sysdyn/manager/SysdynGameExperiment.java | 10 +-- .../sysdyn/manager/SysdynResult.java | 21 ++++- 6 files changed, 185 insertions(+), 46 deletions(-) diff --git a/org.simantics.modelica/src/org/simantics/modelica/data/MatSimulationResult.java b/org.simantics.modelica/src/org/simantics/modelica/data/MatSimulationResult.java index 9e8a9c76..d748ffe7 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/MatSimulationResult.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/MatSimulationResult.java @@ -11,16 +11,21 @@ *******************************************************************************/ package org.simantics.modelica.data; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Map; +import org.simantics.modelica.reader.MatFileReader; + /** * SimulationResult for Mat-formatted simulations results * * @author Teemu Lempinen * */ + public class MatSimulationResult extends SimulationResult { @Override @@ -47,4 +52,10 @@ public class MatSimulationResult extends SimulationResult { } } } + + @Override + public void initRead(File file) throws FileNotFoundException, IOException { + super.initRead(file); + resultFileReader = new MatFileReader(file); + } } 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 03325da6..35537877 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java +++ b/org.simantics.modelica/src/org/simantics/modelica/data/SimulationResult.java @@ -33,6 +33,7 @@ import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.simantics.modelica.reader.ResultFileReader; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -53,6 +54,9 @@ public class SimulationResult { protected List variables = new ArrayList(); protected List initials = new ArrayList(); protected int numberOfLines = 0; + protected ResultFileReader resultFileReader; + protected double[] allTimes; + protected int skip; /** * Private class used in displaying errors @@ -263,8 +267,6 @@ public class SimulationResult { } } - - /** * Read result file. Read all values in the result file. * @@ -276,16 +278,28 @@ public class SimulationResult { read(file, 1); } - /** - * Read result file + * Initialize result file reading and read the whole result file * * @param file result file * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... * @throws FileNotFoundException * @throws IOException */ - public void read(File file, int interval) throws FileNotFoundException, IOException { + public void read(File file, int interval) throws FileNotFoundException, IOException { + initRead(file); + readAll(file, interval); + } + + /** + * Initialize result file reading + * + * @param file result file + * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... + * @throws FileNotFoundException + * @throws IOException + */ + public void initRead(File file) throws FileNotFoundException, IOException { // First check the number of time steps. // With *.mat result file this is not necessary if (!(this instanceof MatSimulationResult)) { @@ -296,13 +310,24 @@ public class SimulationResult { lnr.close(); fr.close(); } + } + + /** + * Read the whole result file + * + * @param file result file + * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... + * @throws FileNotFoundException + * @throws IOException + */ + public void readAll(File file, int interval) throws FileNotFoundException, IOException { InputStream is = openStream(file); - //InputStream is = new FileInputStream(file); read(is, interval); is.close(); } - private InputStream openStream(File file) throws FileNotFoundException { + + protected InputStream openStream(File file) throws FileNotFoundException { return new BufferedInputStream(new FileInputStream(file)); } @@ -410,4 +435,40 @@ public class SimulationResult { } return errorString.toString(); } + + /** + * Read a defined variable from result file + * + * @param file result file + * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... + * @throws FileNotFoundException + * @throws IOException + */ + public void readVariable(String variable, File file) throws FileNotFoundException, IOException { + DataSet ds; + List names = resultFileReader.getNames(); + if (names.contains(variable)) { + double[] resArray = resultFileReader.readData(variable, 0, allTimes.length, skip); + ds = new DataSet(variable, allTimes, resArray); + variables.add(ds); + } + } + + /** + * Read time array from result file + * + * @param file result file + * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... + * @throws FileNotFoundException + * @throws IOException + */ + public void readTime(File file, int interval) throws FileNotFoundException, IOException { + skip = interval - 1; + int totalCount = resultFileReader.getCount("time"); + int count = totalCount / interval; + if (totalCount % interval != 0) + count++; + allTimes = resultFileReader.readData("time", 0, count, skip); + } + } diff --git a/org.simantics.modelica/src/org/simantics/modelica/reader/MatFileReader.java b/org.simantics.modelica/src/org/simantics/modelica/reader/MatFileReader.java index 11184279..afb7a0b7 100644 --- a/org.simantics.modelica/src/org/simantics/modelica/reader/MatFileReader.java +++ b/org.simantics.modelica/src/org/simantics/modelica/reader/MatFileReader.java @@ -19,10 +19,12 @@ import org.simantics.modelica.data.StringMatrix; import org.simantics.utils.datastructures.MapList; public class MatFileReader implements ResultFileReader { - private File file; + private final File file; - private List names = new ArrayList(); - private Map indices = new HashMap(); + private final List names = new ArrayList(); + private final Map indices = new HashMap(); + + private HashMap parameterValues; long readBytes = 0; // tracking read data @@ -38,22 +40,29 @@ public class MatFileReader implements ResultFileReader { readVariables(); } - public List getNames() { + @Override + public List getNames() { return names; } - public int getCount(String item) { + @Override + public int getCount(String item) { return dataHeader.columns; } /** * Reads all data of a given item */ - public double[] readData(String item) throws IOException { + @Override + public double[] readData(String item) throws IOException { readBytes = 0; Integer index = indices.get(item); if (index == null) - throw new IOException("Unknown item: " + item); + if (parameterValues.containsKey(item)) { + return parameterValues.get(item); + } else { + throw new IOException("Unknown item: " + item); + } InputStream in = openStream(); skip(dataMark, in); @@ -74,11 +83,16 @@ public class MatFileReader implements ResultFileReader { * @return * @throws IOException */ - public double[] readData(String item, int start, int count, int skip) throws IOException { + @Override + public double[] readData(String item, int start, int count, int skip) throws IOException { readBytes = 0; Integer index = indices.get(item); if (index == null) - throw new IOException("Unknown item: " + item); + if (parameterValues.containsKey(item)) { + return parameterValues.get(item); + } else { + throw new IOException("Unknown item: " + item); + } InputStream in = openStream(); skip(dataMark, in); @@ -90,13 +104,16 @@ public class MatFileReader implements ResultFileReader { } - public double[][] readData(List items) throws IOException { - readBytes = 0; + @Override + public double[][] readData(List items) throws IOException { + readBytes = 0; List indexes = new ArrayList(items.size()); for (String item : items) { Integer index = indices.get(item); if (index == null) - throw new IOException("Unknown item: " + item); + // Parameters cannot be accessed via this method; instead, + // methods with only a single item should be used + throw new IOException("Unknown item: " + item); indexes.add(index); } @@ -126,7 +143,9 @@ public class MatFileReader implements ResultFileReader { for (String item : items) { Integer index = indices.get(item); if (index == null) - throw new IOException("Unknown item: " + item); + // Parameters cannot be accessed via this method; instead, + // methods with only a single item should be used + throw new IOException("Unknown item: " + item); indexes.add(index); } @@ -164,7 +183,10 @@ public class MatFileReader implements ResultFileReader { infoData = info.data; - readMatrix(in); // Some result data matrix? + //Read parameters + parameterValues = new HashMap(); + DoubleMatrix parameters = (DoubleMatrix)readMatrix(in); // Some result data matrix? + readDoubleMatrix(parameters, names, 1, 1, info, 1, parameterValues); dataHeader = new MatrixHeader(in); @@ -175,7 +197,8 @@ public class MatFileReader implements ResultFileReader { // filter incompatible? data. for (int i = this.names.size() -1; i >= 0; i--) { if (infoData[i * 4] != 2) { - String name = this.names.remove(i); + String name = this.names.get(i); + // Remove parameters from indices but not from names list this.indices.remove(name); } @@ -340,7 +363,7 @@ public class MatFileReader implements ResultFileReader { if (infoData[row * 4] != 2) throw new IOException(); // this is checked in initialization phase. int size = header.columns; - if (start+count*(skip+1) > size) + if (start+count*(skip+1)-skip > size) throw new IndexOutOfBoundsException(); // TODO: we could just read available data, instead of throwing exception. int rows = header.rows; double[] v = new double[count]; @@ -413,7 +436,7 @@ public class MatFileReader implements ResultFileReader { - skip((long)c[0] * 8L, in); + skip(c[0] * 8L, in); for (int j = 0; j < size; ++j) { for (int index = 0; index < sortedRows.size(); index++) { @@ -533,7 +556,7 @@ public class MatFileReader implements ResultFileReader { long s = start; - s *= (long)rows; + s *= rows; s *= 8L; skip(s, in); skip(c[0] * 8, in); @@ -592,6 +615,31 @@ public class MatFileReader implements ResultFileReader { } } + private static void readDoubleMatrix(DoubleMatrix matrix, StringMatrix names, int dataMatrixNumber, int startIndex, IntMatrix info, int outputInterval, HashMap result) { + double[] valueData = matrix.data; + int[] infoData = info.data; + int rows = matrix.rows; + //System.out.println("cols="+values.columns+", rows=" +values.rows+ ", data.length="+valueData.length); + + for(int i=startIndex;i 0 ? sc-1 : -sc-1; + //System.out.println("i=" + i + ", sc=" + sc + ", c=" + c); + for(int j=0;j= matrix.columns) adjusted = matrix.columns - 1; + v[j] = valueData[rows * adjusted + c]; + } if(sc < 0) + for(int j=0;j maxIntervalInt) + outIntervalInt = maxIntervalInt; } - result.read(simulationLocation.resFile, outIntervalInt); + result.initRead(simulationLocation.resFile); + result.readTime(simulationLocation.resFile, outIntervalInt); //result.readInits(simulationLocation.initFile); // Parameter values are read from .mat result.filter(); getCurrentResult().setResult(result); + getCurrentResult().setResultFile(simulationLocation.resFile); progressMonitor.worked(1); resultsChanged(); @@ -349,15 +355,11 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment, }; } - protected static double roundUp(double numToRound, double multiple) { - if(multiple == 0) { - return numToRound; - } - double remainder = numToRound % multiple; - if (remainder == 0) { - return numToRound; - } - return numToRound + multiple - remainder; + protected static long getInterval(double outputLength, double stepLength) { + double interval = outputLength / stepLength; + if (interval <= 1) + return 1; + return Math.round(interval); } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java index 11706465..defa0977 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java @@ -25,12 +25,12 @@ import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.AsyncListener; import org.simantics.db.request.Read; +import org.simantics.fmu.FMUControlJNI; +import org.simantics.fmu.FMUJNIException; import org.simantics.modelica.IModelicaMonitor; import org.simantics.modelica.SimulationLocation; import org.simantics.modelica.data.DataSet; import org.simantics.modelica.data.SimulationResult; -import org.simantics.fmu.FMUControlJNI; -import org.simantics.fmu.FMUJNIException; import org.simantics.simulation.experiment.ExperimentState; import org.simantics.sysdyn.SysdynResource; import org.simantics.utils.datastructures.Triple; @@ -113,9 +113,7 @@ public class SysdynGameExperiment extends SysdynExperiment { if(result.third == null) { setOutputInterval(DEFAULT_OUTPUT_INTERVAL); } else { - double nearest = roundUp(result.third, getStepLength()); - int interval = (int)(nearest / getStepLength()); - if(interval <= 0) interval = 1; + int interval = (int)getInterval(result.third, getStepLength()); setOutputInterval(interval); } } @@ -229,7 +227,7 @@ public class SysdynGameExperiment extends SysdynExperiment { private class simulateDurationJob extends Job { private double duration; - private SysdynGameExperiment experiment; + private final SysdynGameExperiment experiment; public simulateDurationJob(String name, SysdynGameExperiment experiment, double duration) { super(name); this.duration = duration; 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 3533d6a9..7a1b29c9 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynResult.java @@ -13,6 +13,7 @@ package org.simantics.sysdyn.manager; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.TreeMap; @@ -54,6 +55,7 @@ public class SysdynResult { protected RecordAccessor accessor; protected String resultName; private SimulationResult simulationResult; + private File resultFile; /** * Create an empty result @@ -301,7 +303,20 @@ public class SysdynResult { try { ma = accessor.getComponent( ref ); } catch (AccessorConstructionException e) { - // Variable was not found, so add it and try again + // Variable was not found, so read it from file + try { + simulationResult.readVariable(variable, resultFile); + } catch (FileNotFoundException e1) { + // Unable to read data from OpenModelica result file + System.err.println("Variable " + variable + " not found in OpenModelica result file"); + return null; + } catch (IOException e1) { + // IoFail + e1.printStackTrace(); + return null; + } + + // Add the read item addDataSet(variable); try { ma = accessor.getComponent( ref ); @@ -339,4 +354,8 @@ public class SysdynResult { public int numberOfVariables() { return simulationResult.getVariableDataSets().size(); } + + public void setResultFile(File resFile) { + this.resultFile = resFile; + } } -- 2.47.1