Modelos Continuos · Tema 10

Sistemas de ecuaciones

Variables que evolucionan juntas: vector de estado, acoplamientos y equilibrios compartidos.

01 · Punto de partida

Una ecuación sola no alcanza

El agua que sale del primer tanque alimenta al segundo. Los susceptibles que se contagian alimentan a los infectados. La posición alimenta a la velocidad y viceversa. En cada caso, la tasa de un estado depende de otro estado: hace falta un sistema de ecuaciones.

El sistema se integra como un todo: no se puede resolver A sin B ni B sin A. El vector evoluciona junto o no evoluciona.

  • ¿Qué estados comparten tasas?
  • ¿Quién alimenta a quién?
  • ¿Qué se conserva entre todos (masa, población, energía)?
  • ¿Dónde está el equilibrio conjunto?

02 · Definición

¿Qué es un sistema de ecuaciones diferenciales?

n estados, n tasas, n arranques:

▦

Vector x

El paquete: [A, B], [S, I, R], [x, v]. Cada uno tiene su curva, todas comparten el tiempo.

⇄

Acoplamiento

Una tasa usa otro estado: dB/dt = k₁·A − k₂·B. Ahí vive la interacción.

◎

Equilibrio conjunto

Todas las tasas en cero a la vez: f(x*) = 0. Un estado quieto no basta.

Si las tasas no se cruzan, no hay sistema: son dos EDOs sueltas que casualmente viven en la misma página.

Tres sistemas arquetípicos del curso.
SistemaEcuacionesAcoplamiento
Tanques en cascadadA/dt = q − k₁A, dB/dt = k₁A − k₂BA alimenta a B en una dirección.
SIRdS, dI, dR con contagio βSI/NS → I → R en cadena cerrada.
Resorte (x, v)dx/dt = v, dv/dt = −kx − cvIda y vuelta entre posición y velocidad.
Depredador-presaDos tasas con encuentro xyMutuo: cada uno mueve al otro.

03 · Anatomía

Cascada, ciclo y conservación

Los acoplamientos tienen formas típicas:

Cascada
A alimenta a B sin retorno: tanques en serie. B retrasa y suaviza lo que A ya hizo.
Ciclo
A mueve a B y B mueve a A: resorte, SIR, depredador-presa. Pueden oscilar.
Conservación
Lo que sale de uno entra a otro: S + I + R constante. La suma de tasas es cero.
Equilibrio del sistema
Resolver f₁ = 0 y f₂ = 0 juntas: A* = q/k₁, B* = q/k₂ en la cascada lineal.

Sin acoplamiento

Dos relojes sueltos

dA/dt = −k₁A, dB/dt = −k₂B: cada uno decae por su cuenta. Juntarlos no crea sistema.

Con acoplamiento

Una historia compartida

dB/dt = k₁A − k₂B: B sube cuando A está alto aunque B parta de cero. B hereda el pasado de A.

04 · Sistemas en el curso

El mismo vector, cinco contenidos

Todo sistema del curso es un vector con su f:

Vector x(t)→Tasas f(x)→Curvas juntas
  1. 1
    Cascada de tanques.

    [A, B]: el primero alimenta al segundo. Retardo y suavizado.

  2. 2
    SIR.

    [S, I, R]: cadena con conservación total. Joroba de I.

  3. 3
    Resorte.

    [x, v]: ciclo posición-velocidad. Oscilación.

  4. 4
    Expuestos (SEIR).

    [S, E, I, R]: latencia que retrasa el pico.

  5. 5
    Dos temperaturas.

    [T₁, T₂]: dos cuerpos que se intercambian calor y convergen.

05 · Representación en Python

El estado es un dict, f devuelve un dict

En Python, el sistema es una función f(estado, t) que recibe el vector y devuelve el vector de derivadas. Euler avanza todo el dict junto con el mismo dt.

Python en tu navegador. Estos bloques se ejecutan localmente con Pyodide, sin instalar nada. Cambiá k1 y observá que B responde aunque sus parámetros no cambien.

def f_cascada(estado, q, k1, k2):
    a, b = estado["A"], estado["B"]
    return {"dA": q - k1 * a, "dB": k1 * a - k2 * b}


print(f_cascada({"A": 0.0, "B": 0.0}, 3, 0.3, 0.2))

Con ambos vacíos, A sube a +3 pero B quieto en 0: B necesita que A tenga algo para arrancar.

Un paso del sistema completo

El paso actualiza A y B con las tasas del mismo instante:

def paso(estado, q, k1, k2, dt):
    d = f_cascada(estado, q, k1, k2)
    return {"A": estado["A"] + d["dA"] * dt, "B": estado["B"] + d["dB"] * dt}


x = {"A": 0.0, "B": 0.0}
for _ in range(3):
    x = paso(x, 3, 0.3, 0.2, dt=1.0)
    print({k: round(v, 2) for k, v in x.items()})

06 · Exploración

Laboratorio: el segundo tanque hereda el pasado

Cascada dA/dt = q − k₁A, dB/dt = k₁A − k₂B desde vacíos. A (dorada) sube primero; B (teal) la sigue con retardo y punteadas en A* y B*. Tocá k₁ y mirá cómo el primero manda sobre el segundo.

EXPERIMENTO 10

Dos niveles, una historia

A → B · q = 3, vacíos al inicio

Los resultados numéricos aparecen debajo.
A* = q/k₁10,00
B* = q/k₂15,00
B final (T=40)14,98
LecturaB sigue a A

Con q 3, A* = 10 y B* = 15: B tarda más en llegar.

B arranca plana (su tasa inicial es cero con A vacío) y despega cuando A le entrega caudal: el retardo es la firma de la cascada.

Preguntas para explorar

  1. ¿Cuál es la tasa inicial de B? ¿Por qué su curva arranca horizontal?
  2. Subí k₁ con q y k₂ fijos. ¿A* y B* se mueven igual?
  3. Si k₂ es mucho mayor que k₁, ¿B sigue de cerca a A o se despega?
Ver respuestas sugeridas
  1. Cero: dB/dt = k₁·0 − k₂·0. B espera a que A tenga nivel: arranque plano = cascada.
  2. A* = q/k₁ baja, B* = q/k₂ no se mueve: el equilibrio de B lo mandan q y k₂, no k₁.
  3. La sigue de cerca: B drena rápido y copia a A con poco retardo. El lento manda la forma.

07 · Comprensión

Confusiones frecuentes

«Integro A y después B»

No: el acoplamiento exige avanzar juntos. Integrar en serie usa valores de A de tiempos que B aún no vivió.

«Equilibrio de A ya es equilibrio»

El sistema reposa cuando todas las tasas son cero. A quieto con B moviéndose es transitorio, no régimen.

«Más estados, mejor modelo»

Cada estado pide condición inicial, tasas y datos. Un estado sin datos es una curva inventada con ecuaciones.

«El orden de actualización no importa»

Sí importa: actualizá con las tasas del mismo instante (todas primero, después todos los estados).

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: equilibrio conjunto

Con q = 4, k₁ = 0,4 y k₂ = 0,2, ¿cuánto valen A* y B*? Comprobalo anulando ambas tasas.

def equilibrios(q, k1, k2):
    return q / k1, q / k2


print(equilibrios(4, 0.4, 0.2))
Ver solución

(10,0, 20,0): A* lo fija k₁ y B* lo fija k₂; q escala a ambos por igual.

Ejercicio 2: arranque de B

Si A = 0 y B = 0, ¿cuánto valen dA y dB con q = 3, k₁ = 0,3, k₂ = 0,2? ¿Y con A = 10, B = 0?

def f_cascada(estado, q, k1, k2):
    return (q - k1 * estado["A"], k1 * estado["A"] - k2 * estado["B"])


print(f_cascada({"A": 0.0, "B": 0.0}, 3, 0.3, 0.2))
print(f_cascada({"A": 10.0, "B": 0.0}, 3, 0.3, 0.2))
Ver solución

(3,0, 0,0) y (0,0, 3,0): B solo despega cuando A le entrega. La cascada se lee en las tasas.

Ejercicio 3: simular el sistema junto

Integrá ambos tanques juntos con Euler (dt = 0,5) hasta T = 40 desde vacíos. ¿A qué valores llegan?

Ver una posible respuesta
def simular(q, k1, k2, t_final, dt=0.5):
    a, b, t = 0.0, 0.0, 0.0
    while t < t_final - 1e-9:
        da = q - k1 * a
        db = k1 * a - k2 * b
        a, b = a + da * dt, b + db * dt
        t += dt
    return round(a, 2), round(b, 2)


print(simular(3, 0.3, 0.2, 40))

Llegan a ≈ (10,0, 15,0): A* y B* con B retardada. Todo junto, todo con el mismo dt.

09 · Síntesis

Ideas para recordar

  • Sistema = vector dx/dt = f(x, t) con tasas que cruzan estados; se integra junto.
  • Cascada (A → B), ciclo (A ⇄ B) y conservación (suma de tasas cero) son las formas típicas.
  • El equilibrio anula todas las tasas a la vez: A* = q/k₁, B* = q/k₂.
  • En Python: f devuelve dict de derivadas; el paso calcula todo y después actualiza todo.
  • B arranca plana y sigue a A con retardo: la firma visual de la cascada.

En el próximo tema fijaremos los arranques: las condiciones iniciales que eligen la curva.