import%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20width%3D%22medium%22%2C%0A%20%20%20%20app_title%3D%22Week%205%20%E2%80%94%20Second-order%20ODEs%3A%20roots%20and%20oscillations%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%205%3A%20Second-order%20linear%20ODEs%20%E2%80%94%20roots%20and%20oscillations%0A%20%20%20%20%23%23%20Computation%20lecture%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%20On%20Monday%20and%20Tuesday%20you%20solved%20equations%20like%20%5C%5Bp%5C%2Cy''%20%2B%20q%5C%2Cy'%20%2B%20r%5C%2Cy%20%3D%200%5C%5D%20by%20trying%20%24y%20%3D%20e%5E%7Bmt%7D%24%20and%20solving%20the%20**auxiliary%20equation**%20%24pm%5E2%20%2B%20qm%20%2B%20r%20%3D%200%24%20(equation%20(4.13)%20in%20the%20notes).%20Its%20roots%20decide%20everything%3A%20two%20real%20roots%2C%20one%20repeated%20root%2C%20or%20a%20complex%20pair.%0A%0A%20%20%20%20Today%20we%20do%20the%20same%20mathematics%20on%20the%20computer%2C%20step%20by%20step%3A%0A%0A%20%20%20%201.%20a%20short%20Python%20warm-up%20(picking%20numbers%20out%20of%20an%20array)%3B%0A%20%20%20%202.%20the%20auxiliary%20equation%20in%20one%20line%20of%20code%3B%0A%20%20%20%203.%20the%20damped%20oscillator%20(4.17)%3A%20watch%20the%20roots%20move%20and%20the%20solution%20change%20with%20them%3B%0A%20%20%20%204.%20how%20the%20computer%20solves%20the%20ODE%20without%20any%20formula%3B%0A%20%20%20%205.%20a%20pendulum%2C%20where%20there%20is%20no%20formula%20at%20all.%0A%0A%20%20%20%20The%20notes%20write%20the%20variable%20as%20%24x%24.%20Here%20it%20is%20always%20time%2C%20so%20we%20call%20it%20%24t%24.%20Nothing%20else%20changes.%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%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(r%22%22%22%0A%20%20%20%20%23%23%201.%20Warm-up%3A%20counting%20from%200%0A%0A%20%20%20%20In%20last%20week's%20poll%20we%20asked%20what%20%60N%5B1%3A3%5D%60%20gives%20for%20%60N%20%3D%20np.array(%5B100%2C%20135%2C%20182%2C%20246%5D)%60.%20Only%2023%25%20chose%20the%20right%20answer%3B%20almost%20half%20chose%20%60%5B135%2C%20182%2C%20246%5D%60.%20Two%20rules%20explain%20it.%0A%0A%20%20%20%20**Rule%201.%20Python%20counts%20positions%20from%200.**%0A%0A%20%20%20%20%7C%20value%20%7C%20100%20%7C%20135%20%7C%20182%20%7C%20246%20%7C%0A%20%20%20%20%7C---%7C---%7C---%7C---%7C---%7C%0A%20%20%20%20%7C%20position%20%7C%200%20%7C%201%20%7C%202%20%7C%203%20%7C%0A%20%20%20%20%7C%20from%20the%20end%20%7C%20%E2%88%924%20%7C%20%E2%88%923%20%7C%20%E2%88%922%20%7C%20%E2%88%921%20%7C%0A%0A%20%20%20%20**Predict**%20what%20each%20line%20prints%20before%20you%20run%20the%20cell.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20N%20%3D%20np.array(%5B100%2C%20135%2C%20182%2C%20246%5D)%0A%20%20%20%20print(N%5B0%5D)%0A%20%20%20%20print(N%5B1%5D)%0A%20%20%20%20print(N%5B-1%5D)%0A%20%20%20%20return%20(N%2C)%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**Rule%202.%20A%20slice%20%60N%5Bstart%3Astop%5D%60%20includes%20%60start%60%20but%20stops%20*before*%20%60stop%60.**%20So%20%60N%5B1%3A3%5D%60%20is%20positions%201%20and%202%2C%20and%20the%20number%20of%20values%20you%20get%20is%20%60stop%20%E2%88%92%20start%60.%20Leave%20out%20%60start%60%20to%20begin%20at%20the%20beginning%3B%20leave%20out%20%60stop%60%20to%20go%20to%20the%20end.%0A%0A%20%20%20%20**Predict**%20again%2C%20then%20run.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(N)%3A%0A%20%20%20%20print(N%5B1%3A3%5D)%0A%20%20%20%20print(N%5B%3A2%5D)%0A%20%20%20%20print(N%5B2%3A%5D)%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%20Why%20stop%20*before*%3F%20(optional)%0A%0A%20%20%20%20It%20makes%20the%20pieces%20fit%20together%3A%20%60N%5B%3A2%5D%60%20and%20%60N%5B2%3A%5D%60%20split%20the%20array%20at%20position%202%20with%20nothing%20missing%20and%20nothing%20repeated.%20And%20%60N%5B0%3Alen(N)%5D%60%20is%20the%20whole%20array.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Do%20all%20languages%20count%20from%200%3F%20(optional)%0A%0A%20%20%20%20No.%20It%20is%20a%20convention%2C%20and%20languages%20split%20into%20two%20camps.%0A%0A%20%20%20%20%7C%20counts%20from%201%20%7C%20counts%20from%200%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20Julia%2C%20R%2C%20Fortran%2C%20Excel%20rows%20and%20columns%20%7C%20Python%2C%20C%2C%20C%2B%2B%2C%20Java%2C%20JavaScript%2C%20Rust%20%7C%0A%0A%20%20%20%20-%20**Counting%20from%201**%20is%20common%20in%20languages%20built%20for%20maths%20and%20statistics%2C%20because%20it%20matches%20how%20we%20write%20%24x_1%2C%20x_2%2C%20%5Cdots%2C%20x_n%24%20on%20paper.%20In%20Julia%20or%20R%2C%20%60N%5B1%5D%60%20is%20100%20and%20%60N%5B1%3A3%5D%60%20is%20%60%5B100%2C%20135%2C%20182%5D%60%3A%20the%20slice%20**includes%20both%20ends**.%0A%20%20%20%20-%20**Counting%20from%200**%20comes%20from%20C%2C%20where%20the%20position%20is%20the%20distance%20from%20the%20start%20of%20the%20array%20in%20the%20computer's%20memory%3A%20the%20first%20value%20is%200%20steps%20along.%20Most%20general-purpose%20languages%20followed%20C.%0A%20%20%20%20-%20**Negative%20positions**%20differ%20too%3A%20in%20Python%20%60N%5B-1%5D%60%20is%20the%20last%20value%2C%20in%20R%20%60N%5B-1%5D%60%20means%20%22everything%20except%20the%20first%22%2C%20and%20Julia%20writes%20the%20last%20value%20as%20%60N%5Bend%5D%60.%0A%0A%20%20%20%20If%20you%20move%20between%20languages%2C%20these%20are%20the%20first%20things%20to%20check.%20Edsger%20Dijkstra's%20one-page%20note%20*Why%20numbering%20should%20start%20at%20zero*%20(1982%2C%20EWD831)%20argues%20for%20Python's%20choice%3A%20count%20from%200%20and%20stop%20*before*%20the%20end.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20We%20will%20use%20exactly%20these%20today%3A%20%60roots%5B0%5D%60%20and%20%60roots%5B1%5D%60%20are%20the%20two%20roots%20of%20an%20auxiliary%20equation%2C%20and%20in%20Section%204%20a%20loop%20reads%20%60y_values%5B-1%5D%60%2C%20the%20latest%20value%20in%20a%20list.%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%202.%20The%20auxiliary%20equation%20in%20one%20line%0A%0A%20%20%20%20Trying%20%24y%20%3D%20e%5E%7Bmt%7D%24%20in%20%24p%5C%2Cy''%20%2B%20q%5C%2Cy'%20%2B%20r%5C%2Cy%20%3D%200%24%20gave%20%5C%5Bpm%5E2%20%2B%20qm%20%2B%20r%20%3D%200.%20%5Ctag%7B4.13%7D%5C%5D%20NumPy's%20%60np.roots%60%20finds%20the%20roots%20of%20a%20polynomial.%20You%20give%20it%20the%20coefficients%20**in%20a%20list%2C%20highest%20power%20first**%3A%20%60%5Bp%2C%20q%2C%20r%5D%60.%0A%0A%20%20%20%20First%20row%20of%20the%20summary%20table%20in%20Section%204.8%3A%20%24y''%20-%205y'%20%2B%206y%20%3D%200%24%2C%20so%20%24p%20%3D%201%24%2C%20%24q%20%3D%20-5%24%2C%20%24r%20%3D%206%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20roots_example%20%3D%20np.roots(%5B1%2C%20-5%2C%206%5D)%0A%20%20%20%20print(roots_example)%0A%20%20%20%20print(%22first%20root%3A%20%22%2C%20roots_example%5B0%5D)%0A%20%20%20%20print(%22second%20root%3A%22%2C%20roots_example%5B1%5D)%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%20Roots%203%20and%202%2C%20so%20the%20complementary%20function%20(CF)%20is%20%24c_1e%5E%7B3t%7D%20%2B%20c_2e%5E%7B2t%7D%24%2C%20as%20in%20the%20table.%20(%603.0000000000000004%60%20is%203%3A%20the%20computer%20keeps%20about%2016%20digits%2C%20and%20the%20last%20one%20is%20rounding.)%20Now%20all%20five%20rows%20of%20the%20table%20at%20once.%20**Look%20out%20for%20two%20things%3A**%20Python%20writes%20the%20imaginary%20unit%20%24i%24%20as%20%60j%60%2C%20and%20in%20%24y''%20%2B%209y%20%3D%200%24%20there%20is%20no%20%24y'%24%20term%2C%20so%20its%20coefficient%20%24q%24%20is%20a%20**0**%20that%20you%20must%20type%20in.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20print(%22y''%20-%205y'%20%2B%206y%20%3D%200%20%20roots%3A%22%2C%20np.roots(%5B1%2C%20-5%2C%206%5D))%0A%20%20%20%20print(%22y''%20%2B%206y'%20%2B%209y%20%3D%200%20%20roots%3A%22%2C%20np.roots(%5B1%2C%206%2C%209%5D))%0A%20%20%20%20print(%22y''%20-%202y'%20%2B%205y%20%3D%200%20%20roots%3A%22%2C%20np.roots(%5B1%2C%20-2%2C%205%5D))%0A%20%20%20%20print(%22y''%20%20%20%20%20%20%2B%209y%20%3D%200%20%20%20roots%3A%22%2C%20np.roots(%5B1%2C%200%2C%209%5D))%0A%20%20%20%20print(%22y''%20%20%20%20%20%20-%209y%20%3D%200%20%20%20roots%3A%22%2C%20np.roots(%5B1%2C%200%2C%20-9%5D))%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%20The%20repeated%20root%20may%20come%20out%20as%20something%20like%20%60-3.%2B3.7e-08j%60%3A%20%60e-08%60%20means%20%24%5Ctimes%2010%5E%7B-8%7D%24%2C%20so%20the%20imaginary%20part%20is%20%240.000000037%24%2C%20rounding%20error%20again.%20Read%20it%20as%20%24-3%24%20twice.%0A%0A%20%20%20%20%601.%2B2.j%60%20means%20%241%20%2B%202i%24%2C%20so%20%24%5Calpha%20%3D%201%24%2C%20%24%5Cbeta%20%3D%202%24%20and%20the%20CF%20is%20%24e%5E%7Bt%7D(c_1%5Ccos%202t%20%2B%20c_2%5Csin%202t)%24.%20%600.%2B3.j%60%20is%20%243i%24%3A%20pure%20oscillation%2C%20%24c_1%5Ccos%203t%20%2B%20c_2%5Csin%203t%24.%0A%0A%20%20%20%20**Question.**%20What%20would%20%60np.roots(%5B1%2C%209%5D)%60%20solve%3F%20Why%20is%20it%20the%20wrong%20thing%20for%20%24y''%20%2B%209y%20%3D%200%24%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Answer%0A%0A%20%20%20%20%60%5B1%2C%209%5D%60%20means%20%24m%20%2B%209%20%3D%200%24%2C%20a%20polynomial%20of%20degree%201%2C%20with%20the%20single%20root%20%24-9%24.%20Dropping%20the%200%20for%20the%20missing%20%24y'%24%20term%20turns%20the%20quadratic%20into%20a%20different%20equation%2C%20and%20Python%20can't%20tell%20you've%20done%20it.%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.%20The%20damped%20oscillator%0A%0A%20%20%20%20A%20mass%20on%20a%20spring%2C%20with%20friction%20proportional%20to%20its%20speed%20(Section%204.9)%3A%20%5C%5By''%20%2B%202k%5C%2Cy'%20%2B%20%5Comega%5E2%20y%20%3D%200.%20%5Ctag%7B4.17%7D%5C%5D%20Here%20%24y%24%20is%20how%20far%20the%20mass%20is%20from%20its%20rest%20position%2C%20%24%5Comega%24%20is%20set%20by%20the%20spring%20and%20%24k%20%5Cge%200%24%20by%20the%20friction.%20The%20auxiliary%20equation%20is%20%24m%5E2%20%2B%202km%20%2B%20%5Comega%5E2%20%3D%200%24%2C%20so%20in%20code%20the%20coefficients%20are%20%60%5B1%2C%202*k%2C%20omega**2%5D%60.%0A%0A%20%20%20%20We%20fix%20%24%5Comega%20%3D%202%24%2C%20pull%20the%20mass%20to%20%24y%20%3D%201%24%20and%20release%20it%20from%20rest%3A%20%24y(0)%20%3D%201%24%2C%20%24y'(0)%20%3D%200%24.%20Every%20plot%20in%20this%20section%20starts%20this%20way.%0A%0A%20%20%20%20%23%23%23%203.1%20The%20formula%2C%20case%20by%20case%0A%0A%20%20%20%20Each%20case%20from%20the%20notes%20becomes%20one%20branch%20of%20an%20%60if%60.%20The%20roots%20decide%20which%20case%20we%20are%20in%2C%20and%20so%20the%20shape%20of%20the%20motion%3B%20the%20two%20starting%20conditions%20only%20fix%20the%20constants%20%24c_1%24%2C%20%24c_2%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20damped_solution(t%2C%20k%2C%20omega)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Solution%20of%20y''%20%2B%202k%20y'%20%2B%20omega%5E2%20y%20%3D%200%20with%20y(0)%20%3D%201%2C%20y'(0)%20%3D%200.%22%22%22%0A%20%20%20%20%20%20%20%20if%20k%20%3C%20omega%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Case%203%3A%20complex%20roots%20-k%20%C2%B1%20ip%20%20(underdamped)%0A%20%20%20%20%20%20%20%20%20%20%20%20p%20%3D%20np.sqrt(omega**2%20-%20k**2)%0A%20%20%20%20%20%20%20%20%20%20%20%20c1%20%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20c2%20%3D%20k%20%2F%20p%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20np.exp(-k%20*%20t)%20*%20(c1%20*%20np.cos(p%20*%20t)%20%2B%20c2%20*%20np.sin(p%20*%20t))%0A%20%20%20%20%20%20%20%20elif%20k%20%3D%3D%20omega%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Case%202%3A%20one%20repeated%20root%20-k%20%20(critically%20damped)%0A%20%20%20%20%20%20%20%20%20%20%20%20c1%20%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20c2%20%3D%20k%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(c1%20%2B%20c2%20*%20t)%20*%20np.exp(-k%20*%20t)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Case%201%3A%20two%20real%20roots%20m1%2C%20m2%20%20(overdamped)%0A%20%20%20%20%20%20%20%20%20%20%20%20m1%20%3D%20-k%20%2B%20np.sqrt(k**2%20-%20omega**2)%0A%20%20%20%20%20%20%20%20%20%20%20%20m2%20%3D%20-k%20-%20np.sqrt(k**2%20-%20omega**2)%0A%20%20%20%20%20%20%20%20%20%20%20%20c1%20%3D%20-m2%20%2F%20(m1%20-%20m2)%0A%20%20%20%20%20%20%20%20%20%20%20%20c2%20%3D%20m1%20%2F%20(m1%20-%20m2)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20c1%20*%20np.exp(m1%20*%20t)%20%2B%20c2%20*%20np.exp(m2%20*%20t)%0A%0A%20%20%20%20return%20(damped_solution%2C)%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%20Where%20%24c_1%24%20and%20%24c_2%24%20come%20from%0A%0A%20%20%20%20-%20**Underdamped**%2C%20%24y%20%3D%20e%5E%7B-kt%7D(c_1%5Ccos%20pt%20%2B%20c_2%5Csin%20pt)%24%3A%20%24y(0)%20%3D%20c_1%20%3D%201%24.%20Differentiating%2C%20%24y'(0)%20%3D%20-kc_1%20%2B%20pc_2%20%3D%200%24%2C%20so%20%24c_2%20%3D%20k%2Fp%24.%0A%20%20%20%20-%20**Critical**%2C%20%24y%20%3D%20(c_1%20%2B%20c_2t)e%5E%7B-kt%7D%24%3A%20%24y(0)%20%3D%20c_1%20%3D%201%24%20and%20%24y'(0)%20%3D%20c_2%20-%20kc_1%20%3D%200%24%2C%20so%20%24c_2%20%3D%20k%24.%0A%20%20%20%20-%20**Overdamped**%2C%20%24y%20%3D%20c_1e%5E%7Bm_1t%7D%20%2B%20c_2e%5E%7Bm_2t%7D%24%3A%20%24c_1%20%2B%20c_2%20%3D%201%24%20and%20%24m_1c_1%20%2B%20m_2c_2%20%3D%200%24.%20Solve%20these%20two%20equations%20for%20%24c_1%24%2C%20%24c_2%24.%20Since%20%24m_1%20%3E%20m_2%24%2C%20%24c_2%24%20comes%20out%20negative.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%23%203.2%20Watch%20it%20move%0A%0A%20%20%20%20Picture%20the%20mass%20hanging%20on%20its%20spring%20inside%20a%20tank%20of%20oil.%20The%20oil%20is%20the%20friction%3A%20the%20thicker%20the%20oil%2C%20the%20bigger%20%24k%24.%20Drag%20the%20time%20slider%20to%20run%20the%20motion%3B%20the%20dot%20on%20the%20graph%20follows%20the%20mass.%0A%0A%20%20%20%20%24k%20%3D%200%24%20(an%20empty%20tank)%20means%20no%20friction%20at%20all.%20That%20never%20quite%20happens%3A%20even%20in%20a%20vacuum%20the%20spring%20itself%20loses%20a%20little%20energy%20every%20time%20it%20flexes.%20It%20is%20an%20idealisation%2C%20like%20a%20frictionless%20surface.%0A%0A%20%20%20%20**Before%20you%20try%20it%3A**%20what%20will%20the%20mass%20do%20in%20very%20thin%20oil%3F%20In%20something%20as%20thick%20as%20honey%3F%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%20%23%20slider%20positions%3A%20very%20fine%20near%200%2C%20coarser%20further%20up%0A%20%20%20%20k_values%20%3D%20%5B0%2C%200.0005%2C%200.001%2C%200.002%2C%200.005%2C%200.01%2C%200.02%2C%200.05%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%200.1%2C%200.2%2C%200.3%2C%200.4%2C%200.5%2C%200.6%2C%200.7%2C%200.8%2C%200.9%2C%201.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201.1%2C%201.2%2C%201.3%2C%201.4%2C%201.5%2C%201.6%2C%201.7%2C%201.8%2C%201.9%2C%202.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%202.25%2C%202.5%2C%202.75%2C%203.0%2C%203.25%2C%203.5%2C%203.75%2C%204.0%5D%0A%20%20%20%20k_anim_slider%20%3D%20mo.ui.slider(steps%3Dk_values%2C%20value%3D0.5%2C%20show_value%3DTrue%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%20%20%20%20%20%20%20%20label%3Dr%22Friction%20%24k%24%20(thickness%20of%20the%20oil)%22)%0A%20%20%20%20t_anim_slider%20%3D%20mo.ui.slider(0.0%2C%208.0%2C%20step%3D0.05%2C%20value%3D0.0%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%20%20%20%20%20%20%20%20label%3Dr%22Time%20%24t%24%22)%0A%20%20%20%20return%20k_anim_slider%2C%20k_values%2C%20t_anim_slider%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(damped_solution%2C%20k_anim_slider%2C%20mo%2C%20np%2C%20plt%2C%20t_anim_slider)%3A%0A%20%20%20%20_k%20%3D%20k_anim_slider.value%0A%20%20%20%20_t_now%20%3D%20t_anim_slider.value%0A%20%20%20%20_y_now%20%3D%20damped_solution(_t_now%2C%20_k%2C%202.0)%0A%0A%20%20%20%20_fig_a%2C%20(_axm%2C%20_axg)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(11%2C%204.6)%2C%20sharey%3DTrue%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%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gridspec_kw%3D%7B%22width_ratios%22%3A%20%5B1%2C%202.4%5D%7D)%0A%0A%20%20%20%20%23%20left%3A%20ceiling%2C%20tank%20of%20oil%2C%20spring%20and%20mass%0A%20%20%20%20_axm.fill_between(%5B-0.8%2C%200.8%5D%2C%202.0%2C%202.15%2C%20color%3D%22%23555%22)%0A%20%20%20%20_axm.add_patch(plt.Rectangle((-0.6%2C%20-1.6)%2C%201.2%2C%203.1%2C%20facecolor%3D%22%23b9770e%22%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%20%20%20%20%20%20%20%20alpha%3D0.2%20*%20_k%2C%20edgecolor%3D%22none%22))%0A%20%20%20%20_axm.add_patch(plt.Rectangle((-0.6%2C%20-1.6)%2C%201.2%2C%203.1%2C%20facecolor%3D%22none%22%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%20%20%20%20%20%20%20%20edgecolor%3D%22%237e5109%22%2C%20linewidth%3D1.5))%0A%20%20%20%20if%20_k%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20_axm.text(0%2C%20-1.45%2C%20%22no%20oil%3A%20no%20friction%5Cn(an%20idealisation)%22%2C%20ha%3D%22center%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20va%3D%22bottom%22%2C%20fontsize%3D9%2C%20color%3D%22%237e5109%22)%0A%20%20%20%20elif%20_k%20%3D%3D%204%3A%0A%20%20%20%20%20%20%20%20_axm.text(0%2C%20-1.45%2C%20%22very%20thick%20oil%22%2C%20ha%3D%22center%22%2C%20va%3D%22bottom%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fontsize%3D9%2C%20color%3D%22white%22)%0A%20%20%20%20_top_of_mass%20%3D%20_y_now%20%2B%200.2%0A%20%20%20%20_n_zig%20%3D%2010%0A%20%20%20%20_zig_y%20%3D%20np.linspace(2.0%2C%20_top_of_mass%2C%202%20*%20_n_zig%20%2B%202)%0A%20%20%20%20_zig_x%20%3D%20np.zeros_like(_zig_y)%0A%20%20%20%20_zig_x%5B1%3A-1%5D%20%3D%200.15%20*%20np.array(%5B1%2C%20-1%5D%20*%20_n_zig)%0A%20%20%20%20_axm.plot(_zig_x%2C%20_zig_y%2C%20color%3D%22%23333%22%2C%20linewidth%3D1.6)%0A%20%20%20%20_axm.add_patch(plt.Rectangle((-0.25%2C%20_y_now%20-%200.2)%2C%200.5%2C%200.4%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%20%20%20%20%20%20%20%20facecolor%3D%22%231a5276%22%2C%20edgecolor%3D%22black%22%2C%20zorder%3D5))%0A%20%20%20%20_axm.axhline(0%2C%20color%3D%22grey%22%2C%20linestyle%3D%22--%22%2C%20linewidth%3D1)%0A%20%20%20%20_axm.text(0.62%2C%200.05%2C%20%22rest%22%2C%20fontsize%3D10%2C%20color%3D%22grey%22%2C%20va%3D%22bottom%22)%0A%20%20%20%20_axm.set_xlim(-0.9%2C%200.9)%0A%20%20%20%20_axm.set_ylim(-1.7%2C%202.2)%0A%20%20%20%20_axm.set_xticks(%5B%5D)%0A%20%20%20%20_axm.set_ylabel(r%22%24y%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axm.set_title(%22the%20mass%22%2C%20fontsize%3D12)%0A%0A%20%20%20%20%23%20right%3A%20the%20graph%20of%20y(t)%2C%20drawn%20up%20to%20now%0A%20%20%20%20_t_all%20%3D%20np.linspace(0%2C%208%2C%20600)%0A%20%20%20%20_y_all%20%3D%20damped_solution(_t_all%2C%20_k%2C%202.0)%0A%20%20%20%20_past%20%3D%20_t_all%20%3C%3D%20_t_now%0A%20%20%20%20_axg.plot(_t_all%2C%20_y_all%2C%20color%3D%22lightgrey%22%2C%20linewidth%3D1.5)%0A%20%20%20%20_axg.plot(_t_all%5B_past%5D%2C%20_y_all%5B_past%5D%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2.5)%0A%20%20%20%20_axg.plot(_t_now%2C%20_y_now%2C%20%22o%22%2C%20color%3D%22%231a5276%22%2C%20markersize%3D10%2C%20zorder%3D5)%0A%20%20%20%20_axg.axhline(_y_now%2C%20color%3D%22%231a5276%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D1)%0A%20%20%20%20_axg.axhline(0%2C%20color%3D%22grey%22%2C%20linestyle%3D%22--%22%2C%20linewidth%3D1)%0A%20%20%20%20_axg.set_xlim(0%2C%208)%0A%20%20%20%20_axg.set_xlabel(r%22%24t%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axg.set_title(rf%22%24y''%20%2B%202k%5C%2Cy'%20%2B%204y%20%3D%200%24%2C%20%20%20%24k%20%3D%20%7B_k%3Ag%7D%24%2C%20%20%20%24t%20%3D%20%7B_t_now%3A.2f%7D%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fontsize%3D12)%0A%20%20%20%20_axg.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig_a.tight_layout()%0A%20%20%20%20mo.vstack(%5Bk_anim_slider%2C%20t_anim_slider%2C%20_fig_a%5D)%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%203.3%20Roots%20and%20solution%20together%0A%0A%20%20%20%20**Before%20you%20move%20the%20slider%3A**%0A%0A%20%20%20%201.%20With%20no%20friction%20(%24k%20%3D%200%24)%20the%20equation%20is%20%24y''%20%2B%20%5Comega%5E2%20y%20%3D%200%24%2C%20**simple%20harmonic%20motion**%20(SHM%2C%20equation%20(4.14)).%20Where%20are%20the%20two%20roots%2C%20and%20what%20does%20the%20solution%20look%20like%3F%0A%20%20%20%202.%20As%20%24k%24%20grows%20the%20roots%20%24-k%20%5Cpm%20%5Csqrt%7Bk%5E2%20-%20%5Comega%5E2%7D%24%20move.%20What%20happens%20to%20them%20at%20%24k%20%3D%20%5Comega%20%3D%202%24%3F%0A%20%20%20%203.%20Which%20%24k%24%20do%20you%20think%20brings%20the%20mass%20back%20to%20rest%20fastest%3F%0A%20%20%20%204.%20Past%20%24k%20%3D%202%24%20there%20are%20two%20real%20roots%20but%20only%20one%20curve.%20How%20does%20each%20root%20show%20up%20in%20the%20solution%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(k_values%2C%20mo)%3A%0A%20%20%20%20k_slider%20%3D%20mo.ui.slider(steps%3Dk_values%2C%20value%3D0.5%2C%20show_value%3DTrue%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%20%20%20label%3Dr%22Friction%20%24k%24%20%20(%24%5Comega%20%3D%202%24)%22)%0A%20%20%20%20return%20(k_slider%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(damped_solution%2C%20k_slider%2C%20mo%2C%20np%2C%20plt)%3A%0A%20%20%20%20_k%20%3D%20k_slider.value%0A%20%20%20%20_omega%20%3D%202.0%0A%20%20%20%20_roots%20%3D%20np.roots(%5B1%2C%202%20*%20_k%2C%20_omega**2%5D)%0A%0A%20%20%20%20if%20_k%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20_case%20%3D%20r%22no%20friction%20(SHM)%3A%20roots%20%24%5Cpm%202i%24%2C%20oscillation%20forever%22%0A%20%20%20%20%20%20%20%20_col%20%3D%20%22%237d3c98%22%0A%20%20%20%20elif%20_k%20%3C%20_omega%3A%0A%20%20%20%20%20%20%20%20_case%20%3D%20%22underdamped%3A%20complex%20roots%2C%20decaying%20oscillation%22%0A%20%20%20%20%20%20%20%20_col%20%3D%20%22%231a5276%22%0A%20%20%20%20elif%20_k%20%3D%3D%20_omega%3A%0A%20%20%20%20%20%20%20%20_case%20%3D%20%22critically%20damped%3A%20one%20repeated%20root%22%0A%20%20%20%20%20%20%20%20_col%20%3D%20%22%231e8449%22%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_case%20%3D%20%22overdamped%3A%20two%20real%20roots%2C%20no%20oscillation%22%0A%20%20%20%20%20%20%20%20_col%20%3D%20%22%23922b21%22%0A%20%20%20%20_slow_col%20%3D%20%22%23e67e22%22%0A%20%20%20%20_fast_col%20%3D%20%22%2317a589%22%0A%0A%20%20%20%20_fig%2C%20(_axr%2C%20_axy)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%204.6)%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%20%20%20%20%20%20%20%20%20%20%20%20%20gridspec_kw%3D%7B%22width_ratios%22%3A%20%5B1%2C%201.25%5D%7D)%0A%0A%20%20%20%20%23%20left%3A%20the%20path%20the%20roots%20take%20as%20k%20goes%20from%200%20to%204%20(faint)%2C%20and%20where%20they%20are%20now%0A%20%20%20%20_ks%20%3D%20np.linspace(0%2C%204%2C%20400)%0A%20%20%20%20_path%20%3D%20np.array(%5Bnp.roots(%5B1%2C%202%20*%20_kk%2C%20_omega**2%5D)%20for%20_kk%20in%20_ks%5D)%0A%20%20%20%20_axr.plot(_path.real%2C%20_path.imag%2C%20%22.%22%2C%20color%3D%22%23b0b8c0%22%2C%20markersize%3D3%2C%20zorder%3D3)%0A%20%20%20%20_axr.axhline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8%2C%20zorder%3D1)%0A%20%20%20%20_axr.axvline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8%2C%20zorder%3D1)%0A%20%20%20%20if%20_k%20%3E%20_omega%3A%0A%20%20%20%20%20%20%20%20%23%20two%20real%20roots%3A%20colour%20each%20one%20to%20match%20its%20piece%20of%20the%20solution%0A%20%20%20%20%20%20%20%20_m1%20%3D%20-_k%20%2B%20np.sqrt(_k**2%20-%20_omega**2)%0A%20%20%20%20%20%20%20%20_m2%20%3D%20-_k%20-%20np.sqrt(_k**2%20-%20_omega**2)%0A%20%20%20%20%20%20%20%20_axr.plot(_m1%2C%200%2C%20%22o%22%2C%20color%3D_slow_col%2C%20markersize%3D12%2C%20zorder%3D5)%0A%20%20%20%20%20%20%20%20_axr.plot(_m2%2C%200%2C%20%22o%22%2C%20color%3D_fast_col%2C%20markersize%3D12%2C%20zorder%3D5)%0A%20%20%20%20%20%20%20%20_axr.text(_m1%2C%200.35%2C%20%22%24m_1%24%22%2C%20ha%3D%22center%22%2C%20fontsize%3D12%2C%20color%3D_slow_col)%0A%20%20%20%20%20%20%20%20_axr.text(_m2%2C%200.35%2C%20%22%24m_2%24%22%2C%20ha%3D%22center%22%2C%20fontsize%3D12%2C%20color%3D_fast_col)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_axr.plot(_roots.real%2C%20_roots.imag%2C%20%22o%22%2C%20color%3D_col%2C%20markersize%3D12%2C%20zorder%3D5)%0A%20%20%20%20_axr.set_xlim(-8%2C%201)%0A%20%20%20%20_axr.set_ylim(-2.6%2C%202.6)%0A%20%20%20%20_axr.set_aspect(%22equal%22)%0A%20%20%20%20_axr.set_xlabel(%22real%20part%22%2C%20fontsize%3D12)%0A%20%20%20%20_axr.set_ylabel(%22imaginary%20part%22%2C%20fontsize%3D12)%0A%20%20%20%20_axr.set_title(%22roots%20of%20%24m%5E2%20%2B%202km%20%2B%20%5C%5Comega%5E2%20%3D%200%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axr.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20if%20_k%20%3E%20_omega%3A%0A%20%20%20%20%20%20%20%20%23%20name%20each%20real%20root%20and%20colour%20it%20like%20its%20dot%0A%20%20%20%20%20%20%20%20_axr.text(-7.7%2C%202.3%2C%20f%22m1%20%3D%20%7B_m1%3A.4g%7D%22%2C%20fontsize%3D11%2C%20va%3D%22top%22%2C%20color%3D_slow_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20family%3D%22monospace%22)%0A%20%20%20%20%20%20%20%20_axr.text(-7.7%2C%201.85%2C%20f%22m2%20%3D%20%7B_m2%3A.4g%7D%22%2C%20fontsize%3D11%2C%20va%3D%22top%22%2C%20color%3D_fast_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20family%3D%22monospace%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_root_text%20%3D%20%22%5Cn%22.join(f%22%7Bnp.round(_rr%2C%204)%20%2B%200.0%3A.4g%7D%22%20for%20_rr%20in%20_roots)%0A%20%20%20%20%20%20%20%20_axr.text(-7.7%2C%202.3%2C%20_root_text%2C%20fontsize%3D11%2C%20va%3D%22top%22%2C%20color%3D_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20family%3D%22monospace%22)%0A%0A%20%20%20%20%23%20right%3A%20the%20solution%20from%20the%20formula%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C%208%2C%20600)%0A%20%20%20%20_y%20%3D%20damped_solution(_t%2C%20_k%2C%20_omega)%0A%20%20%20%20if%200%20%3C%20_k%20%3C%20_omega%3A%0A%20%20%20%20%20%20%20%20%23%20envelope%3A%20amplitude%20A%20%3D%20sqrt(c1%5E2%20%2B%20c2%5E2)%2C%20as%20in%20(4.16)%2C%20times%20e%5E%7B-kt%7D%0A%20%20%20%20%20%20%20%20_p%20%3D%20np.sqrt(_omega**2%20-%20_k**2)%0A%20%20%20%20%20%20%20%20_A%20%3D%20np.sqrt(1%20%2B%20(_k%20%2F%20_p)**2)%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20_A%20*%20np.exp(-_k%20*%20_t)%2C%20%22%3A%22%2C%20color%3D%22grey%22%2C%20linewidth%3D1.3%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Drf%22envelope%20%24%5Cpm%20A%20e%5E%7B%7B-kt%7D%7D%24%2C%20%20%24A%20%3D%20%7B_A%3A.3f%7D%24%22)%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20-_A%20*%20np.exp(-_k%20*%20_t)%2C%20%22%3A%22%2C%20color%3D%22grey%22%2C%20linewidth%3D1.3)%0A%20%20%20%20elif%20_k%20%3D%3D%20_omega%3A%0A%20%20%20%20%20%20%20%20%23%20the%20two%20pieces%20of%20(c1%20%2B%20c2%20t)%20e%5E%7B-kt%7D%2C%20with%20c1%20%3D%201%2C%20c2%20%3D%20k%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20np.exp(-_k%20*%20_t)%2C%20%22--%22%2C%20color%3D_slow_col%2C%20linewidth%3D1.6%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Dr%22%24c_1%20e%5E%7B-kt%7D%24%22)%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20_k%20*%20_t%20*%20np.exp(-_k%20*%20_t)%2C%20%22--%22%2C%20color%3D_fast_col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D1.6%2C%20label%3Dr%22%24c_2%5C%2Ct%5C%2Ce%5E%7B-kt%7D%24%22)%0A%20%20%20%20elif%20_k%20%3E%20_omega%3A%0A%20%20%20%20%20%20%20%20%23%20the%20two%20pieces%20c1%20e%5E%7Bm1%20t%7D%20and%20c2%20e%5E%7Bm2%20t%7D%2C%20one%20per%20root%0A%20%20%20%20%20%20%20%20_c1%20%3D%20-_m2%20%2F%20(_m1%20-%20_m2)%0A%20%20%20%20%20%20%20%20_c2%20%3D%20_m1%20%2F%20(_m1%20-%20_m2)%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20_c1%20*%20np.exp(_m1%20*%20_t)%2C%20%22--%22%2C%20color%3D_slow_col%2C%20linewidth%3D1.6%2C%20zorder%3D4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Drf%22%24c_1%20e%5E%7B%7Bm_1%20t%7D%7D%24%2C%20%20%24m_1%20%3D%20%7B_m1%3A.2f%7D%24%22)%0A%20%20%20%20%20%20%20%20_axy.plot(_t%2C%20_c2%20*%20np.exp(_m2%20*%20_t)%2C%20%22--%22%2C%20color%3D_fast_col%2C%20linewidth%3D1.6%2C%20zorder%3D4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Drf%22%24c_2%20e%5E%7B%7Bm_2%20t%7D%7D%24%2C%20%20%24m_2%20%3D%20%7B_m2%3A.2f%7D%24%22)%0A%20%20%20%20_axy.plot(_t%2C%20_y%2C%20color%3D_col%2C%20linewidth%3D2.5%2C%20label%3Dr%22%24y(t)%24%22)%0A%20%20%20%20_axy.axhline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8)%0A%20%20%20%20_axy.set_xlim(0%2C%208)%0A%20%20%20%20_axy.set_ylim(-1.1%2C%201.7)%0A%20%20%20%20_axy.set_xlabel(r%22%24t%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axy.set_ylabel(r%22%24y%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axy.set_title(rf%22%24k%20%3D%20%7B_k%3Ag%7D%24%3A%20%7B_case%7D%22%2C%20fontsize%3D12%2C%20color%3D_col)%0A%20%20%20%20_axy.legend(fontsize%3D10%2C%20loc%3D%22upper%20right%22)%0A%20%20%20%20_axy.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20mo.vstack(%5Bk_slider%2C%20_fig%5D)%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%20What%20to%20notice%20(open%20after%20you%20have%20tried%20the%20slider)%0A%0A%20%20%20%201.%20At%20%24k%20%3D%200%24%20the%20roots%20are%20%24%5Cpm%202i%24%2C%20on%20the%20imaginary%20axis%3A%20no%20decay%2C%20the%20mass%20oscillates%20forever%20with%20period%20%242%5Cpi%2F%5Comega%20%3D%20%5Cpi%24.%20Now%20try%20%24k%20%3D%200.001%24%3A%20over%20these%208%20seconds%20it%20loses%20less%20than%201%25%20of%20its%20swing%2C%20and%20you%20cannot%20tell%20it%20apart%20from%20%24k%20%3D%200%24.%20At%20%24k%20%3D%200.01%24%20it%20loses%20under%20a%20tenth%3B%20at%20%24k%20%3D%200.05%24%20the%20decay%20starts%20to%20show.%20That%20is%20why%20SHM%20is%20a%20useful%20model%20even%20though%20no%20real%20oscillator%20is%20frictionless%3A%20when%20the%20friction%20is%20small%2C%20it%20doesn't%20matter%20over%20a%20few%20swings.%0A%20%20%20%202.%20As%20%24k%24%20grows%20the%20roots%20move%20left%20along%20a%20circle%20of%20radius%20%24%5Comega%20%3D%202%24.%20The%20**real%20part**%20%24-k%24%20sets%20how%20fast%20the%20oscillation%20dies%20out%3A%20the%20envelope%20is%20%24%5Cpm%20A%20e%5E%7B-kt%7D%24%2C%20where%20%24A%20%3D%20%5Csqrt%7Bc_1%5E2%20%2B%20c_2%5E2%7D%24%20is%20the%20amplitude%2C%20as%20in%20(4.16).%20With%20%24c_1%20%3D%201%24%20and%20%24c_2%20%3D%20k%2Fp%24%2C%20%24A%24%20is%20bigger%20than%201%3A%20only%20slightly%20for%20small%20%24k%24%2C%20but%20a%20lot%20as%20%24k%24%20gets%20close%20to%202.%20The%20curve%20stays%20inside%20the%20envelope%20and%20touches%20it%20once%20every%20half%20swing.%20The%20**imaginary%20part**%20%24p%20%3D%20%5Csqrt%7B%5Comega%5E2%20-%20k%5E2%7D%24%20sets%20how%20fast%20it%20oscillates.%20At%20%24k%20%3D%202%24%20the%20two%20roots%20meet%20on%20the%20real%20axis%20(the%20repeated%20root%2C%20critical%20damping)%20and%20then%20split%20apart%20along%20it%3A%20no%20imaginary%20part%2C%20no%20oscillation.%0A%20%20%20%203.%20At%20%24k%20%3D%202%24%20the%20formula%20is%20%24(c_1%20%2B%20c_2t)e%5E%7B-kt%7D%24%2C%20drawn%20as%20its%20two%20dashed%20pieces%20%24c_1e%5E%7B-kt%7D%24%20and%20%24c_2te%5E%7B-kt%7D%24.%0A%20%20%20%204.%20Past%20%24k%20%3D%202%24%20the%20solution%20is%20%24c_1e%5E%7Bm_1t%7D%20%2B%20c_2e%5E%7Bm_2t%7D%24%3A%20one%20decaying%20exponential%20per%20root%2C%20drawn%20dashed%20in%20the%20colour%20of%20its%20root.%20The%20root%20far%20to%20the%20left%2C%20%24m_2%24%2C%20gives%20a%20piece%20that%20dies%20out%20almost%20at%20once.%20The%20root%20near%200%2C%20%24m_1%24%2C%20gives%20a%20piece%20that%20decays%20slowly%20and%20does%20almost%20all%20the%20work%2C%20so%20it%20decides%20how%20long%20the%20return%20takes.%20As%20%24k%24%20grows%2C%20%24m_1%24%20creeps%20towards%200%3A%20more%20friction%20makes%20the%20mass%20*slower*%20to%20return.%0A%20%20%20%205.%20So%20for%20a%20mass%20released%20from%20rest%2C%20critical%20damping%20is%20the%20fastest%20return%20to%20rest%20that%20never%20overshoots%2C%20as%20in%20the%20key%20idea%20in%20Section%204.9.%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.%20Solving%20the%20ODE%20without%20a%20formula%0A%0A%20%20%20%20The%20formula%20in%203.1%20needed%20three%20cases%20and%20some%20algebra%20for%20%24c_1%24%20and%20%24c_2%24.%20This%20section%20shows%20a%20second%20route%20that%20needs%20no%20formula%20at%20all.%20It%20is%20a%20first%20look%20at%20Chapter%206%20of%20the%20notes%2C%20so%20we%20go%20one%20small%20step%20at%20a%20time.%0A%0A%20%20%20%20%23%23%23%204.1%20Recap%3A%20one%20number%20and%20its%20slope%20(Week%204)%0A%0A%20%20%20%20In%20Week%204%20the%20ODEs%20were%20first%20order%2C%20%24y'%20%3D%20f(t%2C%20y)%24.%20The%20ODE%20tells%20you%20the%20slope%20%24y'%24%20at%20every%20point.%20To%20trace%20a%20solution%20we%20stood%20at%20a%20point%2C%20took%20a%20tiny%20step%20of%20time%20%24h%24%20along%20that%20slope%2C%20and%20looked%20again%3A%20%5C%5By_%5Ctext%7Bnew%7D%20%3D%20y%20%2B%20h%20%5Ctimes%20%5Ctext%7Bslope%7D.%5C%5D%20This%20works%20because%20the%20ODE%20hands%20us%20the%20slope%20%24y'%24%20directly.%0A%0A%20%20%20%20%23%23%23%204.2%20The%20problem%20with%20%24y''%24%0A%0A%20%20%20%20Rearrange%20(4.17)%20to%20get%20%24y''%24%20on%20its%20own%3A%20%5C%5By''%20%3D%20-2k%5C%2Cy'%20-%20%5Comega%5E2%20y.%5C%5D%20This%20gives%20%24y''%24%2C%20not%20%24y'%24.%20To%20step%20%24y%24%20forward%20we%20need%20its%20slope%20%24y'%24%2C%20and%20the%20equation%20doesn't%20tell%20us%20what%20it%20is.%0A%0A%20%20%20%20The%20way%20out%20is%20to%20keep%20track%20of%20%24y'%24%20as%20a%20**second%20number**.%20Call%20it%20%24v%20%3D%20y'%24%2C%20the%20velocity%20of%20the%20mass.%20Now%20think%20of%20two%20numbers%20that%20both%20change%20in%20time%3A%0A%0A%20%20%20%20-%20the%20position%20%24y%24%20changes%20at%20the%20rate%20%24v%24%2C%20because%20that%20is%20what%20velocity%20means%3A%20%24%5Cquad%20y'%20%3D%20v%24%0A%20%20%20%20-%20the%20velocity%20%24v%24%20changes%20at%20the%20rate%20%24y''%24%2C%20the%20acceleration%2C%20and%20the%20ODE%20tells%20us%20that%3A%20%24%5Cquad%20v'%20%3D%20-2k%5C%2Cv%20-%20%5Comega%5E2%20y%24%0A%0A%20%20%20%20These%20are%20two%20**first-order**%20ODEs%2C%20each%20giving%20the%20slope%20of%20one%20number.%20Both%20right-hand%20sides%20use%20only%20%24y%24%20and%20%24v%24%2C%20so%20if%20we%20know%20where%20the%20mass%20is%20and%20how%20fast%20it%20is%20moving%20right%20now%2C%20we%20know%20both%20slopes%2C%20and%20Week%204's%20rule%20works%20on%20each%20number.%0A%0A%20%20%20%20This%20also%20explains%20the%20two%20starting%20conditions%3A%20we%20need%20a%20starting%20value%20for%20each%20number%2C%20%24y(0)%20%3D%201%24%20and%20%24v(0)%20%3D%20y'(0)%20%3D%200%24.%20Turning%20one%20second-order%20ODE%20into%20two%20first-order%20ones%20works%20for%20any%20order%3B%20Section%206.3%20of%20the%20notes%20does%20it%20in%20general.%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%23%204.3%20One%20step%2C%20by%20hand%0A%0A%20%20%20%20One%20step%20of%20time%20%24h%24%20is%20three%20lines%20of%20arithmetic%3A%0A%0A%20%20%20%201.%20acceleration%20%24a%20%3D%20-2k%5C%2Cv%20-%20%5Comega%5E2%20y%24%2C%20using%20the%20current%20%24y%24%20and%20%24v%24%0A%20%20%20%202.%20new%20velocity%20%24%3D%24%20velocity%20%24%2B%5C%20h%20%5Ctimes%20a%24%0A%20%20%20%203.%20new%20position%20%24%3D%24%20position%20%24%2B%5C%20h%20%5Ctimes%24%20new%20velocity%0A%0A%20%20%20%20Line%203%20uses%20the%20velocity%20we%20have%20just%20updated%20in%20line%202.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Why%20use%20the%20*new*%20velocity%20in%20line%203%3F%20(optional)%0A%0A%20%20%20%20Using%20the%20old%20velocity%20also%20works%20when%20%24h%24%20is%20tiny%2C%20but%20for%20oscillations%20it%20slowly%20pumps%20energy%20in%2C%20so%20the%20swings%20grow.%20Moving%20with%20the%20freshly%20updated%20velocity%20avoids%20that.%20Chapter%206%20comes%20back%20to%20how%20the%20choice%20of%20update%20rule%20affects%20accuracy.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20Take%20%24k%20%3D%200.5%24%2C%20%24%5Comega%20%3D%202%24%2C%20a%20step%20of%20%24h%20%3D%200.1%24%2C%20and%20start%20released%20from%20rest%20at%20%24y%20%3D%201%24%2C%20%24v%20%3D%200%24.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell%3A**%20do%20the%20first%20step%20on%20paper.%20What%20are%20%24a%24%2C%20the%20new%20%24v%24%20and%20the%20new%20%24y%24%3F%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%20k_demo%20%3D%200.5%0A%20%20%20%20omega_demo%20%3D%202.0%0A%20%20%20%20h_demo%20%3D%200.1%0A%0A%20%20%20%20%23%20start%3A%20released%20from%20rest%20at%20y%20%3D%201%0A%20%20%20%20y_0%20%3D%201.0%0A%20%20%20%20v_0%20%3D%200.0%0A%0A%20%20%20%20%23%20step%201%0A%20%20%20%20a_0%20%3D%20-2%20*%20k_demo%20*%20v_0%20-%20omega_demo**2%20*%20y_0%0A%20%20%20%20v_1%20%3D%20v_0%20%2B%20h_demo%20*%20a_0%0A%20%20%20%20y_1%20%3D%20y_0%20%2B%20h_demo%20*%20v_1%0A%20%20%20%20print(%22step%201%3A%20%20a%20%3D%22%2C%20round(a_0%2C%204)%2C%20%22%20%20new%20v%20%3D%22%2C%20round(v_1%2C%204)%2C%20%22%20%20new%20y%20%3D%22%2C%20round(y_1%2C%204))%0A%20%20%20%20return%20h_demo%2C%20k_demo%2C%20omega_demo%2C%20v_1%2C%20y_1%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%20Step%201%20written%20out%0A%0A%20%20%20%20-%20%24a%20%3D%20-2(0.5)(0)%20-%204(1)%20%3D%20-4%24.%20The%20spring%20pulls%20the%20mass%20back%20towards%20rest%3B%20there%20is%20no%20friction%20yet%20because%20the%20mass%20isn't%20moving.%0A%20%20%20%20-%20new%20%24v%20%3D%200%20%2B%200.1%20%5Ctimes%20(-4)%20%3D%20-0.4%24.%20The%20mass%20starts%20moving%20down%2C%20towards%20rest.%0A%20%20%20%20-%20new%20%24y%20%3D%201%20%2B%200.1%20%5Ctimes%20(-0.4)%20%3D%200.96%24.%20It%20has%20moved%20a%20little.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20Step%202%20is%20the%20same%20three%20lines%2C%20starting%20from%20the%20numbers%20step%201%20gave%20us.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(h_demo%2C%20k_demo%2C%20omega_demo%2C%20v_1%2C%20y_1)%3A%0A%20%20%20%20%23%20step%202%3A%20the%20same%20three%20lines%2C%20starting%20from%20y_1%20and%20v_1%0A%20%20%20%20a_1%20%3D%20-2%20*%20k_demo%20*%20v_1%20-%20omega_demo**2%20*%20y_1%0A%20%20%20%20v_2%20%3D%20v_1%20%2B%20h_demo%20*%20a_1%0A%20%20%20%20y_2%20%3D%20y_1%20%2B%20h_demo%20*%20v_2%0A%20%20%20%20print(%22step%202%3A%20%20a%20%3D%22%2C%20round(a_1%2C%204)%2C%20%22%20%20new%20v%20%3D%22%2C%20round(v_2%2C%204)%2C%20%22%20%20new%20y%20%3D%22%2C%20round(y_2%2C%204))%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**Question%3A**%20the%20acceleration%20went%20from%20%24-4%24%20in%20step%201%20to%20%24-3.44%24%20in%20step%202.%20Why%20is%20it%20smaller%3F%20There%20are%20two%20reasons.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Answer%0A%0A%20%20%20%20The%20spring%20is%20stretched%20a%20little%20less%20(%24y%20%3D%200.96%24%20instead%20of%201)%2C%20so%20it%20pulls%20less%3A%20%24-4%20%5Ctimes%200.96%20%3D%20-3.84%24.%20And%20the%20mass%20is%20now%20moving%2C%20so%20friction%20acts%20against%20the%20motion%3A%20%24-2%20%5Ctimes%200.5%20%5Ctimes%20(-0.4)%20%3D%20%2B0.4%24.%20Together%2C%20%24-3.84%20%2B%200.4%20%3D%20-3.44%24.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%23%204.4%20Many%20steps%0A%0A%20%20%20%20Each%20dot%20below%20is%20one%20step%3A%20the%20same%20three%20lines%2C%20using%20the%20numbers%20from%20the%20dot%20before.%20The%20faint%20curves%20are%20the%20formula%20from%203.1%2C%20for%20the%20position%20and%20for%20the%20velocity.%20Start%20with%20%24h%20%3D%200.1%24%20and%20move%20the%20time%20slider%3A%20each%20notch%20is%20one%20more%20step%2C%20and%20both%20numbers%20move%20together.%0A%0A%20%20%20%20**Then%20change%20%24h%24.**%20Before%20you%20do%3A%20if%20you%20halve%20the%20step%2C%20what%20happens%20to%20the%20gap%20between%20the%20dots%20and%20the%20formula%3F%20What%20do%20you%20expect%20for%20a%20big%20step%20like%20%24h%20%3D%200.8%24%3F%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%20h_demo_slider%20%3D%20mo.ui.slider(steps%3D%5B0.01%2C%200.02%2C%200.05%2C%200.1%2C%200.2%2C%200.25%2C%200.5%2C%200.8%5D%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%20%20%20%20%20%20%20%20value%3D0.1%2C%20show_value%3DTrue%2C%20label%3Dr%22Step%20size%20%24h%24%22)%0A%20%20%20%20t_demo_slider%20%3D%20mo.ui.slider(0.0%2C%208.0%2C%20step%3D0.1%2C%20value%3D0.2%2C%20show_value%3DTrue%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%20%20%20%20%20%20%20%20label%3Dr%22Run%20up%20to%20time%20%24t%24%22)%0A%20%20%20%20return%20h_demo_slider%2C%20t_demo_slider%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20damped_solution%2C%0A%20%20%20%20h_demo_slider%2C%0A%20%20%20%20k_demo%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20np%2C%0A%20%20%20%20omega_demo%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20t_demo_slider%2C%0A)%3A%0A%20%20%20%20_h%20%3D%20h_demo_slider.value%0A%20%20%20%20_n%20%3D%20int(t_demo_slider.value%20%2F%20_h%20%2B%201e-9)%20%20%20%20%23%20whole%20steps%20that%20fit%20before%20t%0A%20%20%20%20_ys%20%3D%20%5B1.0%5D%0A%20%20%20%20_vs%20%3D%20%5B0.0%5D%0A%20%20%20%20for%20_i%20in%20range(_n)%3A%0A%20%20%20%20%20%20%20%20_a%20%3D%20-2%20*%20k_demo%20*%20_vs%5B-1%5D%20-%20omega_demo**2%20*%20_ys%5B-1%5D%0A%20%20%20%20%20%20%20%20_vs.append(_vs%5B-1%5D%20%2B%20_h%20*%20_a)%0A%20%20%20%20%20%20%20%20_ys.append(_ys%5B-1%5D%20%2B%20_h%20*%20_vs%5B-1%5D)%0A%20%20%20%20_ts%20%3D%20_h%20*%20np.arange(_n%20%2B%201)%0A%20%20%20%20_gap%20%3D%20np.max(np.abs(np.array(_ys)%20-%20damped_solution(_ts%2C%20k_demo%2C%20omega_demo)))%0A%20%20%20%20_dot%20%3D%204%20if%20_h%20%3E%3D%200.05%20else%200%20%20%20%20%23%20with%20many%20tiny%20steps%2C%20draw%20a%20line%20instead%20of%20dots%0A%0A%20%20%20%20%23%20formula%20for%20y%20from%203.1%2C%20and%20its%20derivative%20for%20v%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C%208%2C%20600)%0A%20%20%20%20_p%20%3D%20np.sqrt(omega_demo**2%20-%20k_demo**2)%0A%20%20%20%20_v_formula%20%3D%20-(omega_demo**2%20%2F%20_p)%20*%20np.exp(-k_demo%20*%20_t)%20*%20np.sin(_p%20*%20_t)%0A%0A%20%20%20%20_fig4%2C%20(_axp%2C%20_axv)%20%3D%20plt.subplots(2%2C%201%2C%20figsize%3D(10%2C%206)%2C%20sharex%3DTrue)%0A%20%20%20%20_axp.plot(_t%2C%20damped_solution(_t%2C%20k_demo%2C%20omega_demo)%2C%20color%3D%22lightgrey%22%2C%20linewidth%3D3%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22formula%22)%0A%20%20%20%20_axp.plot(_ts%2C%20_ys%2C%20%22o-%22%2C%20color%3D%22%231a5276%22%2C%20markersize%3D_dot%2C%20linewidth%3D1%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22steps%22)%0A%20%20%20%20_axp.plot(_ts%5B-1%5D%2C%20_ys%5B-1%5D%2C%20%22o%22%2C%20color%3D%22%231a5276%22%2C%20markersize%3D10)%0A%20%20%20%20_axp.set_ylabel(r%22position%20%24y%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axp.set_ylim(-1.1%2C%201.1)%0A%20%20%20%20_axp.legend(fontsize%3D10%2C%20loc%3D%22upper%20right%22)%0A%20%20%20%20_axp.text(0.4%2C%20-1.0%2C%20f%22largest%20gap%20from%20the%20formula%20so%20far%3A%20%7B_gap%3A.4f%7D%22%2C%20fontsize%3D11%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22%231a5276%22%2C%20bbox%3D%7B%22facecolor%22%3A%20%22white%22%2C%20%22edgecolor%22%3A%20%22none%22%2C%20%22alpha%22%3A%200.8%7D)%0A%20%20%20%20_axp.set_title(rf%22%24h%20%3D%20%7B_h%3Ag%7D%24%3A%20%20%7B_n%7D%20steps%20to%20reach%20%24t%20%3D%20%7B_ts%5B-1%5D%3A.2f%7D%24%2C%20%20%20%24y%20%3D%20%7B_ys%5B-1%5D%3A.4f%7D%24%2C%20%20%20%24v%20%3D%20%7B_vs%5B-1%5D%3A.4f%7D%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fontsize%3D12)%0A%0A%20%20%20%20_axv.plot(_t%2C%20_v_formula%2C%20color%3D%22lightgrey%22%2C%20linewidth%3D3)%0A%20%20%20%20_axv.plot(_ts%2C%20_vs%2C%20%22o-%22%2C%20color%3D%22%23922b21%22%2C%20markersize%3D_dot%2C%20linewidth%3D1)%0A%20%20%20%20_axv.plot(_ts%5B-1%5D%2C%20_vs%5B-1%5D%2C%20%22o%22%2C%20color%3D%22%23922b21%22%2C%20markersize%3D10)%0A%20%20%20%20_axv.set_ylabel(r%22velocity%20%24v%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axv.set_ylim(-1.8%2C%201.8)%0A%20%20%20%20_axv.set_xlabel(r%22%24t%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_axv.set_xlim(0%2C%208)%0A%20%20%20%20for%20_axx%20in%20(_axp%2C%20_axv)%3A%0A%20%20%20%20%20%20%20%20_axx.axhline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8)%0A%20%20%20%20%20%20%20%20_axx.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig4.tight_layout()%0A%20%20%20%20mo.vstack(%5Bh_demo_slider%2C%20t_demo_slider%2C%20_fig4%5D)%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%20What%20to%20notice%0A%0A%20%20%20%20-%20Where%20the%20velocity%20is%20most%20negative%2C%20the%20position%20is%20falling%20fastest.%20Where%20the%20velocity%20crosses%200%2C%20the%20position%20is%20at%20a%20peak%20or%20a%20trough.%0A%20%20%20%20-%20The%20dots%20stay%20close%20to%20the%20formula%20but%20not%20exactly%20on%20it.%20Run%20to%20%24t%20%3D%208%24%20and%20read%20the%20largest%20gap%3A%20about%20%240.2%24%20for%20%24h%20%3D%200.2%24%2C%20%240.1%24%20for%20%24h%20%3D%200.1%24%2C%20%240.05%24%20for%20%24h%20%3D%200.05%24.%20Halving%20the%20step%20halves%20the%20gap%2C%20as%20in%20Week%204%2C%20but%20it%20also%20doubles%20the%20number%20of%20steps.%0A%20%20%20%20-%20At%20%24h%20%3D%200.5%24%20the%20dots%20still%20swing%20and%20die%20out%2C%20but%20they%20are%20well%20off%20the%20formula%20(a%20gap%20of%20about%200.6).%20At%20%24h%20%3D%200.8%24%20the%20steps%20run%20away%20from%20the%20formula%20and%20the%20swings%20grow%20instead%20of%20dying%20out%3A%20the%20step%20is%20too%20big%20for%20this%20oscillation.%20Chapter%206%20explains%20when%20this%20happens.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20**Both%20numbers%20in%20one%20picture%20(optional).**%20The%20two%20plots%20above%20share%20a%20time%20axis.%20Put%20time%2C%20position%20and%20velocity%20on%20three%20axes%2C%20and%20each%20moment%20becomes%20one%20point%20%24(t%2C%20y%2C%20v)%24%3A%20the%20solution%20is%20one%20curve%20in%203D.%0A%0A%20%20%20%20Now%20the%20arrows%20from%20Week%204%20come%20back.%20At%20every%20point%20%24(t%2C%20y%2C%20v)%24%20the%20ODE%20tells%20us%20which%20way%20to%20go%3A%20in%20a%20small%20step%20%24h%24%2C%20%24t%24%20goes%20up%20by%20%24h%24%2C%20%24y%24%20by%20about%20%24h%20%5Ctimes%20v%24%20and%20%24v%24%20by%20about%20%24h%20%5Ctimes%20a%24%2C%20where%20%24a%20%3D%20-2kv%20-%20%5Comega%5E2%20y%24.%20So%20each%20blue%20arrow%20points%20in%20the%20direction%20%24(1%2C%20v%2C%20a)%24%2C%20and%20the%20orange%20one%20is%20the%20arrow%20at%20the%20solution's%20current%20point.%20Following%20two%20arrows%20is%20following%20one%20arrow%20in%203D%2C%20and%20the%20solution%20curve%20runs%20along%20the%20field%3A%20at%20every%20point%20of%20the%20curve%2C%20the%20arrow%20there%20points%20along%20it.%0A%0A%20%20%20%20Pick%20a%20view%20and%20move%20the%20time%20slider.%20**Before%20you%20look%20side%20on%20at%20position%20against%20time%3A**%20the%20arrows%20there%20ought%20to%20give%20the%20slope%20of%20%24y%24.%20What%20will%20you%20see%20at%20a%20single%20point%3F%20**And%20before%20you%20choose%20%22end%20on%22%3A**%20if%20you%20look%20along%20the%20time%20axis%2C%20so%20that%20time%20disappears%2C%20what%20shape%20will%20the%20curve%20make%3F%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%20view_3d_dropdown%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3D%5B%22tilted%20(turn%20it%20with%20the%20slider)%22%2C%20%22side%20on%3A%20position%20against%20time%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22side%20on%3A%20velocity%20against%20time%22%2C%20%22end%20on%3A%20velocity%20against%20position%22%5D%2C%0A%20%20%20%20%20%20%20%20value%3D%22tilted%20(turn%20it%20with%20the%20slider)%22%2C%20label%3D%22View%22)%0A%20%20%20%20turn_3d_slider%20%3D%20mo.ui.slider(-180%2C%20180%2C%20step%3D5%2C%20value%3D-60%2C%20show_value%3DTrue%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%20%20%20%20%20%20%20%20%20label%3D%22Turn%20(tilted%20view)%22)%0A%20%20%20%20t_3d_slider%20%3D%20mo.ui.slider(0.0%2C%208.0%2C%20step%3D0.1%2C%20value%3D2.0%2C%20show_value%3DTrue%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%20%20%20%20%20%20label%3Dr%22Time%20%24t%24%22)%0A%20%20%20%20return%20t_3d_slider%2C%20turn_3d_slider%2C%20view_3d_dropdown%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20damped_solution%2C%0A%20%20%20%20k_demo%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20np%2C%0A%20%20%20%20omega_demo%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20t_3d_slider%2C%0A%20%20%20%20turn_3d_slider%2C%0A%20%20%20%20view_3d_dropdown%2C%0A)%3A%0A%20%20%20%20_view%20%3D%20view_3d_dropdown.value%0A%20%20%20%20_t_now%20%3D%20t_3d_slider.value%0A%20%20%20%20_p%20%3D%20np.sqrt(omega_demo**2%20-%20k_demo**2)%0A%0A%20%20%20%20%23%20the%20formula%20from%203.1%20for%20y%2C%20and%20its%20derivative%20for%20v%0A%20%20%20%20_t_all%20%3D%20np.linspace(0%2C%208%2C%20800)%0A%20%20%20%20_y_all%20%3D%20damped_solution(_t_all%2C%20k_demo%2C%20omega_demo)%0A%20%20%20%20_v_all%20%3D%20-(omega_demo**2%20%2F%20_p)%20*%20np.exp(-k_demo%20*%20_t_all)%20*%20np.sin(_p%20*%20_t_all)%0A%20%20%20%20_done%20%3D%20_t_all%20%3C%3D%20_t_now%20%2B%201e-9%0A%20%20%20%20_y_now%20%3D%20damped_solution(_t_now%2C%20k_demo%2C%20omega_demo)%0A%20%20%20%20_v_now%20%3D%20-(omega_demo**2%20%2F%20_p)%20*%20np.exp(-k_demo%20*%20_t_now)%20*%20np.sin(_p%20*%20_t_now)%0A%20%20%20%20_a_now%20%3D%20-2%20*%20k_demo%20*%20_v_now%20-%20omega_demo**2%20*%20_y_now%0A%0A%20%20%20%20_end_on%20%3D%20_view.startswith(%22end%20on%22)%0A%20%20%20%20_box%20%3D%20(1%2C%201%2C%201)%20if%20_end_on%20else%20(2.2%2C%201%2C%201)%0A%20%20%20%20%23%20one%20unit%20of%20t%2C%20y%20and%20v%2C%20measured%20on%20screen%2C%20so%20that%20every%20arrow%20can%20be%20drawn%20the%20same%20length%0A%20%20%20%20_unit%20%3D%20np.array(%5B_box%5B0%5D%20%2F%208%2C%20_box%5B1%5D%20%2F%202.2%2C%20_box%5B2%5D%20%2F%203.6%5D)%0A%0A%20%20%20%20def%20_arrows_3d(t%2C%20y%2C%20v%2C%20length)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Arrow%20in%20the%20direction%20(1%2C%20v%2C%20a)%20at%20each%20point%2C%20all%20the%20same%20length%20on%20screen.%22%22%22%0A%20%20%20%20%20%20%20%20a%20%3D%20-2%20*%20k_demo%20*%20v%20-%20omega_demo**2%20*%20y%0A%20%20%20%20%20%20%20%20d%20%3D%20np.array(%5Bnp.ones_like(y)%2C%20v%2C%20a%5D)%20*%20_unit%5B%3A%2C%20None%5D%0A%20%20%20%20%20%20%20%20d%20%3D%20length%20*%20d%20%2F%20np.linalg.norm(d%2C%20axis%3D0)%0A%20%20%20%20%20%20%20%20return%20d%5B0%5D%20%2F%20_unit%5B0%5D%2C%20d%5B1%5D%20%2F%20_unit%5B1%5D%2C%20d%5B2%5D%20%2F%20_unit%5B2%5D%0A%0A%20%20%20%20%23%20a%20grid%20of%20points%20(t%2C%20y%2C%20v)%2C%20with%20an%20arrow%20at%20each%20one%0A%20%20%20%20_Tg%2C%20_Yg%2C%20_Vg%20%3D%20np.meshgrid(np.arange(0.5%2C%208%2C%201.0)%2C%20np.linspace(-1%2C%201%2C%207)%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%20%20%20%20%20%20%20np.linspace(-1.5%2C%201.5%2C%207)%2C%20indexing%3D%22ij%22)%0A%20%20%20%20_Tg%2C%20_Yg%2C%20_Vg%20%3D%20_Tg.ravel()%2C%20_Yg.ravel()%2C%20_Vg.ravel()%0A%20%20%20%20_dT%2C%20_dY%2C%20_dV%20%3D%20_arrows_3d(_Tg%2C%20_Yg%2C%20_Vg%2C%200.12)%0A%0A%20%20%20%20_fig3d%20%3D%20plt.figure(figsize%3D(9%2C%206))%0A%20%20%20%20_ax3d%20%3D%20_fig3d.add_subplot(projection%3D%223d%22)%0A%20%20%20%20_ax3d.set_proj_type(%22ortho%22)%0A%20%20%20%20if%20_view.startswith(%22tilted%22)%3A%0A%20%20%20%20%20%20%20%20_ax3d.view_init(elev%3D22%2C%20azim%3Dturn_3d_slider.value)%0A%20%20%20%20elif%20_view%20%3D%3D%20%22side%20on%3A%20position%20against%20time%22%3A%0A%20%20%20%20%20%20%20%20_ax3d.view_init(elev%3D90%2C%20azim%3D-90)%20%20%20%20%23%20look%20down%20the%20velocity%20axis%0A%20%20%20%20elif%20_view%20%3D%3D%20%22side%20on%3A%20velocity%20against%20time%22%3A%0A%20%20%20%20%20%20%20%20_ax3d.view_init(elev%3D0%2C%20azim%3D-90)%20%20%20%20%20%23%20look%20along%20the%20position%20axis%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_ax3d.view_init(elev%3D0%2C%20azim%3D0)%20%20%20%20%20%20%20%23%20look%20along%20the%20time%20axis%0A%0A%20%20%20%20_ax3d.quiver(_Tg%2C%20_Yg%2C%20_Vg%2C%20_dT%2C%20_dY%2C%20_dV%2C%20color%3D%22%232e86c1%22%2C%20linewidth%3D1.4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20arrow_length_ratio%3D0.35%2C%20alpha%3D0.9)%0A%20%20%20%20_ax3d.plot(_t_all%2C%20_y_all%2C%20_v_all%2C%20color%3D%22lightgrey%22%2C%20linewidth%3D1.5)%0A%20%20%20%20_ax3d.plot(_t_all%5B_done%5D%2C%20_y_all%5B_done%5D%2C%20_v_all%5B_done%5D%2C%20color%3D%22black%22%2C%20linewidth%3D2.5)%0A%20%20%20%20_dt_now%2C%20_dy_now%2C%20_dv_now%20%3D%20_arrows_3d(np.array(%5B_t_now%5D)%2C%20np.array(%5B_y_now%5D)%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%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20np.array(%5B_v_now%5D)%2C%200.3)%0A%20%20%20%20_ax3d.quiver(%5B_t_now%5D%2C%20%5B_y_now%5D%2C%20%5B_v_now%5D%2C%20_dt_now%2C%20_dy_now%2C%20_dv_now%2C%20color%3D%22%23e67e22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D4%2C%20arrow_length_ratio%3D0.3%2C%20zorder%3D10)%0A%20%20%20%20_ax3d.scatter(%5B_t_now%5D%2C%20%5B_y_now%5D%2C%20%5B_v_now%5D%2C%20color%3D%22black%22%2C%20s%3D40)%0A%0A%20%20%20%20_ax3d.set_xlim(0%2C%208)%0A%20%20%20%20_ax3d.set_ylim(-1.1%2C%201.1)%0A%20%20%20%20_ax3d.set_zlim(-1.8%2C%201.8)%0A%20%20%20%20_ax3d.set_yticks(%5B-1%2C%20-0.5%2C%200%2C%200.5%2C%201%5D)%0A%20%20%20%20_ax3d.set_zticks(%5B-1.5%2C%20-1%2C%20-0.5%2C%200%2C%200.5%2C%201%2C%201.5%5D)%0A%20%20%20%20_ax3d.set_xlabel(r%22time%20%24t%24%22%2C%20fontsize%3D11)%0A%20%20%20%20_ax3d.set_ylabel(r%22position%20%24y%24%22%2C%20fontsize%3D11)%0A%20%20%20%20_ax3d.set_zlabel(r%22velocity%20%24v%24%22%2C%20fontsize%3D11)%0A%20%20%20%20%23%20in%20a%20side-on%20view%2C%20hide%20the%20axis%20we%20are%20looking%20along%0A%20%20%20%20if%20_view%20%3D%3D%20%22side%20on%3A%20position%20against%20time%22%3A%0A%20%20%20%20%20%20%20%20_ax3d.set_zticks(%5B%5D)%0A%20%20%20%20%20%20%20%20_ax3d.set_zlabel(%22%22)%0A%20%20%20%20if%20_view%20%3D%3D%20%22side%20on%3A%20velocity%20against%20time%22%3A%0A%20%20%20%20%20%20%20%20_ax3d.set_yticks(%5B%5D)%0A%20%20%20%20%20%20%20%20_ax3d.set_ylabel(%22%22)%0A%20%20%20%20if%20_end_on%3A%0A%20%20%20%20%20%20%20%20_ax3d.set_xticks(%5B%5D)%0A%20%20%20%20%20%20%20%20_ax3d.set_xlabel(%22%22)%0A%20%20%20%20_ax3d.set_box_aspect(_box)%0A%20%20%20%20_ax3d.set_title(rf%22%24t%20%3D%20%7B_t_now%3A.1f%7D%24%3A%20%20%20%24y%20%3D%20%7B_y_now%3A.2f%7D%24%2C%20%20%20%24v%20%3D%20%7B_v_now%3A.2f%7D%24%2C%20%20%20%24a%20%3D%20%7B_a_now%3A.2f%7D%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fontsize%3D12)%0A%20%20%20%20_fig3d.subplots_adjust(left%3D0%2C%20right%3D1%2C%20bottom%3D0.02%2C%20top%3D0.92)%0A%20%20%20%20mo.vstack(%5Bview_3d_dropdown%2C%20turn_3d_slider%2C%20t_3d_slider%2C%20_fig3d%5D)%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%20What%20to%20notice%0A%0A%20%20%20%20-%20Side%20on%2C%20the%203D%20curve%20looks%20exactly%20like%20one%20of%20the%20two%20plots%20from%204.4%3A%20each%20of%20those%20plots%20is%20the%20same%20curve%20seen%20from%20the%20side.%0A%20%20%20%20-%20Side%20on%20at%20position%20against%20time%2C%20every%20point%20has%20a%20whole%20**fan**%20of%20arrows%3A%20the%20arrows%20for%20every%20value%20of%20%24v%24%2C%20stacked%20behind%20each%20other.%20Knowing%20%24t%24%20and%20%24y%24%20is%20not%20enough%20to%20know%20which%20way%20%24y%24%20is%20heading%3B%20you%20also%20need%20%24v%24.%20That%20is%20Section%204.2%20in%20one%20picture%2C%20and%20it%20is%20why%20we%20keep%20track%20of%20the%20second%20number.%0A%20%20%20%20-%20End%20on%2C%20time%20disappears%20and%20you%20see%20velocity%20against%20position.%20The%20arrows%20from%20every%20time%20now%20land%20exactly%20on%20top%20of%20each%20other%2C%20because%20the%20ODE%20doesn't%20contain%20%24t%24%3A%20the%20rule%20for%20moving%20is%20the%20same%20at%20every%20time.%20The%20curve%20follows%20them%20in%20a%20spiral%20into%20%24(0%2C%200)%24.%20Each%20turn%20is%20one%20full%20swing%2C%20and%20the%20spiral%20shrinks%20because%20friction%20takes%20energy%20out.%20With%20no%20friction%20it%20would%20be%20a%20closed%20loop%2C%20going%20round%20for%20ever.%0A%20%20%20%20-%20Chapter%206%20of%20the%20notes%20calls%20a%20plot%20of%20velocity%20against%20position%20a%20*phase%20portrait*.%20It%20shows%20how%20%24y%24%20and%20%24v%24%20move%20together%20without%20needing%20the%20clock.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%23%204.5%20The%20loop%0A%0A%20%20%20%20Doing%20those%20three%20lines%2080%20times%20by%20hand%20(800%20times%20with%20%24h%20%3D%200.01%24)%20is%20no%20fun%2C%20so%20we%20put%20them%20in%20a%20loop%2C%20just%20like%20%60follow_arrows%60%20in%20Week%204.%20Read%20it%20line%20by%20line%3A%0A%0A%20%20%20%20-%20%60h%60%20is%20the%20step%20length%3A%20the%20total%20time%20divided%20by%20the%20number%20of%20steps.%0A%20%20%20%20-%20Three%20lists%20hold%20the%20times%2C%20positions%20and%20velocities%2C%20each%20starting%20with%20its%20starting%20value.%0A%20%20%20%20-%20Each%20time%20round%20the%20loop%20it%20reads%20the%20latest%20%60t%60%2C%20%60y%60%2C%20%60v%60%2C%20does%20the%20three%20lines%20from%204.3%2C%20and%20adds%20the%20new%20values%20to%20the%20end%20of%20the%20lists.%0A%20%20%20%20-%20%60acc%60%20is%20a%20function%20you%20pass%20in%20that%20computes%20the%20acceleration.%20It%20is%20the%20only%20place%20where%20the%20ODE%20appears%2C%20so%20the%20same%20loop%20works%20for%20any%20second-order%20ODE.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20follow_two_arrows(acc%2C%20y_start%2C%20v_start%2C%20t_stop%2C%20n_steps%3D10000)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Step%20position%20y%20and%20velocity%20v%20forward%20together%3B%20acc(t%2C%20y%2C%20v)%20gives%20y''.%22%22%22%0A%20%20%20%20%20%20%20%20h%20%3D%20t_stop%20%2F%20n_steps%0A%20%20%20%20%20%20%20%20t_values%20%3D%20%5B0.0%5D%0A%20%20%20%20%20%20%20%20y_values%20%3D%20%5By_start%5D%0A%20%20%20%20%20%20%20%20v_values%20%3D%20%5Bv_start%5D%0A%20%20%20%20%20%20%20%20for%20step%20in%20range(n_steps)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20t_now%20%3D%20t_values%5B-1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20y_now%20%3D%20y_values%5B-1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20v_now%20%3D%20v_values%5B-1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20a_now%20%3D%20acc(t_now%2C%20y_now%2C%20v_now)%20%20%20%20%23%20line%201%3A%20acceleration%20from%20the%20ODE%0A%20%20%20%20%20%20%20%20%20%20%20%20v_next%20%3D%20v_now%20%2B%20h%20*%20a_now%20%20%20%20%20%20%20%20%20%20%23%20line%202%3A%20new%20velocity%0A%20%20%20%20%20%20%20%20%20%20%20%20y_next%20%3D%20y_now%20%2B%20h%20*%20v_next%20%20%20%20%20%20%20%20%20%23%20line%203%3A%20new%20position%2C%20using%20the%20new%20velocity%0A%20%20%20%20%20%20%20%20%20%20%20%20t_values.append(t_now%20%2B%20h)%0A%20%20%20%20%20%20%20%20%20%20%20%20v_values.append(v_next)%0A%20%20%20%20%20%20%20%20%20%20%20%20y_values.append(y_next)%0A%20%20%20%20%20%20%20%20return%20np.array(t_values)%2C%20np.array(y_values)%0A%0A%20%20%20%20return%20(follow_two_arrows%2C)%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%20First%20a%20check%3A%20with%20the%20same%20%24k%20%3D%200.5%24%20and%2080%20steps%20of%20%24h%20%3D%200.1%24%2C%20the%20loop%20should%20reproduce%20our%20hand%20calculation.%20**This%20line%20is%20equation%20(4.17)%3A**%20%60return%20-2%20*%20k_demo%20*%20v%20-%20omega_demo**2%20*%20y%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(follow_two_arrows%2C%20k_demo%2C%20omega_demo)%3A%0A%20%20%20%20def%20acc_demo(t%2C%20y%2C%20v)%3A%0A%20%20%20%20%20%20%20%20return%20-2%20*%20k_demo%20*%20v%20-%20omega_demo**2%20*%20y%0A%0A%20%20%20%20t_loop%2C%20y_loop%20%3D%20follow_two_arrows(acc_demo%2C%201.0%2C%200.0%2C%208.0%2C%20n_steps%3D80)%0A%20%20%20%20print(%22y%20after%20step%201%3A%22%2C%20round(y_loop%5B1%5D%2C%204))%0A%20%20%20%20print(%22y%20after%20step%202%3A%22%2C%20round(y_loop%5B2%5D%2C%204))%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%20The%20same%20numbers%20as%20by%20hand%3A%200.96%20and%200.8856.%0A%0A%20%20%20%20%23%23%23%204.6%20Loop%20against%20formula%0A%0A%20%20%20%20Now%20use%2010%2C000%20tiny%20steps%20instead%20of%2080%20and%20compare%20with%20the%20formula%20for%20any%20friction%20%24k%24.%20Notice%20that%20the%20loop%20never%20asks%20which%20case%20we%20are%20in%3A%20there%20is%20no%20%60if%60.%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%20k_check_slider%20%3D%20mo.ui.slider(0.0%2C%204.0%2C%20step%3D0.25%2C%20value%3D0.5%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%20%20%20%20%20%20%20%20%20label%3Dr%22Friction%20%24k%24%20%20(%24%5Comega%20%3D%202%24)%22)%0A%20%20%20%20return%20(k_check_slider%2C)%0A%0A%0A%40app.cell%0Adef%20_(damped_solution%2C%20follow_two_arrows%2C%20k_check_slider%2C%20np)%3A%0A%20%20%20%20k_check%20%3D%20k_check_slider.value%0A%20%20%20%20omega_check%20%3D%202.0%0A%0A%20%20%20%20def%20acc_damped(t%2C%20y%2C%20v)%3A%0A%20%20%20%20%20%20%20%20return%20-2%20*%20k_check%20*%20v%20-%20omega_check**2%20*%20y%0A%0A%20%20%20%20t_steps%2C%20y_steps%20%3D%20follow_two_arrows(acc_damped%2C%201.0%2C%200.0%2C%208.0)%0A%20%20%20%20y_formula%20%3D%20damped_solution(t_steps%2C%20k_check%2C%20omega_check)%0A%20%20%20%20print(%22largest%20gap%20between%20loop%20and%20formula%3A%22%2C%20np.max(np.abs(y_steps%20-%20y_formula)))%0A%20%20%20%20return%20t_steps%2C%20y_formula%2C%20y_steps%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(k_check_slider%2C%20mo%2C%20plt%2C%20t_steps%2C%20y_formula%2C%20y_steps)%3A%0A%20%20%20%20_fig2%2C%20_ax2%20%3D%20plt.subplots(figsize%3D(10%2C%204))%0A%20%20%20%20_ax2.plot(t_steps%2C%20y_formula%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D5%2C%20alpha%3D0.35%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22formula%20(Section%203.1)%22)%0A%20%20%20%20_ax2.plot(t_steps%2C%20y_steps%2C%20color%3D%22%23922b21%22%2C%20linewidth%3D1.8%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22following%20two%20arrows%20(10%2C000%20steps)%22)%0A%20%20%20%20_ax2.axhline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8)%0A%20%20%20%20_ax2.set_xlim(0%2C%208)%0A%20%20%20%20_ax2.set_ylim(-1.1%2C%201.1)%0A%20%20%20%20_ax2.set_xlabel(r%22%24t%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_ax2.set_ylabel(r%22%24y%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_ax2.set_title(rf%22Formula%20vs%20loop%2C%20%20%24k%20%3D%20%7Bk_check_slider.value%3Ag%7D%24%22%2C%20fontsize%3D12)%0A%20%20%20%20_ax2.legend(fontsize%3D10%2C%20loc%3D%22upper%20right%22)%0A%20%20%20%20_ax2.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig2.tight_layout()%0A%20%20%20%20mo.vstack(%5Bk_check_slider%2C%20_fig2%5D)%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%20The%20two%20curves%20sit%20on%20top%20of%20each%20other%20for%20every%20%24k%24%2C%20and%20the%20gap%20printed%20above%20is%20tiny.%20Chapter%206%20looks%20at%20this%20loop%20properly%20(it%20is%20a%20version%20of%20Euler's%20method)%20and%20at%20how%20to%20make%20it%20more%20accurate.%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%205.%20A%20pendulum%3A%20no%20formula%20at%20all%0A%0A%20%20%20%20The%20notes%20say%20SHM%20%22describes%20small%20oscillations%20of%20a%20pendulum%22.%20Take%20a%20mass%20on%20a%20light%20rigid%20rod%20of%20length%20%24l%24%2C%20so%20it%20can%20swing%20above%20the%20pivot.%20Measure%20the%20angle%20%24%5Ctheta%24%20from%20straight%20down%2C%20positive%20to%20the%20right%20and%20negative%20to%20the%20left.%20The%20full%20equation%20is%20%5C%5B%5Ctheta''%20%3D%20-%5Cfrac%7Bg%7D%7Bl%7D%5C%2C%5Csin%5Ctheta%20.%5C%5D%20Because%20of%20%24%5Csin%5Ctheta%24%20it%20is%20**not%20linear**%2C%20so%20the%20auxiliary%20equation%20doesn't%20apply.%20For%20small%20angles%20%24%5Csin%5Ctheta%20%5Capprox%20%5Ctheta%24%2C%20which%20gives%20SHM%20(4.14)%20with%20%24%5Comega%5E2%20%3D%20g%2Fl%24%20and%20the%20solution%20%24%5Ctheta_0%5Ccos%5Comega%20t%24.%0A%0A%20%20%20%20For%20the%20loop%2C%20the%20angle%20%24%5Ctheta%24%20plays%20the%20part%20of%20%24y%24%2C%20the%20velocity%20%24v%20%3D%20%5Ctheta'%24%20is%20how%20fast%20the%20angle%20changes%2C%20and%20the%20only%20new%20line%20is%20the%20acceleration.%20Both%20pendulums%20below%20are%20released%20from%20rest%20at%20the%20same%20angle%20%24%5Ctheta_0%24%3A%20one%20moves%20by%20the%20small-angle%20formula%2C%20the%20other%20by%20the%20full%20equation%2C%20stepped%20by%20the%20loop.%20Drag%20the%20time%20slider%20to%20watch%20them%20swing.%0A%0A%20%20%20%20**Question%3A**%20for%20which%20starting%20angles%20do%20you%20expect%20%24%5Ctheta_0%5Ccos%5Comega%20t%24%20to%20be%20good%3F%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%20theta0_slider%20%3D%20mo.ui.slider(10%2C%20170%2C%20step%3D10%2C%20value%3D20%2C%20show_value%3DTrue%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%20%20%20%20%20%20%20%20label%3Dr%22Starting%20angle%20%24%5Ctheta_0%24%20(degrees)%22)%0A%20%20%20%20t_pend_slider%20%3D%20mo.ui.slider(0.0%2C%208.0%2C%20step%3D0.05%2C%20value%3D0.0%2C%20label%3Dr%22Time%20%24t%24%20(s)%22)%0A%20%20%20%20return%20t_pend_slider%2C%20theta0_slider%0A%0A%0A%40app.cell%0Adef%20_(follow_two_arrows%2C%20np%2C%20theta0_slider)%3A%0A%20%20%20%20g_over_l%20%3D%209.81%20%20%20%20%23%20g%20%3D%209.81%20m%2Fs%C2%B2%2C%20l%20%3D%201%20m%0A%0A%20%20%20%20def%20acc_pendulum(t%2C%20theta%2C%20v)%3A%0A%20%20%20%20%20%20%20%20return%20-g_over_l%20*%20np.sin(theta)%0A%0A%20%20%20%20theta0_rad%20%3D%20np.deg2rad(theta0_slider.value)%0A%20%20%20%20t_pend%2C%20theta_pend%20%3D%20follow_two_arrows(acc_pendulum%2C%20theta0_rad%2C%200.0%2C%208.0%2C%20n_steps%3D20000)%0A%20%20%20%20theta_small%20%3D%20theta0_rad%20*%20np.cos(np.sqrt(g_over_l)%20*%20t_pend)%0A%20%20%20%20return%20t_pend%2C%20theta_pend%2C%20theta_small%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20mo%2C%0A%20%20%20%20np%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20t_pend%2C%0A%20%20%20%20t_pend_slider%2C%0A%20%20%20%20theta0_slider%2C%0A%20%20%20%20theta_pend%2C%0A%20%20%20%20theta_small%2C%0A)%3A%0A%20%20%20%20from%20matplotlib.patches%20import%20Arc%0A%0A%20%20%20%20_t_now%20%3D%20t_pend_slider.value%0A%20%20%20%20_th_small_now%20%3D%20np.interp(_t_now%2C%20t_pend%2C%20theta_small)%0A%20%20%20%20_th_full_now%20%3D%20np.interp(_t_now%2C%20t_pend%2C%20theta_pend)%0A%0A%20%20%20%20_fig3%2C%20(_ax_small%2C%20_ax_full%2C%20_ax3)%20%3D%20plt.subplots(%0A%20%20%20%20%20%20%20%201%2C%203%2C%20figsize%3D(13%2C%204.6)%2C%20gridspec_kw%3D%7B%22width_ratios%22%3A%20%5B1%2C%201%2C%202.4%5D%7D)%0A%0A%20%20%20%20%23%20left%3A%20the%20two%20pendulums%2C%20with%20the%20angle%20from%20straight%20down%20marked%0A%20%20%20%20for%20_axp3%2C%20_th%2C%20_name%2C%20_c3%20in%20%5B%0A%20%20%20%20%20%20%20%20(_ax_small%2C%20_th_small_now%2C%20%22small-angle%5Cnformula%22%2C%20%22%231a5276%22)%2C%0A%20%20%20%20%20%20%20%20(_ax_full%2C%20_th_full_now%2C%20%22full%20equation%5Cn(loop)%22%2C%20%22%23922b21%22)%2C%0A%20%20%20%20%5D%3A%0A%20%20%20%20%20%20%20%20_xb3%20%3D%20np.sin(_th)%0A%20%20%20%20%20%20%20%20_yb3%20%3D%20-np.cos(_th)%0A%20%20%20%20%20%20%20%20_axp3.plot(%5B0%2C%200%5D%2C%20%5B0%2C%20-1.15%5D%2C%20color%3D%22grey%22%2C%20linestyle%3D%22--%22%2C%20linewidth%3D1)%0A%20%20%20%20%20%20%20%20_deg%20%3D%20np.rad2deg(_th)%0A%20%20%20%20%20%20%20%20_axp3.add_patch(Arc((0%2C%200)%2C%200.7%2C%200.7%2C%20theta1%3Dmin(-90%2C%20-90%20%2B%20_deg)%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%20%20%20theta2%3Dmax(-90%2C%20-90%20%2B%20_deg)%2C%20color%3D%22%23555%22%2C%20linewidth%3D1.5))%0A%20%20%20%20%20%20%20%20if%20abs(_deg)%20%3E%3D%2015%3A%20%20%20%20%23%20at%20small%20angles%20the%20label%20would%20sit%20on%20the%20rod%0A%20%20%20%20%20%20%20%20%20%20%20%20_mid%20%3D%20np.deg2rad(-90%20%2B%20_deg%20%2F%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20_axp3.text(0.5%20*%20np.cos(_mid)%2C%200.5%20*%20np.sin(_mid)%2C%20r%22%24%5Ctheta%24%22%2C%20fontsize%3D13%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ha%3D%22center%22%2C%20va%3D%22center%22%2C%20color%3D%22%23555%22)%0A%20%20%20%20%20%20%20%20_axp3.plot(%5B0%2C%20_xb3%5D%2C%20%5B0%2C%20_yb3%5D%2C%20color%3D_c3%2C%20linewidth%3D3.5%2C%20solid_capstyle%3D%22round%22)%0A%20%20%20%20%20%20%20%20_axp3.add_patch(plt.Circle((_xb3%2C%20_yb3)%2C%200.09%2C%20color%3D_c3%2C%20zorder%3D5))%0A%20%20%20%20%20%20%20%20_axp3.plot(0%2C%200%2C%20%22o%22%2C%20color%3D%22%23333%22%2C%20markersize%3D9%2C%20zorder%3D6)%0A%20%20%20%20%20%20%20%20_axp3.text(0%2C%20-1.42%2C%20rf%22%24%5Ctheta%20%3D%20%7B_deg%3A.0f%7D%5E%5Ccirc%24%22%2C%20ha%3D%22center%22%2C%20fontsize%3D13%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D_c3)%0A%20%20%20%20%20%20%20%20_axp3.set_xlim(-1.3%2C%201.3)%0A%20%20%20%20%20%20%20%20_axp3.set_ylim(-1.55%2C%201.2)%0A%20%20%20%20%20%20%20%20_axp3.set_aspect(%22equal%22)%0A%20%20%20%20%20%20%20%20_axp3.axis(%22off%22)%0A%20%20%20%20%20%20%20%20_axp3.set_title(_name%2C%20fontsize%3D12%2C%20color%3D_c3)%0A%0A%20%20%20%20%23%20right%3A%20the%20angle%20over%20time%2C%20with%20a%20marker%20at%20the%20current%20time%0A%20%20%20%20_ax3.plot(t_pend%2C%20np.rad2deg(theta_small)%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Dr%22small-angle%20formula%20%24%5Ctheta_0%5Ccos%5Comega%20t%24%22)%0A%20%20%20%20_ax3.plot(t_pend%2C%20np.rad2deg(theta_pend)%2C%20color%3D%22%23922b21%22%2C%20linewidth%3D2%2C%20linestyle%3D%22--%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Dr%22full%20equation%20with%20%24%5Csin%5Ctheta%24%20(loop)%22)%0A%20%20%20%20_ax3.axvline(_t_now%2C%20color%3D%22grey%22%2C%20linewidth%3D1)%0A%20%20%20%20_ax3.plot(_t_now%2C%20np.rad2deg(_th_small_now)%2C%20%22o%22%2C%20color%3D%22%231a5276%22%2C%20markersize%3D9)%0A%20%20%20%20_ax3.plot(_t_now%2C%20np.rad2deg(_th_full_now)%2C%20%22o%22%2C%20color%3D%22%23922b21%22%2C%20markersize%3D9)%0A%20%20%20%20_ax3.axhline(0%2C%20color%3D%22grey%22%2C%20linewidth%3D0.8)%0A%20%20%20%20_ax3.set_xlim(0%2C%208)%0A%20%20%20%20_ax3.set_ylim(-180%2C%20180)%0A%20%20%20%20_ax3.set_yticks(%5B-180%2C%20-90%2C%200%2C%2090%2C%20180%5D)%0A%20%20%20%20_ax3.set_xlabel(r%22%24t%24%20(s)%22%2C%20fontsize%3D12)%0A%20%20%20%20_ax3.set_ylabel(r%22%24%5Ctheta%24%20(degrees)%22%2C%20fontsize%3D12)%0A%20%20%20%20_ax3.set_title(rf%22%24l%20%3D%201%24%20m%2C%20released%20from%20rest%20at%20%24%5Ctheta_0%20%3D%20%7Btheta0_slider.value%7D%5E%5Ccirc%24%2C%20%20%20%24t%20%3D%20%7B_t_now%3A.2f%7D%24%20s%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fontsize%3D12)%0A%20%20%20%20_ax3.legend(fontsize%3D10%2C%20loc%3D%22upper%20center%22%2C%20bbox_to_anchor%3D(0.5%2C%20-0.17)%2C%20ncol%3D2)%0A%20%20%20%20_ax3.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig3.tight_layout()%0A%20%20%20%20mo.vstack(%5Btheta0_slider%2C%20t_pend_slider%2C%20_fig3%5D)%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%20What%20to%20notice%0A%0A%20%20%20%20Up%20to%20about%2020%C2%B0%20the%20two%20pendulums%20swing%20together.%20By%2060%C2%B0%20the%20real%20pendulum%20is%20clearly%20slower%3A%20run%20the%20time%20slider%20and%20watch%20the%20red%20one%20fall%20behind%2C%20because%20big%20swings%20take%20longer%20than%20the%20formula's%20period%20%242%5Cpi%2F%5Comega%20%5Capprox%202.0%24%20s.%20Near%20170%C2%B0%20it%20hangs%20near%20the%20top%20for%20a%20long%20time%20before%20each%20swing.%20The%20formula's%20period%20never%20depends%20on%20%24%5Ctheta_0%24%3B%20the%20real%20one%20does.%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20-%20%60np.roots(%5Bp%2C%20q%2C%20r%5D)%60%20solves%20the%20auxiliary%20equation%20%24pm%5E2%20%2B%20qm%20%2B%20r%20%3D%200%24.%20Coefficients%20go%20highest%20power%20first%2C%20and%20a%20missing%20term%20is%20a%200.%0A%20%20%20%20-%20For%20the%20damped%20oscillator%20the%20roots%20tell%20you%20the%20behaviour%3A%20the%20real%20part%20sets%20the%20decay%2C%20the%20imaginary%20part%20the%20oscillation.%20As%20the%20friction%20%24k%24%20grows%20the%20roots%20meet%20at%20%24k%20%3D%20%5Comega%24%20(critical%20damping)%20and%20split%20along%20the%20real%20axis.%0A%20%20%20%20-%20A%20second-order%20ODE%20can%20be%20stepped%20forward%20by%20updating%20two%20numbers%2C%20position%20and%20velocity.%20This%20needs%20no%20formula%2C%20so%20it%20also%20works%20for%20nonlinear%20equations%20like%20the%20pendulum%2C%20where%20the%20auxiliary%20equation%20doesn't%20apply.%0A%0A%20%20%20%20**In%20the%20lab%3A**%20a%20car's%20suspension%20is%20a%20damped%20spring.%20You%20will%20find%20its%20roots%2C%20code%20its%20solution%20from%20the%20formula%2C%20and%20work%20out%20how%20much%20damping%20it%20needs.%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
3ae7db8d430f56e7661d50545018fa36