* Overridden method to support csv-formatted simulation results\r
*/\r
@Override\r
- public void read(InputStream stream) {\r
+ public void read(InputStream stream, int outputInterval) {\r
errors.clear();\r
\r
// First line contains the variable names in format "name" (including quotes);\r
// Create lists for receiving values for each variable. Names still with quotes.\r
for(String name : names) {\r
if(!name.isEmpty())\r
- valueMap.put(name, new DataSet(name, new double[numberOfTimeSteps], new double[numberOfTimeSteps]));\r
+ valueMap.put(name, new DataSet(name, new double[numberOfLines], new double[numberOfLines]));\r
}\r
\r
int row = 0;\r
}\r
}\r
\r
- public static Map<String, double[]> read(InputStream in) throws IOException {\r
+ /**\r
+ * \r
+ * @param in InputStream of a mat file\r
+ * @param outputInterval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc... \r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ public static Map<String, double[]> read(InputStream in, int outputInterval) throws IOException {\r
Mat4Reader reader = new Mat4Reader(in);\r
reader.readMatrix(); // Header\r
StringMatrix names = (StringMatrix)reader.readMatrix(); // Variable names\r
for(int i=0;i<info.columns;++i) {\r
if(infoData[i*4] != 2)\r
continue;\r
- double[] v = new double[values.columns];\r
+ // If values.columns % outputInterval != 0, the value in the last time step would not be displayed without adding a +1;\r
+ int size = values.columns % outputInterval != 0 ? values.columns / outputInterval + 1 : values.columns; \r
+ double[] v = new double[size];\r
int sc = infoData[i*4+1];\r
int c = sc > 0 ? sc-1 : 1-sc;\r
//System.out.println("i=" + i + ", sc=" + sc + ", c=" + c);\r
- for(int j=0;j<v.length;++j)\r
- v[j] = valueData[rows*j+c];\r
- if(sc < 0)\r
+ for(int j=0;j<v.length;++j) {\r
+ int adjusted = j * outputInterval;\r
+ if(adjusted >= values.columns) adjusted = values.columns - 1;\r
+ v[j] = valueData[rows * adjusted + c];\r
+ } if(sc < 0)\r
for(int j=0;j<v.length;++j)\r
v[j] = -v[j];\r
result.put(names.data[i], v);\r
public class MatSimulationResult extends SimulationResult {\r
\r
@Override\r
- public void read(InputStream stream) {\r
+ public void read(InputStream stream, int interval) {\r
Map<String, double[]> valueMap = null;\r
try {\r
- valueMap = Mat4Reader.read(stream);\r
+ valueMap = Mat4Reader.read(stream, interval);\r
} catch (IOException e) {\r
e.printStackTrace();\r
return;\r
\r
protected List<DataSet> variables = new ArrayList<DataSet>();\r
protected List<DataSet> initials = new ArrayList<DataSet>();\r
- protected int numberOfTimeSteps = 0;\r
+ protected int numberOfLines = 0;\r
\r
/**\r
* Private class used in displaying errors\r
}\r
\r
\r
- final static Pattern p1 = Pattern.compile("DataSet: ([^ ]*)");\r
+ \r
+ /**\r
+ * Read result file. Read all values in the result file.\r
+ * \r
+ * @param file result file\r
+ * @throws FileNotFoundException\r
+ * @throws IOException\r
+ */\r
+ public void read(File file) throws FileNotFoundException, IOException {\r
+ read(file, 1);\r
+ }\r
+\r
\r
/**\r
* Read result file\r
* \r
* @param file result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
* @throws FileNotFoundException\r
* @throws IOException\r
*/\r
- public void read(File file) throws FileNotFoundException, IOException {\r
+ public void read(File file, int interval) throws FileNotFoundException, IOException {\r
// First check the number of time steps\r
FileReader fr = new FileReader(file);\r
LineNumberReader lnr = new LineNumberReader(fr);\r
lnr.skip(Long.MAX_VALUE);\r
- numberOfTimeSteps = lnr.getLineNumber() - 1; // minus the first row, which is for names\r
+ numberOfLines = lnr.getLineNumber() - 1; // minus the first row, which is for names\r
lnr.close();\r
fr.close();\r
\r
InputStream is = new FileInputStream(file);\r
- read(is);\r
+ read(is, interval);\r
is.close();\r
}\r
\r
- \r
+ final static Pattern p1 = Pattern.compile("DataSet: ([^ ]*)");\r
+\r
/**\r
* Read result file. The basic implementation supports\r
* plt-formatted results. Overridden to support other formats. \r
* @param stream FileInputStream for the result file\r
+ * @param interval the interval of results to be read. 1 reads all time steps, 2 reads every other time step, etc...\r
*/\r
- public void read(InputStream stream) {\r
+ public void read(InputStream stream, int outputInterval) {\r
while(true) {\r
String line = getLine(stream);\r
if(line == null)\r
return;\r
String name = matcher.group(1);\r
\r
- double[] dtimes = new double[numberOfTimeSteps];\r
- double[] dvalues = new double[numberOfTimeSteps];\r
+ double[] dtimes = new double[numberOfLines];\r
+ double[] dvalues = new double[numberOfLines];\r
int i = 0;\r
while(true) {\r
String line = getLine(stream);\r
SYSDYN.SysdynModel <T MOD.StructuralModel
>-- SYSDYN.SysdynModel.startTime --> L0.Double <R L0.HasProperty : L0.FunctionalRelation
>-- SYSDYN.SysdynModel.stopTime --> L0.Double <R L0.HasProperty : L0.FunctionalRelation
+ >-- SYSDYN.SysdynModel.simulationStepLength --> L0.Double <R L0.HasProperty : L0.FunctionalRelation
>-- SYSDYN.SysdynModel.outputInterval --> L0.Double <R L0.HasProperty : L0.FunctionalRelation
>-- SYSDYN.SysdynModel.tolerance --> L0.Double <R L0.HasProperty : L0.FunctionalRelation
>-- SYSDYN.SysdynModel.solver --> L0.String <R L0.HasProperty : L0.FunctionalRelation
public final Resource SysdynModel;\r
public final Resource SysdynModel_outputInterval;\r
public final Resource SysdynModel_outputInterval_Inverse;\r
+ public final Resource SysdynModel_simulationStepLength;\r
+ public final Resource SysdynModel_simulationStepLength_Inverse;\r
public final Resource SysdynModel_solver;\r
public final Resource SysdynModel_solver_Inverse;\r
public final Resource SysdynModel_startTime;\r
public static final String SysdynModel = "http://www.simantics.org/Sysdyn-1.1/SysdynModel";\r
public static final String SysdynModel_outputInterval = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/outputInterval";\r
public static final String SysdynModel_outputInterval_Inverse = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/outputInterval/Inverse";\r
+ public static final String SysdynModel_simulationStepLength = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/simulationStepLength";\r
+ public static final String SysdynModel_simulationStepLength_Inverse = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/simulationStepLength/Inverse";\r
public static final String SysdynModel_solver = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/solver";\r
public static final String SysdynModel_solver_Inverse = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/solver/Inverse";\r
public static final String SysdynModel_startTime = "http://www.simantics.org/Sysdyn-1.1/SysdynModel/startTime";\r
SysdynModel = getResourceOrNull(graph, URIs.SysdynModel);\r
SysdynModel_outputInterval = getResourceOrNull(graph, URIs.SysdynModel_outputInterval);\r
SysdynModel_outputInterval_Inverse = getResourceOrNull(graph, URIs.SysdynModel_outputInterval_Inverse);\r
+ SysdynModel_simulationStepLength = getResourceOrNull(graph, URIs.SysdynModel_simulationStepLength);\r
+ SysdynModel_simulationStepLength_Inverse = getResourceOrNull(graph, URIs.SysdynModel_simulationStepLength_Inverse);\r
SysdynModel_solver = getResourceOrNull(graph, URIs.SysdynModel_solver);\r
SysdynModel_solver_Inverse = getResourceOrNull(graph, URIs.SysdynModel_solver_Inverse);\r
SysdynModel_startTime = getResourceOrNull(graph, URIs.SysdynModel_startTime);\r
return;\r
spe = (SysdynPlaybackExperiment)experiment;\r
\r
- Double[] numbers = new Double[3];\r
+ Double[] numbers = new Double[2];\r
try {\r
numbers = SimanticsUI.getSession().syncRequest(new Read<Double[]>() {\r
@Override\r
public Double[] perform(ReadGraph graph) throws DatabaseException {\r
- Double[] numbers = new Double[3];\r
+ Double[] numbers = new Double[2];\r
Resource model = spe.getModel();\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
numbers[0] = graph.getRelatedValue(model, sr.SysdynModel_startTime);\r
numbers[1] = graph.getRelatedValue(model, sr.SysdynModel_stopTime);\r
- numbers[2] = graph.getPossibleRelatedValue(model, sr.SysdynModel_outputInterval);\r
return numbers;\r
}\r
});\r
label = new Label(composite, SWT.NONE);\r
label.setText("Step length\n(empty = default)");\r
\r
+ TrackedText stepLength = new TrackedText(composite, support, SWT.BORDER | SWT.RIGHT);\r
+ stepLength.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.SysdynModel_simulationStepLength));\r
+ stepLength.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.SysdynModel_simulationStepLength));\r
+ stepLength.setInputValidator(new DoubleValidator());\r
+ GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(stepLength.getWidget());\r
+ \r
+ label = new Label(composite, SWT.NONE);\r
+ label.setText("Output interval\n(empty = all steps)");\r
+\r
TrackedText outputInterval = new TrackedText(composite, support, SWT.BORDER | SWT.RIGHT);\r
outputInterval.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.SysdynModel_outputInterval));\r
outputInterval.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.SysdynModel_outputInterval));\r
outputInterval.setInputValidator(new DoubleValidator());\r
GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(outputInterval.getWidget());\r
\r
+ \r
label = new Label(composite, SWT.NONE);\r
label.setText("Method");\r
\r
*/\r
public class HistoryDatasetResult extends SimulationResult {\r
@Override\r
- public void read(File file) {} // Do nothing\r
+ public void read(File file, int interval) {} // Do nothing\r
@Override\r
- public void read(InputStream stream) {} // Do nothing\r
+ public void read(InputStream stream, int interval) {} // Do nothing\r
\r
private boolean disposed;\r
\r
Model model = configuration.getModel();\r
Double startTime = model.getStartTime();\r
Double stopTime = model.getStopTime();\r
- Double numberOfIntervals = model.getOutputInterval();\r
inits.put(SysdynInitKeys.START_VALUE, startTime.toString());\r
inits.put(SysdynInitKeys.STOP_VALUE, stopTime.toString());\r
String outputFormat = "\"mat\"";\r
inits.put(SysdynInitKeys.OUTPUT_FORMAT, outputFormat);\r
- if(numberOfIntervals != null) {\r
- inits.put(SysdynInitKeys.STEP_VALUE, numberOfIntervals.toString());\r
- inits.put(SysdynInitKeys.NUMBER_OF_INTERVALS, "" + ((int)((stopTime - startTime) / numberOfIntervals)));\r
+ \r
+ Double simulationStepLength = model.getSimulationStepLength();\r
+ if(simulationStepLength != null) {\r
+ inits.put(SysdynInitKeys.STEP_VALUE, simulationStepLength.toString());\r
+ inits.put(SysdynInitKeys.NUMBER_OF_INTERVALS, "" + ((int)((stopTime - startTime) / simulationStepLength)));\r
} else {\r
inits.put(SysdynInitKeys.STEP_VALUE, "" + (stopTime - startTime) / 500);\r
}\r
+ \r
+ Double outputInterval = model.getOutputInterval();\r
+ inits.put(SysdynInitKeys.OUTPUT_INTERVAL, outputInterval != null ? outputInterval.toString() : inits.get(SysdynInitKeys.STEP_VALUE));\r
+ \r
String method = "\"" + model.getSolver() + "\"";\r
inits.put(SysdynInitKeys.METHOD, method);\r
if(model.getTolerance() != null)\r
);\r
ModelicaManager.printProcessOutput(process, monitor);\r
\r
- Thread resultThread = getResultThread(simulationLocation, monitor, progressMonitor);\r
+ Thread resultThread = getResultThread(simulationLocation, inits, monitor, progressMonitor);\r
resultThread.run();\r
\r
process = null;\r
/**\r
* Get a thread for reading and saving reuslts from a normal simulation\r
* @param simulationLocation\r
+ * @param inits \r
* @param monitor\r
* @param progressMonitor\r
* @return\r
*/\r
- protected Thread getResultThread(final SimulationLocation simulationLocation, final IModelicaMonitor monitor, final IProgressMonitor progressMonitor) {\r
+ protected Thread getResultThread(final SimulationLocation simulationLocation, final HashMap<String, String> inits, final IModelicaMonitor monitor, final IProgressMonitor progressMonitor) {\r
return new Thread() {\r
@Override\r
public void run() {\r
result = new SimulationResult();\r
else\r
result = new MatSimulationResult(); // The latest format\r
- result.read(simulationLocation.outputFile);\r
+ \r
+ \r
+ // The interval of results saved. Every result? Every other result? etc...\r
+ int outIntervalInt = 1;\r
+ String outputInterval = inits.get(SysdynInitKeys.OUTPUT_INTERVAL);\r
+ if(outputInterval != null) {\r
+ String stepTime = inits.get(SysdynInitKeys.STEP_VALUE);\r
+ \r
+ Double step = Double.parseDouble(stepTime);\r
+ Double outInterval = Double.parseDouble(outputInterval);\r
+ \r
+ double nearest = roundUp(outInterval, step);\r
+ outIntervalInt = (int)(nearest / step);\r
+ if(outIntervalInt <= 0) outIntervalInt = 1;\r
+ }\r
+ \r
+ result.read(simulationLocation.outputFile, outIntervalInt);\r
result.readInits(simulationLocation.initFile);\r
result.filter();\r
sysdynModel.getSysdynResult().setResult(result);\r
}\r
};\r
}\r
+ \r
+ protected static double roundUp(double numToRound, double multiple) { \r
+ if(multiple == 0) {\r
+ return numToRound; \r
+ }\r
+ double remainder = numToRound % multiple; \r
+ if (remainder == 0) {\r
+ return numToRound; \r
+ }\r
+ return numToRound + multiple - remainder; \r
+ } \r
\r
\r
/**\r
\r
protected void storeImportantInits(HashMap<String, String> inits) {\r
previousImportantInits.clear();\r
- previousImportantInits.put("start value", inits.get(SysdynInitKeys.START_VALUE));\r
- previousImportantInits.put("stop value", inits.get(SysdynInitKeys.STOP_VALUE));\r
- previousImportantInits.put("method", inits.get(SysdynInitKeys.METHOD));\r
- previousImportantInits.put("outputFormat", inits.get(SysdynInitKeys.OUTPUT_FORMAT));\r
- previousImportantInits.put("variableFilter", inits.get(SysdynInitKeys.VARIABLE_FILTER));\r
+ previousImportantInits.put(SysdynInitKeys.START_VALUE, inits.get(SysdynInitKeys.START_VALUE));\r
+ previousImportantInits.put(SysdynInitKeys.STOP_VALUE, inits.get(SysdynInitKeys.STOP_VALUE));\r
+ previousImportantInits.put(SysdynInitKeys.METHOD, inits.get(SysdynInitKeys.METHOD));\r
+ previousImportantInits.put(SysdynInitKeys.OUTPUT_FORMAT, inits.get(SysdynInitKeys.OUTPUT_FORMAT));\r
+ previousImportantInits.put(SysdynInitKeys.VARIABLE_FILTER, inits.get(SysdynInitKeys.VARIABLE_FILTER));\r
}\r
\r
/**\r
import org.simantics.modelica.fmi.FMUJNIException;\r
import org.simantics.simulation.experiment.ExperimentState;\r
import org.simantics.sysdyn.SysdynResource;\r
-import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.datastructures.Triple;\r
\r
/**\r
* Game experiment\r
private HashMap<String, ArrayList<Double>> results;\r
private double stepLength = DEFAULT_STEP_LENGTH;\r
private double stepDuration = DEFAULT_STEP_DURATION;\r
+ private int savePer = 1;\r
\r
public static double DEFAULT_STEP_DURATION = 1.0;\r
public static double DEFAULT_STEP_LENGTH = 0.1;\r
+ public static int DEFAULT_OUTPUT_INTERVAL = 1;\r
\r
public SysdynGameExperiment(Resource experiment, Resource model) {\r
super(experiment, model);\r
this.stepLength = stepLength;\r
}\r
\r
+ public void setOutputInterval(int interval) {\r
+ this.savePer = interval;\r
+ }\r
+\r
+ \r
public FMUControlJNI getFMUControl() {\r
return control;\r
}\r
\r
results = new HashMap<String, ArrayList<Double>>();\r
\r
- g.asyncRequest(new Read<Pair<Double, Double>>() {\r
+ g.asyncRequest(new Read<Triple<Double, Double, Double>>() {\r
\r
@Override\r
- public Pair<Double, Double> perform(ReadGraph graph)\r
+ public Triple<Double, Double, Double> perform(ReadGraph graph)\r
throws DatabaseException {\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
Double stepDuration = graph.getPossibleRelatedValue(experiment, sr.GameExperiment_stepDuration);\r
- Double stepLength =graph.getPossibleRelatedValue(experiment, sr.GameExperiment_stepLength);\r
- return new Pair<Double, Double>(stepDuration, stepLength);\r
+ Double stepLength = graph.getPossibleRelatedValue(experiment, sr.GameExperiment_stepLength);\r
+ Double outputInterval = graph.getPossibleRelatedValue(model, sr.SysdynModel_outputInterval);\r
+ return new Triple<Double, Double, Double>(stepDuration, stepLength, outputInterval);\r
}\r
- }, new AsyncListener<Pair<Double, Double>>() {\r
+ }, new AsyncListener<Triple<Double, Double, Double>>() {\r
\r
@Override\r
public void execute(AsyncReadGraph graph,\r
- Pair<Double, Double> result) {\r
+ Triple<Double, Double, Double> result) {\r
setStepDuration(result.first != null ? result.first : DEFAULT_STEP_DURATION);\r
setStepLength(result.second != null ? result.second : DEFAULT_STEP_LENGTH);\r
+ \r
+ if(result.third == null) {\r
+ setOutputInterval(DEFAULT_OUTPUT_INTERVAL);\r
+ } else {\r
+ double nearest = roundUp(result.third, getStepLength());\r
+ int interval = (int)(nearest / getStepLength());\r
+ if(interval <= 0) interval = 1;\r
+ setOutputInterval(interval);\r
+ }\r
}\r
\r
@Override\r
throwable.printStackTrace();\r
setStepDuration(DEFAULT_STEP_DURATION);\r
setStepLength(DEFAULT_STEP_LENGTH);\r
+ setOutputInterval(DEFAULT_OUTPUT_INTERVAL);\r
}\r
\r
@Override\r
\r
@Override\r
protected IStatus run(IProgressMonitor monitor) {\r
- \r
int nSteps = (int)(duration / stepLength); \r
int work = 1 + nSteps * 3 + 2; // initialization + number of steps * number of phases per step + set result + call result listeners \r
\r
double[] results = new double[subscription.length];\r
\r
monitor.worked(1);\r
-\r
+ \r
+ int stepNumber = 1;\r
while(control.getTime() < (eTime - 1e-9)) { // Substract a very small number, because OpenModelica is not very precise with its Real numbers\r
monitor.subTask("Simulate step (time = " + control.getTime() + ")");\r
control.simulateStep();\r
monitor.worked(1);\r
\r
- monitor.subTask("Get results (time = " + control.getTime() + ")");\r
- results = control.getSubscribedResults(results);\r
- monitor.worked(1);\r
-\r
- monitor.subTask("Save results (time = " + control.getTime() + ")");\r
- for(int k = 0; k < subscription.length; k++) {\r
- SysdynGameExperiment.this.results.get(subscription[k]).add(results[k]);\r
+ if(stepNumber % savePer == 0) {\r
+ monitor.subTask("Get results (time = " + control.getTime() + ")");\r
+ results = control.getSubscribedResults(results);\r
+ monitor.worked(1);\r
+\r
+ monitor.subTask("Save results (time = " + control.getTime() + ")");\r
+ for(int k = 0; k < subscription.length; k++) {\r
+ SysdynGameExperiment.this.results.get(subscription[k]).add(results[k]);\r
+ }\r
}\r
+ stepNumber++;\r
monitor.worked(1);\r
}\r
\r
} catch (FMUJNIException e) {\r
System.err.println("SysdynGameExperiment simulateDuration failed: \n\t" + e.getMessage());\r
}\r
- \r
return Status.OK_STATUS;\r
}\r
}\r
public static String METHOD = "method";\r
public static String TOLERANCE = "tolerance";\r
public static String VARIABLE_FILTER = "variableFilter";\r
+ public static String OUTPUT_INTERVAL = "outputInterval";\r
\r
}\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
numbers[0] = graph.getRelatedValue(model, sr.SysdynModel_startTime);\r
numbers[1] = graph.getRelatedValue(model, sr.SysdynModel_stopTime);\r
- numbers[2] = graph.getPossibleRelatedValue(model, sr.SysdynModel_outputInterval);\r
\r
PlaybackConfiguration config = new PlaybackConfiguration();\r
config.simulationDuration = numbers[1] - numbers[0] - time;\r
\r
@RelatedValue(SysdynResource.URIs.SysdynModel_outputInterval)\r
private Double outputInterval;\r
+ \r
+ @RelatedValue(SysdynResource.URIs.SysdynModel_simulationStepLength)\r
+ private Double stepLength;\r
\r
@RelatedValue(SysdynResource.URIs.SysdynModel_tolerance)\r
private Double tolerance;\r
}\r
\r
/**\r
- * Result output interval\r
+ * Simulation output interval\r
* @return\r
*/\r
public Double getOutputInterval() {\r
return outputInterval;\r
}\r
\r
+ /**\r
+ * Simulation step length\r
+ * @return\r
+ */\r
+ public Double getSimulationStepLength() {\r
+ return stepLength;\r
+ }\r
/**\r
* \r
* @return Tolerance for simulation engine\r