[ 
https://issues.apache.org/jira/browse/MATH-979?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13665097#comment-13665097
 ] 

Luc Maisonobe commented on MATH-979:
------------------------------------

The proper way to stop integration before the target time taht was specified 
when calling the integrate method is to use an event handler, not a step 
handler. You can look at the method addEventHandler in the ODEIntegrator 
interface and at the EvenHandler interface that uses it.

Unfortunately, this proper way does not directly match your needs, you will 
need to do some dirty tricks ...

What the event handling does is first specify some g function that implicitly 
defines when some discrete events will occur, and then specify what to do (for 
example stop) when the event effectively occurs. By definition, an even occurs 
when the sign of function g(t, y) changes. This means that events are expected 
to be triggered by the state itself. A typical example would be to stop 
integration when the first component of the state (i.e. y[0] reaches 0, in this 
case you would define g(t, y) simply as "return y[0]" and the integrator would 
detect the event precisely. Then, the integrator would call the second method 
of the interface, which is eventOccurred. If in this method you return the STOP 
constant, the integrator would stop.

In your case, the event is not defined by the state y, but it occurs completely 
out of control of the algorithm, when the user interacts with the graphical 
interface. So the trick would be to have a g(t,y) function that simply returns 
the offset with the current target stop time, and to have this time updated to 
the near future when the button is pressed. So I would suggest you to have the 
EventHandler interface implemented roughly as follows:

{code}
class UserStopEvent implements EventHandler {
  double targetTime;
  public void init(double t0, double[] y0, double t) {
    targetTime = t;
  }
  public double g(double t, double[] y) {
    return t - targetTime;
  }
  public Action eventOccurred(double t, double[] y, boolean increasing) {
    return Action.STOP;
  }
  public void setTargetTime(double targetTime) {
    this.targetTime = targetTime;
  }
{code}

When the user presses the button, you should call yourself the setTargetTime 
with a time that is very slightly after the last step displayed (typically a 
fraction of the last step length), so the integrator only performs a very small 
last step and stops properly. Take care the if the integration is backward, you 
should set the new target time before the last step instead of after it.

Do not put the target time exactly at the last step time, to avoid problems 
with a zero length final step. This would create problems in many places. I 
guess that from the user point of view, it should not be a problem to see the 
integrator stop just a few milliseconds after the button was pressed.

By the way, the JIRA issue tracker is not the place to ask questions, you 
should rather ask them on the users list.
                
> Stop integration in handleStep method
> -------------------------------------
>
>                 Key: MATH-979
>                 URL: https://issues.apache.org/jira/browse/MATH-979
>             Project: Commons Math
>          Issue Type: Improvement
>            Reporter: Sindeev Sergey
>            Priority: Minor
>
> I use ClassicalRungeKutta integrator to solve ODE system. in handleStep 
> method every step value is plotted on chart. integration lasts until stop 
> button is clicked. I need a method to stop integration in handleStep like:
> public void handleStep(StepInterpolator interpolator, boolean isLast) {
> ...
> if (stopButton.isSelected()){
>    getIntegrator().stop();
> }
> ...
> }
> Is this possible ? or there is a better way for this ?

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to