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%22Computational%20Assignment%20%E2%80%94%20Numerical%20Differentiation%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%20Computational%20Assignment%20%E2%80%94%20Numerical%20Differentiation%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%20**Submission.**%20Fill%20in%20the%20blanks%20below%2C%20run%20every%20cell%2C%20then%20save%20this%20notebook%20as%20a%20%60.ipynb%60%20file%20(File%20%E2%86%92%20Download%20%E2%86%92%20Notebook)%20and%20submit%20it%20on%20Moodle.%20Your%20submission%20is%20graded%20on%20the%20completed%20code%20*and*%20the%20short%20written%20answers%20in%20the%20Markdown%20cells%20%E2%80%94%20write%20your%20answers%20directly%20into%20this%20notebook%2C%20don't%20attach%20a%20separate%20document.%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%20The%20idea%0A%0A%20%20%20%20The%20derivative%20of%20%24f%24%20at%20a%20point%20%24x_0%24%20is%20defined%20as%20a%20limit%3A%20%5C%5Bf'(x_0)%20%3D%20%5Clim_%7Bh%20%5Cto%200%7D%20%5Cfrac%7Bf(x_0%20%2B%20h)%20-%20f(x_0)%7D%7Bh%7D.%5C%5D%0A%0A%20%20%20%20We%20can't%20actually%20take%20%24h%20%5Cto%200%24%20on%20a%20computer%2C%20but%20we%20can%20pick%20a%20small%20%24h%24%20and%20use%20the%20ratio%20directly%20%E2%80%94%20that's%20a%20**finite%20difference%20approximation**.%20There%20are%20two%20natural%20choices%3A%0A%0A%20%20%20%20-%20**Forward%20difference**%3A%20%24%5Cdfrac%7Bf(x_0%20%2B%20h)%20-%20f(x_0)%7D%7Bh%7D%24%20%E2%80%94%20exactly%20the%20limit%20definition%20above%2C%20with%20%24h%24%20small%20but%20not%20zero.%0A%20%20%20%20-%20**Centred%20difference**%3A%20%24%5Cdfrac%7Bf(x_0%20%2B%20h)%20-%20f(x_0%20-%20h)%7D%7B2h%7D%24%20%E2%80%94%20uses%20one%20point%20on%20each%20side%20of%20%24x_0%24%20instead%20of%20just%20one%20side.%0A%0A%20%20%20%20Both%20should%20approach%20the%20true%20derivative%20as%20%24h%20%5Cto%200%24.%20The%20question%20this%20assignment%20investigates%3A%20**how%20fast**%2C%20and%20does%20it%20matter%20which%20one%20you%20pick%3F%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%20Parameters%0A%0A%20%20%20%20We'll%20differentiate%20%24f(x)%20%3D%20%5Csin(x)%24%20at%20%24x_0%20%3D%201.0%24%2C%20where%20the%20exact%20derivative%20%24f'(x_0)%20%3D%20%5Ccos(x_0)%24%20is%20known%20%E2%80%94%20so%20we%20can%20measure%20the%20error%20of%20each%20approximation%20directly%2C%20the%20same%20way%20Chapter%206%20measured%20Euler's%20method%20against%20a%20known%20exact%20solution.%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%20f_hw2(x)%3A%0A%20%20%20%20%20%20%20%20return%20np.sin(x)%0A%0A%20%20%20%20def%20df_exact_hw2(x)%3A%0A%20%20%20%20%20%20%20%20return%20np.cos(x)%0A%0A%20%20%20%20x0_hw2%20%3D%201.0%0A%20%20%20%20return%20df_exact_hw2%2C%20f_hw2%2C%20x0_hw2%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%20Exercise%201%20%E2%80%94%20forward%20difference%0A%0A%20%20%20%20**Task.**%20In%20the%20cell%20below%2C%20replace%20the%20%600.0%60%20placeholder%20with%20the%20forward%20difference%20formula%2C%20using%20%60f_hw2%60%2C%20%60x0_hw2%60%2C%20and%20%60h_ex1%60.%20You%20should%20get%20a%20value%20close%20to%20(but%20not%20exactly%20equal%20to)%20%24%5Ccos(1.0)%20%5Capprox%200.5403%24.%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%20h_ex1%20%3D%200.1%0A%20%20%20%20df_forward_ex1%20%3D%200.0%20%20%20%20%23%20%E2%86%90%20fill%20this%20in%0A%20%20%20%20df_forward_ex1%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%20Exercise%202%20%E2%80%94%20centred%20difference%0A%0A%20%20%20%20**Task.**%20Same%20idea%2C%20but%20now%20use%20the%20centred%20difference%20formula.%20Replace%20the%20%600.0%60%20placeholder%20using%20%60f_hw2%60%2C%20%60x0_hw2%60%2C%20and%20%60h_ex2%60.%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%20h_ex2%20%3D%200.1%0A%20%20%20%20df_centred_ex2%20%3D%200.0%20%20%20%20%23%20%E2%86%90%20fill%20this%20in%0A%20%20%20%20df_centred_ex2%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%20Exercise%203%20%E2%80%94%20convergence%20study%0A%0A%20%20%20%20Now%20repeat%20both%20approximations%20for%20a%20whole%20range%20of%20%24h%24%20values%2C%20from%20%24h%20%3D%2010%5E%7B-1%7D%24%20down%20to%20%24h%20%3D%2010%5E%7B-6%7D%24%2C%20and%20measure%20the%20error%20against%20the%20exact%20derivative%20at%20each%20one.%0A%0A%20%20%20%20**Task.**%20Complete%20the%20two%20array%20formulas%20below%20%E2%80%94%20they're%20the%20same%20formulas%20as%20Exercises%201%20and%202%2C%20just%20applied%20to%20the%20array%20%60h_arr%60%20instead%20of%20a%20single%20number.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_exact_hw2%2C%20np%2C%20x0_hw2)%3A%0A%20%20%20%20h_arr%20%3D%2010.0%20**%20(-np.arange(1%2C%207%2C%20dtype%3Dfloat))%0A%20%20%20%20df_forward_arr%20%3D%20np.zeros_like(h_arr)%20%20%20%23%20%E2%86%90%20same%20formula%20as%20Exercise%201%2C%20but%20with%20h_arr%0A%20%20%20%20df_centred_arr%20%3D%20np.zeros_like(h_arr)%20%20%20%23%20%E2%86%90%20same%20formula%20as%20Exercise%202%2C%20but%20with%20h_arr%0A%20%20%20%20forward_error%20%3D%20np.abs(df_forward_arr%20-%20df_exact_hw2(x0_hw2))%0A%20%20%20%20centred_error%20%3D%20np.abs(df_centred_arr%20-%20df_exact_hw2(x0_hw2))%0A%20%20%20%20return%20centred_error%2C%20forward_error%2C%20h_arr%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(centred_error%2C%20forward_error%2C%20h_arr%2C%20plt)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(7%2C%204.5))%0A%20%20%20%20_ax.loglog(h_arr%2C%20forward_error%2C%20%22o-%22%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20markersize%3D7%2C%20label%3D%22forward%20difference%22)%0A%20%20%20%20_ax.loglog(h_arr%2C%20centred_error%2C%20%22s-%22%2C%20color%3D%22tomato%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20markersize%3D7%2C%20label%3D%22centred%20difference%22)%0A%20%20%20%20_h_ref%20%3D%20%5Bh_arr.min()%2C%20h_arr.max()%5D%0A%20%20%20%20_ax.loglog(_h_ref%2C%20%5Bforward_error%5B-1%5D%20%2F%20h_arr%5B-1%5D%20*%20_h%20for%20_h%20in%20_h_ref%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22k--%22%2C%20linewidth%3D1.2%2C%20label%3D%22slope%201%22)%0A%20%20%20%20_ax.loglog(_h_ref%2C%20%5Bcentred_error%5B-1%5D%20%2F%20h_arr%5B-1%5D%20**%202%20*%20_h%20**%202%20for%20_h%20in%20_h_ref%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22k%3A%22%2C%20linewidth%3D1.2%2C%20label%3D%22slope%202%22)%0A%20%20%20%20_ax.set_xlabel(r%22Step%20size%20%24h%24%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.set_ylabel(%22Error%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.set_title(%22Forward%20vs%20centred%20difference%3A%20convergence%20as%20%24h%20%5C%5Cto%200%24%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.legend(fontsize%3D10)%0A%20%20%20%20_ax.grid(True%2C%20which%3D%22both%22%2C%20alpha%3D0.3)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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%20Written%20answer%20%E2%80%94%20required%0A%0A%20%20%20%20**Task.**%20Looking%20at%20the%20log-log%20plot%20above%3A%20which%20line%20is%20steeper%2C%20and%20what%20does%20that%20tell%20you%20about%20how%20each%20method's%20error%20shrinks%20as%20%24h%24%20gets%20smaller%3F%20Relate%20the%20slopes%20you%20see%20(1%20and%202)%20to%20how%20many%20times%20you'd%20need%20to%20halve%20%24h%24%20to%20gain%20one%20extra%20decimal%20digit%20of%20accuracy%20with%20each%20method.%0A%0A%20%20%20%20*Double-click%20this%20cell%20and%20write%203%E2%80%935%20sentences.*%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%20Extension%20%E2%80%94%20when%20smaller%20isn't%20better%0A%0A%20%20%20%20So%20far%2C%20smaller%20%24h%24%20has%20always%20meant%20a%20smaller%20error.%20That%20can't%20continue%20forever%20%E2%80%94%20a%20computer%20only%20stores%20about%2016%20significant%20digits%2C%20and%20%60f_hw2(x0_hw2%20%2B%20h)%20-%20f_hw2(x0_hw2)%60%20subtracts%20two%20nearly-equal%20numbers%2C%20which%20destroys%20precision%20when%20%24h%24%20gets%20*very*%20small%20(a%20phenomenon%20called%20**catastrophic%20cancellation**).%0A%0A%20%20%20%20**Task.**%20Run%20the%20cell%20below%2C%20which%20extends%20the%20study%20down%20to%20%24h%20%3D%2010%5E%7B-14%7D%24.%20Describe%20in%20a%20sentence%20or%20two%20what%20happens%20to%20the%20two%20error%20curves%20once%20%24h%24%20gets%20small%20enough%2C%20and%20why%20shrinking%20%24h%24%20further%20stops%20helping%20(or%20starts%20hurting).%0A%0A%20%20%20%20*Double-click%20this%20cell%20and%20write%202%E2%80%933%20sentences.*%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_exact_hw2%2C%20f_hw2%2C%20np%2C%20x0_hw2)%3A%0A%20%20%20%20h_arr_ext%20%3D%2010.0%20**%20(-np.arange(1%2C%2015%2C%20dtype%3Dfloat))%0A%20%20%20%20df_forward_ext%20%3D%20(f_hw2(x0_hw2%20%2B%20h_arr_ext)%20-%20f_hw2(x0_hw2))%20%2F%20h_arr_ext%0A%20%20%20%20df_centred_ext%20%3D%20(f_hw2(x0_hw2%20%2B%20h_arr_ext)%20-%20f_hw2(x0_hw2%20-%20h_arr_ext))%20%2F%20(2%20*%20h_arr_ext)%0A%20%20%20%20forward_error_ext%20%3D%20np.abs(df_forward_ext%20-%20df_exact_hw2(x0_hw2))%0A%20%20%20%20centred_error_ext%20%3D%20np.abs(df_centred_ext%20-%20df_exact_hw2(x0_hw2))%0A%20%20%20%20return%20centred_error_ext%2C%20forward_error_ext%2C%20h_arr_ext%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(centred_error_ext%2C%20forward_error_ext%2C%20h_arr_ext%2C%20plt)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(7%2C%204.5))%0A%20%20%20%20_ax.loglog(h_arr_ext%2C%20forward_error_ext%2C%20%22o-%22%2C%20color%3D%22%231a5276%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20markersize%3D5%2C%20label%3D%22forward%20difference%22)%0A%20%20%20%20_ax.loglog(h_arr_ext%2C%20centred_error_ext%2C%20%22s-%22%2C%20color%3D%22tomato%22%2C%20linewidth%3D2%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20markersize%3D5%2C%20label%3D%22centred%20difference%22)%0A%20%20%20%20_ax.set_xlabel(r%22Step%20size%20%24h%24%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.set_ylabel(%22Error%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.set_title(%22Extending%20to%20very%20small%20%24h%24%3A%20round-off%20takes%20over%22%2C%20fontsize%3D13)%0A%20%20%20%20_ax.legend(fontsize%3D10)%0A%20%20%20%20_ax.grid(True%2C%20which%3D%22both%22%2C%20alpha%3D0.3)%0A%20%20%20%20_ax.invert_xaxis()%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%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
af9ee11d7b7c900905624998cea96554