我试图通过求解Scilab
在ODE
中进行一些电路分析。但我需要根据函数的当前值更改ODE
。我已使用Scala
方法在RK4
中实施了该解决方案,但效果非常好。现在我尝试使用Scilab
中的标准函数来做同样的事情。它不起作用。我试图单独解决这两个ODE,没关系。
clear
state = 0 // state 0 is charging, 1 is discharging
vb = 300.0; vt = 500.0;
r = 100.0; rd = 10.0;
vcc = 600;
c = 48.0e-6;
function dudx = curfunc(t, uu)
if uu < vb then state = 0
elseif uu > vt state = 1
end
select state
case 0 then // charging
dudx = (vcc - uu) / (r * c)
case 1 then // discharging
dudx = - uu / (rd * c) + (vcc - uu) / (r * c)
end
endfunction
y0 = 0
t0 = 0
t = 0:1e-6:10e-3
%ODEOPTIONS=[1, 0, 0, 1e-6, 1e-12, 2, 500, 12, 5, 0, -1, -1]
y = ode(y0, t0, t, 1e-3, 1e-6, curfunc)
clear %ODEOPTIONS
plot(t, y)
所以我在这里解决节点电压,如果节点电压超过最高阈值(vt),则使用放电ODE
,如果节点电压低于底部电压(vb)则充电{{1 }} 用来。我试过玩ODE
但没有运气
答案 0 :(得分:1)
我认为归结为一个标准问题:标准ODE求解器具有步长控制。与RK4的固定步长相反。为了使步长控制起作用,ODE函数需要具有至少与方法顺序相同的顺序的可微性。因此,在你的功能中跳跃是非常不幸的。
要考虑的另一点是,方法的内部步骤并不总是在增加时间,它们可能会向后跳跃。有关示例,请参阅Dormant-Price的系数表。因此,如果第一个问题被规避,那么基于事件的模型在问题中的变化可能会导致奇怪的效果。
将state
声明为全局变量,因为作为局部变量,值始终会重置为全局常量0。
function dudx = curfunc(t, uu)
global state
...
endfunction
...
y = ode("fix",y0, t0, t, rtol, atol, curfunc)
答案 1 :(得分:1)
你也可以使用ode(&#34; root&#34; ...)选项。
代码将重新组合 明确 state = 0 //状态0正在充电,1正在放电 vb = 300.0; vt = 500.0; r = 100.0; rd = 10.0; vcc = 600; c = 48.0e-6;
function dudx = charging(t, uu)
//uu<vt
dudx = (vcc - uu) / (r * c)
endfunction
function e=chargingssurf(t,uu)
e=uu-vt
endfunction
function dudx = discharging(t, uu)
//uu<vb
dudx = - uu / (rd * c) + (vcc - uu) / (r * c)
endfunction
function e=dischargingssurf(t,uu)
e=uu-vb
endfunction
y0 = 0
t0 = 0
t = 0:1e-6:10e-3
Y=[];
T=[];
[y,rt] = ode("root",y0, t0, t, 1e-3, 1e-6, charging,1,chargingssurf);
disp(rt)
k=find(t(1:$-1)<rt(1)&t(2:$)>=rt(1))
Y=[Y y];;
T=[T t(1:k) rt(1)];
[y,rt] = ode("root",y($), rd(1), t(k+1:$), 1e-3, 1e-6, discharging,1,dischargingssurf);
Y=[Y y];
T=[T t(k+1:$)];
plot(T, Y)
放电代码似乎错了......