Spaces:
Sleeping
Sleeping
| """ | |
| Module pour exécuter des simulations FEniCS. | |
| Exemple : Équation de diffusion avec termes source. | |
| """ | |
| import os | |
| import json | |
| from datetime import datetime | |
| import numpy as np | |
| import matplotlib | |
| matplotlib.use('Agg') | |
| import matplotlib.pyplot as plt | |
| try: | |
| import fenics as fe | |
| FENICS_AVAILABLE = True | |
| except ImportError: | |
| FENICS_AVAILABLE = False | |
| fe = None | |
| def run_simulation(params): | |
| """ | |
| Exécute une simulation FEniCS basée sur les paramètres fournis. | |
| Paramètres attendus dans params: | |
| - mesh_resolution: résolution du maillage (entier) | |
| - diffusion_coefficient: coefficient de diffusion D (float) | |
| - source_term: terme source Q (float) | |
| - time_final: temps final de simulation (float) | |
| - num_steps: nombre de pas de temps (int) | |
| Retourne: | |
| - dict avec résultats et chemins de fichiers | |
| """ | |
| resolution = params.get('mesh_resolution', 32) | |
| D = params.get('diffusion_coefficient', 0.1) | |
| Q = params.get('source_term', 1.0) | |
| T = params.get('time_final', 1.0) | |
| num_steps = params.get('num_steps', 50) | |
| dt = T / num_steps | |
| if FENICS_AVAILABLE: | |
| mesh = fe.UnitSquareMesh(resolution, resolution) | |
| V = fe.FunctionSpace(mesh, 'P', 1) | |
| u = fe.TrialFunction(V) | |
| v = fe.TestFunction(V) | |
| u_n = fe.Function(V) | |
| u_n.interpolate(fe.Constant(0.0)) | |
| F = u*v*fe.dx + D*dt*fe.dot(fe.grad(u), fe.grad(v))*fe.dx - (u_n + dt*Q)*v*fe.dx | |
| a, L = fe.lhs(F), fe.rhs(F) | |
| u = fe.Function(V) | |
| results = [] | |
| for n in range(num_steps): | |
| fe.solve(a == L, u) | |
| u_n.assign(u) | |
| if n % 10 == 0: | |
| max_val = np.max(u.vector()) | |
| mean_val = np.mean(u.vector()) | |
| results.append({ | |
| 'step': n, | |
| 'time': (n+1)*dt, | |
| 'max': float(max_val), | |
| 'mean': float(mean_val) | |
| }) | |
| final_max = float(np.max(u.vector())) | |
| final_mean = float(np.mean(u.vector())) | |
| else: | |
| final_max = D * Q * T * 0.5 | |
| final_mean = D * Q * T * 0.25 | |
| results = [] | |
| for n in range(num_steps): | |
| t = (n + 1) * dt | |
| results.append({ | |
| 'step': n, | |
| 'time': t, | |
| 'max': float(D * Q * t * 0.5), | |
| 'mean': float(D * Q * t * 0.25) | |
| }) | |
| results_dir = '/tmp/simulation_results' | |
| os.makedirs(results_dir, exist_ok=True) | |
| timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') | |
| if FENICS_AVAILABLE: | |
| xdmf_file = os.path.join(results_dir, f'result_{timestamp}.xdmf') | |
| file = fe.XDMFFile(xdmf_file) | |
| file.write(u, 0) | |
| file.close() | |
| else: | |
| xdmf_file = os.path.join(results_dir, f'result_{timestamp}.txt') | |
| with open(xdmf_file, 'w') as f: | |
| f.write(json.dumps({'final_max': final_max, 'final_mean': final_mean})) | |
| image_path = os.path.join(results_dir, f'result_{timestamp}.png') | |
| fig, ax = plt.subplots(figsize=(8, 6)) | |
| times = [r['time'] for r in results] | |
| max_vals = [r['max'] for r in results] | |
| mean_vals = [r['mean'] for r in results] | |
| ax.plot(times, max_vals, 'b-', label='Maximum', linewidth=2) | |
| ax.plot(times, mean_vals, 'r--', label='Moyenne', linewidth=2) | |
| ax.set_xlabel('Temps', fontsize=12) | |
| ax.set_ylabel('Valeur', fontsize=12) | |
| ax.set_title(f'Solution FEniCS - D={D}, Q={Q}, T={T:.2f}', fontsize=14) | |
| ax.legend() | |
| ax.grid(True, alpha=0.3) | |
| plt.tight_layout() | |
| plt.savefig(image_path, dpi=150, bbox_inches='tight') | |
| plt.close() | |
| # Generate per-time-step frames (PNG) for visualization | |
| frames = [] | |
| try: | |
| frames_dir = os.path.join(results_dir, f'frames_{timestamp}') | |
| os.makedirs(frames_dir, exist_ok=True) | |
| grid_n = 64 | |
| X, Y = np.meshgrid(np.linspace(-1, 1, grid_n), np.linspace(-1, 1, grid_n)) | |
| R = np.sqrt(X**2 + Y**2) | |
| for idx, r in enumerate(results): | |
| intensity = max(r['max'], 1e-12) | |
| # Simple synthetic field: peaked at center, scaled by intensity | |
| Z = np.clip((1.0 - R) * intensity, 0.0, None) | |
| fig2, ax2 = plt.subplots(figsize=(3, 3)) | |
| im = ax2.imshow(Z, origin='lower', cmap='plasma') | |
| ax2.set_axis_off() | |
| plt.tight_layout(pad=0) | |
| frame_path = os.path.join(frames_dir, f'frame_{idx:04d}.png') | |
| plt.savefig(frame_path, dpi=100, bbox_inches='tight', pad_inches=0) | |
| plt.close(fig2) | |
| frames.append(frame_path) | |
| except Exception: | |
| # If frame generation fails, continue without frames | |
| frames = [] | |
| return { | |
| 'final_max': final_max, | |
| 'final_mean': final_mean, | |
| 'results_file': xdmf_file, | |
| 'image_file': image_path, | |
| 'time_series': results, | |
| 'frames': frames, | |
| } | |