Spaces:
Runtime error
Runtime error
| import numpy as np | |
| import plotly.graph_objects as go | |
| from plotly.subplots import make_subplots | |
| import panel as pn | |
| # Définition du thème sombre | |
| #pio.templates.default = "plotly_dark" | |
| # Activer les extensions KaTeX et MathJax | |
| pn.extension('katex', 'mathjax', 'plotly') | |
| # Definir les widgets pour les parametres 1D | |
| alpha_1d = pn.widgets.FloatSlider(name='Alpha (1D)', start=0.1, end=2, step=0.1, value=1) | |
| longueur_1d = pn.widgets.FloatSlider(name='Longueur (1D)', start=5, end=20, step=1, value=10) | |
| nombre_points_1d = pn.widgets.IntSlider(name='Nombre de points (1D)', start=50, end=200, step=10, value=100) | |
| nombre_pas_temps_1d = pn.widgets.IntSlider(name='Nombre de pas de temps (1D)', start=50, end=200, step=10, value=100) | |
| pas_temps_1d = pn.widgets.FloatSlider(name='Pas de temps (1D)', start=0.01, end=0.1, step=0.01, value=0.05) | |
| # Definir les widgets pour les parametres 2D | |
| alpha_2d = pn.widgets.FloatSlider(name='Alpha (2D)', start=0.1, end=2, step=0.1, value=1) | |
| longueur_2d = pn.widgets.FloatSlider(name='Longueur (2D)', start=5, end=20, step=1, value=10) | |
| temps_total_2d = pn.widgets.FloatSlider(name='Temps total (2D)', start=1, end=10, step=1, value=5) | |
| nombre_points_x_2d = pn.widgets.IntSlider(name='Nombre de points en x (2D)', start=50, end=200, step=10, value=100) | |
| nombre_points_y_2d = pn.widgets.IntSlider(name='Nombre de points en y (2D)', start=50, end=200, step=10, value=100) | |
| nombre_pas_temps_2d = pn.widgets.IntSlider(name='Nombre de pas de temps (2D)', start=50, end=200, step=10, value=100) | |
| pas_temps_2d = pn.widgets.FloatSlider(name='Pas de temps (2D)', start=0.01, end=0.1, step=0.01, value=0.05) | |
| # Creer un template Bootstrap | |
| template = pn.template.BootstrapTemplate(title="Equations de Transport 1D et 2D") | |
| # Créer un template Bootstrap | |
| template = pn.template.BootstrapTemplate(title="Simulation Numérique Interactive des Équations de Transport 1D et 2D | Méthodes des Différences Finies (Schémas Décentrés à Gauche et à Droite) avec Solution Analytique") | |
| # Ajouter un logo à la barre latérale | |
| logo = pn.pane.PNG("logo_unchk.png", width=320) | |
| template.sidebar.append(logo) | |
| # Ajouter les informations sur le PÔLE STN | |
| info_stn = pn.pane.Markdown( | |
| "### PÔLE STN\n" | |
| "#### Master en Modélisation mathématique, analyse et simulation numériques. " | |
| "[Lien vers le site de l'université](https://www.unchk.sn/nos-formations/formations-initiales/pole-sciences-technologie-et-numerique-stn/master-en-modelisation-mathematique-analyse-et-simulation-numeriques/)" | |
| ) | |
| template.sidebar.append(info_stn) | |
| # Titre pour les formules mathématiques | |
| math_title = pn.pane.Markdown("<h3 style='font-size: 16pt; font-weight: bold;'>Formules Mathématiques</h3>") | |
| template.sidebar.append(math_title) | |
| # Formules de l'équation de transport en 1D et 2D | |
| # Formules de l'équation de transport en 1D et 2D | |
| transport_eq_1d = pn.pane.LaTeX(r""" | |
| $$ | |
| \frac{\partial u}{\partial t} + a \frac{\partial u}{\partial x} = 0 | |
| $$ | |
| """, styles={'font-size': '16pt'}) | |
| transport_eq_2d = pn.pane.LaTeX(r""" | |
| $$ | |
| \frac{\partial u}{\partial t} + a \frac{\partial u}{\partial x} + b \frac{\partial u}{\partial y} = 0 | |
| $$ | |
| """, styles={'font-size': '16pt'}) | |
| # Ajouter les formules à la barre latérale | |
| template.sidebar.append(transport_eq_1d) | |
| template.sidebar.append(transport_eq_2d) | |
| # Titre pour les parametres 1D | |
| params_1d_title = pn.pane.Markdown("<h3 style='font-size: 16pt; font-weight: bold;'>Parametres de l'equation de transport 1D</h3>") | |
| template.sidebar.append(params_1d_title) | |
| # Ajouter les widgets des parametres 1D a la barre laterale | |
| template.sidebar.extend([alpha_1d, longueur_1d, nombre_points_1d, nombre_pas_temps_1d, pas_temps_1d]) | |
| # Titre pour les parametres 2D | |
| params_2d_title = pn.pane.Markdown("<h3 style='font-size: 16pt; font-weight: bold;'>Parametres de l'equation de transport 2D</h3>") | |
| template.sidebar.append(params_2d_title) | |
| # Ajouter les widgets des parametres 2D a la barre laterale | |
| template.sidebar.extend([alpha_2d, longueur_2d, temps_total_2d, nombre_points_x_2d, nombre_points_y_2d, nombre_pas_temps_2d, pas_temps_2d]) | |
| # Fonction pour mettre a jour les graphiques | |
| def update_plots(alpha_1d, longueur_1d, nombre_points_1d, nombre_pas_temps_1d, pas_temps_1d, alpha_2d, longueur_2d, temps_total_2d, nombre_points_x_2d, nombre_points_y_2d, nombre_pas_temps_2d, pas_temps_2d): | |
| # Resolution de l'equation de transport 1D decentree a gauche | |
| x_1d = np.linspace(0, longueur_1d, nombre_points_1d) | |
| dx_1d = x_1d[1] - x_1d[0] | |
| u_left_1d = np.sin(x_1d) | |
| for n in range(nombre_pas_temps_1d): | |
| u_left_1d[1:] -= alpha_1d * pas_temps_1d / dx_1d * (u_left_1d[1:] - u_left_1d[:-1]) | |
| u_left_1d[0] = u_left_1d[-1] # Condition periodique | |
| # Resolution de l'equation de transport 1D decentree a droite | |
| u_right_1d = np.sin(x_1d) | |
| for n in range(nombre_pas_temps_1d): | |
| u_right_1d[:-1] -= alpha_1d * pas_temps_1d / dx_1d * (u_right_1d[1:] - u_right_1d[:-1]) | |
| u_right_1d[-1] = u_right_1d[0] # Condition periodique | |
| # Solution analytique pour 1D | |
| u_exact_1d = np.sin(x_1d - alpha_1d * nombre_pas_temps_1d * pas_temps_1d) | |
| # Resolution de l'equation de transport 2D decentree a gauche | |
| x_2d = np.linspace(0, longueur_2d, nombre_points_x_2d) | |
| y_2d = np.linspace(0, longueur_2d, nombre_points_y_2d) | |
| X, Y = np.meshgrid(x_2d, y_2d) | |
| dx_2d = x_2d[1] - x_2d[0] | |
| dy_2d = y_2d[1] - y_2d[0] | |
| u_left_2d = np.sin(X) * np.sin(Y) | |
| for n in range(nombre_pas_temps_2d): | |
| u_left_2d[1:, :] -= alpha_2d * pas_temps_2d / dx_2d * (u_left_2d[1:, :] - u_left_2d[:-1, :]) | |
| u_left_2d[:, 1:] -= alpha_2d * pas_temps_2d / dy_2d * (u_left_2d[:, 1:] - u_left_2d[:, :-1]) | |
| u_left_2d[-1, :] = u_left_2d[0, :] # Condition periodique | |
| u_left_2d[:, -1] = u_left_2d[:, 0] # Condition periodique | |
| # Resolution de l'equation de transport 2D decentree a droite | |
| u_right_2d = np.sin(X) * np.sin(Y) | |
| for n in range(nombre_pas_temps_2d): | |
| u_right_2d[:-1, :] -= alpha_2d * pas_temps_2d / dx_2d * (u_right_2d[1:, :] - u_right_2d[:-1, :]) | |
| u_right_2d[:, :-1] -= alpha_2d * pas_temps_2d / dy_2d * (u_right_2d[:, 1:] - u_right_2d[:, :-1]) | |
| u_right_2d[-1, :] = u_right_2d[0, :] # Condition periodique | |
| u_right_2d[:, -1] = u_right_2d[:, 0] # Condition periodique | |
| # Solution analytique pour 2D | |
| u_exact_2d = np.sin(X - alpha_2d * temps_total_2d) * np.sin(Y - alpha_2d * temps_total_2d) | |
| # Creer la figure pour les graphiques 1D et 2D | |
| fig = make_subplots( | |
| rows=2, cols=3, | |
| specs=[[{'type': 'scatter'}, {'type': 'scatter'}, {'type': 'scatter'}], | |
| [{'type': 'surface'}, {'type': 'surface'}, {'type': 'surface'}]], | |
| subplot_titles=('1D Decentre a Gauche', '1D Decentre a Droite', 'Solution Analytique 1D', | |
| '2D Decentre a Gauche', '2D Decentre a Droite', 'Solution Analytique 2D') | |
| ) | |
| # Ajouter les traces 1D | |
| fig.add_trace(go.Scatter(x=x_1d, y=u_left_1d, mode='lines', name='1D Decentre a Gauche'), row=1, col=1) | |
| fig.add_trace(go.Scatter(x=x_1d, y=u_right_1d, mode='lines', name='1D Decentre a Droite'), row=1, col=2) | |
| fig.add_trace(go.Scatter(x=x_1d, y=u_exact_1d, mode='lines', name='Solution Analytique 1D'), row=1, col=3) | |
| # Ajouter les traces 2D | |
| fig.add_trace(go.Surface(z=u_left_2d, x=X, y=Y, colorscale='Viridis', name='2D Decentre a Gauche'), row=2, col=1) | |
| fig.add_trace(go.Surface(z=u_right_2d, x=X, y=Y, colorscale='Viridis', name='2D Decentre a Droite'), row=2, col=2) | |
| fig.add_trace(go.Surface(z=u_exact_2d, x=X, y=Y, colorscale='Viridis', name='Solution Analytique 2D'), row=2, col=3) | |
| fig.update_layout(title_text='2D Transport Equation', template="plotly_dark") | |
| fig.update_layout(height=1500, width=1750, | |
| title_text='Solutions des equations de transport 1D et 2D', | |
| font_color="white" , # Couleur du texte en blanc pour le thème sombre | |
| legend=dict( | |
| x=0.5, # Position horizontale | |
| y=0.5, # Position verticale | |
| traceorder='normal', | |
| orientation='v' # Orientation verticale | |
| )) | |
| return fig | |
| # Lier la fonction de mise a jour aux widgets | |
| interactive_plot = pn.bind(update_plots, alpha_1d, longueur_1d, nombre_points_1d, nombre_pas_temps_1d, pas_temps_1d, alpha_2d, longueur_2d, temps_total_2d, nombre_points_x_2d, nombre_points_y_2d, nombre_pas_temps_2d, pas_temps_2d) | |
| # Ajouter la figure mise a jour au template | |
| template.main.append(pn.pane.Plotly(interactive_plot)) | |
| # Afficher le template | |
| template.servable() |