package org.simantics.simulation.experiment; import java.util.Collection; import java.util.UUID; import java.util.function.Consumer; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.progress.IProgressConstants2; import org.simantics.DatabaseJob; import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.procedure.adapter.ProcedureAdapter; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.request.WriteResultRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PossibleActiveExperiment; import org.simantics.db.layer0.request.PossibleActiveRun; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.procedure.Procedure; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.layer0.Layer0; import org.simantics.project.IProject; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.simulation.project.IExperimentManager; /** * @author Tuukka Lehtonen */ public final class ExperimentUtil { public static void refreshExperiment(ReadGraph graph, IExperiment experiment) { experiment.refresh(graph); } public static void stepExperiment(IExperiment experiment, double duration) { if(experiment instanceof IDynamicExperiment) ((IDynamicExperiment)experiment).simulateDuration(duration); } public static void simulateExperiment(IExperiment experiment, boolean enabled) { if(experiment instanceof IDynamicExperiment) ((IDynamicExperiment)experiment).simulate(enabled); } public static ExperimentState getExperimentState(ReadGraph graph, IExperiment experiment) throws DatabaseException { return experiment.getState(graph); } public static void disposeExperiment(final IExperiment experiment) { if(experiment instanceof IDynamicExperiment) { ((IDynamicExperiment)experiment).shutdown(null); Session session = Simantics.getSession(); VirtualGraphSupport vgs = session.getService(VirtualGraphSupport.class); session.asyncRequest(new WriteRequest(vgs.getMemoryPersistent("experiments")) { @Override public void perform(WriteGraph graph) throws DatabaseException { SimulationResource SIMU = SimulationResource.getInstance(graph); Resource activeRun = experiment.getResource(); graph.deny(activeRun, SIMU.IsActive, activeRun); } }); } } public static void step(double duration) { IExperimentManager manager = Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); IExperiment experiment = manager.getActiveExperiment(); if(experiment instanceof IDynamicExperiment) ((IDynamicExperiment)experiment).simulateDuration(duration); } public static boolean canStepUntil(double endTime) { IExperimentManager manager = Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); IExperiment experiment = manager.getActiveExperiment(); if (experiment instanceof IDynamicExperiment) { IDynamicExperiment exp = (IDynamicExperiment) experiment; double currentTime = exp.getSimulationTime(); return currentTime < endTime; } return false; } public static void stepUntil(double endTime) { IExperimentManager manager = Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); IExperiment experiment = manager.getActiveExperiment(); if (experiment instanceof IDynamicExperiment) { IDynamicExperiment exp = (IDynamicExperiment) experiment; double currentTime = exp.getSimulationTime(); if (currentTime < endTime) { exp.simulateDuration(endTime - currentTime); } } } public static void simulate(boolean enabled) { IExperimentManager manager = Simantics.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); IExperiment experiment = manager.getActiveExperiment(); if(experiment instanceof IDynamicExperiment) ((IDynamicExperiment)experiment).simulate(enabled); } /** * Synchronously shutdown active experiment. * * @param project */ public static void shutdownActiveExperiment(IProject project) { shutdownActiveExperiment(project, null); } /** * Synchronously shutdown active experiment. * * @param project */ public static void shutdownActiveExperiment(IProject project, IProgressMonitor monitor) { IExperimentManager manager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); IExperiment experiment = manager.getActiveExperiment(); if (experiment != null) experiment.shutdown(monitor); } /** * If there is an active experiment, schedule a job for its shutdown. * * @param project */ public static void scheduleShutdownActiveExperiment(IProject project) { scheduleShutdownActiveExperiment(project, null); } /** * If there is an active experiment, schedule a job for its shutdown. * * @param project */ public static void scheduleShutdownActiveExperiment(IProject project, Consumer callback) { IExperimentManager manager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); final IExperiment experiment = manager.getActiveExperiment(); if (experiment != null) { Job job = new DatabaseJob("Shutting down experiment") { @Override protected IStatus run(final IProgressMonitor monitor) { try { experiment.shutdown(monitor); return Status.OK_STATUS; } finally { monitor.done(); if (callback != null) callback.accept(null); } } }; job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); job.setUser(true); job.schedule(); } else { if (callback != null) callback.accept(null); } } public static Variable possibleActiveRunVariable(ReadGraph graph, Resource model) throws DatabaseException { return graph.syncRequest(new PossibleActiveRun(model)); } /** * @param processor * @param experiment * @param asyncCallback * @return * @throws DatabaseException */ public static Resource activateExperiment(RequestProcessor processor, Resource experiment, Procedure asyncCallback) throws DatabaseException { VirtualGraphSupport vgs = processor.getService(VirtualGraphSupport.class); WriteResultRequest w = new WriteResultRequest(vgs.getMemoryPersistent("experiments")) { @Override public Resource perform(WriteGraph graph) throws DatabaseException { return activateExperiment(graph, experiment); } }; if (processor instanceof WriteGraph) { return ((WriteGraph) processor).syncRequest(w); } else { if (asyncCallback == null) asyncCallback = new ProcedureAdapter<>(); processor.getSession().asyncRequest(w, asyncCallback); return null; } } /** * @param processor * @param run * @throws DatabaseException */ public static void activateRun(RequestProcessor processor, Resource run) throws DatabaseException { VirtualGraphSupport vgs = processor.getService(VirtualGraphSupport.class); WriteRequest w = new WriteRequest(vgs.getMemoryPersistent("experiments")) { @Override public void perform(WriteGraph graph) throws DatabaseException { ExperimentUtil.activateRun(graph, run); } }; if (processor instanceof WriteGraph) { ((WriteGraph) processor).syncRequest(w); } else { processor.getSession().asyncRequest(w); } } public static Resource activateExperiment(WriteGraph graph, Resource experiment) throws DatabaseException { VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); return graph.syncRequest(new WriteResultRequest(vgs.getMemoryPersistent("experiments")) { @Override public Resource perform(WriteGraph graph) throws DatabaseException { return createExperimentRun(graph, experiment); } }); } public static Resource createExperimentRun(WriteGraph graph, Resource experiment) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); SimulationResource SIMU = SimulationResource.getInstance(graph); Resource experimentType = graph.getPossibleType(experiment, SIMU.Experiment); if (experimentType == null) throw new DatabaseException("No unique experiment type was found for experiment " + graph.getPossibleURI(experiment)); Collection runTypes = graph.sync(new ObjectsWithType(experimentType, L0.ConsistsOf, SIMU.RunType)); if (runTypes.size() != 1) throw new DatabaseException("No unique run type was found for experiment " + graph.getPossibleURI(experiment)); final Resource runType = runTypes.iterator().next(); return createExperimentRunWithType(graph, experiment, runType); } public static Resource createExperimentRunWithType(WriteGraph graph, Resource experiment, Resource runType) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); Resource run = graph.newResource(); graph.claim(run, L0.InstanceOf, runType); graph.addLiteral(run, L0.HasName, L0.NameOf, L0.String, UUID.randomUUID().toString(), Bindings.STRING); graph.claim(experiment, L0.ConsistsOf, run); activateRun(graph, run); return run; } public static void activateRun(WriteGraph graph, Resource run) throws DatabaseException { SimulationResource SIMU = SimulationResource.getInstance(graph); Resource activeRun = graph.syncRequest(new PossibleActiveExperiment(run)); if (activeRun != null) { graph.deny(activeRun, SIMU.IsActive, activeRun); } graph.claim(run, SIMU.IsActive, run); } }