SimSite Deploy
Deploy SimSite - Simulation platform with FEniCS and Dang Van analysis
4464a90
"""
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,
}