Recientemente tuve este problema con un código mío.La solución 'simple' es hacer lo siguiente, en primer lugar, una vez que la solución llegue a 0, hay que mantenerlo a 0, así cambiar
dx = 1/(1+y*z) - x;
a (aviso en el que se evalúa el caso x == 0
)
if x > 0
dx = 1/(1+y*z) - x;
else % if x <= 0
dx = 0;
end
o tal vez a (dependiendo de por qué nunca puede ser 0)
dxTmp = 1/(1+y*z) - x;
if x > 0
dx = dxTmp;
elseif dxTmp > 0
% x becomes positive again
dx = dxTmp;
else
dx = 0;
end
Nota sin embargo que esto crea una discontinuidad de salto en la primera derivada, WHI ch cuando el solucionador DDE llega al punto de tener t - delay
cerca de este punto, no lo resuelve de manera muy eficiente a menos que sepa el punto exacto donde se encuentra esta discontinuidad (generalmente tiene una opción adicional de decirle a Matlab dónde está, pero si siga los pasos a continuación, entonces eso no será necesario).
Para determinar el lugar de esta discontinuidad es necesario utilizar la opción DDE de events (baje hasta 'Evento ubicación Propiedad', también se puede ver en estos examples, uno de esos ejemplos en realidad se ocupa de un sistema similar en negativo los valores no están permitidos en un ODE - los eventos para ODE y DDE son casi idénticos). Básicamente, un evento es una función de Matlab con una salida vectorial, cada una de las entradas del vector es alguna u otra evaluación de sus variables; en cada paso Matlab comprueba si uno de ellos eqauls 0, cuando uno de ellos es igual a 0, el DDE se detiene y devuelve una solución hasta ese punto, desde el cual debe reiniciar el DDE con esa solución parcial como su historial, es decir, en lugar de ejecutar
sol = dde23(ddefun, lags, history, [t0 tEnd], options);
que corren (aviso sol
y t0
cambiado)
sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);
En este caso una de las entradas del vector va a ser x
(como se desea que el DDE para detener cuando x
es igual a 0). Además, la línea del código elseif dxTmp <= 0
crea otra discontinuidad, por lo que necesita un evento para cuando dxTmp
se convierta en 0, es decir, 1/(1+y*z) - x
será otro componente de la salida del vector.
Ahora cuando reinicia el ODE, Matlab automáticamente asume que hay una discontinuidad en ese punto, por lo tanto, no tiene que preocuparse de decirle a Matlab que hay uno allí.
El siguiente problema es que Matlab nunca logra hacerlo bien, los valores de x
, y
, z
y X
será ligeramente negativo. Por lo tanto, si se va a crear un problema, tendrá que corregir el valor de x
(y los demás valores de manera similar) con
if x < 0
x = 0;
end
antes de calcular los derivados. Pero esto solo cambia el valor de x
localmente. Por lo tanto, es posible que desee cambiar todos los valores negativos de x
en la solución final a 0 también. Sugiero que no intente cambiar sol
antes de ingresarlo en sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);
ya que hice varios intentos y no pude hacerlo funcionar.
es posible utilizar simplemente ode45 y luego añadir el componente de retardo al vector resultante tiempo ... esto es posible si se puede separar las entradas Retardo de las entradas no – Rasman
de retardo? No lo creo. La razón para usar 'dde23' es porque hay interdependencias ... como X depende del valor de Y hace una hora. – dumbmatter
¿puedes publicar tus ecuaciones? – Rasman