Reading Time: 10 minutes

tl;dr

Les simulations multi-physiques nécessitent souvent un couplage de plusieurs solveurs spécialisés. Precice est une bibliothèque de couplage open-source mature qui permet des simulations multi-physiques partitionnées en Python. Ce didacticiel montre comment coupler Fipy avec un autre solveur utilisant Precice, couvrant l’installation, la mise en œuvre de l’adaptateur, la configuration et les pièges courants. Vous apprendrez quand utiliser le couplage partitionné, comment configurer l’échange de données et comment déboguer les problèmes typiques.

Introduction : lorsqu’un solveur ne suffit pas

De nombreux problèmes scientifiques impliquent plusieurs processus physiques qui interagissent. Par exemple :

  • Transfert de chaleur couplé à un débit de fluide (transfert de chaleur conjugué)
  • Mécanique structurelle interagissant avec la dynamique des fluides (interaction fluide-structure)
  • Électrochimie couplée à des phénomènes de transport (modélisation de la batterie)

FIPY excelle dans la résolution d’équations aux dérivées partielles (EDP) pour les problèmes de transport, de diffusion et de champ de phase. Cependant, certains scénarios multi-physiques nécessitent un couplage de FIPY avec un solveur spécialisé pour un autre domaine physique, comme OpenFoam pour la dynamique des fluides ou un code structurel personnalisé.

Le couplage de code est la pratique de connecter deux ou plusieurs codes de simulation indépendants afin qu’ils échangent des données pendant le calcul. C’est là qu’intervient précise (infrastructure de couplage cloisonnée pour les équations du continuum).

Pourquoi utiliser Precice ?

Précis fournit :

  • Couplage agnostique-langue : connectez les solveurs écrits en C++, Python, Fortran, etc.
  • Mappage de données flexibles : Gérer l’interpolation maillage à maillage entre des grilles non correspondantes
  • Coordination de pas de temps : prend en charge les schémas de couplage explicites, implicites et quasi-newton
  • Évolutivité parallèle : conçue pour les environnements de calcul hautes performances
  • Communauté active : utilisé dans la recherche et l’industrie, avec une bonne documentation

Pour les utilisateurs de Fipy, Precice ouvre la porte à des flux de travail multi-physiques robustes sans créer d’infrastructure de couplage à partir de zéro.

Partitions VS Solveurs monolithiques

Avant de plonger, comprenez les deux principales approches de la multi-physique :

aspect partitionné (précision) Monolithique
structure Solveurs séparés couplés via un échange de données Un seul solveur gère toute la physique ensemble
Réutilisation du code Élevé – Utilisez des solveurs spécialisés existants Faible – Besoin de mise en œuvre unifiée
effort de développement Modéré – Écrire des adaptateurs, configurer le couplage Très élevé – implémentez toute la physique dans un seul code
Performances Bien, mais surcharge de communication Potentiellement mieux pour les problèmes étroitement couplés
Flexibilité Echange ou mise à niveau des solveurs individuels faciles Rigide – Les modifications affectent toute la base de code
Cas d’utilisation Des solveurs matures existent pour chaque physique Modèles physiques nouveaux ou hautement intégrés

Quand choisir un couplage partitionné avec Precice :

  • Vous disposez de solveurs fiables et optimisés pour la physique individuelle (par exemple, FIPY pour diffusion, OpenFoam pour Flow)
  • Les physiques sont couplées de manière lâche ou modérée
  • Vous souhaitez tirer parti des bases de code et des communautés existantes
  • Vous avez besoin de flexibilité pour essayer différentes combinaisons de solveurs

Quand monolithique pourrait être meilleur :

  • Couplage extrêmement serré nécessitant un traitement implicite au niveau de l’algèbre linéaire
  • Simulations HPC critiques pour les performances où la surcharge de communication est inacceptable
  • Très nouvelle physique où il n’existe pas encore de solveur spécialisé

Pour de nombreuses applications de recherche, Couplet cloisonné avec precice est le choix pragmatique.

Aperçu conceptuel : Comment fonctionne Precice

Precice suit une architecture client-server :

  1. Solver A (par exemple, Fipy) s’exécute en tant que Client de precision
  2. Le solveur B (un autre code) s’exécute comme un autre Client de precis
  3. Precice s’exécute comme un processus distinct (le service de couplage) qui gère la communication et la cartographie des données
  4. Au niveau des interfaces de couplage, les solveurs échangent des données de limites (p. ex., température, flux de chaleur, vitesse) à travers
  5. PRECICE gère :
    • Mappage de maillage lorsque les maillages d’interface ne correspondent pas
    • Synchronisation du pas de temps
    • Détentation et sous-relaxation des données pour améliorer la convergence
    • Schémas de couplage (explicite, implicite, quasi-newton)

L’avantage clé : chaque solveur reste inconscient des détails internes de l’autre. Ils n’ont qu’à savoir comment envoyer/recevoir des données à leur limite via l’API de Precice.

Les prérequis

Avant de commencer, assurez-vous d’avoir :

Étape 1 : Installez les fixations Python Python

Precice fournit des liaisons Python afin que Fipy (ou tout code Python) puisse agir en tant que client de couplage.

# Using conda (recommended)
conda install -c conda-forge precice

# Or using pip
pip install precice

Vérifiez l’installation :

python -c "import precice; print('preCICE Python version:', precice.__version__)"

Vous devriez voir la version de précision imprimée sans erreur.

Étape 2 : Concevez votre interface de couplage

Identifiez les deux solveurs interagissent. Scénarios courants :

  • Domaine de Fipy → Champ de température
  • Autre domaine du solveur → Flux de chaleur ou température

Définir :

  • Maille d’interface de chaque côté (peut-être différent)
  • Données de couplage : quelles quantités sont échangées (par exemple, Temperature, Heat-Flux)
  • Mesh Scaling : s’assurer que les systèmes de coordonnées s’alignent

Pour ce didacticiel, nous allons coupler un solveur FIPY Heat Diffusion avec un solveur Simple Python Convective Cooling. L’interface est une ligne 1D où la température et le flux de chaleur sont échangés.

Étape 3 : Écrivez l’adaptateur Fipy Precice

Le Adaptateur est le code qui relie votre solveur (FIPY) à Precice. Il gère :

  • Initialisation de la connexion de précision
  • Définir le maillage de l’interface de couplage
  • Lecture des données entrantes de l’autre solveur
  • Écrire des données sortantes à envoyer
  • Avancement du pas de temps de couplage

Créer un fichier fipy_precice_adapter.py :

import numpy as np
from fipy import CellVariable, Grid1D, DiffusionTerm, TransientTerm
import precice

# --- Configuration ---
# These should match the preCICE configuration file
COUPLING_INTERFACE = "Fluid-Solid"  # Name of the coupling interface
COUPLING_MESH_ID = 0  # ID of the mesh on this solver side
COUPLING_DATA_TEMPERATURE_ID = 0
COUPLING_DATA_HEATFLUX_ID = 1

# Simulation parameters
nx = 50
dx = 1.0
total_time = 10.0
dt = 0.1

# --- FiPy setup ---
mesh = Grid1D(nx=nx, dx=dx)
T = CellVariable(name="Temperature", mesh=mesh, value=300.0)  # Initial temp in K
k = 1.0  # Thermal conductivity

# Boundary conditions
# Left boundary: fixed temperature (will be overwritten by coupling)
# Right boundary: fixed temperature (example)
T.constrain(300.0, mesh.facesRight)

# Equation: transient diffusion
eq = TransientTerm() == DiffusionTerm(coeff=k)

# --- preCICE setup ---
solver_name = "FiPy-Solver"
config_file = "precice-config.xml"  # Provided separately

precice_dll = precice.Participant(solver_name, config_file, 0, 0)

# Get the coupling mesh from preCICE
mesh_vertices = precice_dll.get_mesh_vertices(COUPLING_MESH_ID, COUPLING_INTERFACE)
# In 1D, mesh_vertices is an array of x-coordinates
# We'll map these to our FiPy mesh cells

# Main coupling loop
time = 0.0
while time < total_time:
    # 1. Advance FiPy one time step (without coupling first)
    eq.solve(var=T, dt=dt)
    
    # 2. Read incoming data from the other solver (e.g., heat flux)
    # preCICE expects data at the coupling interface vertices
    heat_flux_in = precice_dll.read_data(
        COUPLING_DATA_HEATFLUX_ID,
        COUPLING_INTERFACE,
        mesh_vertices
    )
    
    # 3. Apply received heat flux as Neumann boundary condition on FiPy
    # This is simplified: in practice you'd map heat_flux_in to FiPy faces
    # For 1D, we can directly apply to left boundary
    if len(heat_flux_in) > 0:
        # Neumann BC: -k * dT/dx = heat_flux
        # In FiPy, you can set flux via constrained faces
        # For simplicity, we'll adjust the left boundary value to mimic flux
        # A proper implementation would use a FluxBoundaryCondition
        pass  # Implementation depends on exact boundary treatment
    
    # 4. Write outgoing data (temperature) to send to the other solver
    # Extract temperature at coupling interface cells
    T_interface = T.value  # In practice, sample at interface mesh locations
    precice_dll.write_data(
        COUPLING_DATA_TEMPERATURE_ID,
        COUPLING_INTERFACE,
        T_interface[:len(mesh_vertices)]  # ensure matching size
    )
    
    # 5. Advance coupling
    precice_dll.advance(dt)
    
    time += dt
    print(f"Time: {time:.2f}, Max T: {T.max():.2f}, Min T: {T.min():.2f}")

precice_dll.finalize()

Notes importantes :

  • Il s’agit d’un exemple minimal. Les implémentations réelles nécessitent un mappage de maillage et une application de conditions aux limites.
  • Le fichier precice-config.xml définit les paramètres de communication, les ID de maillage et les ID de données. Voir étape 4.
  • La mise à jour des conditions aux limites de FIPY est simplifiée ; Pour une utilisation en production, implémentez Neumann BC approprié via FaceVariable ou une contrainte personnalisée.

Étape 4 : Créez le fichier de configuration de prix

Precice utilise un fichier de configuration XML (precice-config.xml) qui définit :

  • Participants (solveurs)
  • Interfaces de couplage
  • Définitions de maillage et de données
  • Paramètres de communication
  • Schéma de couplage (explicite, implicite, quasi-newton)

Une configuration minimale pour le couplage FIPY + Python :

<?xml version="1.0" encoding="UTF-8"?>
<precice-configuration>
  <schema>https://precice.org/schemas/coupling-schema-2.2.xsd</schema>

  <!-- Parallel settings -->
  <parallel>
    <exchange comm-world="true" />
  </parallel>

  <!-- Coupling participants -->
  <participants>
    <participant name="FiPy-Solver">
      <use-mesh name="Fluid-Solid-Mesh-FiPy" provide="true" />
      <use-data name="Temperature" from="FiPy-Solver" />
      <use-data name="Heat-Flux" to="FiPy-Solver" />
    </participant>
    <participant name="SimpleSolver">
      <use-mesh name="Fluid-Solid-Mesh-Simple" provide="true" />
      <use-data name="Temperature" to="SimpleSolver" />
      <use-data name="Heat-Flux" from="SimpleSolver" />
    </participant>
  </participants>

  <!-- Coupling interfaces -->
  <coupling-scheme:serial-explicit>
    <participants first="FiPy-Solver" second="SimpleSolver" />
    <exchange>
      <data name="Temperature" mesh="Fluid-Solid-Mesh-FiPy" />
      <data name="Heat-Flux" mesh="Fluid-Solid-Mesh-Simple" />
    </exchange>
    <max-time>10.0</max-time>
    <max-iterations>10</max-iterations>
  </coupling-scheme:serial-explicit>

  <!-- Meshes -->
  <mesh name="Fluid-Solid-Mesh-FiPy" from="FiPy-Solver" />
  <mesh name="Fluid-Solid-Mesh-Simple" from="SimpleSolver" />

  <!-- Data -->
  <data name="Temperature" mesh="Fluid-Solid-Mesh-FiPy" />
  <data name="Heat-Flux" mesh="Fluid-Solid-Mesh-Simple" />

</precice-configuration>

Éléments clés :

  • Deux participants : FiPy-Solver et SimpleSolver
  • Échange de données : Temperature (FIPY → SimpleSolver) et Heat-Flux (SimpleSolver → FIPY)
  • serial-explicit Couplage : pas de temps simple explicite (bon pour démarrer)
  • max-iterations contrôle le nombre de sous-itérations par pas de temps (pour les schémas implicites)

Pour un couplage plus avancé, pensez à :

  • serial-implicit avec accélération quasi-newton pour un couplage plus serré
  • Facteurs de sous-relaxation pour améliorer la convergence
  • Définitions de connectivité de maillage si les maillages ne sont pas alignés

Étape 5 : Implémentez le deuxième solveur (exemple simple)

Pour tester le couplage, vous avez besoin d’un deuxième solveur. Voici un solveur Python minimal qui échange le flux de chaleur avec Fipy :

solver_simple.py :

import numpy as np
import precice

# Configuration
COUPLING_INTERFACE = "Fluid-Solid"
COUPLING_MESH_ID = 0
COUPLING_DATA_TEMPERATURE_ID = 0
COUPLING_DATA_HEATFLUX_ID = 1

solver_name = "SimpleSolver"
config_file = "precice-config.xml"

precice_dll = precice.Participant(solver_name, config_file, 0, 0)

# Simple 1D mesh (could be completely different from FiPy's mesh)
mesh_vertices = np.array([[0.0], [1.0]])  # Two points at interface
T_interface = np.array([300.0, 300.0])    # Initial guess

total_time = 10.0
dt = 0.1
time = 0.0

while time < total_time:
    # 1. Read incoming temperature from FiPy
    T_from_fipy = precice_dll.read_data(
        COUPLING_DATA_TEMPERATURE_ID,
        COUPLING_INTERFACE,
        mesh_vertices
    )
    
    # 2. Compute outgoing heat flux (simple Newton's law of cooling)
    # q = h * (T_fluid - T_solid)
    h = 10.0  # Heat transfer coefficient
    T_fluid = 350.0  # Ambient fluid temperature
    heat_flux = h * (T_fluid - T_from_fipy.mean())
    
    # Send same flux to all interface vertices (simplified)
    heat_flux_out = np.full_like(T_from_fipy, heat_flux)
    
    # 3. Write heat flux to send to FiPy
    precice_dll.write_data(
        COUPLING_DATA_HEATFLUX_ID,
        COUPLING_INTERFACE,
        heat_flux_out
    )
    
    # 4. Advance coupling
    precice_dll.advance(dt)
    
    time += dt
    print(f"[SimpleSolver] Time: {time:.2f}, T_fipy: {T_from_fipy.mean():.2f}, q: {heat_flux:.2f}")

precice_dll.finalize()

Ce simple solveur représente un environnement de refroidissement convectif qui applique un flux de chaleur proportionnel à la différence de température par rapport au solide FIPY.

Étape 6 : Exécutez la simulation couplée

  1. Démarrez les deux solveurs simultanément (le precice gère leur communication):
# Terminal 1
python fipy_precice_adapter.py &

# Terminal 2
python solver_simple.py &
  1. Regardez la sortie. Vous devriez voir l’évolution du temps dans les solveurs et les valeurs de flux de température/chaleur évoluant.
  2. La simulation se termine lorsque total_time est atteint ou que le schéma de couplage est terminé.

Comportement attendu :

  • La température de Fipy devrait progressivement diminuer de 300 K initiaux à la courbe de refroidissement
  • Le flux de chaleur de SimpleSolver doit être positif (chaleur en laissant FIPY)
  • Les deux solveurs doivent rester synchronisés dans le temps

Étape 7 : Visualisez les résultats

Après avoir exécuté, vous pouvez tracer le profil de température de Fipy :

import matplotlib.pyplot as plt
from fipy import Grid1D, CellVariable, DiffusionTerm

# Re-run simulation while storing history
# (or modify the adapter to save snapshots to file)
# Then plot T vs x at final time

Dépannage : problèmes et solutions courants

Symptôme cause probable Solution
precice: error: XML file not found Chemin de configuration manquant ou incorrect Assurez-vous que precice-config.xml est dans le répertoire de travail ou fournit un chemin complet
Mesh vertex count mismatch Les maillages d’interface Fipy et Precice ont des nombres différents de sommets cochez get_mesh_vertices() renvoie le nombre attendu ; Mapper correctement
Data not found in configuration Le nom ou l’ID des données ne correspond pas au XML Vérifier COUPLING_DATA_* Les constantes correspondent aux entrées <data name="...">
Coupling diverges (temperatures explode) Sous-relaxation nécessaire ou schéma explicite instable Ajouter <relaxation value="0.5"/> en XML ou passer au couplage implicite
Time step mismatch Les solveurs utilisent différentes valeurs dt Assurez-vous que les deux utilisent le même dt ou laissez le temps de contrôle de précision (precice_dll.advance(dt))
Segmentation fault in preCICE Versions de prix incompatibles entre les participants Réinstallez Precice pour vous assurer que tous les participants utilisent la même version
FiPy boundary not updating L’adaptateur n’applique pas correctement le flux reçu Implémenter la condition limite appropriée de Neumann en utilisant FaceVariable ou modifier le terme source d’équation
Communication timeout Un solveur s’est écrasé ou bloqué Vérifiez que les deux solveurs sont en cours d’exécution ; Vérifiez qu’ils appellent advance() régulièrement

Conseils de débogage :

  • Exécutez les solveurs avec PRECICE_DEBUG=1 Variable d’environnement pour les journaux verbeux
  • Commencez avec un maillage grossier et un temps total court pour tester rapidement
  • Utilisez serial-explicit le couplage en premier (le plus indulgent) avant d’essayer des schémas implicites
  • Validez chaque solveur sans couplage pour vous assurer qu’ils fonctionnent de manière autonome

Sujets avancés

Une fois que le couplage de base fonctionne, explorez :

Couplage implicite avec Quasi-Newton

Pour les problèmes étroitement couplés, les schémas explicites peuvent nécessiter de nombreuses sous-itérations ou devenir instables. Precice prend en charge les couplage implicite avec une accélération quasi-newton :

<coupling-scheme:serial-implicit>
  <participants first="FiPy-Solver" second="SimpleSolver" />
  <exchange>
    <data name="Temperature" mesh="Fluid-Solid-Mesh-FiPy" />
    <data name="Heat-Flux" mesh="Fluid-Solid-Mesh-Simple" />
  </exchange>
  <max-time>10.0</max-time>
  <max-iterations>10</max-iterations>
  <convergence-measure>
    <data name="Temperature" mesh="Fluid-Solid-Mesh-FiPy" />
  </convergence-measure>
  <relaxation value="0.5"/>
</coupling-scheme:serial-implicit>

Mappage maillage vers maillage

Si le maillage d’interface de Fipy ne correspond pas au maillage de l’autre solveur, Precice effectue Mappage de maillage (interpolation). Vous pouvez configurer la méthode de mappage en XML :

<mesh name="Fluid-Solid-Mesh-FiPy" from="FiPy-Solver">
  <use-data name="Temperature" />
  <mapping:nearest-neighbor />
</mesh>

Options : nearest-neighbor, linear, rbf (fonctions de base radiale). Choisissez en fonction de la qualité du maillage et de la physique.

Gestion des pas de temps non-correspondants

Precice permet à chaque solveur d’utiliser son propre pas de temps tout en coordonnant les interfaces de couplage. définir dt indépendamment dans chaque solveur ; Precice interpolera les données au besoin. Cependant, de grandes différences peuvent réduire la précision.

Considérations relatives aux performances

  • Frais généraux de communication peuvent dominer pour les petits problèmes. Profile to ensure coupling isn’t the bottleneck.
  • Under-relaxation (<relaxation> en XML) améliore la stabilité mais ralentit la convergence.
  • résolution de maillage sur l’interface affecte la précision de la cartographie. Utilisez des maillages d’interface suffisamment raffinés.
  • Échelle parallèle : Precice fonctionne avec les solveurs compatibles MPI. Assurez-vous que Fipy (avec PETSC) et l’autre solveur s’exécutent en parallèle si nécessaire.

Prochaines étapes

Après avoir maîtrisé le couplage de base :

  1. Essayez un véritable deuxième solveur (par exemple, OpenFoam pour le flux de fluide) au lieu de l’espace réservé Python
  2. Explorer les schémas de couplage avancés (serial-implicit, multi)
  3. Ajouter plus de physique (par exemple, coupler trois solveurs : thermique, fluide, structurel)
  4. Mettre en place des conditions aux limites appropriées dans FIPY en utilisant FaceVariable ou des termes personnalisés
  5. Optimisez les performances avec une exécution et un profilage parallèles
  6. Étude de cas comme le couplage thermique-fluide ou l’interaction fluide-structure

Pour des connaissances approfondies de FIPY, consultez De équations aux simulations : le pipeline de modélisation et méthode de volume fini expliquée simplement.

Lectures complémentaires

Besoin d’aide pour votre projet multi-physique ?

La construction de simulations couplées robustes nécessite une expertise approfondie tant dans les méthodes numériques que dans l’intégration de logiciels. Si vous vous attaquez à un problème complexe multi-physique et avez besoin de conseils sur :

  • Conception d’un workflow de couplage avec Precice
  • Implémentation d’adaptateurs Fipy pour votre physique spécifique
  • Déboguer les problèmes de convergence
  • Optimisation des performances pour les simulations à grande échelle

MatForge offre des services de consultation pour les flux de travail des logiciels de recherche. Nous pouvons vous aider à mettre en place des simulations multi-physiques fiables et reproductibles adaptées à votre projet. Visitez la page d’accueil de Matforge pour en savoir plus et discuter de vos besoins spécifiques.


Résumé

  • Précice permet un couplage multi-physique partitionné, permettant à Fipy de travailler avec d’autres solveurs
  • Approche cloisonnée est pratique pour la recherche : réutiliser les codes existants, maintenir la flexibilité
  • Étapes clés : installez Precice, Write Adapter, configurez XML, implémentez l’échange de données aux limites
  • Démarrer simple : couplage explicite avec un exemple minimal, puis progression vers des schémas implicites
  • Valider chaque solveur d’abord autonome, puis ensemble
  • Moniteur Convergence et utilisation de la sous-relaxation si nécessaire

Avec cette base, vous pouvez étendre Fipy à pratiquement n’importe quel scénario multi-physique.