Siru en Simusol · Documentación · Manual

PLAN

siru: integración temporal con Calcula

Objetivo y alcance

siru será un programa en Perl que integrará sistemas de ecuaciones diferenciales usando calcula 6.0 como resolvedor de cada evaluación. El primer caso será circuito-rlc, ya expresado a mano en ~/svn/calcula/calcula-6.0/sistemas/circuito-rlc.din y registrado por su archivo .sis.

La conversión y la integración son dos procesos independientes. El camino directo ya implementado es .d → slex/d2datdinc → .din ampliado → bin/siru: el .din incluye como comentario los parámetros, estados iniciales y controles de integración, y siru no necesita .dat al correr. El camino anterior por .dat → bin/dat2din sigue disponible. Ninguno incorpora los módulos antiguos de Siru, Circuito, SWIG o el Calcula en siruviejo/varios.

Estado del conversor: ya genera ecuaciones de componentes y Kirchhoff para ramas RB, LB, CB y EB con valores constantes; construye las etapas desde los coeficientes RK del .dat. Las tablas de texto de GLOBAL.tablas se conservan dentro del .din. Secciones y controles todavía no traducidos se dejan como # PENDIENTE y no se emite configuración ejecutable. Otros tipos de rama o valores no constantes todavía requieren ampliar el conversor.

Reparto de responsabilidades

Componente Responsabilidad
Sistema .sis/.din de Calcula Definir variables, parámetros, ecuaciones, dominios y derivadas.
Ejecutable calcula Cargar el sistema una vez, resolver cada estado y ofrecer el protocolo máquina preciso; GSL y ExprTk quedan dentro de Calcula.
bin/dat2din, en Perl Leer el .dat, generar las ecuaciones algebraicas y las etapas RK en .din, y señalar lo que falta traducir.
bin/siru, en Perl Mantener abierto Calcula, pasar estado y paso, recoger el estado siguiente, controlar errores y escribir la trayectoria.
tabular2 Intervenir únicamente si una ecuación .din llama a tabla(); el conversor puede incorporar tablas de texto al .din, pero siru no interpola directamente.

La interfaz de cada paso será evaluar(t, estado, parámetros, dt) → estado_siguiente, observables. Para circuito-rlc-ED0.din, el estado actual es (il2, il23, vc3), el siguiente (p_il2, p_il23, p_vc3) y los parámetros fijos son (e1, r12, l2, l23, c3, r3). Este sistema no usa el tiempo explícitamente; en uno que sí lo haga, t deberá figurar entre los datos de su .din.

Los archivos ampliados conservarán el nombre base y terminarán en -EDNRO.din, con el número histórico de Runge–Kutta de Simul (Euler explícito = 0). Cada archivo se carga una sola vez; siru no cambia las ecuaciones en cada paso.

Hito 1: modo máquina de Calcula y comunicación persistente

La adaptación de Calcula es obligatoria antes de escribir el integrador. El modo interactivo existente conserva su comportamiento; siru usará un modo nuevo, por ejemplo --machine, sin readline, prompt, eco ni mensajes informativos en stdout.

Protocolo de texto propuesto (versión 1)

  1. Calcula carga un único sistema al arrancar. Cuando ya acepta peticiones, escribe READY 1 y vacía stdout; si la carga falla, escribe el diagnóstico en stderr y termina con estado distinto de cero.
  2. Cada petición ocupa una línea ASCII con campos separados por espacios: EVAL id cantidad_datos nombre=valor ... cantidad_salidas nombre .... id es un entero positivo. Los nombres siguen la sintaxis de identificadores de Calcula y no contienen espacios; los números decimales, con punto y exponente opcional, deben ser finitos. Los conteos hacen detectables líneas truncadas o campos sobrantes. No se aceptan comandos interactivos ni expresiones.
  3. Cada petición recibe exactamente una línea: OK id cantidad_salidas nombre=valor ... o ERR id clase codigo. Los campos de ERR son palabras estables sin espacios; el detalle para diagnóstico va a stderr con el mismo id. stdout contiene solo el protocolo, y Calcula lo vacía tras cada respuesta. siru no envía otra petición hasta recibir la respuesta anterior.
  4. Antes de escribir en los arreglos internos o resolver, validar la longitud y los conteos, nombres conocidos y no duplicados, correspondencia con todos los datos exigidos y números finitos. Toda falla de sintaxis, dominio, cantidad de datos o resolución produce ERR, no solo texto para personas. Documentar si Calcula continúa tras cada clase de error. Reutilizar intentar_punto() para el cálculo y las restricciones, sin duplicar reglas del sistema.
  5. Los valores de OK salen directamente del vector numérico calculado, con locale numérico C y formato %.17g; no pasan por para_imprimir() ni por otro filtro que fuerce a cero resultados pequeños. El filtro actual compara magnitudes de variables con unidades distintas, y imp= imprime solo diez cifras. Diecisiete cifras preservan el transporte de un double, pero no garantizan la exactitud del resolvedor: tolerancias y escalas se verificarán por separado.

Ejemplo con parámetros unitarios y estado inicial nulo:

READY 1
EVAL 1 9 e1=1 r12=1 l2=1 l23=1 c3=1 r3=1 il2=0 il23=0 vc3=0 3 dil2dt dil23dt dvc3dt
OK 1 3 dil2dt=1 dil23dt=1 dvc3dt=0

Errores que siru puede interpretar

Clase Códigos iniciales propuestos Tratamiento en siru v1
INPUT SYNTAX, COUNT, UNKNOWN_NAME, DUPLICATE_NAME, NONFINITE Detener la simulación: es una petición o configuración inválida.
DOMAIN OUT_OF_RANGE, CONSTRAINT Detener e informar el estado y la etapa que fallaron.
SOLVER NO_CONVERGENCE, SINGULAR, FAILURE Detener e informar el estado, la etapa y el diagnóstico de Calcula.
INTERNAL MISSING_SYMBOL, FAILURE Detener; es un fallo del ejecutable o del sistema cargado.

Estos nombres son un contrato a fijar al implementar Calcula: asignar un código específico solo si la causa puede distinguirse de forma fiable. Si GSL no permite separar dos fallas, usar un código general como SOLVER FAILURE y conservar el detalle en stderr; no inventar una causa. El fin inesperado del proceso y el timeout son errores del adaptador Perl, no respuestas ERR. siru v1 no reintentará automáticamente con otro paso; esa política podrá agregarse tras medir qué fallas son recuperables.

Pasos de implementación y comprobación:

  1. Añadir el modo máquina y documentar su versión y sus códigos de error. Revisar límites de los arreglos de entrada y vida de buffers durante sesiones largas.
  2. Abrir calcula una sola vez desde Perl, sin pasar por un shell, con --machine y el sistema elegido mediante -s ID o -m modulodinamico --dinamico=ARCHIVO. Mantener separados stdin, stdout y stderr, y drenar este último sin bloquear.
  3. Leer READY 1; enviar una petición completa y leer su respuesta con timeout. Comprobar id, conteos, nombres pedidos y valores finitos. Detectar EOF prematuro, respuesta incompleta, ERR o timeout. Cerrar descriptores y recoger el proceso también ante errores; evitar PTY, expect y dependencias adicionales.
  4. Probar dos consultas que reciben respuesta antes de cerrar stdin. La prueba anterior devolvió 1,1,0 y 0,0,0 en un mismo proceso, pero cerraba la entrada al final y no demuestra que cada respuesta llegue por un pipe vivo.

Criterio de cierre: dos consultas sucesivas reciben respuestas correctas con Calcula aún abierto y un único arranque; las clases de error se distinguen de un resultado numérico; una salida pequeña no se cambia artificialmente por cero.

Hito 2: integrador mínimo

  1. Crear un ejecutable bin/siru y módulos propios bajo lib/Siru/: un adaptador de Calcula y un integrador. Usar módulos estándar de Perl para argumentos, procesos y espera de datos.
  2. Definir por argumentos o un pequeño archivo de configuración el ejecutable y sistema de Calcula, parámetros fijos, pares explícitos estado → derivada con sus valores iniciales, tiempo inicial y final, tamaño de paso y archivo de salida. Rechazar nombres repetidos o conflictos entre parámetros, estados y tiempo; incluir t solo si el sistema lo declara como dato.
  3. Para Euler explícito, añadir al .din las variables del estado siguiente y las ecuaciones p_y = y + dt·f(t,y). En cada paso, consultar a Calcula los p_y y usarlos como nuevos datos. Ajustar el último paso para terminar exactamente en el tiempo final; rechazar tiempos o pasos no finitos, tamaños de paso no positivos, t+h == t, resultados no finitos y errores del resolvedor.
  4. Escribir una tabla reproducible en texto/CSV con cabecera, tiempo y variables de estado. Los observables algebraicos podrán añadirse después, consultando Calcula sin cambiar la lógica de integración.

Criterio de cierre: circuito-rlc se integra desde (0,0,0) con parámetros unitarios; cada fila contiene un tiempo y un estado válidos; la última fila está en el tiempo solicitado.

Hito 3: verificación numérica y de proceso

  1. Comprobar las derivadas iniciales conocidas del circuito y al menos una segunda consulta distinta al mismo proceso.
  2. Comparar Euler con las ecuaciones independientes del circuito: con parámetros unitarios y estado inicial nulo, tras un paso de tamaño h se obtiene (h,h,0) y tras dos pasos (2h-2h²,2h-2h²,h²). Verificar convergencia al reducir h. Comparar con Simul antiguo solo si se reproduce su secuencia de pasos.
  3. Probar peticiones inválidas de distintas clases, una consulta inválida intercalada, respuesta fragmentada, stderr abundante, salida pequeña no truncada, EOF y timeout; verificar que ningún fallo publique una trayectoria aparentemente completa.
  4. Verificar que la cantidad de arranques de Calcula es uno por simulación, no uno por etapa ni por paso.

Criterio de cierre: los resultados numéricos coinciden dentro de la precisión acordada y las fallas se informan con un estado de salida distinto de cero.

Hito 4: métodos posteriores

Los generadores ya construyen etapas de métodos explícitos e implícitos desde la tabla de Butcher. El control adaptativo es optativo: con bc el .din agrega q_estado como segunda estimación; sin bc, siru compara un paso completo con dos medios. El integrador acepta o reintenta según tolerancias y límites configurados; conserva un solo proceso de Calcula y no publica pasos rechazados. Quedan por verificar sistemáticamente métodos dependientes del tiempo, discontinuidades y la correspondencia de tolerancias y resultados con el Simul antiguo. Véase README.md, «Paso adaptativo».

Estructura prevista

siru/
  PLAN.md
  README.md
  bin/siru
  lib/Siru/Calcula.pm
  lib/Siru/Integrador.pm
  ejemplos/circuito-rlc.*
  tests/

Se incorporarán los archivos solo al llegar a cada hito. Los cambios permanecerán locales hasta que se autorice expresamente un commit de SVN.