import%20marimo%0A%0A__generated_with%20%3D%20%220.13.0%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20width%3D%22medium%22%2C%0A%20%20%20%20app_title%3D%22Week%201%20%E2%80%94%20What%20is%20a%20Mathematical%20Model%3F%22%2C%0A)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%20Week%201%3A%20What%20is%20a%20mathematical%20model%3F%0A%20%20%20%20%20%20%20%20%23%23%20Computation%20lecture%0A%0A%20%20%20%20%20%20%20%20**MATH4120%20%E2%80%94%20Mathematical%20Modelling%20and%20Programming**%0A%20%20%20%20%20%20%20%20Lancaster%20University%2C%202026%E2%80%9327%0A%0A%20%20%20%20%20%20%20%20---%0A%0A%20%20%20%20%20%20%20%20In%20the%20pen-and-paper%20lectures%20this%20week%20we%20introduced%20the%20**modelling%20cycle**%20and%0A%20%20%20%20%20%20%20%20the%20idea%20of%20a%20**rate%20law**%20leading%20to%20the%20exponential%20ODE%20%24dN%2Fdt%20%3D%20rN%24.%0A%0A%20%20%20%20%20%20%20%20Here%20we%20bring%20that%20to%20life%20computationally.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%201.%20A%20motivating%20question%0A%0A%20%20%20%20%20%20%20%20Suppose%20a%20bacterial%20colony%20starts%20with%20100%20cells%20and%20you%20observe%20it%20doubling%0A%20%20%20%20%20%20%20%20every%20hour%20under%20ideal%20conditions.%20How%20many%20cells%20are%20there%20after%2012%20hours%3F%0A%20%20%20%20%20%20%20%20After%2024%20hours%3F%0A%0A%20%20%20%20%20%20%20%20Before%20we%20compute%20anything%20%E2%80%94%20make%20a%20guess.%20Most%20people%20underestimate%0A%20%20%20%20%20%20%20%20exponential%20growth%20dramatically.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20return%20np%2C%20plt%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%202.%20The%20exponential%20model%0A%0A%20%20%20%20%20%20%20%20Our%20model%20is%3A%0A%20%20%20%20%20%20%20%20%24%24%5Cfrac%7BdN%7D%7Bdt%7D%20%3D%20r%20N%2C%20%5Cqquad%20N(0)%20%3D%20N_0%24%24%0A%0A%20%20%20%20%20%20%20%20The%20solution%20(derived%20in%20lectures%20by%20separation%20of%20variables)%20is%3A%0A%20%20%20%20%20%20%20%20%24%24N(t)%20%3D%20N_0%5C%2C%20e%5E%7Brt%7D%24%24%0A%0A%20%20%20%20%20%20%20%20Use%20the%20sliders%20below%20to%20explore%20how%20%24r%24%20and%20%24N_0%24%20shape%20the%20solution.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20r_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D0.1%2C%20stop%3D2.0%2C%20step%3D0.1%2C%20value%3D0.693%2C%0A%20%20%20%20%20%20%20%20label%3D%22Growth%20rate%20r%20(per%20hour)%22%0A%20%20%20%20)%0A%20%20%20%20N0_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D10%2C%20stop%3D500%2C%20step%3D10%2C%20value%3D100%2C%0A%20%20%20%20%20%20%20%20label%3D%22Initial%20population%20N%E2%82%80%22%0A%20%20%20%20)%0A%20%20%20%20t_max_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20start%3D6%2C%20stop%3D48%2C%20step%3D6%2C%20value%3D24%2C%0A%20%20%20%20%20%20%20%20label%3D%22Time%20range%20(hours)%22%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5Br_slider%2C%20N0_slider%2C%20t_max_slider%5D)%0A%20%20%20%20return%20N0_slider%2C%20r_slider%2C%20t_max_slider%0A%0A%0A%40app.cell%0Adef%20_(N0_slider%2C%20np%2C%20plt%2C%20r_slider%2C%20t_max_slider)%3A%0A%20%20%20%20r%20%3D%20r_slider.value%0A%20%20%20%20N0%20%3D%20N0_slider.value%0A%20%20%20%20t_max%20%3D%20t_max_slider.value%0A%0A%20%20%20%20t%20%3D%20np.linspace(0%2C%20t_max%2C%20300)%0A%20%20%20%20N%20%3D%20N0%20*%20np.exp(r%20*%20t)%0A%0A%20%20%20%20fig%2C%20ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20ax.plot(t%2C%20N%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2.5)%0A%20%20%20%20ax.set_xlabel(%22Time%20t%20(hours)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax.set_ylabel(%22Population%20N(t)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax.set_title(f%22Exponential%20growth%3A%20%20N(t)%20%3D%20%7BN0%7D%20%C2%B7%20e%5E(%7Br%3A.2f%7D%20t)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20doubling_time%20%3D%20np.log(2)%20%2F%20r%0A%20%20%20%20ax.axvline(doubling_time%2C%20color%3D%22tomato%22%2C%20linestyle%3D%22--%22%2C%20alpha%3D0.7)%0A%20%20%20%20ax.text(doubling_time%20%2B%200.3%2C%20N0%20*%201.5%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Doubling%20time%5Cn%3D%20%7Bdoubling_time%3A.1f%7D%20h%22%2C%20color%3D%22tomato%22%2C%20fontsize%3D11)%0A%0A%20%20%20%20fig.tight_layout()%0A%20%20%20%20fig%0A%20%20%20%20return%20N0%2C%20r%2C%20t%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%203.%20The%20same%20ODE%2C%20different%20contexts%0A%0A%20%20%20%20%20%20%20%20The%20equation%20%24dN%2Fdt%20%3D%20rN%24%20appears%20in%20many%20different%20disguises.%0A%20%20%20%20%20%20%20%20Change%20the%20interpretation%20of%20the%20variables%20and%20you%20have%20a%20completely%20different%20model.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20scenario%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Bacterial%20growth%20(r%20%3E%200)%22%3A%20(%22population%20N%20(cells)%22%2C%20%22time%20t%20(hours)%22%2C%200.693%2C%20100)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Radioactive%20decay%20(r%20%3C%200)%22%3A%20(%22amount%20N%20(grams)%22%2C%20%22time%20t%20(years)%22%2C%20-0.000121%2C%201000)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Compound%20interest%20(r%20%3E%200)%22%3A%20(%22balance%20N%20(%C2%A3)%22%2C%20%22time%20t%20(years)%22%2C%200.05%2C%201000)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20value%3D%22Bacterial%20growth%20(r%20%3E%200)%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Choose%20scenario%22%0A%20%20%20%20)%0A%20%20%20%20scenario%0A%20%20%20%20return%20(scenario%2C)%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20scenario)%3A%0A%20%20%20%20ylabel_s%2C%20xlabel_s%2C%20r_s%2C%20N0_s%20%3D%20scenario.value%0A%20%20%20%20t_s%20%3D%20np.linspace(0%2C%2020%2C%20300)%0A%20%20%20%20N_s%20%3D%20N0_s%20*%20np.exp(r_s%20*%20t_s)%0A%0A%20%20%20%20fig2%2C%20ax2%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20ax2.plot(t_s%2C%20N_s%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2.5)%0A%20%20%20%20ax2.set_xlabel(xlabel_s%2C%20fontsize%3D13)%0A%20%20%20%20ax2.set_ylabel(ylabel_s%2C%20fontsize%3D13)%0A%20%20%20%20ax2.set_title(f%22dN%2Fdt%20%3D%20rN%20%20%20(r%20%3D%20%7Br_s%7D)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax2.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20fig2.tight_layout()%0A%20%20%20%20fig2%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%204.%20Numerical%20vs%20analytic%20solution%0A%0A%20%20%20%20%20%20%20%20We%20can%20also%20solve%20the%20ODE%20numerically%20using%20Python's%20%60solve_ivp%60%0A%20%20%20%20%20%20%20%20(which%20uses%20a%20Runge-Kutta%20method%20under%20the%20hood).%0A%0A%20%20%20%20%20%20%20%20The%20analytic%20and%20numeric%20solutions%20should%20agree%20%E2%80%94%20this%20is%20a%20useful%20check.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(N0%2C%20np%2C%20plt%2C%20r%2C%20t)%3A%0A%20%20%20%20from%20scipy.integrate%20import%20solve_ivp%0A%0A%20%20%20%20def%20growth_ode(t_var%2C%20N_var)%3A%0A%20%20%20%20%20%20%20%20return%20r%20*%20N_var%0A%0A%20%20%20%20sol%20%3D%20solve_ivp(growth_ode%2C%20t_span%3D%5Bt%5B0%5D%2C%20t%5B-1%5D%5D%2C%20y0%3D%5BN0%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_eval%3Dt%2C%20method%3D%22RK45%22)%0A%0A%20%20%20%20fig3%2C%20ax3%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20ax3.plot(t%2C%20N0%20*%20np.exp(r%20*%20t)%2C%20label%3D%22Analytic%3A%20N%E2%82%80%20e%CA%B3%E1%B5%97%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22%231a5276%22%2C%20linewidth%3D2.5)%0A%20%20%20%20ax3.plot(sol.t%2C%20sol.y%5B0%5D%2C%20label%3D%22Numeric%3A%20solve_ivp%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22tomato%22%2C%20linewidth%3D2%2C%20linestyle%3D%22--%22)%0A%20%20%20%20ax3.set_xlabel(%22Time%20t%20(hours)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax3.set_ylabel(%22N(t)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax3.set_title(%22Analytic%20vs%20numeric%20solution%22%2C%20fontsize%3D13)%0A%20%20%20%20ax3.legend(fontsize%3D12)%0A%20%20%20%20ax3.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20fig3.tight_layout()%0A%20%20%20%20fig3%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%205.%20Summary%0A%0A%20%20%20%20%20%20%20%20-%20The%20modelling%20cycle%3A%20observe%20%E2%86%92%20simplify%20%E2%86%92%20formulate%20%E2%86%92%20solve%20%E2%86%92%20interpret%20%E2%86%92%20validate%20%E2%86%92%20refine%0A%20%20%20%20%20%20%20%20-%20Dimensional%20homogeneity%3A%20every%20term%20in%20an%20equation%20must%20have%20the%20same%20dimensions%0A%20%20%20%20%20%20%20%20-%20The%20exponential%20ODE%20%24dN%2Fdt%20%3D%20rN%24%20arises%20from%20a%20simple%20proportionality%20assumption%0A%20%20%20%20%20%20%20%20-%20Its%20solution%20%24N(t)%20%3D%20N_0%20e%5E%7Brt%7D%24%20describes%20growth%20(%24r%3E0%24)%20and%20decay%20(%24r%3C0%24)%0A%20%20%20%20%20%20%20%20-%20Numeric%20solvers%20(%60solve_ivp%60)%20confirm%20the%20analytic%20result%0A%0A%20%20%20%20%20%20%20%20**In%20the%20lab**%2C%20you%20will%20reproduce%20this%20workflow%20yourself%3A%20set%20up%20the%20ODE%2C%0A%20%20%20%20%20%20%20%20solve%20it%2C%20plot%20it%2C%20and%20fit%20%24r%24%20to%20some%20data.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
3ae7c476176b13c86ffec0bcbd9edf2ec93a96a1a067bae0257f2dac3365cc6e