import streamlit as st import numpy as np import matplotlib.pyplot as plt import pandas as pd class RungeKutta4thOrder: def __init__(self, C, h, A, omega): self.C = C # Capacitance in Farads self.h = h # Step-size in seconds self.A = A # Amplitude in the differential equation self.omega = omega # Angular frequency in the differential equation self.v0 = 0 # Initial voltage self.t0 = 0 # Initial time def f(self, t, v): """Governing differential equation.""" return (1 / self.C) * (-0.1 + max((abs(self.A * np.cos(self.omega * np.pi * t)) - 2 - v) / 0.04, 0)) def k1(self, t, v): return self.f(t, v) def k2(self, t, v): return self.f(t + self.h / 2, v + self.k1(t, v) * self.h / 2) def k3(self, t, v): return self.f(t + self.h / 2, v + self.k2(t, v) * self.h / 2) def k4(self, t, v): return self.f(t + self.h, v + self.k3(t, v) * self.h) def next_step(self, t, v): k1_val = self.k1(t, v) k2_val = self.k2(t, v) k3_val = self.k3(t, v) k4_val = self.k4(t, v) return v + (self.h / 6) * (k1_val + 2 * k2_val + 2 * k3_val + k4_val) def print_k_values(self, t, v): k1_val = self.k1(t, v) k2_val = self.k2(t, v) k3_val = self.k3(t, v) k4_val = self.k4(t, v) st.write(f"k1: {k1_val}") st.write(f"k2: {k2_val}") st.write(f"k3: {k3_val}") st.write(f"k4: {k4_val}") def solve(self, t_end): t_values = [self.t0] v_values = [self.v0] t = self.t0 v = self.v0 while t < t_end: v = self.next_step(t, v) t += self.h t_values.append(t) v_values.append(v) return t_values, v_values # Streamlit App st.title('Runge-Kutta 4th Order Method Visualization') # Sliders for parameters C = st.slider('Capacitance (C)', min_value=150*10**-6, max_value=375*10**-6, value=150*10**-6, step=1*10**-6) A = st.slider('Amplitude (A)', min_value=18.0, max_value=30.0, value=18.0, step=0.1) omega = st.slider('Angular Frequency (ω)', min_value=120.0, max_value=222.0, value=120.0, step=0.1) # Step size selection step_sizes = [0.00004, 0.00002, 0.00001, 0.000005, 0.0000025] h = st.selectbox('Select Step Size (h)', step_sizes) t_end = 4e-05 # Solving the differential equation for the selected step size rk4 = RungeKutta4thOrder(C=C, h=h, A=A, omega=omega) t_values, v_values = rk4.solve(t_end=t_end) # Plotting the results fig, ax = plt.subplots() ax.plot(t_values, v_values) ax.set_xlabel('Time (s)') ax.set_ylabel('Voltage (V)') ax.set_title('Runge-Kutta 4th Order Method') ax.set_ylim([0, 60]) ax.set_xticks([i * 0.5e-5 for i in range(9)]) # Adding annotation for the voltage at the end of the time interval v_end = v_values[-1] ax.annotate(f'{v_end:.4f} V', xy=(t_values[-1], v_end), xytext=(t_values[-1], v_end + 5), arrowprops=dict(facecolor='black', shrink=0.05)) st.pyplot(fig) # Creating the DataFrame data = {'Step size h': [], 'v(0.00004)': [], 'Et': [], '|Error| %': []} for h in step_sizes: rk4 = RungeKutta4thOrder(C=C, h=h, A=A, omega=omega) t_values, v_values = rk4.solve(t_end=t_end) v_at_00004 = [v for t, v in zip(t_values, v_values) if t == 0.00004][0] error = np.abs(15.974 - v_at_00004) data['Step size h'].append(f'{h:.7f}') # Formatting the step size to ensure it displays correctly data['v(0.00004)'].append(v_at_00004) data['Et'].append(15.974 - v_at_00004) data['|Error| %'].append((error / 15.974) * 100) df = pd.DataFrame(data) st.write(df)