Spaces:
Runtime error
Runtime error
| """ | |
| Solves a single second-order ordinary differential equation of the form | |
| d²y/dt² = f(t, y, dy/dt) with initial conditions y(t0)=y0 and dy/dt(t0)=dy0_dt. | |
| """ | |
| import numpy as np | |
| from scipy.integrate import solve_ivp | |
| from typing import Callable, List, Tuple, Dict, Any, Union | |
| import matplotlib.pyplot as plt | |
| from maths.differential_equations.ode_interface_utils import parse_float_list, parse_time_span, string_to_ode_func | |
| import gradio as gr | |
| def solve_second_order_ode( | |
| ode_func_second_order: Callable[[float, float, float], float], | |
| t_span: Tuple[float, float], | |
| y0: float, | |
| dy0_dt: float, | |
| t_eval_count: int = 100, | |
| method: str = 'RK45', | |
| **kwargs: Any | |
| ) -> Dict[str, Union[np.ndarray, str, bool]]: | |
| # ...existing code... | |
| def system_func(t: float, z: np.ndarray) -> List[float]: | |
| y_val, dy_dt_val = z[0], z[1] | |
| d2y_dt2_val = ode_func_second_order(t, y_val, dy_dt_val) | |
| return [dy_dt_val, d2y_dt2_val] | |
| initial_conditions_system = [y0, dy0_dt] | |
| try: | |
| t_eval = np.linspace(t_span[0], t_span[1], t_eval_count) | |
| sol = solve_ivp(system_func, t_span, initial_conditions_system, method=method, t_eval=t_eval, **kwargs) | |
| plot_path = None | |
| if sol.success: | |
| try: | |
| plt.figure(figsize=(12, 7)) | |
| plt.subplot(2,1,1) | |
| plt.plot(sol.t, sol.y[0], label=f'y(t), y0={y0}') | |
| plt.xlabel("Time (t)") | |
| plt.ylabel("y(t)") | |
| plt.title(f"Solution of Second-Order ODE: y(t) ({method})") | |
| plt.legend() | |
| plt.grid(True) | |
| plt.subplot(2,1,2) | |
| plt.plot(sol.t, sol.y[1], label=f'dy/dt(t), dy0/dt={dy0_dt}', color='orange') | |
| plt.xlabel("Time (t)") | |
| plt.ylabel("dy/dt(t)") | |
| plt.title(f"Solution of Second-Order ODE: dy/dt(t) ({method})") | |
| plt.legend() | |
| plt.grid(True) | |
| plt.tight_layout() | |
| plot_path = "ode_second_order_solution_plot.png" | |
| plt.savefig(plot_path) | |
| plt.close() | |
| except Exception as e_plot: | |
| print(f"Warning: Could not generate plot: {e_plot}") | |
| plot_path = None | |
| return { | |
| 't': sol.t, | |
| 'y': sol.y[0], # First component of the system's solution | |
| 'dy_dt': sol.y[1], # Second component of the system's solution | |
| 'message': sol.message, | |
| 'success': sol.success, | |
| 'plot_path': plot_path | |
| } | |
| except Exception as e: | |
| return { | |
| 't': np.array([]), | |
| 'y': np.array([]), | |
| 'dy_dt': np.array([]), | |
| 'message': f"Error during ODE solving: {str(e)}", | |
| 'success': False, | |
| 'plot_path': None | |
| } | |
| # --- Gradio Interface for Second-Order ODEs --- | |
| second_order_ode_interface = gr.Interface( | |
| fn=lambda ode_str, t_span_str, y0_val_str, dy0_dt_val_str, t_eval_count, method: solve_second_order_ode( | |
| string_to_ode_func(ode_str, ('t', 'y', 'dy_dt')), | |
| parse_time_span(t_span_str), | |
| parse_float_list(y0_val_str, expected_len=1)[0], | |
| parse_float_list(dy0_dt_val_str, expected_len=1)[0], | |
| int(t_eval_count), | |
| method | |
| ), | |
| inputs=[ | |
| gr.Textbox(label="ODE Function (lambda t, y, dy_dt: ...)", | |
| placeholder="e.g., lambda t, y, dy_dt: -0.1*dy_dt - math.sin(y)", | |
| info="Define d²y/dt². `y` is current value, `dy_dt` is current first derivative."), | |
| gr.Textbox(label="Time Span (t_start, t_end)", placeholder="e.g., 0,20"), | |
| gr.Textbox(label="Initial y(t_start)", placeholder="e.g., 1.0"), | |
| gr.Textbox(label="Initial dy/dt(t_start)", placeholder="e.g., 0.0"), | |
| gr.Slider(minimum=10, maximum=1000, value=100, step=10, label="Evaluation Points Count"), | |
| gr.Radio(choices=['RK45', 'LSODA', 'BDF', 'RK23', 'DOP853'], value='RK45', label="Solver Method") | |
| ], | |
| outputs=[ | |
| gr.Image(label="Solution Plot (y(t) and dy/dt(t))", type="filepath", show_label=True, visible=lambda res: res['success'] and res['plot_path'] is not None), | |
| gr.Textbox(label="Solver Message"), | |
| gr.Textbox(label="Success Status"), | |
| gr.JSON(label="Raw Data (t, y, dy_dt values)", visible=lambda res: res['success']) | |
| ], | |
| title="Second-Order ODE Solver", | |
| description=""" | |
| Solves d²y/dt² = f(t, y, dy/dt) for a single second-order ODE. | |
| - Enter a Python lambda for the ODE (e.g., `lambda t, y, dy_dt: -0.1*dy_dt - math.sin(y)`). | |
| - Initial y(t_start) and dy/dt(t_start) must be single values. | |
| **Examples:** | |
| - Damped oscillator: `lambda t, y, dy_dt: -0.1*dy_dt - y`, y0: `1.0`, dy0/dt: `0.0`, t_span: `0,20` | |
| - Simple pendulum: `lambda t, y, dy_dt: -9.81/1.0 * math.sin(y)`, y0: `math.pi/4`, dy0/dt: `0`, t_span: `0,10` | |
| WARNING: Uses eval() for the ODE function string - potential security risk. | |
| """, | |
| flagging_mode="manual" | |
| ) | |