import%20marimo%0A%0A__generated_with%20%3D%20%220.25.0%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20width%3D%22medium%22%2C%0A%20%20%20%20app_title%3D%22Welcome%20week%3A%20can%20a%20computer%20get%20a%20simulation%20wrong%3F%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%20Welcome%20week%3A%20can%20a%20computer%20get%20a%20simulation%20wrong%3F%0A%20%20%20%20%23%23%20MATH4120%20orientation-week%20activity%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%20Picture%20a%20metal%20plate%20shaped%20like%20a%20thick%20letter%20L%3A%20a%20square%20with%20one%20corner%20sliced%20off.%20Heat%20one%20point%20on%20it%20to%20100%C2%B0C%2C%20hold%20every%20edge%20(including%20the%20edge%20of%20that%20missing%20corner)%20at%20a%20cold%200%C2%B0C%2C%20and%20let%20a%20computer%20work%20out%20what%20happens%20next.%0A%0A%20%20%20%20Before%20any%20explanation%2C%20here's%20what%20a%20real%2C%20localised%20point%20of%20heat%20on%20a%20piece%20of%20metal%20actually%20looks%20like.%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.Html(%0A%20%20%20%20%20%20%20%20'%3Ciframe%20width%3D%22100%25%22%20height%3D%22400%22%20'%0A%20%20%20%20%20%20%20%20'src%3D%22https%3A%2F%2Fwww.youtube.com%2Fembed%2Fbyvr-dwwao4%3Fstart%3D291%22%20'%0A%20%20%20%20%20%20%20%20'title%3D%22Thermal%20camera%20imaging%20of%20soldering%20vs%20spot%20welding%22%20frameborder%3D%220%22%20'%0A%20%20%20%20%20%20%20%20'allow%3D%22accelerometer%3B%20autoplay%3B%20clipboard-write%3B%20encrypted-media%3B%20gyroscope%3B%20picture-in-picture%3B%20web-share%22%20'%0A%20%20%20%20%20%20%20%20'allowfullscreen%3E%3C%2Fiframe%3E'%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20A%20thermal%20camera%20comparing%20soldering%20and%20spot%20welding%2C%20two%20ways%20of%20heating%20a%20small%2C%20localised%20point%20on%20a%20piece%20of%20metal%2C%20the%20kind%20of%20thing%20used%20to%20connect%20battery%20tabs.%20Same%20idea%20as%20the%20plate%20you're%20about%20to%20see%2C%20just%20on%20a%20real%20workbench.%0A%0A%20%20%20%20Now%20here's%20a%20simplified%20computer%20model%20of%20exactly%20this.%20Try%20the%20sliders.%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_(%0A%20%20%20%20N_slider%2C%0A%20%20%20%20alpha%2C%0A%20%20%20%20laplacian%2C%0A%20%20%20%20make_L_mask%2C%0A%20%20%20%20make_hot_spot%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_slider%2C%0A%20%20%20%20plot_field%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20step_slider%2C%0A)%3A%0A%20%20%20%20_n%20%3D%20n_slider.value%0A%20%20%20%20_N%20%3D%20N_slider.value%0A%20%20%20%20_step%20%3D%20step_slider.value%0A%20%20%20%20_T%20%3D%200.0125%0A%20%20%20%20_mask%20%3D%20make_L_mask(_n)%0A%20%20%20%20_u0%20%3D%20make_hot_spot(_n%2C%20_n%20%2F%2F%204%2C%20_n%20%2F%2F%204%2C%20100.0)%0A%20%20%20%20_dx%20%3D%201.0%20%2F%20(_n%20-%201)%0A%20%20%20%20_u%20%3D%20run_heat_partial(_u0%2C%20_mask%2C%20alpha%2C%20_T%2C%20_N%2C%20_step%2C%20_dx%2C%20laplacian%2C%20heat_step)%0A%20%20%20%20_t_elapsed%20%3D%20_step%20*%20(_T%20%2F%20_N)%0A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(5.5%2C%205.5))%0A%20%20%20%20_im%20%3D%20plot_field(_ax%2C%20_u%2C%20_mask%2C%20f%22grid%20%7B_n%7Dx%7B_n%7D%2C%20step%20%7B_step%7D%20of%20%7B_N%7D%2C%20t%20%3D%20%7B_t_elapsed%3A.5f%7D%22)%0A%20%20%20%20_cbar%20%3D%20plt.colorbar(_im%2C%20ax%3D_ax%2C%20fraction%3D0.046)%0A%20%20%20%20_cbar.set_label(%22Temperature%20(%C2%B0C)%22)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20mo.vstack(%5Bn_slider%2C%20N_slider%2C%20step_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%20Three%20independent%20controls%3A%20how%20fine%20the%20grid%20is%2C%20how%20many%20steps%20the%20computer%20takes%20to%20reach%20a%20fixed%20moment%20in%20time%2C%20and%20which%20of%20those%20steps%20you're%20currently%20looking%20at.%20Move%20each%20one%20on%20its%20own%20and%20see%20what%20changes.%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%20Before%20you%20go%20any%20further%3A%20discuss%20in%20your%20group%0A%0A%20%20%20%20Leave%20every%20slider%20at%20its%20starting%20position%20for%20a%20moment%2C%20so%20you're%20looking%20at%20%24t%20%3D%200%24%3A%20just%20the%20plate%20and%20the%20hot%20spot.%0A%0A%20%20%20%20**Discuss%20with%20your%20group%2C%20then%20agree%20on%20a%20prediction%2C%20before%20you%20touch%20a%20slider%3A**%0A%0A%20%20%20%20-%20As%20you%20drag%20the%20step%20slider%20forward%2C%20what%20do%20you%20expect%20the%20plate%20to%20look%20like%3F%20Remember%20every%20edge%20is%20held%20at%200%C2%B0C.%0A%20%20%20%20-%20Could%20any%20cell%20on%20the%20plate%20ever%20end%20up%20colder%20than%200%C2%B0C%3F%20Why%20or%20why%20not%3F%0A%20%20%20%20-%20If%20you%20force%20the%20same%20final%20moment%20in%20time%20to%20be%20reached%20using%20only%20a%20handful%20of%20much%20bigger%20steps%2C%20what%20do%20you%20expect%20happens%20to%20the%20picture%3F%0A%0A%20%20%20%20Write%20your%20prediction%20down%2C%20then%20go%20and%20test%20it.%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%20How%20this%20actually%20works%0A%0A%20%20%20%20Now%20the%20machinery%20behind%20the%20plate%20you've%20been%20dragging%20sliders%20on.%20The%20plate%20is%20a%20grid%20of%20points.%20The%20function%20below%20marks%20which%20points%20are%20actually%20part%20of%20the%20plate%3A%20it%20starts%20with%20a%20full%20square%20and%20removes%20the%20top%20right%20quarter%2C%20leaving%20an%20L%20shape%2C%20at%20whatever%20resolution%20it's%20asked%20for.%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%20make_L_mask(n)%3A%0A%20%20%20%20%20%20%20%20mask%20%3D%20np.ones((n%2C%20n)%2C%20dtype%3Dbool)%0A%20%20%20%20%20%20%20%20half%20%3D%20n%20%2F%2F%202%0A%20%20%20%20%20%20%20%20mask%5Bhalf%3A%2C%20half%3A%5D%20%3D%20False%0A%20%20%20%20%20%20%20%20return%20mask%0A%0A%20%20%20%20return%20(make_L_mask%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%20Next%2C%20a%20function%20that%20builds%20a%20starting%20temperature%20grid%20at%20that%20same%20resolution%3A%20one%20point%20heated%20to%20some%20value%2C%20everywhere%20else%20at%20zero.%20Zero%20here%20just%20means%20as%20cold%20as%20the%20edges%20of%20the%20plate.%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%20make_hot_spot(n%2C%20i0%2C%20j0%2C%20value)%3A%0A%20%20%20%20%20%20%20%20u0%20%3D%20np.zeros((n%2C%20n))%0A%20%20%20%20%20%20%20%20u0%5Bi0%2C%20j0%5D%20%3D%20value%0A%20%20%20%20%20%20%20%20return%20u0%0A%0A%20%20%20%20return%20(make_hot_spot%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%20And%20the%20function%20that%20draws%20it%3A%20red%20for%20hot%2C%20blue%20for%20colder%20than%20the%20edges%2C%20white%20sitting%20exactly%20at%200%C2%B0C%2C%20with%20faint%20lines%20marking%20every%20individual%20grid%20cell.%20Anything%20outside%20the%20L%20shape%20is%20greyed%20out.%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%20def%20plot_field(ax%2C%20u%2C%20mask%2C%20title%2C%20vmax%3DNone)%3A%0A%20%20%20%20%20%20%20%20disp%20%3D%20np.where(mask%2C%20u%2C%20np.nan)%0A%20%20%20%20%20%20%20%20if%20vmax%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20vmax%20%3D%20np.nanmax(np.abs(disp))%0A%20%20%20%20%20%20%20%20if%20vmax%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20vmax%20%3D%201.0%0A%20%20%20%20%20%20%20%20cmap%20%3D%20plt.get_cmap(%22RdBu_r%22).copy()%0A%20%20%20%20%20%20%20%20cmap.set_bad(%22%23dddddd%22)%0A%20%20%20%20%20%20%20%20n_side%20%3D%20u.shape%5B0%5D%0A%20%20%20%20%20%20%20%20im%20%3D%20ax.imshow(disp%2C%20cmap%3Dcmap%2C%20vmin%3D-vmax%2C%20vmax%3Dvmax%2C%20origin%3D%22lower%22%2C%20interpolation%3D%22nearest%22)%0A%20%20%20%20%20%20%20%20ax.set_xticks(np.arange(-0.5%2C%20n_side%2C%201)%2C%20minor%3DTrue)%0A%20%20%20%20%20%20%20%20ax.set_yticks(np.arange(-0.5%2C%20n_side%2C%201)%2C%20minor%3DTrue)%0A%20%20%20%20%20%20%20%20ax.grid(which%3D%22minor%22%2C%20color%3D%22%23888888%22%2C%20linewidth%3D0.3%2C%20alpha%3D0.6)%0A%20%20%20%20%20%20%20%20ax.tick_params(which%3D%22minor%22%2C%20size%3D0)%0A%20%20%20%20%20%20%20%20ax.set_title(title%2C%20fontsize%3D12)%0A%20%20%20%20%20%20%20%20ax.set_xticks(%5B%5D)%0A%20%20%20%20%20%20%20%20ax.set_yticks(%5B%5D)%0A%20%20%20%20%20%20%20%20return%20im%0A%0A%20%20%20%20return%20(plot_field%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%20Heat%20flowing%20through%20a%20surface%20obeys%20an%20equation%20relating%20how%20fast%20a%20point's%20temperature%20changes%20to%20the%20temperatures%20of%20its%20four%20neighbours.%20The%20function%20below%20computes%20that%20quantity%20at%20every%20cell%20of%20the%20grid%20in%20one%20go.%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%20laplacian(u%2C%20dx)%3A%0A%20%20%20%20%20%20%20%20lap%20%3D%20np.zeros_like(u)%0A%20%20%20%20%20%20%20%20lap%5B1%3A-1%2C%201%3A-1%5D%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20u%5B2%3A%2C%201%3A-1%5D%20%2B%20u%5B%3A-2%2C%201%3A-1%5D%20%2B%20u%5B1%3A-1%2C%202%3A%5D%20%2B%20u%5B1%3A-1%2C%20%3A-2%5D%20-%204%20*%20u%5B1%3A-1%2C%201%3A-1%5D%0A%20%20%20%20%20%20%20%20)%20%2F%20dx**2%0A%20%20%20%20%20%20%20%20return%20lap%0A%0A%20%20%20%20return%20(laplacian%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%20From%20here%20it's%20the%20same%20idea%20as%20Euler's%20method%20for%20a%20single%20number%2C%20just%20applied%20at%20every%20cell%20of%20the%20grid%20at%20once%3A%20take%20the%20current%20temperature%2C%20add%20a%20small%20step%20times%20the%20rate%20of%20change%2C%20repeat.%20Anywhere%20off%20the%20plate%20is%20held%20fixed%20at%200%C2%B0C.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20heat_step(u%2C%20mask%2C%20alpha%2C%20dt%2C%20dx%2C%20laplacian)%3A%0A%20%20%20%20u_new%20%3D%20u%20%2B%20dt%20*%20alpha%20*%20laplacian(u%2C%20dx)%0A%20%20%20%20u_new%5B~mask%5D%20%3D%200.0%0A%20%20%20%20return%20u_new%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%20And%20the%20function%20driving%20the%20plate%20above%3A%20it%20aims%20for%20a%20fixed%20total%20time%20%24T%24%2C%20splits%20it%20into%20%24N%24%20equal%20steps%2C%20then%20runs%20however%20many%20of%20those%20steps%20you%20ask%20for.%20Run%20all%20%24N%24%20of%20them%20and%20you%20get%20the%20final%20picture%3B%20stop%20partway%20and%20you%20get%20a%20snapshot%20mid%20way%20through.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20run_heat_partial(u0%2C%20mask%2C%20alpha%2C%20T%2C%20N%2C%20step%2C%20dx%2C%20laplacian%2C%20heat_step)%3A%0A%20%20%20%20dt%20%3D%20T%20%2F%20N%0A%20%20%20%20u%20%3D%20u0.copy()%0A%20%20%20%20for%20_%20in%20range(step)%3A%0A%20%20%20%20%20%20%20%20u%20%3D%20heat_step(u%2C%20mask%2C%20alpha%2C%20dt%2C%20dx%2C%20laplacian)%0A%20%20%20%20return%20u%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20alpha%20%3D%201.0%0A%20%20%20%20return%20(alpha%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20n_slider%20%3D%20mo.ui.slider(6%2C%2040%2C%20step%3D2%2C%20value%3D20%2C%20label%3D%22Grid%20resolution%20n%22)%0A%20%20%20%20return%20(n_slider%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20N_slider%20%3D%20mo.ui.slider(2%2C%20200%2C%20step%3D2%2C%20value%3D25%2C%20label%3D%22Total%20steps%20N%20to%20reach%20t%20%3D%200.0125%22)%0A%20%20%20%20return%20(N_slider%2C)%0A%0A%0A%40app.cell%0Adef%20_(N_slider%2C%20mo)%3A%0A%20%20%20%20step_slider%20%3D%20mo.ui.slider(0%2C%20N_slider.value%2C%20step%3D1%2C%20value%3D0%2C%20label%3D%22Step%20to%20view%22)%0A%20%20%20%20return%20(step_slider%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%23%23%20Discuss%0A%0A%20%20%20%20-%20Did%20dragging%20the%20step%20slider%20forward%20match%20your%20group's%20prediction%3F%0A%20%20%20%20-%20The%20colour%20never%20turns%20blue%20while%20%24N%24%20is%20large%20enough.%20Push%20%24N%24%20down%20while%20keeping%20the%20grid%20resolution%20fixed%3A%20at%20some%20point%20it%20does.%20What%20does%20that%20mean%20physically%3F%0A%20%20%20%20-%20Now%20push%20the%20grid%20resolution%20%24n%24%20up%20while%20keeping%20%24N%24%20fixed%20at%20a%20value%20that%20looked%20safe%20before.%20Does%20it%20stay%20safe%3F%20A%20finer%20grid%20means%20smaller%20cells%2C%20which%20means%20the%20same%20%24N%24%20covers%20less%20real%20time%20per%20step...%20or%20does%20it%3F%20Work%20out%20with%20your%20group%20what's%20actually%20changing.%0A%20%20%20%20-%20Check%20the%20actual%20numbers%20printed%20on%20the%20colour%20scale%3A%20how%20do%20they%20compare%20with%20the%200%20to%20100%C2%B0C%20range%20you%20started%20with%3F%0A%20%20%20%20-%20So%20why%20not%20simply%20always%20run%20the%20finest%20grid%20and%20the%20smallest%20steps%2C%20every%20time%3F%20Drag%20both%20%24n%24%20and%20%24N%24%20right%20up%20together%20and%20notice%20how%20much%20longer%20the%20plot%20takes%20to%20redraw.%20What's%20actually%20being%20traded%20off%20here%2C%20and%20why%20might%20a%20scientist%20or%20engineer%20sometimes%20deliberately%20choose%20a%20coarser%2C%20faster%20simulation%20over%20this%20safest%20one%3F%0A%0A%20%20%20%20We're%20leaving%20the%20precise%20explanation%20open%20for%20now.%20You'll%20get%20it%2C%20condition%20and%20all%2C%20in%20Chapter%206%20(taught%20in%20Week%207)%2C%20for%20the%20single%20number%20version%20of%20exactly%20this%20idea.%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%20Now%20it's%20your%20turn%0A%0A%20%20%20%20Everything%20below%20runs%20directly%20in%20your%20browser%2C%20and%20unlike%20the%20demo%20above%2C%20these%20are%20cells%20you%20can%20edit%20yourself.%20Press%20**Ctrl%2BEnter**%20(or%20**Shift%2BEnter**)%20to%20run%20a%20cell%20after%20changing%20it.%20Both%20tasks%20below%20give%20you%20the%20same%20three%20sliders%20as%20the%20demo%20above%2C%20this%20time%20on%20a%20plate%20you've%20placed%20the%20hot%20spots%20on%20yourself.%0A%0A%20%20%20%20Rather%20than%20a%20grid%20index%2C%20you'll%20place%20hot%20spots%20using%20real%20coordinates%3A%20%24x%24%20and%20%24y%24%20both%20running%20from%200%20(the%20left%20or%20bottom%20edge)%20to%201%20(the%20right%20or%20top%20edge)%2C%20regardless%20of%20how%20fine%20the%20grid%20is.%20The%20function%20below%20rounds%20whatever%20%24x%2C%20y%24%20you%20pick%20to%20the%20nearest%20actual%20grid%20point.%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%20nearest_grid_point(x%2C%20y%2C%20n)%3A%0A%20%20%20%20%20%20%20%20j%20%3D%20int(np.clip(round(x%20*%20(n%20-%201))%2C%200%2C%20n%20-%201))%0A%20%20%20%20%20%20%20%20i%20%3D%20int(np.clip(round(y%20*%20(n%20-%201))%2C%200%2C%20n%20-%201))%0A%20%20%20%20%20%20%20%20return%20i%2C%20j%0A%0A%20%20%20%20return%20(nearest_grid_point%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%23%23%23%20Task%201%3A%20change%20a%20number%20yourself%0A%0A%20%20%20%20%60x0_task1%60%20and%20%60y0_task1%60%20below%20set%20where%20the%20hot%20spot%20starts%2C%20as%20real%20coordinates%20from%200%20to%201.%20Right%20now%20it%20sits%20in%20the%20arm%20of%20the%20L%2C%20away%20from%20the%20corner.%0A%0A%20%20%20%20**Edit%20those%20two%20numbers**%20to%20move%20the%20hot%20spot%20somewhere%20else%20on%20the%20plate%20(anywhere%20works%2C%20except%20where%20both%20%24x%24%20and%20%24y%24%20are%20above%200.5%2C%20since%20that's%20the%20missing%20corner).%20Run%20the%20cell%20and%20the%20one%20below%20it%2C%20then%20try%20the%20three%20sliders%20exactly%20as%20you%20did%20above%2C%20on%20your%20own%20hot%20spot%20this%20time.%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%20x0_task1%20%3D%200.15%0A%20%20%20%20y0_task1%20%3D%200.75%0A%20%20%20%20return%20x0_task1%2C%20y0_task1%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20n_slider_task1%20%3D%20mo.ui.slider(6%2C%2040%2C%20step%3D2%2C%20value%3D20%2C%20label%3D%22Grid%20resolution%20n%22)%0A%20%20%20%20return%20(n_slider_task1%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20N_slider_task1%20%3D%20mo.ui.slider(2%2C%20200%2C%20step%3D2%2C%20value%3D25%2C%20label%3D%22Total%20steps%20N%22)%0A%20%20%20%20return%20(N_slider_task1%2C)%0A%0A%0A%40app.cell%0Adef%20_(N_slider_task1%2C%20mo)%3A%0A%20%20%20%20step_slider_task1%20%3D%20mo.ui.slider(0%2C%20N_slider_task1.value%2C%20step%3D1%2C%20value%3DN_slider_task1.value%2C%20label%3D%22Step%20to%20view%22)%0A%20%20%20%20return%20(step_slider_task1%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20N_slider_task1%2C%0A%20%20%20%20alpha%2C%0A%20%20%20%20laplacian%2C%0A%20%20%20%20make_L_mask%2C%0A%20%20%20%20make_hot_spot%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_slider_task1%2C%0A%20%20%20%20nearest_grid_point%2C%0A%20%20%20%20plot_field%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20step_slider_task1%2C%0A%20%20%20%20x0_task1%2C%0A%20%20%20%20y0_task1%2C%0A)%3A%0A%20%20%20%20_n%20%3D%20n_slider_task1.value%0A%20%20%20%20_N%20%3D%20N_slider_task1.value%0A%20%20%20%20_step%20%3D%20step_slider_task1.value%0A%20%20%20%20_T%20%3D%200.0125%0A%20%20%20%20_mask%20%3D%20make_L_mask(_n)%0A%20%20%20%20_i0%2C%20_j0%20%3D%20nearest_grid_point(x0_task1%2C%20y0_task1%2C%20_n)%0A%20%20%20%20_u0%20%3D%20make_hot_spot(_n%2C%20_i0%2C%20_j0%2C%20100.0)%0A%20%20%20%20_dx%20%3D%201.0%20%2F%20(_n%20-%201)%0A%20%20%20%20_u%20%3D%20run_heat_partial(_u0%2C%20_mask%2C%20alpha%2C%20_T%2C%20_N%2C%20_step%2C%20_dx%2C%20laplacian%2C%20heat_step)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(5.5%2C%205.5))%0A%20%20%20%20_im%20%3D%20plot_field(_ax%2C%20_u%2C%20_mask%2C%20f%22hot%20spot%20at%20(x%3D%7Bx0_task1%7D%2C%20y%3D%7By0_task1%7D)%2C%20grid%20%7B_n%7Dx%7B_n%7D%22)%0A%20%20%20%20_cbar%20%3D%20plt.colorbar(_im%2C%20ax%3D_ax%2C%20fraction%3D0.046)%0A%20%20%20%20_cbar.set_label(%22Temperature%20(%C2%B0C)%22)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20mo.vstack(%5Bn_slider_task1%2C%20N_slider_task1%2C%20step_slider_task1%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%23%23%23%20Task%202%3A%20write%20a%20line%20yourself%0A%0A%20%20%20%20The%20function%20below%20is%20meant%20to%20place%20**two**%20hot%20spots%20instead%20of%20one.%20It%20already%20places%20the%20first%20one%3B%20the%20second%20line%20is%20left%20for%20you%20to%20finish.%0A%0A%20%20%20%20**Complete%20the%20marked%20line**%20so%20the%20second%20spot%20is%20set%20to%20%60value%60%20too%2C%20the%20same%20way%20the%20line%20above%20it%20does%20it.%20Then%20run%20the%20cell%20and%20the%20one%20below%20it%2C%20and%20try%20the%20sliders%20again.%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%20make_two_hot_spots(n%2C%20i0%2C%20j0%2C%20i1%2C%20j1%2C%20value)%3A%0A%20%20%20%20%20%20%20%20u0%20%3D%20np.zeros((n%2C%20n))%0A%20%20%20%20%20%20%20%20u0%5Bi0%2C%20j0%5D%20%3D%20value%0A%20%20%20%20%20%20%20%20u0%5Bi1%2C%20j1%5D%20%3D%200.0%20%20%23%20complete%20this%0A%20%20%20%20%20%20%20%20return%20u0%0A%0A%20%20%20%20return%20(make_two_hot_spots%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20n_slider_task2%20%3D%20mo.ui.slider(6%2C%2040%2C%20step%3D2%2C%20value%3D20%2C%20label%3D%22Grid%20resolution%20n%22)%0A%20%20%20%20return%20(n_slider_task2%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20N_slider_task2%20%3D%20mo.ui.slider(2%2C%20200%2C%20step%3D2%2C%20value%3D25%2C%20label%3D%22Total%20steps%20N%22)%0A%20%20%20%20return%20(N_slider_task2%2C)%0A%0A%0A%40app.cell%0Adef%20_(N_slider_task2%2C%20mo)%3A%0A%20%20%20%20step_slider_task2%20%3D%20mo.ui.slider(0%2C%20N_slider_task2.value%2C%20step%3D1%2C%20value%3DN_slider_task2.value%2C%20label%3D%22Step%20to%20view%22)%0A%20%20%20%20return%20(step_slider_task2%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20N_slider_task2%2C%0A%20%20%20%20alpha%2C%0A%20%20%20%20laplacian%2C%0A%20%20%20%20make_L_mask%2C%0A%20%20%20%20make_two_hot_spots%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_slider_task2%2C%0A%20%20%20%20nearest_grid_point%2C%0A%20%20%20%20plot_field%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20step_slider_task2%2C%0A)%3A%0A%20%20%20%20_n%20%3D%20n_slider_task2.value%0A%20%20%20%20_N%20%3D%20N_slider_task2.value%0A%20%20%20%20_step%20%3D%20step_slider_task2.value%0A%20%20%20%20_T%20%3D%200.0125%0A%20%20%20%20_mask%20%3D%20make_L_mask(_n)%0A%20%20%20%20_i0%2C%20_j0%20%3D%20nearest_grid_point(0.25%2C%200.25%2C%20_n)%0A%20%20%20%20_i1%2C%20_j1%20%3D%20nearest_grid_point(0.75%2C%200.15%2C%20_n)%0A%20%20%20%20_u0%20%3D%20make_two_hot_spots(_n%2C%20_i0%2C%20_j0%2C%20_i1%2C%20_j1%2C%20100.0)%0A%20%20%20%20_dx%20%3D%201.0%20%2F%20(_n%20-%201)%0A%20%20%20%20_u%20%3D%20run_heat_partial(_u0%2C%20_mask%2C%20alpha%2C%20_T%2C%20_N%2C%20_step%2C%20_dx%2C%20laplacian%2C%20heat_step)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(5.5%2C%205.5))%0A%20%20%20%20_im%20%3D%20plot_field(_ax%2C%20_u%2C%20_mask%2C%20f%22two%20hot%20spots%2C%20grid%20%7B_n%7Dx%7B_n%7D%22)%0A%20%20%20%20_cbar%20%3D%20plt.colorbar(_im%2C%20ax%3D_ax%2C%20fraction%3D0.046)%0A%20%20%20%20_cbar.set_label(%22Temperature%20(%C2%B0C)%22)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20mo.vstack(%5Bn_slider_task2%2C%20N_slider_task2%2C%20step_slider_task2%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%20If%20you%20still%20see%20only%20one%20glow%20above%2C%20the%20marked%20line%20hasn't%20been%20completed%20yet.%20Once%20it%20has%2C%20you%20should%20see%20two%20separate%20patches%20of%20warmth%2C%20each%20spreading%20out%20from%20its%20own%20point.%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%20Wrap-up%0A%0A%20%20%20%20-%20Real%20heat%20never%20flows%20somewhere%20and%20makes%20it%20colder%20than%20the%20coldest%20thing%20around.%20Whenever%20this%20simulation%20showed%20blue%2C%20that's%20exactly%20what%20it%20claimed%20happened%3A%20a%20clear%20sign%20the%20answer%20has%20gone%20wrong%20in%20a%20fundamental%20way.%0A%20%20%20%20-%20A%20simulation%20going%20wrong%20isn't%20always%20a%20matter%20of%20getting%20slightly%20less%20accurate.%20Sometimes%20it%20turns%20into%20something%20qualitatively%20different%20from%20the%20thing%20it's%20supposed%20to%20be%20modelling.%0A%20%20%20%20-%20This%20is%20a%20real%2C%20well%20known%20phenomenon%20called%20**numerical%20instability**.%20It%20shows%20up%20whenever%20a%20method%20takes%20steps%20that%20are%20too%20large%20relative%20to%20the%20grid%20it's%20running%20on%2C%20in%20any%20equation%2C%20on%20any%20grid.%0A%20%20%20%20-%20Everything%20here%2C%20the%20update%20rule%2C%20the%20instability%2C%20the%20grid%20itself%2C%20is%20built%20from%20the%20same%20single%20idea%20you'll%20meet%20properly%20in%20Chapter%206%20(taught%20in%20Week%207)%3A%20Euler's%20method.%20There%2C%20it's%20one%20number%20changing%20in%20time.%20Here%2C%20it's%20every%20cell%20of%20a%20grid%20changing%20at%20once.%20Same%20rule%2C%20much%20bigger%20picture.%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
db62c7761a3eda47c8fcdc52d8a58d24