1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2012 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.manager;
\r
14 import java.io.File;
\r
15 import java.io.FileNotFoundException;
\r
16 import java.io.IOException;
\r
17 import java.util.ArrayList;
\r
18 import java.util.Collection;
\r
19 import java.util.HashMap;
\r
20 import java.util.List;
\r
22 import org.eclipse.core.runtime.IProgressMonitor;
\r
23 import org.simantics.databoard.Bindings;
\r
24 import org.simantics.db.ReadGraph;
\r
25 import org.simantics.db.Resource;
\r
26 import org.simantics.db.common.request.ReadRequest;
\r
27 import org.simantics.db.common.utils.ListUtils;
\r
28 import org.simantics.db.exception.DatabaseException;
\r
29 import org.simantics.db.request.Read;
\r
30 import org.simantics.modelica.IModelicaMonitor;
\r
31 import org.simantics.modelica.ModelicaKeys;
\r
32 import org.simantics.modelica.ModelicaManager;
\r
33 import org.simantics.modelica.SimulationLocation;
\r
34 import org.simantics.modelica.data.CSVSimulationResult;
\r
35 import org.simantics.modelica.data.MatSimulationResult;
\r
36 import org.simantics.modelica.data.SimulationResult;
\r
37 import org.simantics.sysdyn.SysdynResource;
\r
38 import org.simantics.sysdyn.adapter.SensitivityExperimentParameter;
\r
41 * Sensitivity analysis experiment
\r
42 * @author Tuomas Miettinen
\r
45 public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment {
\r
49 private ArrayList<MemoryResult> results = null;
\r
51 public SysdynSensitivityAnalysisExperiment(Resource experiment, Resource model) {
\r
52 super(experiment, model);
\r
56 private void findValuesAndRun(List<SensitivityExperimentParameter> parameters, HashMap<String, String> values, HashMap<String, String> experimentParameters) {
\r
57 findValuesAndRun(parameters, 0, values, experimentParameters);
\r
60 private void findValuesAndRun(List<SensitivityExperimentParameter> parameters, int index, HashMap<String, String> values, HashMap<String, String> experimentParameters) {
\r
61 SensitivityExperimentParameter p = parameters.get(index);
\r
63 while(p.getDistribution().hasNext()) {
\r
64 values.put(p.getFullName(), Double.toString(p.getDistribution().next()));
\r
65 if((index + 1) < parameters.size()) {
\r
66 findValuesAndRun(parameters, index + 1, values, experimentParameters);
\r
69 runSensitivityRun(values, experimentParameters);
\r
72 p.getDistribution().initialize();
\r
75 private void runSensitivityRun(HashMap<String, String> values, HashMap<String, String> experimentParameters) {
\r
76 int indexOfDot = simulationLocation.resFile.toString().lastIndexOf('.');
\r
77 if (indexOfDot > 1) {
\r
78 String resFile = simulationLocation.resFile.toString();
\r
79 String newResFile = resFile.substring(0, indexOfDot) + currentRun + resFile.substring(indexOfDot);
\r
80 experimentParameters.put(ModelicaManager.RESULT_FILE_NAME, newResFile);
\r
82 // Simulate the model for one parameter set
\r
83 progressMonitor.subTask("Simulation iteration " + (currentRun+1) + "/" + numberOfRuns);
\r
87 process = ModelicaManager.runModelica(
\r
90 experimentParameters,
\r
93 } catch (IOException e) {
\r
94 e.printStackTrace();
\r
97 ModelicaManager.printProcessOutput(process, monitor);
\r
99 File resFile = new File(experimentParameters.get(ModelicaManager.RESULT_FILE_NAME));
\r
100 Thread resultThread = getResultThread(resFile, experimentParameters, monitor, progressMonitor, currentRun % refreshRate == 0);
\r
101 resultThread.run();
\r
105 progressMonitor.worked(1);
\r
110 private SimulationLocation simulationLocation;
\r
111 private IModelicaMonitor monitor;
\r
112 private IProgressMonitor progressMonitor;
\r
113 // private HashMap<String, String> experimentParameters;
\r
114 private int numberOfRuns = 0;
\r
115 private int currentRun = 0;
\r
116 private int refreshRate = 1;
\r
117 private List<SensitivityExperimentParameter> parameters = new ArrayList<SensitivityExperimentParameter>();
\r
120 protected void runModelica(SimulationLocation simulationLocation, IModelicaMonitor monitor, IProgressMonitor progressMonitor, HashMap<String, String> experimentParameters, HashMap<String, String> changes) throws IOException {
\r
123 this.simulationLocation = simulationLocation;
\r
124 this.monitor = monitor;
\r
125 this.progressMonitor = progressMonitor;
\r
127 if (changes == null) {
\r
128 changes = new HashMap<String, String>();
\r
131 String version = ModelicaManager.getOMCVersion(simulationLocation.omcHome);
\r
132 experimentParameters.put(ModelicaManager.OMC_VERSION, version);
\r
135 loadConfiguration();
\r
140 findValuesAndRun(parameters, changes, experimentParameters);
\r
143 private void loadConfiguration(){
\r
145 session.syncRequest(new ReadRequest() {
\r
147 public void run(ReadGraph graph) throws DatabaseException {
\r
149 SysdynResource SR = SysdynResource.getInstance(graph);
\r
151 Integer rRate = graph.getPossibleRelatedValue(experiment, SR.SensitivityAnalysisExperiment_resultRefreshRate, Bindings.INTEGER);
\r
153 refreshRate = rRate;
\r
155 Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList);
\r
156 List<Resource> parameterResources = ListUtils.toList(graph, parameterListResource);
\r
158 if(parameters != null) {
\r
159 parameters.clear();
\r
160 for(Resource p : parameterResources) {
\r
161 SensitivityExperimentParameter parameter = graph.adapt(p, SensitivityExperimentParameter.class);
\r
162 parameters.add(parameter);
\r
167 } catch (DatabaseException e) {
\r
168 e.printStackTrace();
\r
173 * Get a thread for reading and saving reuslts from a normal simulation
\r
174 * @param simulationLocation
\r
177 * @param progressMonitor
\r
180 protected Thread getResultThread(final File resFile,
\r
181 final HashMap<String, String> experimentParameters,
\r
182 final IModelicaMonitor monitor,
\r
183 final IProgressMonitor progressMonitor,
\r
184 final boolean updateMonitors) {
\r
185 return new Thread() {
\r
187 public void run() {
\r
192 // Get and store results
\r
193 SimulationResult result;
\r
194 if(resFile.getName().endsWith(".csv"))
\r
195 result = new CSVSimulationResult();
\r
196 else if(resFile.getName().endsWith(".plt"))
\r
197 result = new SimulationResult();
\r
199 result = new MatSimulationResult(); // The latest format
\r
201 // The interval of results saved. Every result? Every other result? etc...
\r
202 int outIntervalInt = 1;
\r
203 String outputInterval = experimentParameters.get(ModelicaKeys.OUTPUT_INTERVAL);
\r
204 if(outputInterval != null) {
\r
205 String stepTime = experimentParameters.get(ModelicaKeys.STEP_VALUE);
\r
206 String stopTime = experimentParameters.get(ModelicaKeys.STOP_VALUE);
\r
208 Double step = Double.parseDouble(stepTime);
\r
209 Double stop = Double.parseDouble(stopTime);
\r
210 Double outInterval = Double.parseDouble(outputInterval);
\r
212 outIntervalInt = (int)getInterval(outInterval, step);
\r
213 // Actually you might be able to use an outInterval one or two longer.
\r
214 int maxIntervalInt = (int)Math.round(stop / step);
\r
215 if (outIntervalInt > maxIntervalInt)
\r
216 outIntervalInt = maxIntervalInt;
\r
219 result.initRead(resFile);
\r
220 result.readTime(resFile, outIntervalInt);
\r
221 //result.readInits(simulationLocation.initFile); // Parameter values are read from .mat
\r
224 MemoryResult currentResult = new MemoryResult(null, null);
\r
225 getCurrentResults().add(currentResult);
\r
226 currentResult.setResult(result);
\r
227 currentResult.setResultFile(resFile);
\r
234 String errorString = result.getResultReadErrors();
\r
235 if(errorString != null && !errorString.isEmpty())
\r
236 monitor.message(errorString);
\r
238 } catch (FileNotFoundException e) {
\r
239 e.printStackTrace();
\r
240 } catch (IOException e) {
\r
241 e.printStackTrace();
\r
242 } catch (InterruptedException e) {
\r
243 e.printStackTrace();
\r
249 public ArrayList<MemoryResult> getCurrentResults() {
\r
250 if(this.results == null) {
\r
251 this.results = new ArrayList<MemoryResult>();
\r
253 return this.results;
\r
257 public Collection<SysdynResult> getActiveResults() {
\r
258 ArrayList<SysdynResult> result = new ArrayList<SysdynResult>();
\r
259 result.addAll(getCurrentResults());
\r
260 result.addAll(sysdynModel.getDisplayedResults());
\r
265 public MemoryResult getCurrentResult() {
\r
266 if (this.results == null || this.results.size() < 1)
\r
268 /* There should be a better alternative solution for this. Currently
\r
269 * the return value is next to nonsense.
\r
271 return this.results.get(0);
\r
275 public void resultsChanged() {
\r
276 long time = System.nanoTime();
\r
277 updateSubscriptions();
\r
278 previousVariableUpdateTime = time;
\r
282 public void saveState() {
\r
283 if(results == null || !(results instanceof ArrayList<?>))
\r
285 //SaveResultJob saveResultJob = new SaveResultJob(SysdynSensitivityAnalysisExperiment.this, session, results);
\r
286 //saveResultJob.schedule();
\r
290 public int numberOfSimulationRunSteps() {
\r
292 Integer numberOfIterations = session.syncRequest(new Read<Integer>() {
\r
294 public Integer perform(ReadGraph graph) throws DatabaseException {
\r
295 SysdynResource SR = SysdynResource.getInstance(graph);
\r
297 Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList);
\r
298 List<Resource> parameterResources = ListUtils.toList(graph, parameterListResource);
\r
300 Integer numberOfIterations = null;
\r
302 for(Resource parameter : parameterResources) {
\r
303 Integer n = graph.getPossibleRelatedValue(parameter, SR.SensitivityAnalysisExperiment_Parameter_numberOfValues, Bindings.INTEGER);
\r
305 if(numberOfIterations == null)
\r
306 numberOfIterations = n;
\r
308 numberOfIterations = numberOfIterations * n;
\r
312 return numberOfIterations;
\r
316 if(numberOfIterations == null)
\r
317 numberOfIterations = 0;
\r
319 // 3 steps before sensitivity iterations
\r
320 return 3 + numberOfIterations;
\r
321 } catch (DatabaseException e) {
\r
322 e.printStackTrace();
\r
325 return super.numberOfSimulationRunSteps();
\r
331 public synchronized void simulate(IModelicaMonitor monitor, IProgressMonitor progressMonitor) throws IOException {
\r
333 File home = ModelicaManager.getModelicaHome();
\r
334 if (omcHome == null || !home.getAbsolutePath().equals(omcHome)) {
\r
335 omcVersion = ModelicaManager.getOMCVersion(home);
\r
336 omcHome = home.getAbsolutePath();
\r
339 // Make sure that omc version is 1.9 or higher.
\r
340 // Builtin version during this change is 1.9 beta 4
\r
341 if(omcVersion != null) {
\r
343 double v = Double.parseDouble(omcVersion.substring(0, 3));
\r
345 monitor.message("Error: Sensitivity analysis requires OMC version >= 1.9 \n" +
\r
346 "Current version is " + omcVersion +"\n" +
\r
347 "Change version from Window->Preferences->Modelica");
\r
351 } catch (NumberFormatException e) {}
\r
354 super.simulate(monitor, progressMonitor);
\r