Modelica中if、when、while语句疑问:循环终止条件的语句选择
Modelica中while与when的选择及你的代码问题分析
首先看你现有代码的核心问题:
你写的while循环在Modelica的algorithm块中属于同时间步内的离散迭代,但循环里依赖了time变量——而在同一个仿真时间步中,time是固定不变的。第一次计算c = time - 0.6后,只要这个值的绝对值大于0.1,后续循环里c的结果不会有任何变化,循环会直接陷入死循环;如果初始c(start=2)的绝对值大于0.1,这个循环永远不会终止。
什么时候用while,什么时候用when?
- while循环:适用于同一个时间步内完成的纯数值迭代,比如牛顿法求解方程、固定逻辑的迭代计算——只要循环内的变量能在迭代过程中持续变化,最终满足退出条件,就可以用。它不会推进仿真时间,所有迭代都在当前时间步完成。
- when语句:属于事件触发逻辑,当指定的条件(变量阈值、时间点等)满足时,执行一次代码块。它会推进仿真时间,每次事件触发都是在新的时间步中执行。
针对你的需求的正确实现
你的需求是“随着仿真推进,更新a、b、c直到|c|<0.1时终止并输出”,这需要跨时间步更新变量,因此应该用when结合控制变量来实现:
model TerminateOnCAbsThreshold Real a; Real b; Real c(start=2); Boolean keepUpdating(start=true); // 控制是否继续更新变量 algorithm // 当允许更新时,每次事件触发更新a、b、c when keepUpdating then a := 2*time - 0.5; b := time + 0.1; c := a - b; // 当|c|<0.1时,停止后续更新 keepUpdating := abs(c) >= 0.1; end when; // 满足终止条件时输出变量值 when not keepUpdating then assert(true, "终止时变量值:c = " + String(c) + ",a = " + String(a) + ",b = " + String(b)); end when; end TerminateOnCAbsThreshold;
如果你的需求是不依赖仿真时间,仅做纯数值迭代(比如用迭代次数代替time),那可以用while循环,示例如下:
model IterateToConverge Real a; Real b; Real c(start=2); Integer iteration(start=0); algorithm while abs(c) > 0.1 loop iteration := iteration + 1; a := 2*iteration - 0.5; b := iteration + 0.1; c := a - b; end while; assert(true, "迭代终止于第" + String(iteration) + "次,c = " + String(c)); end IterateToConverge;
内容的提问来源于stack exchange,提问作者white
相关产品推荐
相关产品推荐

