package stoppers; import java.lang.*; import java.io.*; import main.BetterTokenizer; import main.Cell; import main.GeneralInput; import main.Model; /** The NoChangeStop stops when the trajectory of a given node stabilizes or StopTime is reached. * The trajectory is stable if the time-derivative divided by absolute value is less than thresholdChange or * if the derivative is negative and the value is less that thresholdAbs. * Returns the derivative divided by the value of the node */ public class NoChangeStop extends SimpleStop { int nodeNum; float thresholdChange, thresholdAbs, interval; /** Values of the given node in each cell the last time we checked them. */ float [] lastValues; /** Whether the values for the given node satisfid the no change criterion. */ boolean [] good; /** The first time at which to check for stability. */ float firstStabilityCheckTime; // No arg constructor for instantiating by name public NoChangeStop() { this(1); } public NoChangeStop(float stop_time) { stopTime = stop_time; } public void init(Model model) { super.init(model); lastValues = new float[model.numCells]; good = new boolean[model.numCells]; for(int cell = 0; cell < model.numCells; cell++) { lastValues[cell] = model.cells[cell].getValue(nodeNum); good[cell] = false; } } public boolean stop(float time) { boolean done = true; int cell; float val, deriv; // trivial reasons to return if(time < firstStabilityCheckTime) return false; if(time < lastTime + interval) return false; if(time > stopTime) return true; score = 0; for(cell = 0; cell < model.numCells; cell++) { val = model.cells[cell].getValue(nodeNum); deriv = (val - lastValues[cell]) / (time - lastTime); if(Math.abs(deriv / val) > thresholdChange && !(val < thresholdAbs && deriv < 0)) { done = false; good[cell] = false; } else good[cell] = true; score += Math.abs(deriv); lastValues[cell] = val; } lastTime = time; return done; } public void reset() { lastTime = -10; for(int cell = 0; cell < model.numCells; cell++) lastValues[cell] = model.cells[cell].getValue(nodeNum); score = 10000; super.reset(); } public boolean getGood(int cell) { return good[cell]; } protected void loadParameter(String info, BetterTokenizer tokenizer) throws Exception { if(info.equals("Node")) { GeneralInput.nextToken(tokenizer); nodeNum = model.cells[0].getNodeNum(tokenizer.sval); } else if(info.equals("AbsoluteThreshold")) { GeneralInput.nextToken(tokenizer); thresholdAbs = ((float)tokenizer.nval); } else if(info.equals("FirstStabilityCheckTime")) { GeneralInput.nextToken(tokenizer); firstStabilityCheckTime = ((float)tokenizer.nval); } else if(info.equals("ChangeThreshold")) { GeneralInput.nextToken(tokenizer); thresholdChange = ((float)tokenizer.nval); } else if(info.equals("Interval")) { GeneralInput.nextToken(tokenizer); interval = ((float)tokenizer.nval); } else super.loadParameter(info,tokenizer); } }