ktongue/docker_container / approximations_function /mesh_examples_pratiques.py
download
raw
10.1 kB
"""
Exemples pratiques illustrant les concepts du cours sur les maillages
"""
from dolfinx import mesh
from mpi4py import MPI
import numpy as np
import matplotlib.pyplot as plt
print("="*70)
print("EXEMPLES PRATIQUES: Structure d'un maillage FEniCS")
print("="*70)
# =============================================================================
# Exemple 1: Anatomie d'un maillage simple
# =============================================================================
print("\n" + "="*70)
print("Exemple 1: Anatomie d'un maillage 2x2")
print("="*70)
domain = mesh.create_rectangle(
MPI.COMM_WORLD,
[np.array([0, 0]), np.array([1, 1])],
[2, 2], # Maillage 2x2
mesh.CellType.triangle
)
# Extraire les informations
print("\n📊 GÉOMÉTRIE:")
print(f" - Coordonnées des sommets (geometry.x):")
coords = domain.geometry.x
for i, coord in enumerate(coords):
print(f" Sommet {i}: ({coord[0]:.2f}, {coord[1]:.2f})")
print(f"\n - Nombre total de sommets: {len(coords)}")
print("\n📐 TOPOLOGIE:")
# Créer les entités topologiques avant d'y accéder
domain.topology.create_entities(0) # Sommets
domain.topology.create_entities(1) # Arêtes
domain.topology.create_entities(2) # Cellules
# Nombre d'entités de chaque dimension
num_vertices = domain.topology.index_map(0).size_local
num_edges = domain.topology.index_map(1).size_local
num_cells = domain.topology.index_map(2).size_local
print(f" - Dimension 0 (sommets): {num_vertices}")
print(f" - Dimension 1 (arêtes): {num_edges}")
print(f" - Dimension 2 (cellules): {num_cells}")
print("\n🔗 CONNECTIVITÉ:")
print(" - Cellule → Sommets (dofmap):")
dofmap = domain.geometry.dofmap
for i, cell_vertices in enumerate(dofmap):
vertex_coords = coords[cell_vertices]
print(f" Cellule {i}: sommets {cell_vertices.tolist()}")
print(f" coords: {[(v[0], v[1]) for v in vertex_coords]}")
# Visualiser
fig, ax = plt.subplots(figsize=(8, 8))
# Dessiner les cellules
for i, cell_vertices in enumerate(dofmap):
vertices = np.append(cell_vertices, cell_vertices[0])
ax.plot(coords[vertices, 0], coords[vertices, 1], 'b-', linewidth=2)
# Numéro de cellule au centre
center = np.mean(coords[cell_vertices], axis=0)
ax.text(center[0], center[1], f'C{i}', ha='center', va='center',
fontsize=14, color='red', weight='bold',
bbox=dict(boxstyle='round', facecolor='yellow', alpha=0.7))
# Dessiner et numéroter les sommets
ax.plot(coords[:, 0], coords[:, 1], 'ko', markersize=12)
for i, coord in enumerate(coords):
ax.text(coord[0], coord[1], f' V{i}', fontsize=12, color='blue', weight='bold')
ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('y', fontsize=12)
ax.set_title('Anatomie d\'un maillage 2x2\n(C=Cellule, V=Sommet)', fontsize=14, weight='bold')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
plt.savefig('mesh_anatomy_2x2.png', dpi=150, bbox_inches='tight')
print("\n✓ Visualisation sauvegardée: mesh_anatomy_2x2.png")
plt.close()
# =============================================================================
# Exemple 2: Effet du raffinement
# =============================================================================
print("\n" + "="*70)
print("Exemple 2: Effet du nombre d'éléments")
print("="*70)
resolutions = [2, 4, 8, 16]
fig, axes = plt.subplots(2, 2, figsize=(14, 14))
for idx, (ax, n) in enumerate(zip(axes.flat, resolutions)):
domain = mesh.create_rectangle(
MPI.COMM_WORLD,
[np.array([0, 0]), np.array([1, 1])],
[n, n],
mesh.CellType.triangle
)
coords = domain.geometry.x
dofmap = domain.geometry.dofmap
# Dessiner le maillage
for cell_vertices in dofmap:
vertices = np.append(cell_vertices, cell_vertices[0])
ax.plot(coords[vertices, 0], coords[vertices, 1], 'b-', linewidth=0.5)
ax.plot(coords[:, 0], coords[:, 1], 'ro', markersize=2)
num_cells = domain.topology.index_map(2).size_local
num_vertices = len(coords)
ax.set_title(f'{n}×{n} éléments\n{num_cells} cellules, {num_vertices} sommets',
fontsize=12, weight='bold')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
print(f"\n {n}×{n}: {num_cells:4d} cellules, {num_vertices:4d} sommets")
plt.tight_layout()
plt.savefig('mesh_refinement_comparison.png', dpi=150, bbox_inches='tight')
print("\n✓ Visualisation sauvegardée: mesh_refinement_comparison.png")
plt.close()
# =============================================================================
# Exemple 3: Types d'éléments (Triangles vs Quadrilatères)
# =============================================================================
print("\n" + "="*70)
print("Exemple 3: Comparaison Triangles vs Quadrilatères")
print("="*70)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 7))
# Triangles
domain_tri = mesh.create_rectangle(
MPI.COMM_WORLD,
[np.array([0, 0]), np.array([1, 1])],
[4, 4],
mesh.CellType.triangle
)
coords_tri = domain_tri.geometry.x
dofmap_tri = domain_tri.geometry.dofmap
for cell_vertices in dofmap_tri:
vertices = np.append(cell_vertices, cell_vertices[0])
ax1.plot(coords_tri[vertices, 0], coords_tri[vertices, 1], 'b-', linewidth=1.5)
ax1.plot(coords_tri[:, 0], coords_tri[:, 1], 'ro', markersize=6)
ax1.set_title('Maillage Triangulaire\n(2 triangles par carré)',
fontsize=14, weight='bold')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_aspect('equal')
ax1.grid(True, alpha=0.3)
# Quadrilatères
domain_quad = mesh.create_rectangle(
MPI.COMM_WORLD,
[np.array([0, 0]), np.array([1, 1])],
[4, 4],
mesh.CellType.quadrilateral
)
coords_quad = domain_quad.geometry.x
dofmap_quad = domain_quad.geometry.dofmap
for cell_vertices in dofmap_quad:
vertices = np.append(cell_vertices, cell_vertices[0])
ax2.plot(coords_quad[vertices, 0], coords_quad[vertices, 1], 'g-', linewidth=1.5)
ax2.plot(coords_quad[:, 0], coords_quad[:, 1], 'ro', markersize=6)
ax2.set_title('Maillage Quadrilatéral\n(1 quadrilatère par carré)',
fontsize=14, weight='bold')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_aspect('equal')
ax2.grid(True, alpha=0.3)
print(f"\n Triangles: {domain_tri.topology.index_map(2).size_local} cellules")
print(f" Quadrilatères: {domain_quad.topology.index_map(2).size_local} cellules")
plt.tight_layout()
plt.savefig('mesh_element_types.png', dpi=150, bbox_inches='tight')
print("\n✓ Visualisation sauvegardée: mesh_element_types.png")
plt.close()
# =============================================================================
# Exemple 4: Calcul de qualité du maillage
# =============================================================================
print("\n" + "="*70)
print("Exemple 4: Analyse de la qualité du maillage")
print("="*70)
domain = mesh.create_rectangle(
MPI.COMM_WORLD,
[np.array([0, 0]), np.array([2, 1])],
[8, 4],
mesh.CellType.triangle
)
coords = domain.geometry.x
dofmap = domain.geometry.dofmap
# Calculer le rapport d'aspect pour chaque triangle
aspect_ratios = []
angles_min = []
for cell_vertices in dofmap:
# Récupérer les coordonnées
v0, v1, v2 = coords[cell_vertices]
# Calculer les longueurs des côtés
a = np.linalg.norm(v1 - v0)
b = np.linalg.norm(v2 - v1)
c = np.linalg.norm(v0 - v2)
# Rapport d'aspect
max_len = max(a, b, c)
min_len = min(a, b, c)
ar = max_len / min_len if min_len > 0 else float('inf')
aspect_ratios.append(ar)
# Angle minimal (loi des cosinus)
angles = []
for side1, side2, opposite in [(a, c, b), (a, b, c), (b, c, a)]:
cos_angle = (side1**2 + side2**2 - opposite**2) / (2 * side1 * side2)
cos_angle = np.clip(cos_angle, -1, 1) # Pour éviter erreurs numériques
angle = np.arccos(cos_angle) * 180 / np.pi
angles.append(angle)
angles_min.append(min(angles))
print(f"\n📏 STATISTIQUES DE QUALITÉ:")
print(f" Rapport d'aspect:")
print(f" - Minimum: {min(aspect_ratios):.2f}")
print(f" - Maximum: {max(aspect_ratios):.2f}")
print(f" - Moyenne: {np.mean(aspect_ratios):.2f}")
print(f" - Idéal: 1.00 (triangle équilatéral)")
print(f"\n Angle minimal:")
print(f" - Minimum: {min(angles_min):.1f}°")
print(f" - Maximum: {max(angles_min):.1f}°")
print(f" - Moyenne: {np.mean(angles_min):.1f}°")
print(f" - Acceptable: > 30°")
# Visualiser avec code couleur
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
# Visualisation par rapport d'aspect
for cell_vertices, ar in zip(dofmap, aspect_ratios):
vertices = np.append(cell_vertices, cell_vertices[0])
color = plt.cm.RdYlGn_r((ar - 1) / 2) # Rouge=mauvais, Vert=bon
ax1.fill(coords[vertices, 0], coords[vertices, 1], color=color, alpha=0.7, edgecolor='black')
ax1.set_title('Rapport d\'aspect\n(Vert=bon, Rouge=mauvais)', fontsize=14, weight='bold')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_aspect('equal')
# Visualisation par angle minimal
for cell_vertices, angle in zip(dofmap, angles_min):
vertices = np.append(cell_vertices, cell_vertices[0])
color = plt.cm.RdYlGn((angle - 30) / 30) # Normalisé autour de 30-60°
ax2.fill(coords[vertices, 0], coords[vertices, 1], color=color, alpha=0.7, edgecolor='black')
ax2.set_title('Angle minimal\n(Vert=bon, Rouge=mauvais)', fontsize=14, weight='bold')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_aspect('equal')
plt.tight_layout()
plt.savefig('mesh_quality_analysis.png', dpi=150, bbox_inches='tight')
print("\n✓ Visualisation sauvegardée: mesh_quality_analysis.png")
plt.close()
print("\n" + "="*70)
print("✓ Tous les exemples ont été générés avec succès!")
print("="*70)
print("\nFichiers créés:")
print(" 1. mesh_anatomy_2x2.png - Anatomie détaillée")
print(" 2. mesh_refinement_comparison.png - Effet du raffinement")
print(" 3. mesh_element_types.png - Types d'éléments")
print(" 4. mesh_quality_analysis.png - Analyse de qualité")

Xet Storage Details

Size:
10.1 kB
·
Xet hash:
5eb611bf202effdc9039b8acd6940c423523cb5a9aa9ac079cacbe06ef49a420

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.