/** * * <!-- begin-user-doc --> * <!-- end-user-doc --> * * @generated NOT */ @Override public boolean step(STEMTime time, long timeDelta, int cycle) { // Validate all decorators that return deltas to make sure // they are of deterministic nature. The Runge Kutta integratio // can only handle determininistic variants for (Decorator decorator : this.getDecorators()) if (decorator instanceof IntegrationDecorator) { IntegrationDecorator idec = (IntegrationDecorator) decorator; if (!idec.isDeterministic()) { Activator.logError( "Error, decorator: " + idec + " is not deterministic. The Runge Kutta Integrator can only handle deterministic models.", new Exception()); return false; } } Activator act = org.eclipse.stem.ui.Activator.getDefault(); if (act != null) { final Preferences preferences = act.getPluginPreferences(); num_threads = (short) preferences.getInt( org.eclipse.stem.ui.preferences.PreferenceConstants.SIMULATION_THREADS); } else num_threads = 2; // Just so we can run inside junit test final int c = cycle; // Initialize latches stepSizeBarrier = new CyclicBarrier( num_threads, new Runnable() { public void run() { // All threads successfully advanced time by some step h. // Find the smallest smallestH = Double.MAX_VALUE; maximumError = -Double.MAX_VALUE; for (int i = 0; i < num_threads; ++i) { if (jobs[i].h <= smallestH) { if (maximumError < jobs[i].maxerror) maximumError = jobs[i].maxerror; smallestH = jobs[i].h; } } } }); updateDoneBarrier = new CyclicBarrier(num_threads); // Find triggers and make sure they are invoked for (Decorator decorator : this.getDecorators()) { if (decorator instanceof Trigger) { decorator.updateLabels(time, timeDelta, cycle); } } // First initialize the probe and temp label values from the current // label values. for (Decorator decorator : this.getDecorators()) { EList<DynamicLabel> allLabels = decorator.getLabelsToUpdate(); for (final Iterator<DynamicLabel> currentStateLabelIter = allLabels.iterator(); currentStateLabelIter.hasNext(); ) { if (decorator instanceof IntegrationDecorator) { // It's a standard disease model with a standard disease model label final IntegrationLabel iLabel = (IntegrationLabel) currentStateLabelIter.next(); ((IntegrationLabelValue) iLabel.getProbeValue()) .set((IntegrationLabelValue) iLabel.getCurrentValue()); ((IntegrationLabelValue) iLabel.getTempValue()) .set((IntegrationLabelValue) iLabel.getCurrentValue()); ((IntegrationLabelValue) iLabel.getTempValue()).prepareCycle(); ((IntegrationLabelValue) iLabel.getProbeValue()).prepareCycle(); } else currentStateLabelIter.next(); } } if (jobs == null || jobs.length != num_threads) { // Initialize the jobs if not done yet or of the number of threads changes jobs = new RkJob[num_threads]; for (short i = 0; i < num_threads; ++i) { final short threadnum = i; jobs[i] = new RkJob("Worker " + i, threadnum, this); } // For each job } // If not initialized // Initialize int thread = 0; for (RkJob j : jobs) { j.cycle = c; j.time = time; j.timeDelta = timeDelta; } // Schedule. Jobs can be rescheduled after finished for (RkJob j : jobs) j.schedule(); // Wait until all jobs completed for (RkJob j : jobs) { try { j.join(); } catch (InterruptedException ie) { Activator.logError(ie.getMessage(), ie); } } // Set the common time and step size here and validate everything is right double minStep = Double.MAX_VALUE; double currentT = jobs[0].t; for (RkJob j : jobs) { // The jobs have calculated new step sizes after they finished. Pick the // smallest one for the next cycle if (j.h < minStep) minStep = j.h; if (j.t != currentT) Activator.logError( "Error, one thread was in misstep with other threads, its time was " + j.t + " versus " + currentT, new Exception()); } return true; }