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("

Formules Mathématiques

") 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("

Parametres de l'equation de transport 1D

") 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("

Parametres de l'equation de transport 2D

") 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()