import%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22%2C%20app_title%3D%22Python%20Basics%20%E2%80%94%20Practice%22)%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%20Python%20basics%3A%20practice%0A%20%20%20%20%23%23%20Reading%20the%20lecture%20code%2C%20one%20piece%20at%20a%20time%0A%0A%20%20%20%20**MATH4120%20%E2%80%94%20Mathematical%20Modelling%20and%20Programming**%20Lancaster%20University%2C%202026%E2%80%9327%0A%0A%20%20%20%20---%0A%0A%20%20%20%20If%20the%20code%20in%20the%20computing%20lectures%20looks%20like%20a%20wall%20of%20text%2C%20start%20here.%20You%20are%20not%20expected%20to%20write%20lecture-style%20code%20from%20scratch.%20The%20aim%20is%20that%20you%20can%20look%20at%20any%20cell%20from%20a%20lecture%20and%20say%20what%20it%20does%2C%20which%20lines%20matter%2C%20and%20which%20lines%20you%20can%20skim%20past.%0A%0A%20%20%20%20Every%20exercise%20below%20uses%20code%20taken%20from%20the%20Week%201%E2%80%933%20lectures%2C%20or%20something%20very%20close%20to%20it.%20Allow%20about%20an%20hour.%20You%20need%20no%20previous%20programming%20at%20all.%0A%0A%20%20%20%20**How%20the%20exercises%20work.**%20Some%20ask%20you%20to%20*predict*%20what%20a%20piece%20of%20code%20does%20before%20you%20run%20it%3A%20write%20your%20guess%20down%20first%2C%20then%20type%20the%20code%20into%20the%20empty%20cell%20underneath%20and%20run%20it.%20Others%20ask%20you%20to%20*write%20or%20fix*%20a%20line%20yourself%2C%20and%20a%20check%20cell%20underneath%20tells%20you%20whether%20you've%20got%20it.%20Answers%20are%20hidden%20under%20**Show%20answer**%3A%20open%20one%20only%20after%20you've%20committed%20to%20a%20guess.%0A%0A%20%20%20%20Press%20**Ctrl%2BEnter**%20(or%20**Shift%2BEnter**)%20to%20run%20a%20cell%20after%20changing%20it.%20For%20explanations%20of%20anything%20you%20meet%20here%2C%20and%20much%20more%2C%20see%20the%20%5BPython%20Basics%20reference%20guide%5D(python_basics_guide.html).%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%200.%20Most%20of%20a%20lecture%20cell%20is%20presentation%0A%0A%20%20%20%20Here%20is%20the%20first%20plot%20from%20the%20Week%201%20lecture%20(geometric%20growth%2C%20%24N_n%20%3D%20R%5En%20N_0%24)%2C%20with%20comments%20added.%20In%20the%20lecture%20the%20three%20inputs%20come%20from%20sliders%3B%20here%20they%20are%20plain%20numbers.%0A%0A%20%20%20%20Look%20at%20how%20the%20cell%20splits%20up.%20The%20mathematical%20model%20is%20**two%20lines**.%20Everything%20after%20that%20is%20about%20making%20the%20picture%20look%20right%3A%20size%2C%20colours%2C%20labels%2C%20font%20sizes%2C%20a%20grid.%20Those%20lines%20are%20worth%20recognising%2C%20but%20you%20can%20skim%20them.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20%23%20----%20the%20inputs%20(in%20the%20lecture%20these%20come%20from%20sliders)%20----%0A%20%20%20%20R_d%20%3D%201.5%0A%20%20%20%20N0_d%20%3D%2050%0A%20%20%20%20n_d%20%3D%2015%0A%0A%20%20%20%20%23%20----%20the%20model%3A%20two%20lines%20----%0A%20%20%20%20n_disc%20%3D%20np.arange(n_d%20%2B%201)%20%20%20%20%20%20%20%23%20the%20generations%200%2C%201%2C%202%2C%20...%2C%2015%0A%20%20%20%20N_geom%20%3D%20N0_d%20*%20R_d%20**%20n_disc%20%20%20%20%20%23%20N_n%20%3D%20R%5En%20N_0%2C%20for%20every%20n%20at%20once%0A%0A%20%20%20%20%23%20----%20the%20plot%3A%20everything%20from%20here%20on%20is%20presentation%20----%0A%20%20%20%20fig_disc%2C%20ax_disc%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20ax_disc.stem(n_disc%2C%20N_geom%2C%20linefmt%3D%22%231a5276%22%2C%20markerfmt%3D%22C0o%22%2C%20basefmt%3D%22k-%22)%0A%20%20%20%20ax_disc.set_xlabel(%22Generation%20%24n%24%22%2C%20fontsize%3D13)%0A%20%20%20%20ax_disc.set_ylabel(%22Population%20%24N_n%24%22%2C%20fontsize%3D13)%0A%20%20%20%20ax_disc.set_title(f%22Geometric%20growth%20%20%24N_n%20%3D%20R%5En%20N_0%24%20%20%20(%24R%20%3D%20%7BR_d%7D%24%2C%20%20%24N_0%20%3D%20%7BN0_d%7D%24)%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_disc.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20fig_disc.tight_layout()%0A%20%20%20%20fig_disc%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%23%20Exercise%200%0A%0A%20%20%20%20Without%20running%20anything%2C%20answer%20these%20by%20reading%20the%20cell%20above%3A%0A%0A%20%20%20%201.%20Which%20single%20line%20would%20you%20change%20to%20show%2025%20generations%20instead%20of%2015%3F%0A%20%20%20%202.%20Why%20does%20the%20code%20say%20%60n_d%20%2B%201%60%20rather%20than%20%60n_d%60%3F%20(Guess%2C%20if%20you%20don't%20know%20yet.%20Section%203%20explains%20it.)%0A%20%20%20%203.%20Which%20line%20would%20you%20delete%20to%20get%20rid%20of%20the%20faint%20grid%20lines%3F%0A%20%20%20%204.%20Which%20line%20would%20you%20change%20to%20model%20a%20population%20that%20halves%20every%20generation%3F%0A%0A%20%20%20%20Now%20edit%20the%20cell%20to%20check%20your%20answers%20to%201%2C%203%20and%204.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%201.%20%60n_d%20%3D%2015%60%20becomes%20%60n_d%20%3D%2025%60.%20Nothing%20else%20needs%20to%20change%3A%20every%20later%20line%20uses%20%60n_d%60%2C%20so%20it%20all%20follows.%0A%20%20%20%202.%20%60np.arange(16)%60%20gives%20the%2016%20numbers%200%2C%201%2C%20...%2C%2015.%20It%20stops%20*before*%20the%20number%20you%20give%20it%2C%20so%20%60n_d%20%2B%201%60%20is%20needed%20to%20include%20generation%2015%20itself.%0A%20%20%20%203.%20%60ax_disc.grid(True%2C%20alpha%3D0.3)%60.%0A%20%20%20%204.%20%60R_d%20%3D%201.5%60%20becomes%20%60R_d%20%3D%200.5%60%2C%20since%20halving%20means%20%24N_%7Bn%2B1%7D%20%3D%200.5%5C%2CN_n%24.%0A%0A%20%20%20%20%2F%2F%2F%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%201.%20Variables%20and%20arithmetic%0A%0A%20%20%20%20%60x%20%3D%205%60%20means%20%22store%205%20under%20the%20name%20%60x%60%22.%20It%20is%20an%20instruction%2C%20not%20an%20equation%3A%20the%20right-hand%20side%20is%20worked%20out%20first%2C%20then%20stored.%20Python%20reads%20a%20cell%20from%20top%20to%20bottom%2C%20one%20line%20at%20a%20time.%0A%0A%20%20%20%20The%20arithmetic%20is%20%60%2B%20-%20*%20%2F%60%20as%20usual%2C%20and%20%60**%60%20for%20powers%3A%20%24R%5En%24%20is%20written%20%60R%20**%20n%60.%20Names%20are%20case-sensitive%2C%20so%20%60N0%60%20and%20%60n0%60%20are%20different%20variables.%0A%0A%20%20%20%20%23%23%23%20Exercise%201.1%3A%20predict%0A%0A%20%20%20%20What%20does%20this%20show%3F%20Write%20your%20answer%20down%2C%20then%20type%20it%20into%20the%20empty%20cell%20below%20and%20run%20it.%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20a%20%3D%203%0A%20%20%20%20b%20%3D%20a%20*%202%0A%20%20%20%20a%20%3D%2010%0A%20%20%20%20b%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%606%60.%20When%20the%20line%20%60b%20%3D%20a%20*%202%60%20runs%2C%20%60a%60%20is%203%2C%20so%20%60b%60%20becomes%206.%20Changing%20%60a%60%20afterwards%20doesn't%20go%20back%20and%20change%20%60b%60%3A%20%60b%60%20stores%20a%20number%2C%20not%20a%20formula.%20(Marimo%20does%20re-run%20*other%20cells*%20when%20something%20they%20depend%20on%20changes%2C%20which%20is%20how%20sliders%20work%2C%20but%20within%20one%20cell%20it's%20strictly%20top%20to%20bottom.)%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20type%20the%20code%20from%20Exercise%201.1%20here%2C%20then%20run%20this%20cell%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%23%20Exercise%201.2%3A%20predict%0A%0A%20%20%20%20Many%20people's%20first%20guess%20for%20%222%20to%20the%20power%203%22%20is%20%602%20%5E%203%60.%20What%20does%20Python%20give%20for%20it%3F%20Try%20it%20in%20the%20cell%20below.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%601%60%2C%20not%208.%20In%20Python%20%60%5E%60%20is%20a%20completely%20different%20operation%20(it%20works%20on%20the%20binary%20digits%20of%20whole%20numbers)%2C%20and%20with%20a%20decimal%20number%20such%20as%20%601.5%20%5E%2010%60%20it%20stops%20with%20a%20%60TypeError%60.%20Powers%20are%20always%20%60**%60.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20try%202%20%5E%203%20here%2C%20then%202%20**%203%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%23%20Exercise%201.3%3A%20write%20a%20line%0A%0A%20%20%20%20Using%20the%20geometric%20growth%20model%20%24N_n%20%3D%20R%5En%20N_0%24%2C%20work%20out%20the%20population%20after%20%24n%20%3D%2010%24%20generations%2C%20starting%20from%20%24N_0%20%3D%2050%24%20with%20%24R%20%3D%201.5%24.%20Replace%20%60None%60%20with%20your%20calculation%2C%20then%20run%20the%20cell.%20The%20check%20cell%20after%20it%20tells%20you%20whether%20it's%20right.%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%20N_10%20%3D%20None%20%20%23%20%E2%86%90%20replace%20None%20with%20your%20calculation%0A%20%20%20%20N_10%0A%20%20%20%20return%20(N_10%2C)%0A%0A%0A%40app.cell%0Adef%20_(N_10)%3A%0A%20%20%20%20if%20N_10%20is%20None%3A%0A%20%20%20%20%20%20%20%20print(%22Not%20attempted%20yet%3A%20replace%20None%20in%20the%20cell%20above.%22)%0A%20%20%20%20elif%20abs(N_10%20-%202883.251953125)%20%3C%201e-6%3A%0A%20%20%20%20%20%20%20%20print(f%22%E2%9C%93%20Correct%3A%20N_10%20%3D%20%7BN_10%3A.1f%7D%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print(f%22Not%20yet%3A%20you%20got%20%7BN_10%7D.%20Check%20you%20used%20**%20for%20the%20power%2C%20and%20the%20right%20numbers.%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%202.%20Functions%0A%0A%20%20%20%20A%20**function**%20packages%20up%20a%20calculation%20so%20you%20can%20reuse%20it%20with%20different%20inputs.%20In%20the%20lectures%2C%20every%20ODE%20you%20hand%20to%20the%20solver%20is%20written%20as%20a%20function.%20The%20pattern%20is%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20def%20name(input1%2C%20input2)%3A%0A%20%20%20%20%20%20%20%20result%20%3D%20...%0A%20%20%20%20%20%20%20%20return%20result%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%60def%60%20starts%20it%2C%20the%20inputs%20go%20in%20brackets%2C%20the%20colon%20%60%3A%60%20is%20required%2C%20and%20the%20**indented**%20lines%20underneath%20are%20the%20body.%20%60return%60%20hands%20the%20answer%20back.%20Defining%20a%20function%20doesn't%20run%20it%3A%20it%20runs%20when%20you%20**call**%20it%2C%20as%20in%20%60name(3%2C%204)%60.%0A%0A%20%20%20%20%23%23%23%20Exercise%202.1%3A%20predict%0A%0A%20%20%20%20What%20do%20the%20last%20two%20lines%20give%3F%20Predict%20both%2C%20then%20try%20it%20below.%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20def%20double_then_add(x%2C%20y)%3A%0A%20%20%20%20%20%20%20%20return%202%20*%20x%20%2B%20y%0A%0A%20%20%20%20double_then_add(3%2C%204)%2C%20double_then_add(4%2C%203)%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%60(10%2C%2011)%60.%20Inputs%20are%20matched%20up%20by%20position%3A%20in%20the%20first%20call%20%60x%60%20is%203%20and%20%60y%60%20is%204%2C%20giving%20%242%20%5Ccdot%203%20%2B%204%20%3D%2010%24%3B%20in%20the%20second%20they%20swap%2C%20giving%20%242%20%5Ccdot%204%20%2B%203%20%3D%2011%24.%20The%20order%20you%20pass%20things%20in%20matters.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20type%20the%20code%20from%20Exercise%202.1%20here%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%23%20Exercise%202.2%3A%20write%20a%20function%0A%0A%20%20%20%20Newton's%20law%20of%20cooling%20(Week%202)%20says%20the%20temperature%20%24T%24%20of%20a%20cup%20of%20tea%20changes%20at%20the%20rate%20%5C%5B%5Cfrac%7BdT%7D%7Bdt%7D%20%3D%20-k%5C%2C(T%20-%20T_%5Cinfty)%2C%5C%5D%20where%20%24k%24%20is%20a%20cooling%20constant%20and%20%24T_%5Cinfty%24%20is%20the%20room%20temperature.%20Complete%20the%20function%20below%20so%20that%20it%20returns%20this%20rate.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20cooling_rate(T%2C%20k%2C%20T_inf)%3A%0A%20%20%20%20return%200.0%20%20%23%20%E2%86%90%20replace%200.0%20with%20the%20right-hand%20side%20of%20the%20ODE%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_tests%20%3D%20%5B(80%2C%200.5%2C%2020%2C%20-30.0)%2C%20(20%2C%200.5%2C%2020%2C%200.0)%2C%20(5%2C%201.0%2C%2020%2C%2015.0)%5D%0A%20%20%20%20_all_ok%20%3D%20True%0A%20%20%20%20for%20_T%2C%20_k%2C%20_Tinf%2C%20_expected%20in%20_tests%3A%0A%20%20%20%20%20%20%20%20_got%20%3D%20cooling_rate(_T%2C%20_k%2C%20_Tinf)%0A%20%20%20%20%20%20%20%20if%20abs(_got%20-%20_expected)%20%3E%201e-9%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_all_ok%20%3D%20False%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Not%20yet%3A%20cooling_rate(%7B_T%7D%2C%20%7B_k%7D%2C%20%7B_Tinf%7D)%20gave%20%7B_got%7D%2C%20expected%20%7B_expected%7D%22)%0A%20%20%20%20if%20_all_ok%3A%0A%20%20%20%20%20%20%20%20print(%22%E2%9C%93%20Correct%20on%20all%20three%20test%20cases.%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%20Once%20it%20passes%3A%20the%20third%20test%20case%20has%20the%20tea%20at%205%20%C2%B0C%20in%20a%2020%20%C2%B0C%20room.%20Why%20is%20the%20rate%20*positive*%20there%2C%20and%20what%20does%20that%20mean%20physically%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20One%20version%20that%20works%3A%20%60return%20-k%20*%20(T%20-%20T_inf)%60.%20The%20brackets%20matter%3A%20%60-k%20*%20T%20-%20T_inf%60%20would%20be%20a%20different%20formula.%0A%0A%20%20%20%20When%20%24T%20%3C%20T_%5Cinfty%24%2C%20%24T%20-%20T_%5Cinfty%24%20is%20negative%2C%20and%20minus%20a%20negative%20is%20positive%3A%20a%20cold%20drink%20warms%20up%20towards%20room%20temperature.%20The%20same%20formula%20covers%20both%20cooling%20and%20warming.%0A%0A%20%20%20%20%2F%2F%2F%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.%20NumPy%20arrays%3A%20lots%20of%20numbers%20at%20once%0A%0A%20%20%20%20Every%20lecture%20starts%20with%20%60import%20numpy%20as%20np%60%2C%20which%20is%20why%20so%20many%20lines%20start%20with%20%60np.%60.%20NumPy%20gives%20you%20**arrays**%2C%20lists%20of%20numbers%20you%20can%20do%20arithmetic%20on%20all%20at%20once.%20Two%20ways%20of%20making%20them%20appear%20everywhere%20in%20the%20lectures%3A%0A%0A%20%20%20%20-%20%60np.arange(n)%60%20gives%20the%20whole%20numbers%20%600%2C%201%2C%20...%2C%20n-1%60.%20It%20stops%20*before*%20%60n%60.%0A%20%20%20%20-%20%60np.linspace(start%2C%20stop%2C%20num)%60%20gives%20%60num%60%20evenly%20spaced%20numbers%20from%20%60start%60%20to%20%60stop%60%2C%20*including*%20both%20ends.%20This%20is%20how%20every%20time%20axis%20in%20the%20course%20is%20made.%0A%0A%20%20%20%20Arithmetic%20on%20an%20array%20acts%20on%20**every%20entry**.%20That's%20why%20the%20Week%201%20cell%20had%20no%20loop%3A%20%60N0_d%20*%20R_d%20**%20n_disc%60%20works%20out%20%24R%5En%20N_0%24%20for%20all%20sixteen%20values%20of%20%24n%24%20in%20one%20line.%20NumPy%20versions%20of%20the%20usual%20functions%2C%20such%20as%20%60np.exp%60%2C%20%60np.sqrt%60%20and%20%60np.log%60%2C%20work%20on%20whole%20arrays%20in%20the%20same%20way.%0A%0A%20%20%20%20%23%23%23%20Exercise%203.1%3A%20predict%0A%0A%20%20%20%20Predict%20what%20each%20of%20these%20shows%2C%20then%20check%20in%20the%20cell%20below%20(one%20line%20at%20a%20time%20works%20best).%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20np.arange(5)%0A%20%20%20%20np.linspace(0%2C%201%2C%205)%0A%20%20%20%20np.arange(4)%20**%202%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20-%20%60np.arange(5)%60%20gives%20%60%5B0%201%202%203%204%5D%60%3A%20five%20numbers%2C%20starting%20at%200%2C%20stopping%20before%205.%0A%20%20%20%20-%20%60np.linspace(0%2C%201%2C%205)%60%20gives%20%60%5B0.%20%20%200.25%200.5%20%200.75%201.%20%20%5D%60%3A%20five%20points%2C%20both%20ends%20included%2C%20so%20four%20gaps%20of%200.25.%0A%20%20%20%20-%20%60np.arange(4)%20**%202%60%20gives%20%60%5B0%201%204%209%5D%60%3A%20each%20entry%20squared.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20try%20the%20Exercise%203.1%20lines%20here%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%23%20Exercise%203.2%3A%20write%20two%20lines%0A%0A%20%20%20%20The%20exact%20solution%20of%20the%20cooling%20ODE%20from%20Exercise%202.2%20is%20%5C%5BT(t)%20%3D%20T_%5Cinfty%20%2B%20(T_0%20-%20T_%5Cinfty)%5C%2Ce%5E%7B-kt%7D.%5C%5D%20Take%20%24T_0%20%3D%2080%24%2C%20%24T_%5Cinfty%20%3D%2020%24%20and%20%24k%20%3D%200.5%24.%0A%0A%20%20%20%201.%20Make%20%60t_cool%60%2C%20an%20array%20of%20101%20equally%20spaced%20times%20from%200%20to%2010.%0A%20%20%20%202.%20Make%20%60T_cool%60%2C%20the%20temperature%20at%20every%20one%20of%20those%20times%2C%20using%20the%20formula%20above.%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%20t_cool%20%3D%20None%20%20%23%20%E2%86%90%20replace%20None%0A%20%20%20%20T_cool%20%3D%20None%20%20%23%20%E2%86%90%20replace%20None%0A%20%20%20%20return%20T_cool%2C%20t_cool%0A%0A%0A%40app.cell%0Adef%20_(T_cool%2C%20t_cool)%3A%0A%20%20%20%20if%20t_cool%20is%20None%20or%20T_cool%20is%20None%3A%0A%20%20%20%20%20%20%20%20print(%22Not%20attempted%20yet%3A%20replace%20both%20Nones%20in%20the%20cell%20above.%22)%0A%20%20%20%20elif%20len(t_cool)%20!%3D%20101%20or%20abs(t_cool%5B0%5D)%20%3E%201e-9%20or%20abs(t_cool%5B-1%5D%20-%2010)%20%3E%201e-9%3A%0A%20%20%20%20%20%20%20%20print(f%22t_cool%20not%20right%20yet%3A%20it%20has%20%7Blen(t_cool)%7D%20entries%2C%20from%20%7Bt_cool%5B0%5D%7D%20to%20%7Bt_cool%5B-1%5D%7D.%22)%0A%20%20%20%20elif%20abs(T_cool%5B0%5D%20-%2080)%20%3E%201e-6%20or%20abs(T_cool%5B-1%5D%20-%2020.404276819945128)%20%3E%201e-6%3A%0A%20%20%20%20%20%20%20%20print(f%22t_cool%20is%20right.%20T_cool%20not%20yet%3A%20it%20starts%20at%20%7BT_cool%5B0%5D%3A.3f%7D%20(should%20be%2080)%20and%20ends%20at%20%7BT_cool%5B-1%5D%3A.3f%7D.%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print(f%22%E2%9C%93%20Correct%3A%20the%20tea%20cools%20from%20%7BT_cool%5B0%5D%3A.0f%7D%20%C2%B0C%20to%20%7BT_cool%5B-1%5D%3A.2f%7D%20%C2%B0C%20by%20t%20%3D%2010.%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%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20t_cool%20%3D%20np.linspace(0%2C%2010%2C%20101)%0A%20%20%20%20T_cool%20%3D%2020%20%2B%20(80%20-%2020)%20*%20np.exp(-0.5%20*%20t_cool)%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20Note%20%60np.exp%60%2C%20not%20%60exp%60%20on%20its%20own%3A%20plain%20Python%20doesn't%20know%20%60exp%60%20(and%20the%20%60math%60%20version%20won't%20take%20an%20array).%20This%20is%20the%20same%20line%20as%20the%20Week%202%20lecture's%20%60T_sol%20%3D%20Tinf%20%2B%20(T0%20-%20Tinf)%20*%20np.exp(-k%20*%20t_dim)%60%2C%20with%20numbers%20instead%20of%20names.%0A%0A%20%20%20%20%2F%2F%2F%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%204.%20Picking%20entries%20out%20of%20an%20array%0A%0A%20%20%20%20Square%20brackets%20pick%20out%20entries.%20Python%20counts%20from%20**0**%2C%20so%20%60x%5B0%5D%60%20is%20the%20first%20entry%2C%20and%20%60x%5B-1%5D%60%20is%20the%20last%20one.%20A%20colon%20picks%20out%20a%20range%3A%20%60x%5B2%3A5%5D%60%20is%20entries%202%2C%203%2C%204%20(again%20stopping%20*before*%20the%20end%20number).%0A%0A%20%20%20%20For%20a%202D%20array%20(a%20matrix)%2C%20you%20give%20a%20row%20and%20a%20column%3A%20%60D%5Bi%2C%20j%5D%60.%20A%20colon%20on%20its%20own%20means%20%22all%20of%20them%22%2C%20so%20%60D%5B%3A%2C%20j%5D%60%20is%20the%20whole%20of%20column%20%60j%60.%20You've%20already%20seen%20this%20in%20the%20Week%203%20lecture%3A%20%60ns_pend%5B%3A%2C%200%5D%60%20takes%20the%20first%20column%20of%20the%20null%20space.%0A%0A%20%20%20%20%23%23%23%20Exercise%204.1%3A%20predict%0A%0A%20%20%20%20Here%20is%20the%20Week%203%20dimension%20matrix%20for%20the%20pendulum.%20Rows%20are%20the%20dimensions%20%24%5BL%2C%20T%5D%24%20and%20columns%20are%20the%20quantities%20%24%5B%5Ctau%2C%20%5Cell%2C%20g%5D%24.%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20D_demo%20%3D%20np.array(%5B%0A%20%20%20%20%20%20%20%20%5B0%2C%201%2C%20%201%5D%2C%20%20%20%23%20L%20exponents%0A%20%20%20%20%20%20%20%20%5B1%2C%200%2C%20-2%5D%2C%20%20%20%23%20T%20exponents%0A%20%20%20%20%5D)%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20Predict%20each%20of%20these%2C%20then%20check%20them%20below%3A%0A%0A%20%20%20%201.%20%60D_demo%5B1%5D%60%0A%20%20%20%202.%20%60D_demo%5B0%2C%202%5D%60%0A%20%20%20%203.%20%60D_demo%5B%3A%2C%202%5D%60%2C%20and%20what%20that%20column%20means%20physically%0A%20%20%20%204.%20%60D_demo.shape%60%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%201.%20%60%5B1%200%20-2%5D%60%3A%20the%20second%20row%20(row%20number%201)%2C%20the%20%24T%24%20exponents.%0A%20%20%20%202.%20%601%60%3A%20row%200%2C%20column%202%2C%20the%20%24L%24%20exponent%20of%20%24g%24.%0A%20%20%20%203.%20%60%5B1%20-2%5D%60%3A%20the%20whole%20of%20column%202%2C%20i.e.%20the%20dimensions%20of%20%24g%24%2C%20%24L%5E1%20T%5E%7B-2%7D%24.%20An%20acceleration%2C%20as%20it%20should%20be.%0A%20%20%20%204.%20%60(2%2C%203)%60%3A%202%20rows%20and%203%20columns.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20type%20D_demo%20in%20here%20and%20try%20the%20four%20expressions%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%205.%20Loops%2C%20%60zip%60%2C%20and%20f-strings%0A%0A%20%20%20%20A%20%60for%60%20loop%20repeats%20the%20indented%20lines%20underneath%20once%20for%20each%20item%20in%20a%20list.%20Plot%20cells%20in%20the%20lectures%20use%20one%20to%20draw%20several%20curves%20on%20one%20plot%2C%20for%20example%20this%20line%20from%20Week%202%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20for%20k%2C%20color%20in%20zip(k_values%2C%20colors)%3A%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%60zip%60%20walks%20along%20two%20lists%20side%20by%20side%2C%20so%20on%20each%20pass%20round%20the%20loop%20%60k%60%20is%20the%20next%20value%20of%20%24k%24%20and%20%60color%60%20is%20its%20matching%20colour.%0A%0A%20%20%20%20The%20labels%20on%20those%20curves%20use%20**f-strings**%3A%20an%20%60f%60%20before%20the%20quote%2C%20and%20anything%20inside%20%60%7Bcurly%20brackets%7D%60%20gets%20replaced%20by%20its%20value.%20%60%7Bx%3A.2f%7D%60%20means%20%22show%20%60x%60%20to%202%20decimal%20places%22.%0A%0A%20%20%20%20%23%23%23%20Exercise%205.1%3A%20predict%0A%0A%20%20%20%20How%20many%20lines%20does%20this%20print%2C%20and%20what%20is%20the%20first%20one%3F%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20for%20k_demo%20in%20%5B0.1%2C%200.5%2C%202.0%5D%3A%0A%20%20%20%20%20%20%20%20print(f%22k%20%3D%20%7Bk_demo%7D%2C%20half-life%20%3D%20%7Bnp.log(2)%20%2F%20k_demo%3A.2f%7D%22)%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20Three%20lines%2C%20one%20per%20value%20of%20%60k_demo%60%3A%0A%0A%20%20%20%20%60%60%60%0A%20%20%20%20k%20%3D%200.1%2C%20half-life%20%3D%206.93%0A%20%20%20%20k%20%3D%200.5%2C%20half-life%20%3D%201.39%0A%20%20%20%20k%20%3D%202.0%2C%20half-life%20%3D%200.35%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20The%20half-life%20%24%5Cln%202%20%2F%20k%24%20is%20the%20time%20it%20takes%20for%20the%20gap%20between%20%24T%24%20and%20%24T_%5Cinfty%24%20to%20halve.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20type%20the%20code%20from%20Exercise%205.1%20here%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%23%20Exercise%205.2%3A%20discuss%20first%2C%20then%20run%0A%0A%20%20%20%20Someone%20copies%20the%20Week%202%20plot%20cell%20and%20adds%20a%20fourth%20value%20of%20%24k%24%2C%20but%20forgets%20to%20add%20a%20fourth%20colour%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20k_list%20%3D%20%5B0.1%2C%200.5%2C%202.0%2C%205.0%5D%0A%20%20%20%20colour_list%20%3D%20%5B%22navy%22%2C%20%22green%22%2C%20%22darkred%22%5D%0A%0A%20%20%20%20for%20k_z%2C%20c_z%20in%20zip(k_list%2C%20colour_list)%3A%0A%20%20%20%20%20%20%20%20print(k_z%2C%20c_z)%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20**Before%20running%20it%3A**%20do%20you%20expect%20an%20error%20message%2C%20four%20lines%2C%20or%20something%20else%3F%20Would%20you%20notice%20if%20this%20happened%20inside%20a%20plot%3F%0A%0A%20%20%20%20Then%20run%20it%20below%2C%20and%20fix%20it%20so%20that%20all%20four%20values%20of%20%24k%24%20are%20printed.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20No%20error%20at%20all%3A%20it%20prints%20three%20lines%20and%20quietly%20drops%20%605.0%60.%20%60zip%60%20stops%20as%20soon%20as%20the%20shorter%20list%20runs%20out.%20In%20a%20plot%2C%20the%20fourth%20curve%20would%20just%20be%20missing%2C%20with%20no%20warning%2C%20which%20is%20easy%20to%20miss.%20The%20fix%20is%20to%20add%20a%20fourth%20colour%2C%20e.g.%20%60colour_list%20%3D%20%5B%22navy%22%2C%20%22green%22%2C%20%22darkred%22%2C%20%22orange%22%5D%60.%0A%0A%20%20%20%20The%20lesson%3A%20no%20error%20message%20doesn't%20mean%20the%20code%20is%20right.%20Always%20check%20the%20output%20looks%20like%20what%20you%20expected.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20type%20the%20code%20from%20Exercise%205.2%20here%2C%20then%20fix%20it%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%206.%20Plotting%3A%20the%20minimum%2C%20then%20the%20extras%0A%0A%20%20%20%20Every%20plot%20in%20the%20course%20comes%20from%20%60import%20matplotlib.pyplot%20as%20plt%60.%20The%20minimum%20is%20three%20lines%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20fig%2C%20ax%20%3D%20plt.subplots()%20%20%20%23%20make%20an%20empty%20figure%20(fig)%20with%20one%20set%20of%20axes%20(ax)%0A%20%20%20%20ax.plot(x%2C%20y)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20draw%20a%20line%20through%20the%20points%20(x%2C%20y)%0A%20%20%20%20fig%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20show%20it%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20Everything%20else%20in%20a%20lecture%20plot%20cell%20is%20optional%20extras.%20These%20are%20the%20ones%20you'll%20see%20most%3A%0A%0A%20%20%20%20%7C%20Code%20%7C%20What%20it%20does%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20%60plt.subplots(figsize%3D(8%2C%204))%60%20%7C%20figure%20size%2C%20width%20by%20height%20%7C%0A%20%20%20%20%7C%20%60ax.plot(x%2C%20y%2C%20color%3D%22red%22)%60%20%7C%20line%20colour%20%7C%0A%20%20%20%20%7C%20%60ax.plot(x%2C%20y%2C%20linestyle%3D%22--%22)%60%20%7C%20dashed%20line%20(%60%22%3A%22%60%20is%20dotted)%20%7C%0A%20%20%20%20%7C%20%60ax.plot(x%2C%20y%2C%20linewidth%3D2.5)%60%20%7C%20thicker%20line%20%7C%0A%20%20%20%20%7C%20%60ax.plot(x%2C%20y%2C%20label%3D%22text%22)%60%20with%20%60ax.legend()%60%20%7C%20name%20a%20curve%2C%20then%20show%20the%20key%20%7C%0A%20%20%20%20%7C%20%60ax.set_xlabel(%22text%22)%60%2C%20%60ax.set_ylabel(%22text%22)%60%2C%20%60ax.set_title(%22text%22)%60%20%7C%20axis%20labels%20and%20title%20%7C%0A%20%20%20%20%7C%20%60ax.grid(True%2C%20alpha%3D0.3)%60%20%7C%20faint%20grid%3B%20%60alpha%60%20controls%20transparency%20%7C%0A%20%20%20%20%7C%20%60fontsize%3D13%60%20%7C%20text%20size%2C%20on%20any%20label%20%7C%0A%20%20%20%20%7C%20%60fig.tight_layout()%60%20%7C%20stops%20labels%20overlapping%20%7C%0A%0A%20%20%20%20%23%23%23%20Exercise%206.1%3A%20change%20a%20plot%20yourself%0A%0A%20%20%20%20The%20cell%20below%20plots%20the%20cooling%20curve%20with%20the%20bare%20minimum.%20Edit%20it%2C%20one%20change%20at%20a%20time%2C%20re-running%20after%20each%3A%0A%0A%20%20%20%201.%20Make%20the%20curve%20red%20and%20dashed.%0A%20%20%20%202.%20Label%20the%20axes%20%22Time%20t%20(s)%22%20and%20%22Temperature%20(%C2%B0C)%22.%0A%20%20%20%203.%20Add%20a%20second%20curve%20for%20a%20faster-cooling%20cup%2C%20with%20%24k%20%3D%202%24%2C%20on%20the%20same%20axes.%20Give%20both%20curves%20labels%20and%20show%20a%20legend.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20t_plot%20%3D%20np.linspace(0%2C%2010%2C%20101)%0A%20%20%20%20T_plot%20%3D%2020%20%2B%2060%20*%20np.exp(-0.5%20*%20t_plot)%0A%0A%20%20%20%20fig_ex6%2C%20ax_ex6%20%3D%20plt.subplots()%0A%20%20%20%20ax_ex6.plot(t_plot%2C%20T_plot)%0A%20%20%20%20fig_ex6%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%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20t_plot%20%3D%20np.linspace(0%2C%2010%2C%20101)%0A%20%20%20%20T_plot%20%3D%2020%20%2B%2060%20*%20np.exp(-0.5%20*%20t_plot)%0A%20%20%20%20T_plot_fast%20%3D%2020%20%2B%2060%20*%20np.exp(-2%20*%20t_plot)%0A%0A%20%20%20%20fig_ex6%2C%20ax_ex6%20%3D%20plt.subplots()%0A%20%20%20%20ax_ex6.plot(t_plot%2C%20T_plot%2C%20color%3D%22red%22%2C%20linestyle%3D%22--%22%2C%20label%3D%22k%20%3D%200.5%22)%0A%20%20%20%20ax_ex6.plot(t_plot%2C%20T_plot_fast%2C%20label%3D%22k%20%3D%202%22)%0A%20%20%20%20ax_ex6.set_xlabel(%22Time%20t%20(s)%22)%0A%20%20%20%20ax_ex6.set_ylabel(%22Temperature%20(%C2%B0C)%22)%0A%20%20%20%20ax_ex6.legend()%0A%20%20%20%20fig_ex6%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20Calling%20%60ax_ex6.plot%60%20twice%20draws%20two%20curves%20on%20the%20same%20axes.%20If%20you%20leave%20out%20%60color%60%2C%20Matplotlib%20picks%20one%20for%20you.%0A%0A%20%20%20%20%2F%2F%2F%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%207.%20Solving%20an%20ODE%20with%20%60solve_ivp%60%0A%0A%20%20%20%20When%20there's%20no%20formula%20for%20the%20solution%2C%20the%20lectures%20hand%20the%20ODE%20to%20%60solve_ivp%60%20from%20SciPy.%20You%20never%20need%20to%20know%20how%20it%20works%20inside%20(that's%20Chapter%206).%20You%20do%20need%20to%20know%20the%20recipe%2C%20which%20is%20the%20same%20every%20time%3A%0A%0A%20%20%20%201.%20Write%20the%20right-hand%20side%20of%20%24%5Cfrac%7Bdy%7D%7Bdt%7D%20%3D%20f(t%2C%20y)%24%20as%20a%20function%20of%20%60t%60%20and%20%60y%60%2C%20in%20that%20order.%0A%20%20%20%202.%20Call%20%60solve_ivp(function%2C%20%5Bstart%20time%2C%20end%20time%5D%2C%20%5Binitial%20value%5D)%60.%20Adding%20%60t_eval%3D...%60%20tells%20it%20which%20times%20you%20want%20answers%20at.%0A%20%20%20%203.%20The%20times%20come%20back%20as%20%60sol.t%60%20and%20the%20solution%20values%20as%20%60sol.y%5B0%5D%60.%0A%0A%20%20%20%20Why%20the%20square%20brackets%20around%20the%20initial%20value%2C%20and%20why%20%60y%5B0%5D%60%20rather%20than%20%60y%60%3F%20%60solve_ivp%60%20is%20built%20to%20handle%20*systems*%20of%20several%20ODEs%20at%20once%20(you'll%20need%20that%20later)%2C%20so%20the%20unknown%20is%20always%20a%20list%2C%20even%20when%20it%20has%20only%20one%20entry.%20That's%20also%20why%20the%20function%20returns%20a%20list%2C%20%60%5B...%5D%60.%0A%0A%20%20%20%20Here%20is%20the%20cooling%20ODE%20solved%20this%20way%2C%20plotted%20against%20the%20exact%20formula%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20solve_ivp)%3A%0A%20%20%20%20def%20cooling_rhs(t%2C%20T)%3A%0A%20%20%20%20%20%20%20%20return%20%5B-0.5%20*%20(T%5B0%5D%20-%2020)%5D%0A%0A%20%20%20%20t_eval_cool%20%3D%20np.linspace(0%2C%2010%2C%20101)%0A%20%20%20%20sol_cool%20%3D%20solve_ivp(cooling_rhs%2C%20%5B0%2C%2010%5D%2C%20%5B80%5D%2C%20t_eval%3Dt_eval_cool)%0A%0A%20%20%20%20fig_cool%2C%20ax_cool%20%3D%20plt.subplots()%0A%20%20%20%20ax_cool.plot(sol_cool.t%2C%20sol_cool.y%5B0%5D%2C%20label%3D%22solve_ivp%22)%0A%20%20%20%20ax_cool.plot(t_eval_cool%2C%2020%20%2B%2060%20*%20np.exp(-0.5%20*%20t_eval_cool)%2C%20linestyle%3D%22--%22%2C%20label%3D%22exact%20formula%22)%0A%20%20%20%20ax_cool.set_xlabel(%22t%22)%0A%20%20%20%20ax_cool.set_ylabel(%22T%22)%0A%20%20%20%20ax_cool.legend()%0A%20%20%20%20fig_cool%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%23%20Exercise%207.1%3A%20adapt%20the%20recipe%0A%0A%20%20%20%20The%20logistic%20equation%20(Week%202)%20models%20a%20population%20%24N%24%20that%20grows%20but%20is%20limited%20by%20a%20carrying%20capacity%20%24K%24%3A%20%5C%5B%5Cfrac%7BdN%7D%7Bdt%7D%20%3D%20r%20N%20%5Cleft(1%20-%20%5Cfrac%7BN%7D%7BK%7D%5Cright).%5C%5D%0A%0A%20%20%20%20**Before%20writing%20any%20code%3A**%20start%20with%20%24N(0)%20%3D%205%24%2C%20%24r%20%3D%200.8%24%20and%20%24K%20%3D%20100%24.%20Sketch%20on%20paper%20what%20you%20expect%20%24N(t)%24%20to%20look%20like%20for%20%240%20%5Cle%20t%20%5Cle%2015%24.%20Where%20does%20it%20end%20up%3F%20Is%20it%20fastest%20at%20the%20start%2C%20the%20middle%2C%20or%20the%20end%3F%0A%0A%20%20%20%20Then%2C%20using%20the%20cooling%20cell%20above%20as%20a%20template%3A%0A%0A%20%20%20%201.%20Complete%20%60logistic_rhs%60%20so%20it%20returns%20the%20right-hand%20side.%0A%20%20%20%202.%20Replace%20%60None%60%20with%20a%20call%20to%20%60solve_ivp%60%20that%20solves%20it%20from%20%24N(0)%20%3D%205%24%20over%20%240%20%5Cle%20t%20%5Cle%2015%24%2C%20at%20151%20equally%20spaced%20times.%0A%0A%20%20%20%20The%20cell%20after%20that%20plots%20your%20solution%20once%20it's%20right%2C%20so%20you%20can%20compare%20it%20with%20your%20sketch.%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%20def%20logistic_rhs(t%2C%20N)%3A%0A%20%20%20%20%20%20%20%20return%20%5B0.0%5D%20%20%23%20%E2%86%90%20replace%200.0%0A%0A%20%20%20%20sol_logistic%20%3D%20None%20%20%23%20%E2%86%90%20replace%20None%20with%20a%20call%20to%20solve_ivp%0A%20%20%20%20return%20(sol_logistic%2C)%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20sol_logistic)%3A%0A%20%20%20%20if%20sol_logistic%20is%20None%3A%0A%20%20%20%20%20%20%20%20print(%22Not%20attempted%20yet%3A%20replace%20None%20in%20the%20cell%20above.%22)%0A%20%20%20%20elif%20len(sol_logistic.t)%20!%3D%20151%20or%20abs(sol_logistic.t%5B-1%5D%20-%2015)%20%3E%201e-9%3A%0A%20%20%20%20%20%20%20%20print(f%22The%20solver%20ran%2C%20but%20not%20at%20the%20right%20times%3A%20it%20gave%20%7Blen(sol_logistic.t)%7D%20times%2C%20ending%20at%20t%20%3D%20%7Bsol_logistic.t%5B-1%5D%7D.%20Check%20t_eval.%22)%0A%20%20%20%20elif%20abs(sol_logistic.y%5B0%5D%5B0%5D%20-%205)%20%3E%201e-9%3A%0A%20%20%20%20%20%20%20%20print(f%22Check%20the%20initial%20value%3A%20N(0)%20came%20out%20as%20%7Bsol_logistic.y%5B0%5D%5B0%5D%7D.%22)%0A%20%20%20%20elif%20not%20(99%20%3C%20sol_logistic.y%5B0%5D%5B-1%5D%20%3C%20100.5)%3A%0A%20%20%20%20%20%20%20%20print(f%22Not%20yet%3A%20N(15)%20came%20out%20as%20%7Bsol_logistic.y%5B0%5D%5B-1%5D%3A.2f%7D.%20Check%20logistic_rhs%2C%20including%20its%20brackets.%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print(f%22%E2%9C%93%20Correct%3A%20N(15)%20%3D%20%7Bsol_logistic.y%5B0%5D%5B-1%5D%3A.2f%7D%22)%0A%20%20%20%20%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots()%0A%20%20%20%20%20%20%20%20_ax.plot(sol_logistic.t%2C%20sol_logistic.y%5B0%5D)%0A%20%20%20%20%20%20%20%20_ax.axhline(100%2C%20color%3D%22grey%22%2C%20linestyle%3D%22%3A%22)%0A%20%20%20%20%20%20%20%20_ax.set_xlabel(%22t%22)%0A%20%20%20%20%20%20%20%20_ax.set_ylabel(%22N%22)%0A%20%20%20%20%20%20%20%20plt.show()%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%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20def%20logistic_rhs(t%2C%20N)%3A%0A%20%20%20%20%20%20%20%20return%20%5B0.8%20*%20N%5B0%5D%20*%20(1%20-%20N%5B0%5D%20%2F%20100)%5D%0A%0A%20%20%20%20sol_logistic%20%3D%20solve_ivp(logistic_rhs%2C%20%5B0%2C%2015%5D%2C%20%5B5%5D%2C%20t_eval%3Dnp.linspace(0%2C%2015%2C%20151))%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20An%20S-shaped%20curve%3A%20slow%20at%20first%20(few%20individuals)%2C%20fastest%20around%20%24N%20%3D%20K%2F2%20%3D%2050%24%2C%20then%20levelling%20off%20at%20%24K%20%3D%20100%24.%20The%20three%20changes%20from%20the%20cooling%20template%20were%20the%20formula%2C%20the%20time%20span%2C%20and%20the%20initial%20value.%20Everything%20else%20was%20copied.%0A%0A%20%20%20%20%2F%2F%2F%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%208.%20Reading%20error%20messages%0A%0A%20%20%20%20Error%20messages%20look%20alarming%20but%20are%20usually%20helpful.%20**Read%20the%20last%20line%20first**%3A%20it%20names%20the%20kind%20of%20error%20and%2C%20usually%2C%20the%20exact%20problem.%20The%20lines%20above%20it%20show%20where%20it%20happened.%0A%0A%20%20%20%20%23%23%23%20Exercise%208.1%3A%20what%20went%20wrong%3F%0A%0A%20%20%20%20For%20each%20piece%20of%20code%2C%20the%20last%20line%20of%20its%20error%20message%20is%20shown.%20Say%20what's%20wrong%20and%20how%20you'd%20fix%20it.%20(You%20can%20type%20them%20into%20the%20cell%20below%20to%20see%20the%20full%20messages.)%0A%0A%20%20%20%20**(a)**%0A%20%20%20%20%60%60%60python%0A%20%20%20%20N0%20%3D%2050%0A%20%20%20%20N_5%20%3D%20N0%20*%20r%20**%205%0A%20%20%20%20%60%60%60%0A%20%20%20%20%60NameError%3A%20name%20'r'%20is%20not%20defined%60%0A%0A%20%20%20%20**(b)**%0A%20%20%20%20%60%60%60python%0A%20%20%20%20def%20growth(N0%2C%20R%2C%20n)%3A%0A%20%20%20%20return%20N0%20*%20R%20**%20n%0A%20%20%20%20%60%60%60%0A%20%20%20%20%60IndentationError%3A%20expected%20an%20indented%20block%20after%20function%20definition%20on%20line%201%60%0A%0A%20%20%20%20**(c)**%0A%20%20%20%20%60%60%60python%0A%20%20%20%20times%20%3D%20np.linspace(0%2C%2010%2C%20101)%0A%20%20%20%20times(0)%0A%20%20%20%20%60%60%60%0A%20%20%20%20%60TypeError%3A%20'numpy.ndarray'%20object%20is%20not%20callable%60%0A%0A%20%20%20%20**(d)**%0A%20%20%20%20%60%60%60python%0A%20%20%20%20T%20%3D%2020%20%2B%2060%20*%20np.exp(-0.5%20*%203%0A%20%20%20%20%60%60%60%0A%20%20%20%20%60SyntaxError%3A%20'('%20was%20never%20closed%60%0A%0A%20%20%20%20**(e)**%20You%20copy%20two%20lecture%20cells%20into%20your%20own%20notebook%2C%20and%20both%20contain%20the%20line%20%60k%20%3D%200.5%60.%20Marimo%20refuses%20to%20run%20them%20and%20says%20the%20variable%20%60k%60%20is%20defined%20in%20more%20than%20one%20cell.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%20-%20**(a)**%20%60r%60%20was%20never%20given%20a%20value.%20Either%20add%20a%20line%20like%20%60r%20%3D%201.5%60%20before%20it%2C%20or%20this%20is%20a%20typo%20for%20a%20name%20you%20did%20define%20(names%20are%20case-sensitive%3A%20%60R%60%20is%20not%20%60r%60).%0A%20%20%20%20-%20**(b)**%20The%20body%20of%20a%20function%20must%20be%20indented.%20Put%20four%20spaces%20before%20%60return%60.%0A%20%20%20%20-%20**(c)**%20Round%20brackets%20mean%20%22call%20a%20function%22.%20To%20get%20an%20entry%20of%20an%20array%2C%20use%20square%20brackets%3A%20%60times%5B0%5D%60.%0A%20%20%20%20-%20**(d)**%20A%20missing%20closing%20bracket.%20Count%20them%3A%20every%20%60(%60%20needs%20a%20%60)%60.%20Here%20it%20should%20end%20%60np.exp(-0.5%20*%203)%60.%0A%20%20%20%20-%20**(e)**%20In%20marimo%2C%20every%20name%20can%20be%20defined%20in%20only%20one%20cell%2C%20so%20it%20always%20knows%20which%20cell%20a%20value%20came%20from.%20Rename%20one%20of%20them%20(%60k2%60%2C%20%60k_fast%60%2C%20...)%2C%20or%20start%20the%20name%20with%20an%20underscore%2C%20%60_k%60%2C%20which%20makes%20it%20private%20to%20its%20own%20cell.%0A%0A%20%20%20%20%2F%2F%2F%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%20%23%20try%20the%20broken%20code%20from%20Exercise%208.1%20here%2C%20if%20you%20want%20to%20see%20the%20full%20messages%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%209.%20Putting%20it%20together%3A%20read%20a%20whole%20lecture%20cell%0A%0A%20%20%20%20Below%20is%20the%20draining-tank%20cell%20from%20the%20Week%201%20lecture%2C%20with%20the%20sliders%20replaced%20by%20numbers%20(and%20one%20solver%20option%20dropped).%20It's%20the%20longest%20cell%20in%20that%20lecture.%20You%20now%20know%20every%20piece%20of%20it.%0A%0A%20%20%20%20%23%23%23%20Exercise%209.1%0A%0A%20%20%20%20Read%20the%20cell%2C%20then%20answer%3A%0A%0A%20%20%20%201.%20Which%20line%20is%20the%20exact%20(analytic)%20solution%20for%20the%20depth%3F%0A%20%20%20%202.%20Which%20lines%20set%20up%20and%20solve%20the%20ODE%20numerically%3F%20Write%20the%20ODE%20being%20solved%20in%20mathematical%20notation.%0A%20%20%20%203.%20Which%20lines%20could%20you%20delete%20and%20still%20get%20a%20(plainer)%20plot%20with%20both%20curves%20on%20it%3F%0A%20%20%20%204.%20The%20tank%20currently%20starts%202%20m%20deep.%20**Before%20changing%20anything**%2C%20use%20the%20line%20that%20defines%20%60t_drain%60%20to%20predict%20how%20much%20longer%20the%20tank%20takes%20to%20drain%20if%20it%20starts%204%20m%20deep.%20Then%20change%20%60h0_tank%60%20and%20check.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20solve_ivp)%3A%0A%20%20%20%20h0_tank%20%3D%202.0%20%20%20%20%20%23%20initial%20depth%20(m)%0A%20%20%20%20aA%20%3D%200.005%20%20%20%20%20%20%20%20%23%20area%20ratio%20a%2FA%0A%20%20%20%20g%20%3D%209.81%0A%0A%20%20%20%20c_tank%20%3D%20aA%20*%20np.sqrt(2%20*%20g)%20%20%20%20%20%20%20%20%20%20%23%20shorthand%3A%20(a%2FA)%20sqrt(2g)%0A%20%20%20%20t_drain%20%3D%202%20*%20np.sqrt(h0_tank)%20%2F%20c_tank%0A%20%20%20%20t_eval_tank%20%3D%20np.linspace(0%2C%20t_drain%20*%201.05%2C%20400)%0A%20%20%20%20h_exact%20%3D%20h0_tank%20*%20np.maximum(1%20-%20t_eval_tank%20%2F%20t_drain%2C%200.0)%20**%202%0A%0A%20%20%20%20def%20tank_ode(t%2C%20h)%3A%0A%20%20%20%20%20%20%20%20return%20%5B-c_tank%20*%20np.sqrt(max(h%5B0%5D%2C%200.0))%5D%0A%0A%20%20%20%20sol_tank%20%3D%20solve_ivp(tank_ode%2C%20%5B0%2C%20t_drain%20*%201.05%5D%2C%20%5Bh0_tank%5D%2C%20t_eval%3Dt_eval_tank)%0A%0A%20%20%20%20fig_tank%2C%20ax_tank%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20ax_tank.plot(t_eval_tank%2C%20h_exact%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2.5%2C%20label%3D%22Analytic%22)%0A%20%20%20%20ax_tank.plot(sol_tank.t%2C%20sol_tank.y%5B0%5D%2C%20color%3D%22tomato%22%2C%20linewidth%3D2%2C%20linestyle%3D%22--%22%2C%20label%3D%22solve_ivp%22)%0A%20%20%20%20ax_tank.axvline(t_drain%2C%20color%3D%22grey%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D1.5)%0A%20%20%20%20ax_tank.set_xlabel(%22Time%20%24t%24%20(s)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax_tank.set_ylabel(%22Depth%20%24h(t)%24%20(m)%22%2C%20fontsize%3D13)%0A%20%20%20%20ax_tank.set_title(f%22Draining%20tank%3A%20%24h_0%20%3D%20%7Bh0_tank%7D%24%20m%2C%20drains%20in%20%7Bt_drain%3A.1f%7D%20s%22%2C%20fontsize%3D13)%0A%20%20%20%20ax_tank.legend(fontsize%3D11)%0A%20%20%20%20ax_tank.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20fig_tank.tight_layout()%0A%20%20%20%20fig_tank%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%2F%2F%2F%20details%20%7C%20Show%20answer%0A%0A%20%20%20%201.%20%60h_exact%20%3D%20h0_tank%20*%20np.maximum(1%20-%20t_eval_tank%20%2F%20t_drain%2C%200.0)%20**%202%60%2C%20which%20is%20%24h(t)%20%3D%20h_0%5C%2C(1%20-%20t%2Ft_%5Ctext%7Bdrain%7D)%5E2%24.%20The%20%60np.maximum(...%2C%200.0)%60%20keeps%20it%20at%20zero%20once%20the%20tank%20is%20empty%2C%20instead%20of%20the%20formula%20curving%20back%20up.%0A%20%20%20%202.%20%60def%20tank_ode%60%20(two%20lines)%20and%20the%20%60sol_tank%20%3D%20solve_ivp(...)%60%20line.%20The%20ODE%20is%20%24%5Cfrac%7Bdh%7D%7Bdt%7D%20%3D%20-%5Cfrac%7Ba%7D%7BA%7D%5Csqrt%7B2gh%7D%24.%20Inside%20%60tank_ode%60%2C%20%60max(h%5B0%5D%2C%200.0)%60%20stops%20the%20solver%20ever%20taking%20the%20square%20root%20of%20a%20tiny%20negative%20number.%0A%20%20%20%203.%20%60figsize%3D...%60%2C%20every%20%60color%3D%60%2C%20%60linewidth%3D%60%2C%20%60linestyle%3D%60%20and%20%60fontsize%3D%60%2C%20the%20%60axvline%60%20line%2C%20the%20labels%2C%20title%2C%20grid%20and%20%60tight_layout%60.%20Keeping%20the%20legend%20(and%20the%20%60label%3D%60s)%20is%20what%20tells%20you%20which%20curve%20is%20which.%0A%20%20%20%204.%20%24t_%5Ctext%7Bdrain%7D%20%3D%202%5Csqrt%7Bh_0%7D%2Fc%24%20grows%20like%20%24%5Csqrt%7Bh_0%7D%24%2C%20so%20doubling%20the%20depth%20multiplies%20the%20time%20by%20%24%5Csqrt%7B2%7D%20%5Capprox%201.41%24%3A%20from%20about%20127.7%20s%20to%20about%20180.6%20s.%20Twice%20the%20water%2C%20but%20it%20comes%20out%20faster%20at%20the%20start%20because%20the%20pressure%20is%20higher.%0A%0A%20%20%20%20%2F%2F%2F%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%20Lines%20you%20can%20safely%20skim%0A%0A%20%20%20%20When%20you%20look%20at%20a%20lecture%20cell%2C%20these%20are%20bookkeeping%2C%20not%20mathematics%3A%0A%0A%20%20%20%20-%20**Styling**%3A%20%60figsize%60%2C%20%60color%60%2C%20%60linewidth%60%2C%20%60linestyle%60%2C%20%60fontsize%60%2C%20%60alpha%60%2C%20%60grid%60%2C%20%60tight_layout%60.%0A%20%20%20%20-%20**%60mo.vstack(%5Bslider1%2C%20slider2%2C%20fig%5D)%60**%3A%20just%20%22show%20the%20sliders%2C%20then%20the%20figure%20underneath%22.%0A%20%20%20%20-%20**%60something_slider.value%60**%3A%20the%20number%20the%20slider%20is%20currently%20set%20to.%20A%20line%20like%20%60R_d%20%3D%20R_slider.value%60%20just%20means%20%22R%20is%20whatever%20the%20slider%20says%22.%0A%20%20%20%20-%20**Names%20starting%20with%20%60_%60**%2C%20like%20%60_fig%60%3A%20a%20marimo%20convention%20for%20names%20used%20inside%20one%20cell%20only.%20Read%20%60_fig%60%20as%20%60fig%60.%0A%20%20%20%20-%20**%60def%20_(...)%3A%60%20and%20%60return%60%20around%20every%20cell**%2C%20if%20you%20ever%20open%20a%20notebook's%20%60.py%60%20file%3A%20marimo%20writes%20these%20for%20you.%20You%20never%20type%20them.%0A%0A%20%20%20%20What's%20left%20is%20usually%20a%20few%20lines%3A%20the%20inputs%2C%20the%20formula%20or%20the%20ODE%2C%20and%20%60ax.plot%60.%20Find%20those%20first.%0A%0A%20%20%20%20If%20something%20in%20a%20lecture%20still%20doesn't%20make%20sense%2C%20look%20it%20up%20in%20the%20%5BPython%20Basics%20reference%20guide%5D(python_basics_guide.html)%2C%20or%20ask%20in%20the%20lab%3A%20that's%20what%20it's%20for.%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
f99175017253b5ee38e0bab1f961f8a9