import org.simantics.db.ReadGraph;\r
import org.simantics.db.Resource;\r
import org.simantics.db.Session;\r
-import org.simantics.db.common.request.ReadRequest;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.request.Read;\r
import org.simantics.layer0.Layer0;\r
import org.simantics.modelica.IModelicaMonitor;\r
import org.simantics.modelica.ModelicaException;\r
import org.simantics.modelica.ModelicaManager;\r
import org.simantics.modelica.SimulationLocation;\r
import org.simantics.modelica.data.CSVSimulationResult;\r
+import org.simantics.modelica.data.MatSimulationResult;\r
import org.simantics.modelica.data.SimulationResult;\r
import org.simantics.objmap.IMapping;\r
import org.simantics.objmap.IMappingListener;\r
\r
/**\r
* Maintains a Java representation of system dynamic model.\r
- * @author Hannu Niemistö\r
+ * @author Hannu Niemistö\r
*/\r
public class SysdynModel implements IMappingListener, IModel {\r
\r
- private Session session;\r
+ private Session session;\r
\r
- private IMapping mapping;\r
+ private IMapping mapping;\r
\r
- private Resource configurationResource;\r
- private Resource modelResource;\r
- \r
- private Configuration configuration;\r
+ private Resource configurationResource;\r
+ private Resource modelResource;\r
\r
- private Set<Configuration> modules = new HashSet<Configuration>();\r
+ private Configuration configuration;\r
\r
- private Process process;\r
- private boolean canceled;\r
- private SimulationResult result;\r
- private SysdynResult sysdynResult;\r
+ private Set<Configuration> modules = new HashSet<Configuration>();\r
+\r
+ private Process process;\r
+ private boolean canceled;\r
+ private SimulationResult result;\r
+ private SysdynResult sysdynResult;\r
+\r
+ private CopyOnWriteArrayList<Runnable> modificationListeners =\r
+ new CopyOnWriteArrayList<Runnable>();\r
+ private CopyOnWriteArrayList<Runnable> resultListeners =\r
+ new CopyOnWriteArrayList<Runnable>();\r
\r
- private CopyOnWriteArrayList<Runnable> modificationListeners =\r
- new CopyOnWriteArrayList<Runnable>();\r
- private CopyOnWriteArrayList<Runnable> resultListeners =\r
- new CopyOnWriteArrayList<Runnable>();\r
- \r
protected THashSet<VariableValueSubscription> variableValueSubscriptions = new THashSet<VariableValueSubscription>();\r
protected volatile VariableValueSubscription[] variableValueSubscriptionsSnapshot = null;\r
\r
- @SuppressWarnings("rawtypes")\r
- private Map<Class, Object> services = new HashMap<Class, Object>();\r
-\r
- private String previousModelStructure;\r
- private HashMap<String, String> previousImportantInits = new HashMap<String, String>();\r
-\r
- private File simulationDir;\r
-\r
- void readModules(ReadGraph graph, Resource configResource, Set<Resource> result) throws DatabaseException {\r
-\r
- if(!result.add(configResource)) return;\r
-\r
- Layer0 l0 = Layer0.getInstance(graph);\r
- SysdynResource sr = SysdynResource.getInstance(graph);\r
- StructuralResource2 str = StructuralResource2.getInstance(graph);\r
-\r
- for(Resource part : graph.getObjects(configResource, l0.ConsistsOf)) {\r
- if(graph.isInstanceOf(part, sr.Module)) {\r
- Resource type = graph.getPossibleType(part, sr.Module);\r
- Resource config = graph.getPossibleObject(type, str.IsDefinedBy);\r
- readModules(graph, config, result);\r
- }\r
- }\r
-\r
- }\r
-\r
- Set<Resource> readModules(ReadGraph graph, Resource configResource) throws DatabaseException {\r
- HashSet<Resource> result = new HashSet<Resource>();\r
- readModules(graph, configResource, result);\r
- return result;\r
- }\r
-\r
- private void createMapping(ReadGraph g) throws DatabaseException {\r
- SysdynSchema schema = new SysdynSchema(g);\r
- mapping = Mappings.createWithListening(schema);\r
- mapping.addMappingListener(SysdynModel.this);\r
- configuration = (Configuration)mapping.map(g, configurationResource);\r
- for(Resource config : readModules(g, configurationResource)) {\r
- modules.add((Configuration)mapping.map(g, config));\r
- }\r
-// System.out.println("Loaded model with " + modules.size() + " modules.");\r
- }\r
-\r
- public SysdynModel(ReadGraph g, Resource configurationResource) {\r
- this.session = g.getSession();\r
- this.configurationResource = configurationResource;\r
-\r
- try {\r
- createMapping(g);\r
- } catch(DatabaseException e) {\r
- e.printStackTrace();\r
- }\r
- sysdynResult = new SysdynResult();\r
- sysdynResult.setResult(new SimulationResult());\r
-\r
- previousModelStructure = "";\r
- }\r
-\r
-\r
- /*\r
- * some dummy(?) stuff for experiments\r
- */\r
- public SysdynModel(Resource modelResource) {\r
- this.modelResource = modelResource;\r
- }\r
-\r
- public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor, final Experiment experiment) throws IOException {\r
- canceled = false;\r
- progressMonitor.subTask("Write modelica classes");\r
- \r
- // Write Modelica files\r
- ModelicaWriter writer = new ModelicaWriter();\r
- try {\r
- for(Configuration c : modules) {\r
- writer.write(c);\r
- }\r
- } catch (Exception e) {\r
- setExperimentStopped(experiment);\r
- \r
- \r
- monitor.showConsole();\r
- \r
- monitor.message("Error when writing Modelica code.");\r
- return;\r
- }\r
- \r
- progressMonitor.worked(1);\r
-\r
- progressMonitor.subTask("Write initial files");\r
- String modelText = writer.toString();\r
- HashMap<String, String> inits = getInits(configuration, "");\r
- Model model = configuration.getModel();\r
- Double startTime = model.getStartTime();\r
- Double stopTime = model.getStopTime();\r
- Double numberOfIntervals = model.getOutputInterval();\r
- inits.put("start value", startTime.toString());\r
- inits.put("stop value", stopTime.toString());\r
- String outputFormat = "\"csv\"";\r
- inits.put("outputFormat", outputFormat);\r
- if(numberOfIntervals != null) {\r
- inits.put("step value", numberOfIntervals.toString());\r
- } else {\r
- inits.put("step value", "" + (stopTime - startTime) / 500);\r
- }\r
- String method = "\"" + model.getSolver() + "\"";\r
- inits.put("method", method);\r
- if(model.getTolerance() != null)\r
- inits.put("tolerance", model.getTolerance().toString());\r
-\r
- StringBuilder functionscript = new StringBuilder();\r
- for(String path : FunctionUtils.getLibraryPathsForModelica(this)) {\r
- System.out.println("loadFile(\"" + path + "\");\n");\r
- functionscript.append("loadFile(\"" + path + "\");\n"); \r
- }\r
- \r
- final SimulationLocation simulationLocation = ModelicaManager.createInputFiles(\r
- getSimulationDir(),\r
- configuration.getName(),\r
- modelText,\r
- inits,\r
- functionscript.toString());\r
- \r
-\r
- progressMonitor.worked(1);\r
-\r
-\r
- if (!simulationLocation.exeFile.isFile() || hasStructureChanged(modelText, inits)) {\r
- progressMonitor.subTask("Build model");\r
- previousModelStructure = modelText;\r
- System.out.println("== Modelica == ");\r
+ @SuppressWarnings("rawtypes")\r
+ private Map<Class, Object> services = new HashMap<Class, Object>();\r
+\r
+ private String previousModelStructure;\r
+ private HashMap<String, String> previousImportantInits = new HashMap<String, String>();\r
+\r
+ private File simulationDir;\r
+\r
+ /**\r
+ * Recursively read all module configurations that are used in \r
+ * configResource and its components children\r
+ * \r
+ * @param graph ReadGraph\r
+ * @param configResource Configuration\r
+ * @param result set containing all encountered configurations\r
+ * @throws DatabaseException\r
+ */\r
+ void readModules(ReadGraph graph, Resource configResource, Set<Resource> result) throws DatabaseException {\r
+\r
+ // if result does not contain this resource, add it to the result\r
+ if(!result.add(configResource)) return;\r
+\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ StructuralResource2 str = StructuralResource2.getInstance(graph);\r
+\r
+ for(Resource part : graph.getObjects(configResource, l0.ConsistsOf)) {\r
+ if(graph.isInstanceOf(part, sr.Module)) {\r
+ Resource type = graph.getPossibleType(part, sr.Module);\r
+ Resource config = graph.getPossibleObject(type, str.IsDefinedBy);\r
+ // Recursively readModules\r
+ readModules(graph, config, result);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Get all modules that have been used in configResource and its children\r
+ * @param graph ReadGraph\r
+ * @param configResource Configuration\r
+ * @return All modules (configuration resources) that have been used in configResource \r
+ * @throws DatabaseException\r
+ */\r
+ Set<Resource> readModules(ReadGraph graph, Resource configResource) throws DatabaseException {\r
+ HashSet<Resource> result = new HashSet<Resource>();\r
+ readModules(graph, configResource, result);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Create an ObjMapping\r
+ * @param g ReadGraph\r
+ * @throws DatabaseException\r
+ */\r
+ private void createMapping(ReadGraph g) throws DatabaseException {\r
+ SysdynSchema schema = new SysdynSchema(g);\r
+ mapping = Mappings.createWithListening(schema);\r
+ mapping.addMappingListener(SysdynModel.this);\r
+ configuration = (Configuration)mapping.map(g, configurationResource);\r
+ for(Resource config : readModules(g, configurationResource)) {\r
+ modules.add((Configuration)mapping.map(g, config));\r
+ }\r
+ }\r
+\r
+ /**\r
+ * New Sysdyn model\r
+ * @param g ReadGraph\r
+ * @param configurationResource Configration resource of the model\r
+ */\r
+ public SysdynModel(ReadGraph g, Resource configurationResource) {\r
+ this.session = g.getSession();\r
+ this.configurationResource = configurationResource;\r
+\r
+ try {\r
+ createMapping(g);\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ // initialize results\r
+ sysdynResult = new SysdynResult();\r
+ sysdynResult.setResult(new SimulationResult());\r
+\r
+ previousModelStructure = "";\r
+ }\r
+\r
+\r
+ /*\r
+ * a dummy(?) call for experiments\r
+ */\r
+ public SysdynModel(Resource modelResource) {\r
+ this.modelResource = modelResource;\r
+ }\r
+\r
+ /**\r
+ * Simulate this model\r
+ * @param monitor IModelicaMonitor\r
+ * @param progressMonitor IProgressMonitor\r
+ * @param experiment SysdynExperiment\r
+ * @throws IOException\r
+ */\r
+ public synchronized void simulate(final IModelicaMonitor monitor, final IProgressMonitor progressMonitor, final Experiment experiment) throws IOException {\r
+ canceled = false;\r
+ progressMonitor.subTask("Write modelica classes");\r
+\r
+ // Write Modelica files\r
+ ModelicaWriter writer = new ModelicaWriter();\r
+ try {\r
+ // Write all configurations once\r
+ for(Configuration c : modules) {\r
+ writer.write(c);\r
+ }\r
+ } catch (Exception e) {\r
+ // Stop experiment and show console\r
+ setExperimentStopped(experiment);\r
+ monitor.showConsole();\r
+ monitor.message("Error when writing Modelica code.");\r
+ return;\r
+ }\r
+ String modelText = writer.toString();\r
+ progressMonitor.worked(1);\r
+\r
+ // Write initial files and add init-parameters\r
+ progressMonitor.subTask("Write initial files");\r
+ HashMap<String, String> inits = getInits(configuration, "");\r
+ Model model = configuration.getModel();\r
+ Double startTime = model.getStartTime();\r
+ Double stopTime = model.getStopTime();\r
+ Double numberOfIntervals = model.getOutputInterval();\r
+ inits.put("start value", startTime.toString());\r
+ inits.put("stop value", stopTime.toString());\r
+ String outputFormat = "\"mat\"";\r
+ inits.put("outputFormat", outputFormat);\r
+ if(numberOfIntervals != null) {\r
+ inits.put("step value", numberOfIntervals.toString());\r
+ } else {\r
+ inits.put("step value", "" + (stopTime - startTime) / 500);\r
+ }\r
+ String method = "\"" + model.getSolver() + "\"";\r
+ inits.put("method", method);\r
+ if(model.getTolerance() != null)\r
+ inits.put("tolerance", model.getTolerance().toString());\r
+\r
+ // add loadFile script to load all related functions and function libraries \r
+ StringBuilder functionscript = new StringBuilder();\r
+ for(String path : FunctionUtils.getLibraryPathsForModelica(this)) {\r
+ functionscript.append("loadFile(\"" + path + "\");\n"); \r
+ }\r
+\r
+ // Create simulation files\r
+ final SimulationLocation simulationLocation = ModelicaManager.createInputFiles(\r
+ getSimulationDir(),\r
+ configuration.getName(),\r
+ modelText,\r
+ inits,\r
+ functionscript.toString());\r
+\r
+\r
+ progressMonitor.worked(1);\r
+\r
+ // Build the model and store previous model structure and inits that affect the building\r
+ // If there is no exe file OR the model structure has not changed, no need to build\r
+ if (!simulationLocation.exeFile.isFile() || hasStructureChanged(modelText, inits)) {\r
+ progressMonitor.subTask("Build model");\r
+ previousModelStructure = modelText;\r
+// System.out.println("== Modelica == ");\r
// System.out.println(writer.toString());\r
- System.out.println("== Modelica ends == ");\r
-\r
- try {\r
- simulationLocation.exeFile.delete();\r
- ModelicaManager.buildModel(simulationLocation, monitor);\r
- previousImportantInits.clear();\r
- previousImportantInits.put("start value", startTime.toString());\r
- previousImportantInits.put("stop value", stopTime.toString());\r
- previousImportantInits.put("method", method);\r
- previousImportantInits.put("outputFormat", outputFormat);\r
- } catch (ModelicaException e) {\r
- if(e.getMessage() != null)\r
- monitor.message(e.getMessage());\r
- monitor.showConsole();\r
- canceled = true;\r
- previousModelStructure = "";\r
- }\r
- }\r
-\r
- progressMonitor.worked(1);\r
-\r
- if(simulationLocation != null && !canceled) {\r
- progressMonitor.subTask("Simulate model");\r
- process = ModelicaManager.runModelica(\r
- simulationLocation,\r
- monitor,\r
- inits\r
- );\r
- ModelicaManager.printProcessOutput(process, monitor);\r
-\r
- Thread resultThread = new Thread() {\r
- @Override\r
- public void run() {\r
- try {\r
- process.waitFor();\r
-\r
- if(!canceled) {\r
- progressMonitor.worked(1);\r
- progressMonitor.subTask("Read results");\r
- result = new CSVSimulationResult();\r
- result.read(simulationLocation.outputFile);\r
- result.readInits(simulationLocation.initFile);\r
- result.filter();\r
- sysdynResult.setResult(result);\r
- progressMonitor.worked(1);\r
- resultChanged();\r
- \r
- setExperimentStopped(experiment);\r
- \r
- String errorString = result.getResultReadErrors();\r
- if(errorString != null && !errorString.isEmpty()) \r
- monitor.message(errorString);\r
- }\r
- } catch (FileNotFoundException e) {\r
- e.printStackTrace();\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- };\r
- resultThread.run();\r
- }\r
- if(canceled)\r
- setExperimentStopped(experiment);\r
- process = null;\r
- }\r
-\r
- private void setExperimentStopped(Experiment experiment) {\r
- if(experiment instanceof SysdynExperiment) {\r
- SysdynExperiment e = (SysdynExperiment)experiment;\r
- if(e.getState() != ExperimentState.DISPOSED)\r
- e.simulate(false);\r
- }\r
- }\r
-\r
- private boolean hasStructureChanged(String modelText, Map<String, String> inits) {\r
- \r
- \r
- BufferedReader current = new BufferedReader(\r
- new StringReader(modelText));\r
- BufferedReader previous = new BufferedReader(\r
- new StringReader(previousModelStructure));\r
-\r
- String c, p;\r
- try {\r
- c = current.readLine();\r
- p = previous.readLine();\r
- \r
- while (c != null && p != null) {\r
- if(!c.equals(p)) {\r
- if(c.contains("parameter") && p.contains("parameter")) {\r
- int i = c.indexOf("=");\r
- if(!c.substring(0, i).equals(p.substring(0, i))) {\r
- // different parameter definition\r
- return true;\r
- }\r
- } else {\r
- // other than a line containing parameters differs\r
- return true;\r
- }\r
- }\r
- c = current.readLine();\r
- p = previous.readLine();\r
- }\r
- \r
- if((c == null && p != null) || (c != null && p == null)) {\r
- // different lengths\r
- return true;\r
- }\r
-\r
- } catch(IOException e) {\r
- //e.printStackTrace();\r
- return true;\r
- }\r
-\r
- for(String key : previousImportantInits.keySet()) {\r
- if(!inits.containsKey(key) || !previousImportantInits.get(key).equals(inits.get(key)))\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- public void cancelSimulation() {\r
- canceled = true;\r
- if(process != null) {\r
- process.destroy();\r
- }\r
- }\r
-\r
- public synchronized boolean update(ReadGraph graph) throws DatabaseException {\r
- if(mapping.isDomainModified()) {\r
- mapping.updateRange(graph);\r
- Set<Resource> configs = readModules(graph, configurationResource); \r
- for(Resource config : configs) {\r
- if(!modules.contains(config))\r
- modules.add((Configuration)mapping.map(graph, config));\r
- }\r
- \r
- HashSet<Configuration> toBeRemoved = null;\r
- for(Configuration module : modules) {\r
- if(!configs.contains(mapping.inverseGet(module))) {\r
- if(toBeRemoved == null)\r
- toBeRemoved = new HashSet<Configuration>();\r
- toBeRemoved.add(module);\r
- }\r
- }\r
- if(toBeRemoved != null)\r
- modules.removeAll(toBeRemoved);\r
- return true;\r
- }\r
- else\r
- return false;\r
- }\r
- \r
- public synchronized boolean update() throws DatabaseException {\r
- if(mapping.isDomainModified()) {\r
- session.syncRequest(new ReadRequest() {\r
- @Override\r
- public void run(ReadGraph graph) throws DatabaseException {\r
- mapping.updateRange(graph);\r
- Set<Resource> configs = readModules(graph, configurationResource); \r
- for(Resource config : configs) {\r
- if(!modules.contains(config))\r
- modules.add((Configuration)mapping.map(graph, config));\r
- }\r
- \r
- HashSet<Configuration> toBeRemoved = null;\r
- for(Configuration module : modules) {\r
- if(!configs.contains(mapping.inverseGet(module))) {\r
- if(toBeRemoved == null)\r
- toBeRemoved = new HashSet<Configuration>();\r
- toBeRemoved.add(module);\r
- }\r
- }\r
- if(toBeRemoved != null)\r
- modules.removeAll(toBeRemoved);\r
- }\r
- });\r
- return true;\r
- }\r
- else\r
- return false;\r
- }\r
-\r
- public SimulationResult getSimulationResult() {\r
- return result;\r
- }\r
-\r
- public SysdynResult getSysdynResult() {\r
- return sysdynResult;\r
- }\r
-\r
- public void addResultListener(Runnable listener) {\r
- synchronized(resultListeners) {\r
- resultListeners.add(listener);\r
- }\r
- }\r
-\r
- public void removeResultListener(Runnable listener) {\r
- synchronized(resultListeners) {\r
- resultListeners.remove(listener);\r
- }\r
- }\r
- \r
- public void resultChanged() {\r
- synchronized(resultListeners) {\r
- for(Runnable listener : resultListeners) {\r
- listener.run();\r
- }\r
- }\r
- \r
- updateSubscriptions();\r
- }\r
-\r
- public void addModificationListener(Runnable listener) {\r
- synchronized(modificationListeners) {\r
- modificationListeners.add(listener);\r
- }\r
- }\r
-\r
- public void removeModificationListener(Runnable listener) {\r
- synchronized(modificationListeners) {\r
- modificationListeners.remove(listener);\r
- }\r
- }\r
-\r
- @Override\r
- public void domainModified() {\r
- synchronized(modificationListeners) {\r
- for(Runnable listener : modificationListeners)\r
- listener.run();\r
- }\r
- }\r
-\r
- @Override\r
- public void rangeModified() {\r
- }\r
-\r
- public Configuration getConfiguration() {\r
- return configuration;\r
- }\r
- \r
- public Resource getConfigurationResource() {\r
- return configurationResource;\r
- }\r
-\r
- public IMapping getMapping() {\r
- return mapping;\r
- }\r
-\r
- public synchronized IElement getElement(Resource resource) {\r
- return (IElement)mapping.get(resource);\r
- }\r
-\r
- public <T> T getService(Class<T> clazz) {\r
- synchronized(services) {\r
- return clazz.cast(services.get(clazz));\r
- }\r
- }\r
-\r
- public <T> void addService(Class<T> clazz, T service) {\r
- synchronized(services) {\r
- services.put(clazz, service);\r
- }\r
- }\r
-\r
- @Override\r
- public IExperiment loadExperiment(ReadGraph g, Resource experiment, IExperimentActivationListener listener) {\r
- \r
- // Not good. IModel pushes only modelResource and it is assumed that\r
- // SysdynModel is based on configuration\r
- if(configurationResource == null && modelResource != null) {\r
- SimulationResource simu = SimulationResource.getInstance(g);\r
- try {\r
- configurationResource = g.getPossibleObject(modelResource, simu.HasConfiguration);\r
- } catch (ManyObjectsForFunctionalRelationException e) {\r
- e.printStackTrace();\r
- } catch (ServiceException e) {\r
- e.printStackTrace();\r
- } \r
- }\r
- \r
-\r
- try {\r
- \r
- SysdynResource sr = SysdynResource.getInstance(g);\r
- IDynamicExperiment exp;\r
- if(g.isInstanceOf(experiment, sr.PlaybackExperiment)) {\r
- exp = new SysdynPlaybackExperiment(experiment, modelResource);\r
- ((SysdynPlaybackExperiment)exp).init(g);\r
- } else if(g.isInstanceOf(experiment, sr.BasicExperiment)) {\r
- exp = new SysdynExperiment(experiment, modelResource);\r
- ((SysdynExperiment)exp).init(g);\r
- } else {\r
- return null;\r
- }\r
- \r
- ExperimentRuns.createRun(g.getSession(), experiment, exp, listener, null);\r
- if(listener != null)\r
- listener.onExperimentActivated(exp);\r
- return exp;\r
- } catch(Exception e) {\r
- if(listener != null)\r
- listener.onFailure(e);\r
- return null;\r
- }\r
- }\r
-\r
- public Collection<SysdynResult> getActiveResults(ReadGraph graph) {\r
- ArrayList<SysdynResult> results = new ArrayList<SysdynResult>();\r
-\r
- try {\r
- Layer0 l0 = Layer0.getInstance(graph);\r
- SysdynResource sr = SysdynResource.getInstance(graph);\r
- SimulationResource SIMU = SimulationResource.getInstance(graph);\r
- Resource model = graph.getSingleObject(configurationResource, SIMU.IsConfigurationOf);\r
- Collection<Resource> experiments = graph.getObjects(model, l0.ConsistsOf);\r
- for(Resource experiment : experiments) {\r
- Collection<Resource> experimentResults = graph.getObjects(experiment, sr.HasResult);\r
- for(Resource result : experimentResults) {\r
- if(graph.hasStatement(result, SIMU.IsActive)) {\r
- SysdynResult sysdynResult = new SysdynResult(\r
- (String) graph.getPossibleRelatedValue(result, l0.HasLabel),\r
- (String) graph.getPossibleRelatedValue(result, sr.HasResultFile));\r
- results.add(sysdynResult);\r
- }\r
- }\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
-\r
- if(getSysdynResult() != null)\r
- results.add(0, getSysdynResult() );\r
-\r
-\r
-\r
- return results;\r
- }\r
-\r
- private HashMap<String, String> getInits(Configuration configuration, String prefix) {\r
- HashMap<String, String> inits = new HashMap<String, String>();\r
- for (IElement element : configuration.getElements()) {\r
- if (element instanceof Module) {\r
- Module module = (Module) element;\r
- Configuration conf = module.getType().getConfiguration();\r
- inits.putAll(getInits(conf, prefix + module.getName() + "."));\r
- } else if (element instanceof IndependentVariable) {\r
- IndependentVariable variable = (IndependentVariable) element;\r
- //FIXME: more general solution?\r
- IExpression expression = variable.getExpressions().getExpressions().get(0);\r
- if (expression instanceof ParameterExpression) {\r
- Double value = ((ParameterExpression)expression).getValue();\r
- if(value != null)\r
- inits.put(prefix + variable.getName(), "" + value);\r
- }\r
- }\r
- }\r
- return inits;\r
- }\r
- \r
- public File getSimulationDir() {\r
- if(simulationDir == null) {\r
- File modelsDir = Activator.getBundleContext().getDataFile("models");\r
- String configName = configuration.getName();\r
- List<String> files = Arrays.asList(modelsDir.list());\r
- if (files.contains(configName)) {\r
- int i = 2;\r
- while (files.contains(configName + "_" + i)){\r
- i++;\r
- }\r
- configName += "_" + i;\r
- }\r
-\r
- simulationDir = Activator.getBundleContext().getDataFile("models/" + configName);\r
- if (!simulationDir.exists()) {\r
- simulationDir.mkdir();\r
- }\r
- }\r
- return simulationDir;\r
- }\r
- \r
- \r
- \r
- \r
- \r
+// System.out.println("== Modelica ends == ");\r
+\r
+ try {\r
+ simulationLocation.exeFile.delete();\r
+ ModelicaManager.buildModel(simulationLocation, monitor);\r
+ previousImportantInits.clear();\r
+ previousImportantInits.put("start value", startTime.toString());\r
+ previousImportantInits.put("stop value", stopTime.toString());\r
+ previousImportantInits.put("method", method);\r
+ previousImportantInits.put("outputFormat", outputFormat);\r
+ } catch (ModelicaException e) {\r
+ if(e.getMessage() != null)\r
+ monitor.message(e.getMessage());\r
+ monitor.showConsole();\r
+ canceled = true;\r
+ previousModelStructure = "";\r
+ }\r
+ }\r
+\r
+ progressMonitor.worked(1);\r
+\r
+ if(simulationLocation != null && !canceled) {\r
+ // Simulate the model\r
+ progressMonitor.subTask("Simulate model");\r
+ process = ModelicaManager.runModelica(\r
+ simulationLocation,\r
+ monitor,\r
+ inits\r
+ );\r
+ ModelicaManager.printProcessOutput(process, monitor);\r
+\r
+ Thread resultThread = new Thread() {\r
+ @Override\r
+ public void run() {\r
+ try {\r
+ process.waitFor();\r
+\r
+ if(!canceled) {\r
+ // Get and store results \r
+ progressMonitor.worked(1);\r
+ progressMonitor.subTask("Read results");\r
+ if(simulationLocation.outputFile.getName().endsWith(".csv"))\r
+ result = new CSVSimulationResult();\r
+ else if(simulationLocation.outputFile.getName().endsWith(".plt"))\r
+ result = new SimulationResult();\r
+ else\r
+ result = new MatSimulationResult(); // The latest format\r
+ result.read(simulationLocation.outputFile);\r
+ result.readInits(simulationLocation.initFile);\r
+ result.filter();\r
+ sysdynResult.setResult(result);\r
+ progressMonitor.worked(1);\r
+ resultChanged();\r
+\r
+ setExperimentStopped(experiment);\r
+\r
+ String errorString = result.getResultReadErrors();\r
+ if(errorString != null && !errorString.isEmpty()) \r
+ monitor.message(errorString);\r
+ }\r
+ } catch (FileNotFoundException e) {\r
+ e.printStackTrace();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ };\r
+ resultThread.run();\r
+ }\r
+ if(canceled)\r
+ setExperimentStopped(experiment);\r
+ process = null;\r
+ }\r
+\r
+ /**\r
+ * Stop an experiment\r
+ * \r
+ * @param experiment Experiment to be stopped\r
+ */\r
+ private void setExperimentStopped(Experiment experiment) {\r
+ if(experiment instanceof SysdynExperiment) {\r
+ SysdynExperiment e = (SysdynExperiment)experiment;\r
+ if(e.getState() != ExperimentState.DISPOSED)\r
+ e.simulate(false);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that compares given modelText and inits to previous model and inits \r
+ * @param modelText Textual representation of a model (Modelica code)\r
+ * @param inits map of init parameters\r
+ * @return true if the model has changed, false otherwise\r
+ */\r
+ private boolean hasStructureChanged(String modelText, Map<String, String> inits) {\r
+\r
+ // Compare inits first because it is faster\r
+ for(String key : previousImportantInits.keySet()) {\r
+ if(!inits.containsKey(key) || !previousImportantInits.get(key).equals(inits.get(key)))\r
+ return true;\r
+ } \r
+\r
+ // Then compare the actual model structure\r
+ BufferedReader current = new BufferedReader(\r
+ new StringReader(modelText));\r
+ BufferedReader previous = new BufferedReader(\r
+ new StringReader(previousModelStructure));\r
+\r
+ String c, p;\r
+ try {\r
+ // Read both current and previous model texts at the same time\r
+ c = current.readLine();\r
+ p = previous.readLine();\r
+\r
+ while (c != null && p != null) {\r
+ // if the lines are the same, no need for further examination\r
+ if(!c.equals(p)) {\r
+ if(c.contains("parameter") && p.contains("parameter")) {\r
+ /*\r
+ * The line is a parameter definition.\r
+ * In this case only what is before '=' matters\r
+ * \r
+ * parameter Real Var = 1;\r
+ * is structurally same as\r
+ * parameter Real Var = 2; \r
+ */\r
+ int i = c.indexOf("=");\r
+ if(!c.substring(0, i).equals(p.substring(0, i))) {\r
+ // different parameter definition\r
+ return true;\r
+ }\r
+ } else {\r
+ // other than a line containing parameters differs\r
+ return true;\r
+ }\r
+ }\r
+ c = current.readLine();\r
+ p = previous.readLine();\r
+ }\r
+\r
+ if((c == null && p != null) || (c != null && p == null)) {\r
+ // different lengths\r
+ return true;\r
+ }\r
+\r
+ } catch(IOException e) {\r
+ // Something went wrong in the comparison, it is safer to say that the structure has changed \r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Cancel a possible ongoing simulation\r
+ */\r
+ public void cancelSimulation() {\r
+ canceled = true;\r
+ if(process != null) {\r
+ process.destroy();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Update mapping.\r
+ * \r
+ * Use this if inside a transaction.\r
+ * \r
+ * @param graph ReadGraph\r
+ * @return has the range been modified\r
+ * @throws DatabaseException\r
+ */\r
+ public synchronized boolean update(ReadGraph graph) throws DatabaseException {\r
+ if(mapping.isDomainModified()) {\r
+ mapping.updateRange(graph);\r
+\r
+ // Remove all unnecessary module configurations from modules \r
+ Set<Resource> configs = readModules(graph, configurationResource); \r
+ for(Resource config : configs) {\r
+ if(!modules.contains(config))\r
+ modules.add((Configuration)mapping.map(graph, config));\r
+ }\r
+\r
+ HashSet<Configuration> toBeRemoved = null;\r
+ for(Configuration module : modules) {\r
+ if(!configs.contains(mapping.inverseGet(module))) {\r
+ if(toBeRemoved == null)\r
+ toBeRemoved = new HashSet<Configuration>();\r
+ toBeRemoved.add(module);\r
+ }\r
+ }\r
+ if(toBeRemoved != null)\r
+ modules.removeAll(toBeRemoved);\r
+ return true;\r
+ }\r
+ else\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Update mapping.\r
+ * \r
+ * Use only if not inside a transaction\r
+ * @return has range been updated\r
+ * @throws DatabaseException\r
+ */\r
+ public boolean update() throws DatabaseException {\r
+ return session.syncRequest(new Read<Boolean>() {\r
+ @Override\r
+ public Boolean perform(ReadGraph graph) throws DatabaseException {\r
+ return update(graph);\r
+ }\r
+ });\r
+ }\r
+\r
+ public SimulationResult getSimulationResult() {\r
+ return result;\r
+ }\r
+\r
+ public SysdynResult getSysdynResult() {\r
+ return sysdynResult;\r
+ }\r
+\r
+ public void addResultListener(Runnable listener) {\r
+ synchronized(resultListeners) {\r
+ resultListeners.add(listener);\r
+ }\r
+ }\r
+\r
+ public void removeResultListener(Runnable listener) {\r
+ synchronized(resultListeners) {\r
+ resultListeners.remove(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Fires an update to all result listeners and subscriptions\r
+ * after results have changed\r
+ */\r
+ public void resultChanged() {\r
+ synchronized(resultListeners) {\r
+ for(Runnable listener : resultListeners) {\r
+ listener.run();\r
+ }\r
+ }\r
+\r
+ updateSubscriptions();\r
+ }\r
+\r
+ public void addModificationListener(Runnable listener) {\r
+ synchronized(modificationListeners) {\r
+ modificationListeners.add(listener);\r
+ }\r
+ }\r
+\r
+ public void removeModificationListener(Runnable listener) {\r
+ synchronized(modificationListeners) {\r
+ modificationListeners.remove(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Fires all modification listeners after a change in the domain\r
+ */\r
+ @Override\r
+ public void domainModified() {\r
+ synchronized(modificationListeners) {\r
+ for(Runnable listener : modificationListeners)\r
+ listener.run();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void rangeModified() {\r
+ }\r
+\r
+ public Configuration getConfiguration() {\r
+ return configuration;\r
+ }\r
+\r
+ public Resource getConfigurationResource() {\r
+ return configurationResource;\r
+ }\r
+\r
+ public IMapping getMapping() {\r
+ return mapping;\r
+ }\r
+\r
+ public synchronized IElement getElement(Resource resource) {\r
+ return (IElement)mapping.get(resource);\r
+ }\r
+\r
+ public <T> T getService(Class<T> clazz) {\r
+ synchronized(services) {\r
+ return clazz.cast(services.get(clazz));\r
+ }\r
+ }\r
+\r
+ public <T> void addService(Class<T> clazz, T service) {\r
+ synchronized(services) {\r
+ services.put(clazz, service);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public IExperiment loadExperiment(ReadGraph g, Resource experiment, IExperimentActivationListener listener) {\r
+\r
+ // Make sure that configurationResource exists\r
+ if(configurationResource == null && modelResource != null) {\r
+ SimulationResource simu = SimulationResource.getInstance(g);\r
+ try {\r
+ configurationResource = g.getPossibleObject(modelResource, simu.HasConfiguration);\r
+ } catch (ManyObjectsForFunctionalRelationException e) {\r
+ e.printStackTrace();\r
+ } catch (ServiceException e) {\r
+ e.printStackTrace();\r
+ } \r
+ }\r
+\r
+\r
+ try {\r
+ // Create a new experiment based on the experiment resource type\r
+ SysdynResource sr = SysdynResource.getInstance(g);\r
+ IDynamicExperiment exp;\r
+ if(g.isInstanceOf(experiment, sr.PlaybackExperiment)) {\r
+ exp = new SysdynPlaybackExperiment(experiment, modelResource);\r
+ } else if(g.isInstanceOf(experiment, sr.BasicExperiment)) {\r
+ exp = new SysdynExperiment(experiment, modelResource);\r
+ } else {\r
+ return null;\r
+ }\r
+ \r
+ ((SysdynExperiment)exp).init(g);\r
+\r
+ ExperimentRuns.createRun(g.getSession(), experiment, exp, listener, null);\r
+ if(listener != null)\r
+ listener.onExperimentActivated(exp);\r
+ return exp;\r
+ } catch(Exception e) {\r
+ if(listener != null)\r
+ listener.onFailure(e);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get all active results for this model including the current result and \r
+ * all saved results that are active \r
+ * @param graph ReadGraph\r
+ * @return all active SysdynResults\r
+ */\r
+ public Collection<SysdynResult> getActiveResults(ReadGraph graph) {\r
+ ArrayList<SysdynResult> results = new ArrayList<SysdynResult>();\r
+\r
+ try {\r
+ // Find all active saved results\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+ Resource model = graph.getSingleObject(configurationResource, SIMU.IsConfigurationOf);\r
+ Collection<Resource> experiments = graph.getObjects(model, l0.ConsistsOf);\r
+ for(Resource experiment : experiments) {\r
+ Collection<Resource> experimentResults = graph.getObjects(experiment, sr.HasResult);\r
+ for(Resource result : experimentResults) {\r
+ if(graph.hasStatement(result, SIMU.IsActive)) {\r
+ SysdynResult sysdynResult = new SysdynResult(\r
+ (String) graph.getPossibleRelatedValue(result, l0.HasLabel),\r
+ (String) graph.getPossibleRelatedValue(result, sr.HasResultFile));\r
+ results.add(sysdynResult);\r
+ }\r
+ }\r
+ }\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ // Add the current result if there is one\r
+ if(getSysdynResult() != null)\r
+ results.add(0, getSysdynResult() );\r
+\r
+ return results;\r
+ }\r
+\r
+ /**\r
+ * Get all parameters for Configuration\r
+ * \r
+ * @param configuration Configuration\r
+ * @param prefix String prefix of configuration in this model (Module1.Module2...)\r
+ * @return\r
+ */\r
+ private HashMap<String, String> getInits(Configuration configuration, String prefix) {\r
+ HashMap<String, String> inits = new HashMap<String, String>();\r
+ for (IElement element : configuration.getElements()) {\r
+ if (element instanceof Module) {\r
+ Module module = (Module) element;\r
+ Configuration conf = module.getType().getConfiguration();\r
+ inits.putAll(getInits(conf, prefix + module.getName() + "."));\r
+ } else if (element instanceof IndependentVariable) {\r
+ IndependentVariable variable = (IndependentVariable) element;\r
+ //FIXME: more general solution for finding out if the variable is a parameter\r
+ IExpression expression = variable.getExpressions().getExpressions().get(0);\r
+ if (expression instanceof ParameterExpression) {\r
+ Double value = ((ParameterExpression)expression).getValue();\r
+ if(value != null)\r
+ inits.put(prefix + variable.getName(), "" + value);\r
+ }\r
+ }\r
+ }\r
+ return inits;\r
+ }\r
+\r
+ /**\r
+ * Get a simulation directory for this model\r
+ * @return File directory\r
+ */\r
+ public File getSimulationDir() {\r
+ if(simulationDir == null) {\r
+ File modelsDir = Activator.getBundleContext().getDataFile("models");\r
+ String configName = configuration.getName();\r
+ List<String> files = Arrays.asList(modelsDir.list());\r
+ if (files.contains(configName)) {\r
+ int i = 2;\r
+ while (files.contains(configName + "_" + i)){\r
+ i++;\r
+ }\r
+ configName += "_" + i;\r
+ }\r
+\r
+ simulationDir = Activator.getBundleContext().getDataFile("models/" + configName);\r
+ if (!simulationDir.exists()) {\r
+ simulationDir.mkdir();\r
+ }\r
+ }\r
+ return simulationDir;\r
+ }\r
+\r
+\r
/**\r
* Copy from AprosExperiment\r
* @param subscription\r
variableValueSubscriptionsSnapshot = null;\r
}\r
}\r
- \r
+\r
/**\r
* Copy from AprosExperiment\r
* @param subscription\r