Reading Time: 9 minutes

Cuando trabaja con simulaciones multifísicas, a menudo necesita acoplar dos o más solucionadores especializados para que intercambien datos durante el cálculo. Precice es una biblioteca de acoplamiento de código abierto maduro para simulaciones multifísicas particionadas, especialmente cuando se conectan solucionadores independientes como Fipy, OpenFoam o Calculix.

Pero Precise no siempre es una opción. Puede trabajar en un entorno en el que no es práctico instalar una biblioteca basada en C++ con enlaces de Python. Puede utilizar un solucionador comercial que no es compatible con Precice. O su problema multifísico puede ser lo suficientemente simple como para que un marco de acoplamiento completo se sienta excesivo.

Este artículo cubre alternativas prácticas, incluida la actualización secuencial dentro de Fipy, la división del operador, los métodos de extrapolación polinómica y las bibliotecas de acoplamiento de propósito general.

Comida clave

  • Precice es potente, pero no es la única opción para el acoplamiento multifísico. La alternativa correcta depende de la disponibilidad del solucionador, las preferencias de idioma, la preparación de HPC y la complejidad del problema.
  • El acoplamiento secuencial dentro de Fipy funciona bien cuando ambas ecuaciones viven en el mismo proceso de Python. Es simple, depurable y no requiere ninguna biblioteca de acoplamiento externo.
  • La división del operador desacopla la física resolviendo cada ecuación por separado. Es útil cuando diferentes procesos físicos operan en diferentes escalas de tiempo.
  • Las bibliotecas de acoplamiento de propósito general, como MUI y Moose MultiApps, ofrecen arquitecturas alternativas con diferentes compensaciones en complejidad, soporte de lenguaje y escalabilidad.
  • La orquestación basada en polinomios a través de herramientas como Rhapsopy es un enfoque de alto orden emergente que adapta los pasos de tiempo utilizando estimaciones de error de acoplamiento variable.

Acoplamiento particionado vs monolítico vs secuencial

Antes de comparar alternativas, ayuda a aclarar las principales estrategias de acoplamiento. El acoplamiento multifísico generalmente se divide en tres categorías.

Acoplamiento dividido

En el acoplamiento particionado, los solucionadores separados se comunican a través de una interfaz externa o una capa de middleware. Los solucionadores siguen siendo cajas negras independientes, y cada solucionador no necesita conocer la estructura interna del otro.

PRECICE es el ejemplo canónico. Las ventajas incluyen la reutilización del código, la flexibilidad y la capacidad de acoplar códigos comerciales o heredados. La compensación es la sobrecarga de comunicación y la necesidad de mapeo de malla, transferencia de datos y coordinación de acoplamiento.

Acoplamiento monolítico

En el acoplamiento monolítico, todas las físicas se resuelven juntas en un solo solucionador y, a menudo, comparten la misma matriz del sistema. Esto puede ser más eficiente para problemas estrechamente acoplados porque las no linealidades se manejan implícitamente.

La compensación es un alto esfuerzo de desarrollo. Toda la física debe implementarse dentro de un marco. Moose es un marco notable que admite flujos de trabajo de estilo monolítico y también ofrece patrones particionados a través de múltiples aplicaciones.

Acoplamiento secuencial

El acoplamiento secuencial funciona cuando toda la física se puede expresar dentro de un marco de resolución. En Fipy, por ejemplo, puede resolver ecuaciones acopladas una tras otra dentro del mismo proceso de Python.

Esto evita por completo el middleware externo. La compensación es que pierdes la capacidad de acoplar solucionadores independientes escritos en diferentes idiomas o mantenidos por diferentes organizaciones.

Acoplamiento secuencial con barrido fibroso

La alternativa más simple a Precice es resolver ecuaciones acopladas secuencialmente en el mismo proceso de Python. Fipy admite este patrón a través de los métodos sweep() y updateOld().

el patrón

La implementación estándar sigue un bucle anidado:

  1. Declare variables con hasOld=True para que puedan almacenar valores anteriores para términos transitorios.
  2. Llame a updateOld() una vez por paso de tiempo físico para bloquear el estado actual como el valor anterior.
  3. Llame a eq.sweep() repetidamente en un bucle interno hasta que convergen los residuos.
from fipy import CellVariable, Grid1D
from fipy import TransientTerm, DiffusionTerm, ImplicitSourceTerm

# 1. Setup mesh and variables
mesh = Grid1D(nx=50, Lx=1.0)

v0 = CellVariable(
    name="Variable 0",
    mesh=mesh,
    value=0.5,
    hasOld=True
)

v1 = CellVariable(
    name="Variable 1",
    mesh=mesh,
    value=0.5,
    hasOld=True
)

# 2. Define coupled equations
eq0 = (
    TransientTerm(var=v0)
    == DiffusionTerm(coeff=0.01, var=v0)
    - ImplicitSourceTerm(coeff=1.0, var=v1)
)

eq1 = (
    TransientTerm(var=v1)
    == DiffusionTerm(coeff=0.01, var=v1)
    - ImplicitSourceTerm(coeff=1.0, var=v0)
)

# 3. Simulation parameters
dt = 1e-3
steps = 100
tolerance = 1e-4

# 4. Time-stepping and sweeping loop
for step in range(steps):
    v0.updateOld()
    v1.updateOld()
    
    residual0 = residual1 = 1.0
    
    while (residual0 > tolerance) or (residual1 > tolerance):
        residual0 = eq0.sweep(var=v0, dt=dt)
        residual1 = eq1.sweep(var=v1, dt=dt)

Cuando esto funciona mejor

  • Ambas físicas se pueden expresar como PDES dentro de Fipy.
  • Necesita crear prototipos rápidos o depurar sin dependencias externas.
  • El sistema acoplado tiene una no linealidad moderada que converge con el barrido iterativo.
  • Está resolviendo modelos de campo de fase, sistemas de reacción de difusión o problemas de transporte acoplado.

cuando falla

  • Necesitas unir solucionadores escritos en C++, Fortran u otros idiomas.
  • La física está tan estrechamente acoplada que los barridos secuenciales requieren demasiadas iteraciones.
  • Sus solucionadores son ejecutables separados de diferentes organizaciones.
  • Necesita escalado paralelo de memoria distribuida en varios nodos de cálculo.

Enfoques de división de operador

La división del operador, también llamada paso fraccional, descompone un sistema acoplado en subpasos secuenciales. Cada subpaso resuelve un modelo de física. Esto es útil cuando los procesos físicos operan en diferentes escalas de tiempo.

Divisiones aditivas vs multiplicativas

La división aditiva descompone una ecuación en operadores separados y resuelve cada contribución de forma independiente. La división multiplicativa se aplica secuencialmente a los operadores con un orden definido, que importa cuando los operadores no viajan.

Para los flujos de trabajo multifísico, la división aditiva suele ser más fácil de aplicar. Cada modelo de física puede usar su propio solucionador optimizado, y la lógica de acoplamiento sigue siendo modular.

Bibliotecas de división de operadores de Python

Varias herramientas y ejemplos orientados a Python admiten los flujos de trabajo de división de operadores:

  • pythos es una biblioteca de Python para la división sistemática de ecuaciones diferenciales. Soporta patrones como la división extraña, métodos implícitos explícitos y pasos de tiempo adaptativos.
  • venice es un algoritmo de división de operadores de múltiples escalas que utiliza la división extraña con pasos de tiempo adaptativos. Es relevante cuando la física acoplada opera en diferentes escalas de tiempo.
  • Operator-Splitting-Methods Proporciona scripts de Python independientes para uso educativo. Estos scripts son útiles para el aprendizaje pero no están preparados para la producción.

Fipy con división del operador

También puede combinar Fipy con la división del operador manualmente. Un sistema de reacción de difusión se puede dividir en un paso de difusión y un paso de reacción:

# Separate the reaction step from diffusion
dt_diffusion = 0.001
dt_reaction = 0.1

# Solve diffusion with a small time step
eq_diff = TransientTerm(var=T) == DiffusionTerm(coeff=k, var=T)
eq_diff.sweep(dt=dt_diffusion)

# Solve reaction with a larger time step
eq_react = TransientTerm(var=T) == ReactionTerm(source, var=T)
eq_react.sweep(dt=dt_reaction)

El esquema básico es preciso de primer orden. Para una precisión de segundo orden, utilice la división de Strang: difusión de medio paso, reacción de paso completo, luego difusión de medio paso.

Bibliotecas de acoplamiento de uso general

Si necesita acoplamiento particionado pero no puede usar Precice, existen varias alternativas.

MUI: interfaz universal multiescala

mui es una biblioteca C++ solo encabezado para acoplar solucionadores heterogéneos. Trata los datos intercambiados como nubes de puntos y maneja automáticamente la interpolación espacial y temporal.

Las características clave incluyen:

  • Representación basada en puntos. MUI puede transferir datos sin requerir que un solucionador conozca la conectividad de malla de otro solucionador.
  • Interpolación de espacio y tiempo. Las herramientas de interpolación integradas ayudan a los solucionadores que operan en diferentes escalas a comunicarse.
  • Envío inteligente. Este algoritmo restringe la comunicación a los dominios superpuestos y reduce la comunicación innecesaria de todo a todos.
  • Apoyo del lenguaje. MUI está escrito en C++ y ofrece envoltorios para Python, Fortran y C.

MUI es útil cuando necesita acoplar solucionadores con discretizaciones fundamentalmente diferentes, como FEM, FVM, DEM o SPH.

Elija MUI sobre Precice cuando necesite una interfaz integrada liviana o cuando las diferencias de conectividad de malla hacen que la infraestructura de acoplamiento estándar sea demasiado pesada.

Quédese con Precice cuando necesite escalado paralelo maduro, aceleración cuasi-Newton para problemas fuertemente acoplados y un ecosistema adaptador más grande.

Moose MultiApps y sistemas de transferencia

Moose puede resolver sistemas completamente acoplados, pero sus sistemas MultiApps y Transfer también admiten enfoques particionados. Moose crea sub-aplicaciones que pasan los datos de campo de un lado a otro.

Moose admite varios estilos de acoplamiento:

  • Flujos de trabajo completamente acoplados donde toda la física se resuelve en una iteración no lineal.
  • Los flujos de trabajo de Picard o de estilo Newton estrechamente acoplados donde las sub-aplicaciones de física se iteran dentro de cada paso de tiempo.
  • Flujos de trabajo escalonados donde cada física avanza de forma independiente e intercambia datos en los límites definidos.

El alce está principalmente centrado en C++. Existen herramientas de Python, pero el ecosistema es menos nativo de Python que los flujos de trabajo creados alrededor de Fipy o Precice.

Acoplamiento basado en polinomios con rapsopía

Rhapsopy utiliza aproximaciones polinómicas de las variables de acoplamiento a lo largo del tiempo. En lugar de intercambiar un solo valor en cada paso de acoplamiento, cada subsistema se integra utilizando una aproximación polinomial de su entrada desde el otro subsistema.

Cómo funciona?

Durante un paso de acoplamiento, cada subsistema se integra con su propio solucionador mientras utiliza variables de entrada aproximadas polinómicamente. Al final del paso, se calculan nuevas variables de acoplamiento y se actualizan los polinomios.

Este enfoque puede ayudar con:

  1. Precisión. Las aproximaciones polinomiales de orden superior capturan los cambios temporales mejor que la extrapolación constante o lineal.
  2. Paso de tiempo adaptativo. Las estimaciones de error de aproximaciones polinómicas pueden guiar el tamaño del paso de tiempo de acoplamiento.
  3. acoplamiento explícito e implícito. Las versiones implícitas pueden mejorar la estabilidad pero requieren resolver un problema de punto fijo en cada paso.

Estado actual

Rhapsopy se considera mejor actualmente como una herramienta de demostración para problemas de pequeña escala. Es prometedor para los usuarios de Python que desean un acoplamiento adaptativo de alto orden, pero aún no es una solución HPC a gran escala madura.

Acoplamiento nativo COMSOL

Comsol Multiphysics utiliza un modelo diferente. En lugar de acoplar solucionadores externos, COMSOL define los acoplamientos multifísicos de forma nativa dentro del mismo entorno de software.

Los usuarios de COMSOL pueden:

  • Defina condiciones de interfaz como la continuidad del flujo de calor o el equilibrio de tensión.
  • Use estrategias de solución totalmente acopladas para problemas no lineales.
  • Cambie entre estrategias segregadas y completamente acopladas dependiendo de la complejidad del problema.

Esto es sencillo para los usuarios que ya están dentro de COMSOL. La compensación es el bloqueo del proveedor. El acoplamiento de los solucionadores externos generalmente requiere interfaces específicas de COMSOL, flujos de trabajo de LiveLink o puentes de script.

Resumen de comparación

Enfoque mejor para ventajas y ganas Contras dependencia externa
barrido secuencial ficticio PDES acoplados en el mismo proceso Simple, depurable, sin biblioteca de acoplamiento externo Limitado a iteraciones fibrosas y secuenciales Ninguno
Operación de división Diferentes escalas de tiempo Soludores modulares y reutilizables optimizados Errores de división y restricciones de estabilidad Biblioteca opcional como Pythos
casa Diferentes tipos de malla y discretizaciones Diseño solo de cabecera y amplio rango de simulación Escalado paralelo menos maduro que el precisión en algunos casos Biblioteca MU
Multiaplicaciones de alce Flujos de trabajo del ecosistema C++ y Moose Opciones monolíticas y particionadas Principalmente C++ y menos nativo de Python Marco de alce
rapsopía Acoplamiento adaptativo de alto orden Estimaciones de error y paso de tiempo dinámico Etapa temprana y solo a pequeña escala rapsopía
Acoplamiento nativo COMSOL Flujos de trabajo comerciales integrados Interfaz totalmente acoplada e intuitiva Bloqueo de vendedor Licencia comsol
precisión Acoplamiento maduro dividido Probado, documentado y apoyado por una comunidad Requiere enlaces C++/Python y la configuración del adaptador Biblioteca de precios

Guía práctica de decisiones

Utilice esta guía de decisión cuando no pueda o no quiera usar Precice.

  1. ¿Todas las físicas son expresables dentro de Fipy? Utilice barrido secuencial. Es el camino más simple y no requiere dependencias externas.
  2. ¿Su física opera en escalas de tiempo muy diferentes? intente dividir el operador. El desacoplamiento permite que cada física use su propio paso de tiempo.
  3. ¿Estás acoplando a los solucionadores con discretizaciones fundamentalmente diferentes? Considere MUI. Su representación basada en puntos puede manejar el acoplamiento de malla a malla y de malla a partícula.
  4. ¿Estás trabajando en C++ o en el ecosistema Moose? Las multiapps Moose ofrecen opciones monolíticas, estrechamente acopladas y escalonadas dentro de un marco.
  5. ¿Necesita un paso de tiempo adaptativo basado en errores de acoplamiento? Pruebe Rhapsopy para experimentos a pequeña escala o monitoree su desarrollo para obtener flujos de trabajo más grandes.
  6. ¿Está utilizando un solucionador comercial? Compruebe si tiene características multifísicas nativas o admite bibliotecas de acoplamiento externos.

Lo que recomendamos

Para los usuarios de Fipy que trabajan en Python, la recomendación depende de la complejidad del problema.

  • Acoplamiento simple, como difusión-reacción, campo de fase o transporte: Utilice el barrido secuencial con sweep(). Es sencillo y no requiere dependencias externas.
  • Complejidad moderada, como solucionadores externos poco acoplados o diferentes escalas de tiempo: utilice la división del operador con una biblioteca estructurada como Pythos.
  • Alta complejidad, como solucionadores estrechamente acoplados en diferentes idiomas: use Precice cuando sea posible. Las alternativas aún no ofrecen la misma madurez, escalabilidad paralela o aceleración de convergencia.

Si Precice no está disponible, la siguiente mejor opción depende de su entorno. Para la investigación académica sin acceso a HPC, el diseño solo de encabezado de MUI puede ser más fácil de integrar. Para las simulaciones de producción que requieren escalado paralelo, Precice sigue siendo la opción más fuerte si puede usarla.

Qué evitar

  • Intercambio de datos manual en bucles sin iteración o criterios de convergencia. Esto puede divergir o producir resultados inexactos.
  • Extrapolando variables de acoplamiento sin control de errores. Usar el valor de acoplamiento del paso de tiempo anterior como el valor actual solo es preciso de primer orden y puede ser inestable para problemas fuertemente acoplados.
  • Descuidar la baja relajación. Para el acoplamiento no lineal, incluya parámetros de baja relajación para reducir la divergencia del solucionador.
  • Asumiendo escalas de barrido secuenciales. El acoplamiento secuencial dentro de un proceso de Python no se escalará en los nodos de cálculo de memoria distribuida.

Guías relacionadas

¿Necesita ayuda para diseñar su flujo de trabajo multifísico?

Elegir el enfoque de acoplamiento adecuado depende de sus solucionadores, restricciones y complejidad del problema. MatForge ofrece servicios de consulta para software de investigación y diseño de simulación. Podemos ayudar a evaluar las compensaciones entre Precice, el acoplamiento secuencial, la división del operador y otros enfoques para su problema multifísico específico.

Visite la página de inicio de Matforge para obtener más información sobre los servicios de consulta y los flujos de trabajo de investigación.