]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
432ff044a6bbe529656a7c3eb1bcc5f10b1e5b4a
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.sysdyn.manager;\r
13 \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
21 \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
39 \r
40 /**\r
41  * Sensitivity analysis experiment\r
42  * @author Tuomas Miettinen\r
43  *\r
44  */\r
45 public class SysdynSensitivityAnalysisExperiment extends SysdynExperiment {\r
46 \r
47     \r
48 \r
49     private ArrayList<MemoryResult> results = null;\r
50 \r
51     public SysdynSensitivityAnalysisExperiment(Resource experiment, Resource model) {\r
52         super(experiment, model);\r
53     }\r
54     \r
55     \r
56     private void findValuesAndRun(List<SensitivityExperimentParameter> parameters, HashMap<String, String> values, HashMap<String, String> experimentParameters) {\r
57         findValuesAndRun(parameters, 0, values, experimentParameters);\r
58     }\r
59     \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
62         \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
67             } else {\r
68                 // Run with values\r
69                 runSensitivityRun(values, experimentParameters);\r
70             }\r
71         }\r
72         p.getDistribution().initialize();\r
73     }\r
74     \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
81         }                \r
82         // Simulate the model for one parameter set\r
83         progressMonitor.subTask("Simulation iteration " + (currentRun+1) + "/" + numberOfRuns);\r
84 \r
85         \r
86         try {\r
87             process = ModelicaManager.runModelica(\r
88                     simulationLocation,\r
89                     monitor,\r
90                     experimentParameters, \r
91                     values\r
92                     );\r
93         } catch (IOException e) {\r
94             e.printStackTrace();\r
95         }\r
96 \r
97         ModelicaManager.printProcessOutput(process, monitor);\r
98 \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
102 \r
103         process = null;\r
104         \r
105         progressMonitor.worked(1);\r
106         currentRun++;\r
107 \r
108     }\r
109     \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
118     \r
119     @Override\r
120     protected void runModelica(SimulationLocation simulationLocation, IModelicaMonitor monitor, IProgressMonitor progressMonitor, HashMap<String, String> experimentParameters, HashMap<String, String> changes) throws IOException {\r
121         results = null;\r
122         \r
123         this.simulationLocation = simulationLocation;\r
124         this.monitor = monitor;\r
125         this.progressMonitor = progressMonitor;\r
126         \r
127         if (changes == null) {\r
128             changes = new HashMap<String, String>();\r
129         }\r
130         \r
131         String version = ModelicaManager.getOMCVersion(simulationLocation.omcHome);\r
132         experimentParameters.put(ModelicaManager.OMC_VERSION, version);\r
133         \r
134         \r
135         loadConfiguration();\r
136         \r
137         currentRun = 0;\r
138         \r
139         \r
140         findValuesAndRun(parameters, changes, experimentParameters);\r
141     }\r
142 \r
143     private void loadConfiguration(){\r
144         try {\r
145             session.syncRequest(new ReadRequest() {\r
146                 @Override\r
147                 public void run(ReadGraph graph) throws DatabaseException {\r
148                     \r
149                     SysdynResource SR = SysdynResource.getInstance(graph);\r
150                     \r
151                     Integer rRate = graph.getPossibleRelatedValue(experiment,  SR.SensitivityAnalysisExperiment_resultRefreshRate, Bindings.INTEGER);\r
152                     if(rRate != null)\r
153                         refreshRate = rRate;\r
154                     \r
155                     Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList);\r
156                     List<Resource> parameterResources = ListUtils.toList(graph, parameterListResource);\r
157                     \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
163                         }\r
164                     }\r
165                 }\r
166             });\r
167         } catch (DatabaseException e) {\r
168             e.printStackTrace();\r
169         }\r
170     }\r
171     \r
172     /**\r
173      * Get a thread for reading and saving reuslts from a normal simulation\r
174      * @param simulationLocation\r
175      * @param inits\r
176      * @param monitor\r
177      * @param progressMonitor\r
178      * @return\r
179      */\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
186             @Override\r
187             public void run() {\r
188                 try {\r
189                     process.waitFor();\r
190 \r
191                     if(!canceled) {\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
198                         else\r
199                             result = new MatSimulationResult(); // The latest format\r
200 \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
207                             \r
208                             Double step = Double.parseDouble(stepTime);\r
209                             Double stop = Double.parseDouble(stopTime);\r
210                             Double outInterval = Double.parseDouble(outputInterval);\r
211 \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
217                         }\r
218 \r
219                         result.initRead(resFile);\r
220                         result.readTime(resFile, outIntervalInt);\r
221                         //result.readInits(simulationLocation.initFile); // Parameter values are read from .mat\r
222                         result.filter();\r
223                         \r
224                         MemoryResult currentResult = new MemoryResult(null, null);\r
225                         getCurrentResults().add(currentResult);\r
226                         currentResult.setResult(result);\r
227                         currentResult.setResultFile(resFile);\r
228                         \r
229                         if(updateMonitors)\r
230                             resultsChanged();\r
231 \r
232                         simulate(false);\r
233 \r
234                         String errorString = result.getResultReadErrors();\r
235                         if(errorString != null && !errorString.isEmpty())\r
236                             monitor.message(errorString);\r
237                     }\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
244                 }\r
245             }\r
246         };\r
247     }\r
248     \r
249     public ArrayList<MemoryResult> getCurrentResults() {\r
250         if(this.results == null) {\r
251             this.results = new ArrayList<MemoryResult>();\r
252         }\r
253         return this.results;\r
254     }\r
255     \r
256     @Override\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
261         return result;\r
262     }\r
263     \r
264     @Override\r
265     public MemoryResult getCurrentResult() {\r
266         if (this.results == null || this.results.size() < 1)\r
267             return null;\r
268         /* There should be a better alternative solution for this. Currently\r
269          * the return value is next to nonsense.\r
270          */\r
271         return this.results.get(0);\r
272     }\r
273     \r
274     @Override\r
275     public void resultsChanged() {\r
276         long time = System.nanoTime();\r
277         updateSubscriptions();\r
278         previousVariableUpdateTime = time;\r
279     }\r
280     \r
281     @Override\r
282     public void saveState() {\r
283         if(results == null || !(results instanceof ArrayList<?>)) \r
284             return;\r
285         //SaveResultJob saveResultJob = new SaveResultJob(SysdynSensitivityAnalysisExperiment.this, session, results);\r
286         //saveResultJob.schedule();\r
287     }\r
288     \r
289     @Override\r
290     public int numberOfSimulationRunSteps() {\r
291         try {\r
292             Integer numberOfIterations = session.syncRequest(new Read<Integer>() {\r
293                 @Override\r
294                 public Integer perform(ReadGraph graph) throws DatabaseException {\r
295                     SysdynResource SR = SysdynResource.getInstance(graph);\r
296                     \r
297                     Resource parameterListResource = graph.getPossibleObject(experiment, SR.SensitivityAnalysisExperiment_parameterList);\r
298                     List<Resource> parameterResources = ListUtils.toList(graph, parameterListResource);\r
299                     \r
300                     Integer numberOfIterations = null;\r
301                     \r
302                     for(Resource parameter : parameterResources) {\r
303                         Integer n = graph.getPossibleRelatedValue(parameter, SR.SensitivityAnalysisExperiment_Parameter_numberOfValues, Bindings.INTEGER);\r
304                         if(n != null) {\r
305                             if(numberOfIterations == null)\r
306                                 numberOfIterations = n;\r
307                             else\r
308                                 numberOfIterations = numberOfIterations * n;\r
309                         } \r
310                     }\r
311                     \r
312                     return numberOfIterations;\r
313                 }\r
314             });\r
315             \r
316             if(numberOfIterations == null)\r
317                 numberOfIterations = 0;\r
318             \r
319             // 3 steps before sensitivity iterations\r
320             return 3 + numberOfIterations; \r
321         } catch (DatabaseException e) {\r
322             e.printStackTrace();\r
323         }\r
324         \r
325         return super.numberOfSimulationRunSteps();\r
326 \r
327     }\r
328     \r
329     \r
330     @Override\r
331     public synchronized void simulate(IModelicaMonitor monitor, IProgressMonitor progressMonitor) throws IOException {\r
332         \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
337         }\r
338 \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
342             try {\r
343                 double v = Double.parseDouble(omcVersion.substring(0, 3));\r
344                 if(v < 1.9) {\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
348                     simulate(false);\r
349                     return;\r
350                 }\r
351             } catch (NumberFormatException e) {}\r
352         }\r
353         \r
354         super.simulate(monitor, progressMonitor);\r
355     }\r
356 }\r