Visión general
Un Nodo de modelo (Model Node) es un componente que incrusta otro modelo de simulación dentro del actual. En lugar de duplicar componentes entre muchos modelos, defines un submodelo una vez — una celda de producción, una línea de ensamblaje, un departamento — y lo incrustas donde lo necesites. Los cambios al submodelo se propagan a todas partes donde se usa.
Esta es la arquitectura para instalaciones complejas: modela una sola celda rigurosamente, compón un departamento a partir de copias de esa celda, compón una instalación a partir de copias del departamento. Sin modelado jerárquico, una operación compleja significa miles de componentes en un solo lienzo. Con él, obtienes una descomposición limpia que refleja cómo está realmente organizada tu operación.
Cuándo usar Nodos de modelo
- Estructura física repetida — tu instalación tiene cinco celdas de producción idénticas. Modela una, luego incrústala cinco veces vía Nodos de modelo.
- Plantillas (Template) reutilizables — subprocesos estándar (inspección de QC, empaque, kitting) que aparecen en muchos modelos. Define una vez, reutiliza entre modelos e incluso entre fábricas vía export/import.
- Escala — una vez que un modelo supera ~50-100 componentes, la descomposición jerárquica se convierte en la única forma de mantenerlo navegable.
- División del equipo — una persona es dueña del submodelo a nivel de línea, otra es dueña de la composición a nivel de instalación. Los Nodos de modelo les permiten trabajar en paralelo.
Cómo se añade un Nodo de modelo
Un Nodo de modelo es una referencia a un modelo separado que ya existe en la misma fábrica. Para añadir uno al modelo actual:
- Abre el panel izquierdo del Modelador (Modeler) y permanece en la pestaña Library.
- Desplázate a la subsección MODELS en la parte inferior del panel.
- Haz clic en + Import Model para abrir un selector que lista los otros modelos de la fábrica. Seleccionar uno añade el slug del modelo a la lista
imported_models[] del padre y lo expone como una tarjeta arrastrable en la subsección MODELS.
- Arrastra la tarjeta al lienzo. Aparece un Nodo de modelo, haciendo referencia a ese submodelo.
El padre debe listar el submodelo en imported_models[] antes de que un Nodo de modelo que lo referencie pueda validar. Esa lista es la puerta — sin ella, el nested_model_id del ModelNode no se resuelve y el modelo falla la validación. + Import Model gestiona esta lista automáticamente cuando lo usas, pero si autorizas el JSON a mano debes añadir el slug tú mismo.
Campos del esquema
Un ModelNode es un objeto de referencia delgado: la mayor parte de lo que hace vive en el submodelo. Los campos obligatorios son escasos; todo lo demás es opcional y por defecto está vacío.
| Campo | Obligatorio | Propósito |
|---|
id | sí | Id del componente (usado en rutas calificadas, element_id del calendario, columnas de dataset) |
nested_model_id | sí | Slug del submodelo. Debe aparecer en el imported_models[] del padre. |
name | no | Nombre para mostrar (por defecto, el id) |
description | no | Texto libre |
component_type | no | Constante "model_node" (auto-establecido por defecto) |
input_mappings | no | Lista de pares {external_connection_id, internal_component_id} — conecta las conexiones del padre a los componentes del submodelo |
output_mappings | no | Misma forma — conecta los componentes del submodelo a las conexiones del padre |
resource_mappings | no | Mapa de alias por recurso; los recursos no mapeados permanecen locales |
topic_mappings | no | Mapa de alias por tema; puentea padre ↔ submodelo bidireccionalmente |
state_variable_mappings | no | Mapa de alias por variable de estado; puentea lectura/escritura bidireccionalmente |
event_listeners | no | Oyentes basados en tema en el propio ModelNode |
event_hooks | no | El esquema acepta el campo, pero no hay eventos canónicos de ciclo de vida definidos para ModelNodes — ver abajo |
additionalProperties: false. No se permiten otros campos.
Conexiones mapeadas
input_mappings y output_mappings son la capa de cableado: cada entrada empareja un external_connection_id (una conexión en el lienzo del padre) con un internal_component_id (un componente dentro del submodelo). Cuando el flujo del padre alcanza un mapeo de entrada, las entidades fluyen hacia el componente del submodelo nombrado; cuando se dispara un mapeo de salida, las entidades cruzan de vuelta hacia fuera.
Puedes cambiar la estructura interna del submodelo sin romper al padre — siempre que los mapeos aún se resuelvan a componentes válidos dentro, el modelo padre sigue funcionando.
Recursos compartidos
Un Recurso (Resource) puede compartirse entre un padre y un submodelo introduciendo una entrada explícita resource_mappings que aliase un id de recurso del padre al nombre esperado del submodelo. Los recursos no mapeados permanecen locales al submodelo — si no lo mapeas, el submodelo usa su propio recurso de ese nombre.
Usa recursos compartidos para operadores o equipos que físicamente sirven a múltiples celdas.
Temas puenteados
Los Temas (Topics) pueden puentearse a través del límite padre/hijo vía topic_mappings. El puenteo es siempre bidireccional — no hay configuración por dirección, y el validador construye automáticamente la prevención de bucles en el grafo de temas. Un evento emitido dentro del submodelo en un tema puenteado se recibe en el padre, y viceversa.
Variables de estado aliasadas
Las Variables de estado pueden aliasarse: una variable de estado declarada a nivel del padre puede referenciarse desde dentro del submodelo bajo un nombre diferente vía state_variable_mappings. El aliasing es lectura/escritura bidireccional — ambos lados ven y escriben el mismo valor subyacente, con el validador imponiendo tipos coincidentes en ambos extremos.
Esto mantiene los submodelos desacoplados (hacen referencia a sus propios nombres internos) mientras aún les permite participar en el estado a nivel del padre.
Las constantes y tablas de búsqueda no necesitan mapeo
Las Constantes y tablas de búsqueda están limitadas a la fábrica. Tanto el padre como el submodelo las referencian por slug independientemente — no hay capa de aliasing para estas en un ModelNode. Cada modelo tiene su propia lista de opt-in (constants[] / lookup_tables[] en metadata.json); ambos pueden optar por participar en la misma constante a nivel de fábrica sin coordinación.
Rutas calificadas de componentes
Los componentes dentro de un Nodo de modelo se direccionan mediante una ruta calificada usando :: como separador. Un componente con id lathe dentro de un ModelNode con id cell_a se referencia como cell_a::lathe en cualquier lugar fuera de su submodelo padre — la misma forma que verás en SQL de fuente de la vista del Chart, element_id de calendarios y columnas de dataset.
Todos los segmentos son slugs de componente, no nombres para mostrar. El separador :: está reservado: ningún id de componente individual puede contenerlo.
Esto se aplica en tres lugares:
- Consultas de fuente de la vista del Chart. Los identificadores de componentes en
entity_lifecycle, process_activity y otros dataframes usan la forma calificada. Filtrar por nombre para mostrar como aparece en el Modelador — digamos, component = 'Lathe' — omite cada instancia dentro de un Nodo de modelo. Usa component = 'cell_a::lathe', o coincide con LIKE.
- Liberaciones de material del calendario. Una liberación de material programada a una Fuente (Source) dentro de un submodelo debe nombrar la Fuente con su id calificado:
cell_a::raw_material_intake.
- Referencias cruzadas en funciones de consulta de componentes del DSL — pasa el id calificado cuando el componente que estás consultando vive en un submodelo.
Autorizar hooks y listeners dentro del submodelo usa ids de componente locales — el prefijo calificado solo se necesita al cruzar el límite padre-hijo. Los submodelos permanecen reutilizables; no necesitan saber qué nombre les dio su padre.
Para estructuras profundamente anidadas, las rutas se encadenan: plant_1::line_3::cell_2::lathe.
Soporte del Sistema de Eventos en ModelNode
Los ModelNodes pueden llevar Event Listeners (basados en tema) y funcionan completamente: escucha cualquier tema en el padre o puenteado al submodelo, y ejecuta assign / emit / etc. como cualquier otro listener. Útil para coordinación a nivel de ModelNode que no esté vinculada a un solo componente interno.
Los ModelNodes también aceptan un arreglo event_hooks[] en el esquema, pero no hay eventos canónicos de ciclo de vida definidos para ModelNodes — cualquier hook que autorices no tiene un valor de evento válido y fallará la validación. Cíñete a los listeners.
La validación se recurre a través de los límites
Cuando validas el modelo padre, la validación se recurre en cada modelo anidado referenciado por un ModelNode. Los errores dentro de un submodelo burbujean al padre con un prefijo de ruta — por ejemplo:
“Nested model ‘cell_a’ (used by model node ‘fab_cell’): Process ‘lathe’ has expression error in processing_time…”
Arregla el error en el archivo del submodelo; el padre se revalida automáticamente.
Referencia en vivo, no instantánea
Un ModelNode referencia su submodelo por slug. Cualquier cambio que hagas al archivo del submodelo se refleja inmediatamente en cada ModelNode que lo referencia — no hay anclaje de instantánea a nivel de ModelNode. Si necesitas congelar una revisión específica de un submodelo, captura una Instantánea (Snapshot) del padre (que incrusta el registro completo del modelo en ese momento).
Patrones comunes
Plantilla de celda. Un submodelo “celda de producción” se crea una vez con equipo canónico. El modelo de instalación lo instancia cinco veces vía Nodos de modelo, cada uno apuntando al mismo slug de submodelo.
Composición de departamento. Construye un modelo “fabricación” y un modelo “ensamblaje” por separado, luego compónlos en un modelo de instalación con conexiones entre sus salidas y entradas.
Detalle progresivo. Comienza con un modelo de instalación grueso — unos pocos Nodos de modelo, cada uno representando un departamento como una caja negra. A medida que necesitas más fidelidad, reemplaza la referencia de submodelo de un Nodo de modelo por una más detallada. El padre no cambia.
Consejos
- Trata los submodelos como bibliotecas. Una vez que un submodelo es estable, evita editarlo casualmente — los cambios se propagan a cada instancia.
- Nombra las entradas y salidas claramente. Los ids de mapeo coinciden por nombre; los nombres claros previenen errores de cableado.
- Mantén el nivel superior delgado. Un modelo de instalación bien organizado es principalmente Nodos de modelo con un poco de pegamento entre ellos. Si tu nivel superior tiene cientos de componentes directos, estás perdiendo el beneficio.
- Todos los segmentos de ruta son slugs. Cuando dudes sobre un id, verifica el esquema o las columnas del dataset — los nombres para mostrar con espacios no aparecen en las rutas
::.