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%202%20%E2%80%94%20Dimensional%20Analysis%20and%20Nondimensionalisation%22%2C%0A)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Week%202%3A%20Dimensional%20analysis%20and%20nondimensionalisation%0A%20%20%20%20%23%23%20Computation%20lecture%0A%0A%20%20%20%20**MATH4120%20%E2%80%94%20Mathematical%20Modelling%20and%20Programming**%0A%20%20%20%20Lancaster%20University%2C%202026%E2%80%9327%0A%0A%20%20%20%20---%0A%0A%20%20%20%20In%20lectures%20this%20week%20we%20derived%20a%20systematic%20procedure%20for%20nondimensionalising%0A%20%20%20%20an%20ODE%3A%20choose%20characteristic%20scales%2C%20define%20dimensionless%20variables%2C%20and%20rewrite.%0A%0A%20%20%20%20The%20key%20insight%3A%20many%20different%20physical%20problems%20share%20the%20**same%20dimensionless%20structure**.%0A%20%20%20%20Here%20we%20visualise%20that%20through%20**solution%20collapse**.%0A%20%20%20%20%22%22%22)%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%20from%20scipy.integrate%20import%20solve_ivp%0A%0A%20%20%20%20return%20np%2C%20plt%2C%20solve_ivp%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%201.%20Newton's%20cooling%3A%20the%20dimensional%20picture%0A%0A%20%20%20%20The%20dimensional%20equation%20is%3A%0A%20%20%20%20%24%24%5Cfrac%7BdT%7D%7Bdt%7D%20%3D%20-k(T%20-%20T_%5Cinfty)%2C%20%5Cqquad%20T(0)%20%3D%20T_0%24%24%0A%0A%20%20%20%20Its%20analytic%20solution%20is%20%24T(t)%20%3D%20T_%5Cinfty%20%2B%20(T_0%20-%20T_%5Cinfty)e%5E%7B-kt%7D%24.%0A%0A%20%20%20%20Use%20the%20sliders%20to%20vary%20%24T_0%24%20and%20%24T_%5Cinfty%24%20and%20watch%20how%20the%20curves%20shift.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20T0_slider%20%3D%20mo.ui.slider(start%3D20%2C%20stop%3D100%2C%20step%3D5%2C%20value%3D80%2C%20label%3D%22Initial%20temperature%20T0%20(deg%20C)%22)%0A%20%20%20%20Tinf_slider%20%3D%20mo.ui.slider(start%3D0%2C%20stop%3D30%2C%20step%3D5%2C%20value%3D20%2C%20label%3D%22Ambient%20temperature%20Tinf%20(deg%20C)%22)%0A%20%20%20%20mo.vstack(%5BT0_slider%2C%20Tinf_slider%5D)%0A%20%20%20%20return%20T0_slider%2C%20Tinf_slider%0A%0A%0A%40app.cell%0Adef%20_(T0_slider%2C%20Tinf_slider%2C%20np%2C%20plt)%3A%0A%20%20%20%20T0%20%3D%20T0_slider.value%0A%20%20%20%20Tinf%20%3D%20Tinf_slider.value%0A%20%20%20%20k_values%20%3D%20%5B0.1%2C%200.5%2C%202.0%5D%0A%20%20%20%20colors%20%3D%20%5B%22%231a5276%22%2C%20%22%231e8449%22%2C%20%22%23922b21%22%5D%0A%20%20%20%20t_dim%20%3D%20np.linspace(0%2C%2030%2C%20400)%0A%0A%20%20%20%20fig1%2C%20ax1%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20for%20k%2C%20color%20in%20zip(k_values%2C%20colors)%3A%0A%20%20%20%20%20%20%20%20T_sol%20%3D%20Tinf%20%2B%20(T0%20-%20Tinf)%20*%20np.exp(-k%20*%20t_dim)%0A%20%20%20%20%20%20%20%20ax1.plot(t_dim%2C%20T_sol%2C%20color%3Dcolor%2C%20linewidth%3D2.5%2C%20label%3Df%22k%20%3D%20%7Bk%7D%20s%5Cu207b%5Cu00b9%22)%0A%0A%20%20%20%20ax1.axhline(Tinf%2C%20color%3D%22gray%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D1.5%2C%20label%3Df%22Tinf%20%3D%20%7BTinf%7D%20C%22)%0A%20%20%20%20ax1.set_xlabel(%22Time%20t%20(seconds)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax1.set_ylabel(%22Temperature%20T%20(deg%20C)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax1.set_title(%22Dimensional%20solution%3A%20three%20different%20k%20values%22%2C%20fontsize%3D13)%0A%20%20%20%20ax1.legend(fontsize%3D11)%0A%20%20%20%20ax1.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20fig1.tight_layout()%0A%20%20%20%20fig1%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%202.%20Nondimensionalisation%0A%0A%20%20%20%20We%20define%3A%0A%20%20%20%20%24%24%5Ctheta%20%3D%20%5Cfrac%7BT%20-%20T_%5Cinfty%7D%7BT_0%20-%20T_%5Cinfty%7D%2C%20%5Cqquad%20s%20%3D%20k%5C%2Ct%24%24%0A%0A%20%20%20%20The%20ODE%20becomes%3A%0A%20%20%20%20%24%24%5Cfrac%7Bd%5Ctheta%7D%7Bds%7D%20%3D%20-%5Ctheta%2C%20%5Cqquad%20%5Ctheta(0)%20%3D%201%24%24%0A%0A%20%20%20%20**No%20parameters.**%20The%20solution%20is%20%24%5Ctheta(s)%20%3D%20e%5E%7B-s%7D%24.%0A%0A%20%20%20%20Now%20plot%20%24%5Ctheta%24%20vs%20%24s%24%20for%20the%20same%20three%20values%20of%20%24k%24...%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(T0_slider%2C%20Tinf_slider%2C%20np%2C%20plt)%3A%0A%20%20%20%20T0_nd%20%3D%20T0_slider.value%0A%20%20%20%20Tinf_nd%20%3D%20Tinf_slider.value%0A%20%20%20%20k_values_nd%20%3D%20%5B0.1%2C%200.5%2C%202.0%5D%0A%20%20%20%20colors_nd%20%3D%20%5B%22%231a5276%22%2C%20%22%231e8449%22%2C%20%22%23922b21%22%5D%0A%20%20%20%20t_dim_nd%20%3D%20np.linspace(0%2C%2030%2C%20400)%0A%0A%20%20%20%20fig2%2C%20axes%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%204))%0A%0A%20%20%20%20for%20k2%2C%20c2%20in%20zip(k_values_nd%2C%20colors_nd)%3A%0A%20%20%20%20%20%20%20%20T_sol2%20%3D%20Tinf_nd%20%2B%20(T0_nd%20-%20Tinf_nd)%20*%20np.exp(-k2%20*%20t_dim_nd)%0A%20%20%20%20%20%20%20%20axes%5B0%5D.plot(t_dim_nd%2C%20T_sol2%2C%20color%3Dc2%2C%20linewidth%3D2.5%2C%20label%3Df%22k%20%3D%20%7Bk2%7D%22)%0A%20%20%20%20axes%5B0%5D.axhline(Tinf_nd%2C%20color%3D%22gray%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D1.5)%0A%20%20%20%20axes%5B0%5D.set_xlabel(%22t%20(seconds)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B0%5D.set_ylabel(%22T%20(deg%20C)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B0%5D.set_title(%22Dimensional%3A%20T%20vs%20t%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B0%5D.legend(fontsize%3D10)%0A%20%20%20%20axes%5B0%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20s_nondim%20%3D%20np.linspace(0%2C%206%2C%20400)%0A%20%20%20%20theta_exact%20%3D%20np.exp(-s_nondim)%0A%0A%20%20%20%20for%20k2%2C%20c2%20in%20zip(k_values_nd%2C%20colors_nd)%3A%0A%20%20%20%20%20%20%20%20s_vals%20%3D%20k2%20*%20t_dim_nd%0A%20%20%20%20%20%20%20%20T_sol2%20%3D%20Tinf_nd%20%2B%20(T0_nd%20-%20Tinf_nd)%20*%20np.exp(-k2%20*%20t_dim_nd)%0A%20%20%20%20%20%20%20%20theta_vals%20%3D%20(T_sol2%20-%20Tinf_nd)%20%2F%20(T0_nd%20-%20Tinf_nd)%0A%20%20%20%20%20%20%20%20mask2%20%3D%20s_vals%20%3C%3D%206%0A%20%20%20%20%20%20%20%20axes%5B1%5D.plot(s_vals%5Bmask2%5D%2C%20theta_vals%5Bmask2%5D%2C%20color%3Dc2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D2.5%2C%20label%3Df%22k%20%3D%20%7Bk2%7D%22%2C%20alpha%3D0.7)%0A%0A%20%20%20%20axes%5B1%5D.plot(s_nondim%2C%20theta_exact%2C%20%22k--%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Dr%22%24e%5E%7B-s%7D%24%20(exact)%22%2C%20zorder%3D10)%0A%20%20%20%20axes%5B1%5D.set_xlabel(%22s%20%3D%20kt%20(dimensionless%20time)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B1%5D.set_ylabel(r%22%24%5Ctheta%20%3D%20(T%20-%20T_%5Cinfty)%2F(T_0%20-%20T_%5Cinfty)%24%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B1%5D.set_title(%22Nondimensional%3A%20solution%20collapse!%22%2C%20fontsize%3D12)%0A%20%20%20%20axes%5B1%5D.legend(fontsize%3D10)%0A%20%20%20%20axes%5B1%5D.grid(True%2C%20alpha%3D0.3)%0A%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(r%22%22%22%0A%20%20%20%20**All%20three%20curves%20collapse%20onto%20the%20same%20line**%20%24%5Ctheta%20%3D%20e%5E%7B-s%7D%24.%0A%0A%20%20%20%20This%20is%20the%20power%20of%20nondimensionalisation%3A%20instead%20of%20solving%20the%20problem%0A%20%20%20%20for%20each%20value%20of%20%24k%24%2C%20we%20solve%20it%20**once**%20in%20dimensionless%20form.%0A%0A%20%20%20%20Change%20the%20temperatures%20above%20%E2%80%94%20the%20curves%20in%20the%20left%20panel%20shift%2C%0A%20%20%20%20but%20the%20right%20panel%20stays%20fixed%20on%20%24e%5E%7B-s%7D%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%203.%20The%20logistic%20equation%20%E2%80%94%20preview%0A%0A%20%20%20%20Next%20we%20do%20the%20same%20for%20logistic%20growth%3A%0A%20%20%20%20%24%24%5Cfrac%7BdN%7D%7Bdt%7D%20%3D%20rN%5C!%5Cleft(1%20-%20%5Cfrac%7BN%7D%7BK%7D%5Cright)%24%24%0A%0A%20%20%20%20With%20%24u%20%3D%20N%2FK%24%20and%20%24s%20%3D%20rt%24%2C%20this%20becomes%20%24%5Cdfrac%7Bdu%7D%7Bds%7D%20%3D%20u(1-u)%24.%0A%0A%20%20%20%20Use%20the%20sliders%20to%20vary%20%24r%24%20and%20%24K%24%20%E2%80%94%20in%20the%20dimensional%20plot%20the%20curves%20differ%2C%0A%20%20%20%20but%20in%20the%20nondimensional%20plot%20they%20collapse%20(for%20fixed%20%24N_0%2FK%24).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20r_log_slider%20%3D%20mo.ui.slider(start%3D0.2%2C%20stop%3D2.0%2C%20step%3D0.2%2C%20value%3D0.5%2C%20label%3D%22r%20(growth%20rate)%22)%0A%20%20%20%20K_slider%20%3D%20mo.ui.slider(start%3D100%2C%20stop%3D1000%2C%20step%3D100%2C%20value%3D500%2C%20label%3D%22K%20(carrying%20capacity)%22)%0A%20%20%20%20N0_frac_slider%20%3D%20mo.ui.slider(start%3D0.05%2C%20stop%3D0.5%2C%20step%3D0.05%2C%20value%3D0.1%2C%20label%3D%22N0%2FK%20(initial%20fraction)%22)%0A%20%20%20%20mo.vstack(%5Br_log_slider%2C%20K_slider%2C%20N0_frac_slider%5D)%0A%20%20%20%20return%20K_slider%2C%20N0_frac_slider%2C%20r_log_slider%0A%0A%0A%40app.cell%0Adef%20_(K_slider%2C%20N0_frac_slider%2C%20np%2C%20plt%2C%20r_log_slider%2C%20solve_ivp)%3A%0A%20%20%20%20r_log%20%3D%20r_log_slider.value%0A%20%20%20%20K_log%20%3D%20K_slider.value%0A%20%20%20%20u0%20%3D%20N0_frac_slider.value%0A%0A%20%20%20%20r_vals_log%20%3D%20%5B0.3%2C%20r_log%2C%201.5%5D%0A%20%20%20%20K_vals_log%20%3D%20%5B200%2C%20K_log%2C%20800%5D%0A%20%20%20%20col_log%20%3D%20%5B%22%231a5276%22%2C%20%22%231e8449%22%2C%20%22%23922b21%22%5D%0A%0A%20%20%20%20def%20logistic(t_v%2C%20N_v%2C%20r_v%2C%20K_v)%3A%0A%20%20%20%20%20%20%20%20return%20r_v%20*%20N_v%20*%20(1%20-%20N_v%20%2F%20K_v)%0A%0A%20%20%20%20fig3%2C%20axes3%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%204))%0A%0A%20%20%20%20for%20r_v%2C%20K_v%2C%20col%20in%20zip(r_vals_log%2C%20K_vals_log%2C%20col_log)%3A%0A%20%20%20%20%20%20%20%20N0_v%20%3D%20u0%20*%20K_v%0A%20%20%20%20%20%20%20%20sol_v%20%3D%20solve_ivp(logistic%2C%20%5B0%2C%2030%5D%2C%20%5BN0_v%5D%2C%20args%3D(r_v%2C%20K_v)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_eval%3Dnp.linspace(0%2C%2030%2C%20300)%2C%20dense_output%3DTrue)%0A%20%20%20%20%20%20%20%20axes3%5B0%5D.plot(sol_v.t%2C%20sol_v.y%5B0%5D%2C%20color%3Dcol%2C%20linewidth%3D2.5%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Df%22r%3D%7Br_v%7D%2C%20K%3D%7BK_v%7D%22)%0A%20%20%20%20%20%20%20%20s_v%20%3D%20r_v%20*%20sol_v.t%0A%20%20%20%20%20%20%20%20u_v%20%3D%20sol_v.y%5B0%5D%20%2F%20K_v%0A%20%20%20%20%20%20%20%20mask_v%20%3D%20s_v%20%3C%3D%2015%0A%20%20%20%20%20%20%20%20axes3%5B1%5D.plot(s_v%5Bmask_v%5D%2C%20u_v%5Bmask_v%5D%2C%20color%3Dcol%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D2.5%2C%20label%3Df%22r%3D%7Br_v%7D%2C%20K%3D%7BK_v%7D%22%2C%20alpha%3D0.7)%0A%0A%20%20%20%20axes3%5B0%5D.set_xlabel(%22t%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B0%5D.set_ylabel(%22N(t)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B0%5D.set_title(%22Logistic%20growth%3A%20dimensional%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B0%5D.legend(fontsize%3D9)%0A%20%20%20%20axes3%5B0%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20axes3%5B1%5D.set_xlabel(%22s%20%3D%20rt%20(dimensionless)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B1%5D.set_ylabel(%22u%20%3D%20N%2FK%20(dimensionless)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B1%5D.set_title(%22Nondimensional%3A%20collapse%20(fixed%20N0%2FK)%22%2C%20fontsize%3D12)%0A%20%20%20%20axes3%5B1%5D.legend(fontsize%3D9)%0A%20%20%20%20axes3%5B1%5D.grid(True%2C%20alpha%3D0.3)%0A%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(r%22%22%22%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20-%20A%20**characteristic%20scale**%20is%20a%20representative%20size%20for%20a%20variable%20in%20the%20problem%0A%20%20%20%20-%20**Nondimensionalisation**%20removes%20units%20and%20reduces%20the%20number%20of%20parameters%0A%20%20%20%20-%20The%20dimensionless%20ODE%20for%20Newton's%20cooling%20has%20**no%20parameters**%20%E2%80%94%20its%20solution%20%24e%5E%7B-s%7D%24%20is%20universal%0A%20%20%20%20-%20**Solution%20collapse**%3A%20all%20curves%20for%20different%20physical%20parameters%20coincide%20in%20dimensionless%20coordinates%0A%20%20%20%20-%20Next%20week%3A%20the%20Buckingham%20%CE%A0%20theorem%20gives%20a%20systematic%20method%20when%20we%20have%20many%20parameters%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%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
05116ae445e817971b70e73bf409af2d23058a8da0103f9d223d8179b2ac8633