程序包 org.hipparchus.ode.events


package org.hipparchus.ode.events

事件

该包提供了处理常微分方程积分过程中发生的离散事件的类。

离散事件检测基于切换函数。用户在检测器对象中提供一个简单的依赖于当前时间和状态的g(state)函数,以及在处理器对象中的handler函数。积分器将在整个积分范围内监视函数的值,并在其符号发生变化时触发事件。该值的大小几乎无关紧要,但为了进行根查找,它应该是连续的(但不一定是平滑的)。

事件检测基于两个嵌套的搜索算法。一个顶层循环,由maxCheck间隔驱动,对积分步骤期间的g函数进行采样,以识别符号变化,从而确定根的区间。当在两个连续采样之间检测到符号变化时,将触发一个较低级别的根查找算法,以精确定位根,使用提供的阈值作为收敛标准。maxCheck间隔应该足够大,以避免对积分步骤进行过于细致的采样和过于频繁地评估g函数,但它应该足够小,以仍然分隔连续的根,否则可能会错过一些事件。有关maxCheck行为的正式定义,请参见下文。另一方面,阈值通常应该非常小,它实际上对应于必须定位事件的精度。

当触发事件时,有几种不同的选项可用:

  • 积分可以停止(这称为G-stop功能),
  • 状态向量或导数可以更改,
  • 或者积分可以继续进行。

第一种情况,G-stop,是最常见的情况。一个典型的用例是当必须解决ODE直到达到某个目标状态时,其中状态的值已知但发生时间未知。例如,如果我们想要监视化学反应直到第一种物质达到某个预定义浓度,我们可以在检测器中使用以下切换函数设置:

  public double g(final ODEStateAndDerivative state) {
    return state.getState()[0] - targetConcentration;
  }
 

以及在事件处理器中使用以下设置:

  public Action eventOccurred(final ODEStateAndDerivative state, final ODEEventDetector detector, final boolean increasing) {
    return STOP;
  }
 

第二种情况,更改状态向量或导数,是在处理不连续动力学模型时遇到的情况。一个典型的情况是当太空船进行轨道机动时的运动。只要不进行机动,加速度就是平滑的,仅取决于重力、阻力、第三体引力、辐射压力。点火推进器引入了一个不连续性,必须由积分器适当处理。在这种情况下,我们将使用类似于以下设置的切换函数设置:

  public double g(final ODEStateAndDerivative state) {
    return (state.getTime() - tManeuverStart) ∗ (state.getTime() - tManeuverStop);
  }
 

以及在事件处理器中使用以下设置:

  public Action eventOccurred(final ODEStateAndDerivative state, final ODEEventDetector detector, final boolean increasing) {
    return RESET_DERIVATIVES;
  }
 

第三种情况主要用于监视目的,一个简单的例子是:

  public double g(final ODEStateAndDerivative state) {
  final double[] y = state.getState();
    return y[0] - y[1];
  }
 

以及在事件处理器中使用以下设置:

  public Action eventOccurred(final ODEStateAndDerivative state, final ODEEventDetector detector, final boolean increasing) {
    logger.log("y0(t) and y1(t) curves cross at t = " + t);
    return CONTINUE;
  }
 

事件处理规则

这些规则形式化了事件检测的概念,并用于确定何时必须向用户报告事件以及事件发生的顺序。这些规则假定事件处理器和g函数符合ODEEventHandlerODEIntegrator上的文档。

  1. 如果g函数的符号已经改变了超过maxCheck(t, y(t))的时间,则必须检测到一个事件。形式上,给定时间t、t_e1、t_e2,使得t < t_e1 < t_e2,g(t_e1) = 0,g(t_e2) = 0,并且在区间{[t, t_e1>, }上g(t_i) != 0(即t_e1、t_e2是t之后的下两个事件时间),那么如果maxCheck(t, y(t)) < t_e2,则将检测到t_e1。(即,最大检查间隔必须小于第二个事件发生之前的时间。)
  2. MaxCheck(t, y(t))在步骤开始时进行评估,并在上一个maxCheck结束时再次调用;这意味着如果maxCheck在很大程度上取决于状态,则必须小心返回保守值,即最好返回小的maxCheck,因此进行大量检查比因为maxCheck太大而错过事件要好。
  3. MaxCheck应始终返回正值,即使积分是向后的。
  4. 对于给定的公差h和根r,事件可能发生在区间[r-h, r+h]上的任意点。公差是收敛参数和在添加事件检测器时指定的根查找器的收敛设置中较大的那个。
  5. 每个根最多触发一个事件。
  6. 来自同一事件检测器的事件必须在增加和减少事件之间交替。也就是说,对于每一对增加事件,必须存在一个介于减少事件之间的事件,反之亦然。
  7. 当调用eventOccured()方法时,事件开始发生。当eventOccurred()返回或处理器的resetState()方法返回时,事件停止发生,如果eventOccured()返回RESET_STATE
  8. 如果事件A发生在事件B之前,则A发生的效果对B可见。(包括重置状态或导数,或停止)
  9. 事件按时间顺序发生。如果积分是向前的,事件A发生在事件B之前,则事件B的时间大于或等于事件A的时间。
  10. 事件有一个总的顺序。也就是说,对于两个事件A和B,要么A发生在B之前,要么B发生在A之前。