Added Set End Time command and handler as an alternate stepping mode
[simantics/platform.git] / bundles / org.simantics.simulation / src / org / simantics / simulation / experiment / ExperimentUtil.java
1 package org.simantics.simulation.experiment;
2
3 import java.util.Collection;
4 import java.util.UUID;
5 import java.util.function.Consumer;
6
7 import org.eclipse.core.runtime.IProgressMonitor;
8 import org.eclipse.core.runtime.IStatus;
9 import org.eclipse.core.runtime.Status;
10 import org.eclipse.core.runtime.jobs.Job;
11 import org.eclipse.ui.progress.IProgressConstants2;
12 import org.simantics.DatabaseJob;
13 import org.simantics.Simantics;
14 import org.simantics.databoard.Bindings;
15 import org.simantics.db.ReadGraph;
16 import org.simantics.db.RequestProcessor;
17 import org.simantics.db.Resource;
18 import org.simantics.db.Session;
19 import org.simantics.db.WriteGraph;
20 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
21 import org.simantics.db.common.request.ObjectsWithType;
22 import org.simantics.db.common.request.WriteRequest;
23 import org.simantics.db.common.request.WriteResultRequest;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.layer0.request.PossibleActiveExperiment;
26 import org.simantics.db.layer0.request.PossibleActiveRun;
27 import org.simantics.db.layer0.variable.Variable;
28 import org.simantics.db.procedure.Procedure;
29 import org.simantics.db.service.VirtualGraphSupport;
30 import org.simantics.layer0.Layer0;
31 import org.simantics.project.IProject;
32 import org.simantics.simulation.ontology.SimulationResource;
33 import org.simantics.simulation.project.IExperimentManager;
34
35 /**
36  * @author Tuukka Lehtonen
37  */
38 public final class ExperimentUtil {
39
40     public static void refreshExperiment(ReadGraph graph, IExperiment experiment) {
41         experiment.refresh(graph);
42     }
43
44     public static void stepExperiment(IExperiment experiment, double duration) {
45         if(experiment instanceof IDynamicExperiment)
46             ((IDynamicExperiment)experiment).simulateDuration(duration);
47     }
48
49     public static void simulateExperiment(IExperiment experiment, boolean enabled) {
50         if(experiment instanceof IDynamicExperiment)
51             ((IDynamicExperiment)experiment).simulate(enabled);
52     }
53
54     public static ExperimentState getExperimentState(ReadGraph graph, IExperiment experiment) throws DatabaseException {
55         return experiment.getState(graph);
56     }
57         
58     public static void disposeExperiment(final IExperiment experiment) {
59         
60         if(experiment instanceof IDynamicExperiment) {
61                 
62             ((IDynamicExperiment)experiment).shutdown(null);
63             
64             Session session = Simantics.getSession();
65                         VirtualGraphSupport vgs = session.getService(VirtualGraphSupport.class);
66                         session.asyncRequest(new WriteRequest(vgs.getMemoryPersistent("experiments")) {
67
68                                 @Override
69                                 public void perform(WriteGraph graph) throws DatabaseException {
70
71                                         SimulationResource SIMU = SimulationResource.getInstance(graph);
72                                         Resource activeRun = experiment.getResource();
73                                         graph.deny(activeRun, SIMU.IsActive, activeRun);
74
75                                 }
76
77                         });
78
79         }
80         
81     }
82
83     public static void step(double duration) {
84         IExperimentManager manager = 
85             Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
86         IExperiment experiment = manager.getActiveExperiment();
87         if(experiment instanceof IDynamicExperiment)
88             ((IDynamicExperiment)experiment).simulateDuration(duration);
89     }
90
91     public static boolean canStepUntil(double endTime) {
92         IExperimentManager manager = 
93             Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
94         IExperiment experiment = manager.getActiveExperiment();
95         if (experiment instanceof IDynamicExperiment) {
96             IDynamicExperiment exp = (IDynamicExperiment) experiment;
97             double currentTime = exp.getSimulationTime();
98             return currentTime < endTime;
99         }
100         return false;
101     }
102
103     public static void stepUntil(double endTime) {
104         IExperimentManager manager = 
105             Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
106         IExperiment experiment = manager.getActiveExperiment();
107         if (experiment instanceof IDynamicExperiment) {
108             IDynamicExperiment exp = (IDynamicExperiment) experiment;
109             double currentTime = exp.getSimulationTime();
110             if (currentTime < endTime) {
111                 exp.simulateDuration(endTime - currentTime);
112             }
113         }
114     }
115
116     public static void simulate(boolean enabled) {
117         IExperimentManager manager =
118             Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
119         IExperiment experiment = manager.getActiveExperiment();
120         if(experiment instanceof IDynamicExperiment)
121             ((IDynamicExperiment)experiment).simulate(enabled);
122     }
123
124     /**
125      * Synchronously shutdown active experiment.
126      * 
127      * @param project
128      */
129     public static void shutdownActiveExperiment(IProject project) {
130         shutdownActiveExperiment(project, null);
131     }
132
133     /**
134      * Synchronously shutdown active experiment.
135      * 
136      * @param project
137      */
138     public static void shutdownActiveExperiment(IProject project, IProgressMonitor monitor) {
139         IExperimentManager manager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
140         IExperiment experiment = manager.getActiveExperiment();
141         if (experiment != null)
142             experiment.shutdown(monitor);
143     }
144
145     /**
146      * If there is an active experiment, schedule a job for its shutdown.
147      * 
148      * @param project
149      */
150     public static void scheduleShutdownActiveExperiment(IProject project) {
151         scheduleShutdownActiveExperiment(project, null);
152     }
153
154     /**
155      * If there is an active experiment, schedule a job for its shutdown.
156      * 
157      * @param project
158      */
159     public static void scheduleShutdownActiveExperiment(IProject project, Consumer<IExperiment> callback) {
160         IExperimentManager manager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
161         final IExperiment experiment = manager.getActiveExperiment();
162         if (experiment != null) {
163             Job job = new DatabaseJob("Shutting down experiment") {
164                 @Override
165                 protected IStatus run(final IProgressMonitor monitor) {
166                     try {
167                         experiment.shutdown(monitor);
168                         return Status.OK_STATUS;
169                     } finally {
170                         monitor.done();
171                         if (callback != null)
172                             callback.accept(null);
173                     }
174                 }
175             };
176             job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE);
177             job.setUser(true);
178             job.schedule();
179         } else {
180             if (callback != null)
181                 callback.accept(null);
182         }
183     }
184
185     public static Variable possibleActiveRunVariable(ReadGraph graph, Resource model) throws DatabaseException {
186         return graph.syncRequest(new PossibleActiveRun(model));
187     }
188
189     /**
190      * @param processor
191      * @param experiment
192      * @param asyncCallback
193      * @return
194      * @throws DatabaseException
195      */
196     public static Resource activateExperiment(RequestProcessor processor, Resource experiment, Procedure<Resource> asyncCallback) throws DatabaseException {
197         VirtualGraphSupport vgs = processor.getService(VirtualGraphSupport.class);
198         WriteResultRequest<Resource> w = new WriteResultRequest<Resource>(vgs.getMemoryPersistent("experiments")) {
199             @Override
200             public Resource perform(WriteGraph graph) throws DatabaseException {
201                 return activateExperiment(graph, experiment);
202             }
203         };
204         if (processor instanceof WriteGraph) {
205             return ((WriteGraph) processor).syncRequest(w);
206         } else {
207             if (asyncCallback == null)
208                 asyncCallback = new ProcedureAdapter<>();
209             processor.getSession().asyncRequest(w, asyncCallback);
210             return null;
211         }
212     }
213
214     /**
215      * @param processor
216      * @param run
217      * @throws DatabaseException
218      */
219     public static void activateRun(RequestProcessor processor, Resource run) throws DatabaseException {
220         VirtualGraphSupport vgs = processor.getService(VirtualGraphSupport.class);
221         WriteRequest w = new WriteRequest(vgs.getMemoryPersistent("experiments")) {
222             @Override
223             public void perform(WriteGraph graph) throws DatabaseException {
224                 ExperimentUtil.activateRun(graph, run);
225             }
226         };
227         if (processor instanceof WriteGraph) {
228             ((WriteGraph) processor).syncRequest(w);
229         } else {
230             processor.getSession().asyncRequest(w);
231         }
232     }
233
234     public static Resource activateExperiment(WriteGraph graph, Resource experiment) throws DatabaseException {
235
236         VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class);
237         return graph.syncRequest(new WriteResultRequest<Resource>(vgs.getMemoryPersistent("experiments")) {
238             @Override
239             public Resource perform(WriteGraph graph) throws DatabaseException {
240                 return createExperimentRun(graph, experiment);
241             }
242         });
243         
244     }
245
246     public static Resource createExperimentRun(WriteGraph graph, Resource experiment) throws DatabaseException {
247         
248         Layer0 L0 = Layer0.getInstance(graph);
249         SimulationResource SIMU = SimulationResource.getInstance(graph);
250
251         Resource experimentType = graph.getPossibleType(experiment, SIMU.Experiment);
252         if (experimentType == null)
253             throw new DatabaseException("No unique experiment type was found for experiment " + graph.getPossibleURI(experiment));
254         Collection<Resource> runTypes = graph.sync(new ObjectsWithType(experimentType, L0.ConsistsOf, SIMU.RunType));
255         if (runTypes.size() != 1)
256             throw new DatabaseException("No unique run type was found for experiment " + graph.getPossibleURI(experiment));
257         final Resource runType = runTypes.iterator().next();
258         
259         return createExperimentRunWithType(graph, experiment, runType);
260         
261     }
262
263     public static Resource createExperimentRunWithType(WriteGraph graph, Resource experiment, Resource runType) throws DatabaseException {
264         
265         Layer0 L0 = Layer0.getInstance(graph);
266
267         Resource run = graph.newResource();
268         graph.claim(run, L0.InstanceOf, runType);
269         graph.addLiteral(run, L0.HasName, L0.NameOf, L0.String, UUID.randomUUID().toString(), Bindings.STRING);
270         graph.claim(experiment, L0.ConsistsOf, run);
271
272         activateRun(graph, run);
273         
274         return run;
275         
276     }
277
278     public static void activateRun(WriteGraph graph, Resource run) throws DatabaseException {
279         
280         SimulationResource SIMU = SimulationResource.getInstance(graph);
281         Resource activeRun = graph.syncRequest(new PossibleActiveExperiment(run));
282         if (activeRun != null) {
283             graph.deny(activeRun, SIMU.IsActive, activeRun);
284         }
285         graph.claim(run, SIMU.IsActive, run);
286         
287     }
288
289 }