Proyecto integrador · Tema 36

Simulador de sistemas dinámicos

Integrar modelos, métodos numéricos, diagnósticos y gráficos en una herramienta extensible, verificable y segura.

01 · Objetivo del proyecto

Construir una herramienta, no un programa para una sola ecuación

Un simulador útil debe resolver distintos modelos con distintos integradores sin duplicar el bucle temporal. El proyecto recibirá:

Y′=F(t,Y;p),    Y(t₀)=Y₀

junto con un intervalo, un paso y un método. Devolverá una trayectoria formada por muestras independientes, más información para evaluar costo, precisión y comportamiento.

EntradaModelo y configuración ProcesoIntegración y controles SalidaTrayectoria y diagnósticos

02 · Arquitectura por responsabilidades

Cada componente debe responder una pregunta concreta

Componentes del simulador.
ComponenteResponsabilidadNo debería decidir
ModeloCalcular F(t,Y;p).El paso o el método numérico.
IntegradorAvanzar un estado durante h.Cuándo termina toda la simulación.
MotorRecorrer el intervalo, validar y registrar.La física particular del modelo.
DiagnósticoMedir error, invariantes y costo.Modificar la trayectoria.
VistaRepresentar resultados y controles.Recalcular la dinámica.

La separación permite probar cada pieza de forma aislada. También evita que un cambio de colores, por ejemplo, altere accidentalmente la matemática.

03 · Contrato del modelo

Una función pura transforma tiempo y estado en una derivada

Usaremos estados vectoriales incluso para ecuaciones escalares. El contrato básico será:

modelo(t, estado, parámetros) → derivada

La salida debe tener la misma dimensión que el estado y contener números finitos. El modelo no modifica sus argumentos ni conoce el integrador.

const modelos = {
  logistico: (t, [p], { r, K }) => [r * p * (1 - p / K)],
  oscilador: (t, [x, v], { omega }) => [v, -(omega ** 2) * x],
  sir: (t, [S, I, R], { beta, gamma }) => [
    -beta * S * I,
    beta * S * I - gamma * I,
    gamma * I
  ]
};

console.log(modelos.oscilador(0, [1, 0], { omega: 1 }));
// [0, -1]

04 · Contrato del integrador

Todos los métodos comparten la misma interfaz

paso(modelo,t,Y,h,parámetros) → Ysiguiente

Euler, punto medio y RK4 pueden intercambiarse si respetan ese contrato. Cada uno crea un vector nuevo y evalúa el modelo la cantidad de veces esperada.

Integradores disponibles en el proyecto.
MétodoEvaluaciones por pasoOrden globalUso didáctico
Euler11Referencia simple y detección visible de error.
Punto medio22Equilibrio entre costo y precisión.
RK444Referencia precisa para problemas no rígidos.

El motor no contiene condicionales del tipo «si el método es RK4». Solo invoca la función seleccionada.

05 · Ciclo de simulación

Validar, avanzar, registrar y detener de manera predecible

  1. Validar configuración.

    Comprobar tiempos, paso, dimensión, parámetros y funciones.

  2. Copiar el estado inicial.

    Evitar que el motor modifique datos pertenecientes al llamador.

  3. Registrar el nodo inicial.

    Una trayectoria de N pasos contiene N+1 muestras.

  4. Elegir el paso real.

    Acortar el último paso para llegar exactamente a tf.

  5. Avanzar y comprobar.

    Rechazar dimensiones incorrectas, NaN o infinitos.

  6. Detener.

    Finalizar por tiempo, evento, solicitud externa o límite de pasos.

El límite de iteraciones debe calcularse y también imponerse explícitamente. Protege frente a pasos inválidos y errores de redondeo en la condición de parada.

06 · Estructura de resultados

Una trayectoria debe ser fácil de analizar y difícil de corromper

Una salida práctica separa muestras y metadatos:

const resultado = {
  puntos: [
    { t: 0, estado: [1, 0] },
    { t: 0.1, estado: [0.995, -0.0998] }
  ],
  pasos: 1,
  evaluaciones: 4,
  motivo: "tiempo-final",
  metodo: "rk4"
};

Cada muestra debe contener una copia independiente del estado. Si se guarda repetidamente la misma referencia a un arreglo mutable, todos los nodos pueden terminar mostrando el último valor.

Incorrecto

estado compartido

Las muestras cambian cuando cambia el arreglo original.

Correcto

[...estado]

Cada nodo conserva el valor aceptado en ese instante.

07 · Validación y eventos

Una simulación debe fallar con información útil

Controles mínimos del motor.
ControlCondiciónRespuesta
Intervalotf≥t₀Rechazar una dirección no implementada.
PasoFinito y positivo.Evitar bucles infinitos.
DimensiónDerivada y estado compatibles.Indicar el modelo responsable.
FinitudTodos los componentes son finitos.Detener antes de propagar NaN.
DominioRestricciones físicas o matemáticas.Advertir, detener o reducir el paso.
EventoCambio de signo de una función g(t,Y).Localizar el cruce si se requiere precisión.

08 · Evidencia numérica

El gráfico ayuda a interpretar; los diagnósticos ayudan a confiar

Una curva visualmente suave puede ser incorrecta. El simulador debe producir medidas vinculadas con el modelo:

Diagnósticos para distintos sistemas.
ModeloPropiedadDiagnóstico
Crecimiento logístico0<P≤K si parte en ese intervalo.Positividad, cota y comparación exacta.
Oscilador idealEnergía constante.Deriva relativa de (v²+ω²x²)/2.
SIRS+I+R constante.Error de conservación de población.
Cualquier modeloConvergencia numérica.Comparación entre h, h/2 y una referencia.

También deben registrarse pasos, evaluaciones del modelo, tiempo simulado y motivo de finalización. Son parte del resultado, no detalles de depuración.

09 · Del resultado a la interfaz

La vista consume trayectorias sin conocer cómo fueron calculadas

La visualización recibe nombres de variables, unidades, colores y puntos. Para comparar ejecuciones debe mantener escalas comprensibles e identificar claramente método y paso.

ControlesCrean configuración MotorDevuelve resultado VistaDibuja e informa

Conviene recalcular desde el estado inicial ante cada cambio de controles. Reutilizar parcialmente una trayectoria anterior puede mezclar configuraciones incompatibles.

10 · Simulador interactivo

Laboratorio: cambiar modelo, integrador y resolución

El crecimiento logístico posee solución exacta para medir error. El oscilador ideal permite observar la conservación de energía. Ambos usan el mismo motor y los mismos integradores vectoriales.

PROYECTO 36

Banco de pruebas dinámico

P′=0,80P(1−P/10) · P(0)=1

Los resultados y diagnósticos aparecen debajo.
PasosN = 150
Evaluaciones600
Estado finalP = 10,0000
Diagnósticoerror = 0,0000

Simulación completada con RK4 y 150 pasos.

Para el modelo logístico se muestra la solución numérica y la exacta. Para el oscilador se muestran posición y velocidad a lo largo del tiempo.

Preguntas para explorar

  1. En el modelo logístico, compará el error de Euler, punto medio y RK4 con el mismo h.
  2. En el oscilador, aumentá el tiempo final. ¿Cómo evoluciona la deriva de energía de Euler?
  3. Reducí h. ¿Cómo cambia la deriva y cuánto aumenta el número de evaluaciones?
  4. ¿Qué combinación elegirías si el costo de evaluar el modelo fuera muy alto?

11 · Implementación del núcleo

Un motor compacto con métodos intercambiables

Operaciones vectoriales e integradores

const sumar = (a, b, factor = 1) =>
  a.map((valor, i) => valor + factor * b[i]);

const metodos = {
  euler: (f, t, y, h, p) => sumar(y, f(t, y, p), h),

  puntoMedio: (f, t, y, h, p) => {
    const k1 = f(t, y, p);
    const k2 = f(t + h / 2, sumar(y, k1, h / 2), p);
    return sumar(y, k2, h);
  },

  rk4: (f, t, y, h, p) => {
    const k1 = f(t, y, p);
    const k2 = f(t + h / 2, sumar(y, k1, h / 2), p);
    const k3 = f(t + h / 2, sumar(y, k2, h / 2), p);
    const k4 = f(t + h, sumar(y, k3, h), p);
    return y.map((valor, i) => valor + h * (
      k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]
    ) / 6);
  }
};

Motor con validaciones y metadatos

function simular({ modelo, metodo, parametros = {}, t0, tf, estado0, h }) {
  if (![t0, tf, h, ...estado0].every(Number.isFinite)) {
    throw new TypeError("La configuración debe contener números finitos");
  }
  if (tf < t0 || h <= 0 || estado0.length === 0) {
    throw new RangeError("Intervalo, paso o estado inválido");
  }

  let t = t0;
  let estado = [...estado0];
  const puntos = [{ t, estado: [...estado] }];
  const maxPasos = Math.ceil((tf - t0) / h) + 1;

  for (let n = 0; n < maxPasos && t < tf; n++) {
    const hn = Math.min(h, tf - t);
    const siguiente = metodo(modelo, t, estado, hn, parametros);
    if (siguiente.length !== estado.length || !siguiente.every(Number.isFinite)) {
      throw new RangeError(`Estado inválido en el paso ${n + 1}`);
    }
    t = Math.min(tf, t + hn);
    estado = [...siguiente];
    puntos.push({ t, estado: [...estado] });
  }
  return { puntos, pasos: puntos.length - 1, motivo: "tiempo-final" };
}

Configurar y ejecutar un escenario

const sumar = (a, b, factor) =>
  a.map((valor, i) => valor + factor * b[i]);

function pasoRK4(f, t, y, h, parametros) {
  const k1 = f(t, y, parametros);
  const k2 = f(t + h / 2, sumar(y, k1, h / 2), parametros);
  const k3 = f(t + h / 2, sumar(y, k2, h / 2), parametros);
  const k4 = f(t + h, sumar(y, k3, h), parametros);
  return y.map((valor, i) => valor + h * (
    k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]
  ) / 6);
}

const logistico = (t, [P], { r, K }) => [r * P * (1 - P / K)];
const parametros = { r: 0.8, K: 10 };
let t = 0;
let estado = [1];
let pasos = 0;

while (t < 15) {
  const h = Math.min(0.1, 15 - t);
  estado = pasoRK4(logistico, t, estado, h, parametros);
  t = Math.min(15, t + h);
  pasos++;
}

console.log({ pasos, estadoFinal: estado });

12 · Pruebas y fallos frecuentes

Probar propiedades antes de confiar en imágenes

«Una curva suave demuestra que el simulador funciona»

No. Compará con soluciones exactas, refinamientos, invariantes y casos de derivada constante.

«Guardar estado directamente es más eficiente»

Si el arreglo se reutiliza, la historia puede quedar sobrescrita. Guardá copias o usá estructuras inmutables.

«El motor puede corregir estados físicamente inválidos»

Recortar negativos oculta errores y cambia el método. Es preferible informar, reducir el paso o usar un método apropiado.

«El método más preciso siempre es el mejor»

También importan costo, estabilidad, rigidez, eventos, tolerancia y propiedades que deben preservarse.

«Una excepción es suficiente diagnóstico»

Incluí paso, tiempo, estado y componente problemática para reproducir el fallo.

«Validar un modelo valida todos los modelos»

El motor puede tener pruebas generales, pero cada modelo necesita casos, unidades e invariantes propios.

13 · Extensiones del proyecto

Ejercicios de integración

Ejercicio 1: agregar Heun

Implementá el método de Heun respetando el contrato vectorial.

Ver solución orientativa

Calculá k₁, construí el predictor Y*=Y+hk₁, evaluá k₂ en (t+h,Y*) y devolvé Y+h(k₁+k₂)/2 sin mutar arreglos.

Ejercicio 2: incorporar SIR

Agregá el modelo SIR y un diagnóstico para S+I+R.

Ver solución orientativa

Usá estado inicial normalizado cuya suma sea 1. En cada nodo medí |S+I+R−1| y reportá el máximo.

Ejercicio 3: refinamiento automático

Ejecutá con h y h/2 y compará los estados finales.

Ver solución orientativa

Calculá una norma de la diferencia. Repetí el refinamiento hasta cumplir una tolerancia o alcanzar límites de paso y costo.

Ejercicio 4: evento de umbral

Detectá cuándo la población logística supera el 90 % de K.

Ver solución orientativa

Definí g(t,[P])=P−0,9K y buscá un cambio de signo entre nodos. Interpolá o subdividí el paso para localizar mejor el cruce.

Ejercicio 5: exportación

Convertí una trayectoria a CSV sin perder nombres ni unidades.

Ver solución orientativa

Construí una cabecera como tiempo_s,posicion_m,velocidad_m_s y una fila por muestra. Escapá correctamente separadores y decimales.

Ejercicio 6: batería de regresión

Diseñá tres pruebas que detecten cambios incorrectos en el motor.

Ver solución razonada

Ejemplos: exactitud para Y′=constante, extremo exacto con intervalo no divisible y copias independientes de los estados. Añadí una prueba de orden observado para cada integrador.

14 · Cierre del recorrido

Del modelo matemático a una simulación defendible

  • Modelo, integrador, motor, diagnóstico y vista tienen responsabilidades diferentes.
  • Un contrato vectorial permite reutilizar métodos en ecuaciones y sistemas.
  • Los estados auxiliares y las muestras deben evitar mutaciones compartidas.
  • El motor valida entradas, acorta el último paso e impone límites de ejecución.
  • Los metadatos de costo y finalización forman parte del resultado.
  • Los gráficos deben acompañarse con diagnósticos numéricos accesibles.
  • Soluciones exactas, refinamiento e invariantes aportan evidencia complementaria.
  • No existe un método universal: precisión, estabilidad y costo deben equilibrarse.
  • Una buena arquitectura permite extender el simulador sin romper lo ya validado.

El objetivo final no es producir una curva, sino construir un argumento verificable de que esa curva representa razonablemente el modelo, el método y la configuración elegidos.