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á:
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.
02 · Arquitectura por responsabilidades
Cada componente debe responder una pregunta concreta
| Componente | Responsabilidad | No debería decidir |
|---|---|---|
| Modelo | Calcular F(t,Y;p). | El paso o el método numérico. |
| Integrador | Avanzar un estado durante h. | Cuándo termina toda la simulación. |
| Motor | Recorrer el intervalo, validar y registrar. | La física particular del modelo. |
| Diagnóstico | Medir error, invariantes y costo. | Modificar la trayectoria. |
| Vista | Representar 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á:
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
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.
| Método | Evaluaciones por paso | Orden global | Uso didáctico |
|---|---|---|---|
| Euler | 1 | 1 | Referencia simple y detección visible de error. |
| Punto medio | 2 | 2 | Equilibrio entre costo y precisión. |
| RK4 | 4 | 4 | Referencia 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
- Validar configuración.
Comprobar tiempos, paso, dimensión, parámetros y funciones.
- Copiar el estado inicial.
Evitar que el motor modifique datos pertenecientes al llamador.
- Registrar el nodo inicial.
Una trayectoria de
Npasos contieneN+1muestras. - Elegir el paso real.
Acortar el último paso para llegar exactamente a
tf. - Avanzar y comprobar.
Rechazar dimensiones incorrectas,
NaNo infinitos. - 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
| Control | Condición | Respuesta |
|---|---|---|
| Intervalo | tf≥t₀ | Rechazar una dirección no implementada. |
| Paso | Finito y positivo. | Evitar bucles infinitos. |
| Dimensión | Derivada y estado compatibles. | Indicar el modelo responsable. |
| Finitud | Todos los componentes son finitos. | Detener antes de propagar NaN. |
| Dominio | Restricciones físicas o matemáticas. | Advertir, detener o reducir el paso. |
| Evento | Cambio 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:
| Modelo | Propiedad | Diagnóstico |
|---|---|---|
| Crecimiento logístico | 0<P≤K si parte en ese intervalo. | Positividad, cota y comparación exacta. |
| Oscilador ideal | Energía constante. | Deriva relativa de (v²+ω²x²)/2. |
| SIR | S+I+R constante. | Error de conservación de población. |
| Cualquier modelo | Convergencia 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.
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.
Banco de pruebas dinámico
P′=0,80P(1−P/10) · P(0)=1
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
- En el modelo logístico, compará el error de Euler, punto medio y RK4 con el mismo
h. - En el oscilador, aumentá el tiempo final. ¿Cómo evoluciona la deriva de energía de Euler?
- Reducí
h. ¿Cómo cambia la deriva y cuánto aumenta el número de evaluaciones? - ¿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.