├── requirements.txt ├── Figures ├── A1.png ├── A2.png ├── B1.gif ├── B2.png ├── C1.gif ├── C2.png ├── D1.png ├── E1.png ├── E2.png ├── E3.png ├── E4.png ├── E5.png ├── F1.png ├── F2.png ├── F3.png ├── G1.png ├── G2.png ├── G3.png ├── G4.png ├── G5.png ├── H1.png ├── H2.png ├── H3.png ├── H4.png ├── H5.png ├── H6.png └── I1.png ├── Monte Carlo Methods Report.pdf ├── README.md ├── montecarlo2d_floating.py ├── montecarlo2d.py └── montecarlo.py /requirements.txt: -------------------------------------------------------------------------------- 1 | gif==1.0.2 2 | matplotlib==3.2.1 3 | numpy==1.18.2 4 | -------------------------------------------------------------------------------- /Figures/A1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/A1.png -------------------------------------------------------------------------------- /Figures/A2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/A2.png -------------------------------------------------------------------------------- /Figures/B1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/B1.gif -------------------------------------------------------------------------------- /Figures/B2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/B2.png -------------------------------------------------------------------------------- /Figures/C1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/C1.gif -------------------------------------------------------------------------------- /Figures/C2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/C2.png -------------------------------------------------------------------------------- /Figures/D1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/D1.png -------------------------------------------------------------------------------- /Figures/E1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/E1.png -------------------------------------------------------------------------------- /Figures/E2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/E2.png -------------------------------------------------------------------------------- /Figures/E3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/E3.png -------------------------------------------------------------------------------- /Figures/E4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/E4.png -------------------------------------------------------------------------------- /Figures/E5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/E5.png -------------------------------------------------------------------------------- /Figures/F1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/F1.png -------------------------------------------------------------------------------- /Figures/F2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/F2.png -------------------------------------------------------------------------------- /Figures/F3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/F3.png -------------------------------------------------------------------------------- /Figures/G1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/G1.png -------------------------------------------------------------------------------- /Figures/G2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/G2.png -------------------------------------------------------------------------------- /Figures/G3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/G3.png -------------------------------------------------------------------------------- /Figures/G4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/G4.png -------------------------------------------------------------------------------- /Figures/G5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/G5.png -------------------------------------------------------------------------------- /Figures/H1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H1.png -------------------------------------------------------------------------------- /Figures/H2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H2.png -------------------------------------------------------------------------------- /Figures/H3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H3.png -------------------------------------------------------------------------------- /Figures/H4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H4.png -------------------------------------------------------------------------------- /Figures/H5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H5.png -------------------------------------------------------------------------------- /Figures/H6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/H6.png -------------------------------------------------------------------------------- /Figures/I1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Figures/I1.png -------------------------------------------------------------------------------- /Monte Carlo Methods Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-ankur/montecarlo-pde/HEAD/Monte Carlo Methods Report.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # montecarlo-pde 2 | The Poisson Equation, and its special case, the 3 | Laplace Equation, are important partial differential equations 4 | within electrostatics, as they describe the electric potential field 5 | caused by a particular charge distribution. Solving the Poisson 6 | equation for a given set of boundary conditions is a fundamental 7 | problem within the field. This report describes an algorithm for a 8 | Monte Carlo Method solution to the Poisson and Laplace 9 | equations. Monte Carlo Method is a parallelizable non- 10 | deterministic numerical approach towards solving this problem. 11 | A Python implementation is also provided for three versions of the 12 | Monte Carlo Method: Fixed Step, Semi-Floating and Full 13 | Floating. Several examples including the one-dimensional and 14 | two-dimensional parallel plate capacitors are performed to 15 | illustrate the function of the implementation. 16 | 17 | 18 | Keywords: Poisson Equation, Laplace Equation, Monte Carlo 19 | Methods, Electrostatics, Parallel Plate Capacitor, Python 20 | Implementation 21 | 22 | 23 | A. One dimentional capacitor (Laplace Equation) 24 |

25 | 26 | 27 |

28 | 29 | B. Variation of solution with number of random walks 30 | (Laplace Equation) 31 |

32 | 33 | 34 |

35 | 36 | C. Variation of solution with number of lattice points 37 | (Laplace Equation) 38 |

39 | 40 | 41 |

42 | 43 | D.One dimensional capacitor with a linear charge 44 | distribution (Poisson Equation) 45 |

46 | 47 |

48 | 49 | E. Two dimentional capacitor (Laplace Equation) 50 |

51 | 52 | 53 |

54 |

55 | 56 | 57 |

58 | 59 | F.Two dimentional metal box with a spherical charge in 60 | centre (Poisson Equation) 61 |

62 | 63 | 64 | 65 |

66 | 67 | G. Two dimentional metal box with a two oppositely charged 68 | spheres (Poisson Equation) 69 |

70 | 71 | 72 |

73 |

74 | 75 | 76 |

77 | 78 | H.Two dimentional metal box with a spherical charge at 79 | center using semi-floating random walk algorithm 80 | (Poisson Equation) 81 | 82 |

83 | 84 | 85 |

86 | 87 | I. Two dimentional metal box with a spherical charge at 88 | center using full floating random walk algorithm (Poisson 89 | Equation) 90 |

91 | 92 |

93 | -------------------------------------------------------------------------------- /montecarlo2d_floating.py: -------------------------------------------------------------------------------- 1 | """ 2 | All calculations in SI units 3 | """ 4 | import random 5 | from mpl_toolkits.mplot3d import axes3d 6 | import matplotlib.pyplot as plt 7 | from matplotlib import cm 8 | import numpy as np 9 | import math 10 | 11 | h = 10e-2 # Distance between plates = 10cm 12 | lattice_points = 30 # Number of Points in lattice 13 | d = h / lattice_points # Lattice size 14 | boundary_voltage_high = 5.0 # 5 Volts at Positive Plate 15 | boundary_voltage_low = 0.0 # 0 Volts at Negative Plate 16 | epsilon_naught = 8.854e-12 # Permittivity of Vaccum 17 | charge_density = 6e-16 # Coulomb per meter cube 18 | N = 400 # Number of Random Walks 19 | 20 | 21 | def f(x): 22 | # Alternative charge distribution: A charged Sphere in the centre of metal box 23 | if (h / 2 - x[0]) ** 2 + (h / 2 - x[1]) ** 2 <= (h / 5) ** 2: 24 | return -charge_density * 5 / epsilon_naught 25 | else: 26 | return 0 27 | 28 | 29 | def g(x): 30 | # Two Dimentional Alternative Boundary Conditions: uncharged metal box 31 | return 0 32 | 33 | 34 | @np.vectorize 35 | def poisson_approximation_semi_floating(*A): 36 | # Returns the Value of Potential Feild at a given point A with N random walks 37 | result = 0 38 | F = 0 39 | for i in range(N): 40 | x = list(A) 41 | while True: 42 | if x[0] <= 0 or x[0] >= h or x[1] <= 0 or x[1] >= h: 43 | break 44 | random_angle = random.random() * 2 * math.pi 45 | random_unit_vector = np.array( 46 | [math.cos(random_angle), math.sin(random_angle)] 47 | ) 48 | x += random_unit_vector * d 49 | F += f(x) * d ** 2 50 | result += g(x) / N 51 | result = result - F 52 | return result 53 | 54 | 55 | @np.vectorize 56 | def poisson_approximation_full_floating(*A): 57 | # Returns the Value of Potential Feild at a given point A with N random walks 58 | result = 0 59 | F = 0 60 | for i in range(N): 61 | x = list(A) 62 | while True: 63 | if x[0] <= 0 or x[0] >= h or x[1] <= 0 or x[1] >= h: 64 | break 65 | random_angle = random.random() * 2 * math.pi 66 | random_unit_vector = np.array( 67 | [math.cos(random_angle), math.sin(random_angle)] 68 | ) 69 | random_step_size = random.random() * d 70 | x += random_unit_vector * random_step_size 71 | F += f(x) * h ** 2 72 | result += g(x) / N 73 | result = result - F 74 | return result 75 | 76 | 77 | def plot(x, y, z): 78 | # Function for plotting the potential 79 | fig = plt.figure() 80 | ax = fig.add_subplot(111, projection="3d") 81 | 82 | ax.plot_surface(x, y, np.array(z), cmap=cm.jet, linewidth=0.1) 83 | plt.xlabel("X (Meters)") 84 | plt.ylabel("Y (Meters)") 85 | ax.set_zlabel("Potential (Volts)") 86 | plt.show() 87 | 88 | 89 | if __name__ == "__main__": 90 | # Experiment H : Semi Floating Random Walk 91 | print( 92 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Semi Floating Random Walk Algorithm" 93 | ) 94 | lattice_x, lattice_y = np.mgrid[ 95 | 0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j 96 | ] 97 | z = poisson_approximation_semi_floating( 98 | lattice_x.ravel(), lattice_y.ravel() 99 | ).reshape(lattice_x.shape) 100 | plot(lattice_x, lattice_y, z) 101 | 102 | # Experiment H : Full Floating Random Walk 103 | print( 104 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Full Floating Random Walk Algorithm" 105 | ) 106 | lattice_x, lattice_y = np.mgrid[ 107 | 0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j 108 | ] 109 | z = poisson_approximation_full_floating( 110 | lattice_x.ravel(), lattice_y.ravel() 111 | ).reshape(lattice_x.shape) 112 | plot(lattice_x, lattice_y, z) 113 | -------------------------------------------------------------------------------- /montecarlo2d.py: -------------------------------------------------------------------------------- 1 | """ 2 | All calculations in SI units 3 | """ 4 | import random 5 | from mpl_toolkits.mplot3d import axes3d 6 | import matplotlib.pyplot as plt 7 | from matplotlib import cm 8 | import numpy as np 9 | 10 | h = 10e-2 # Distance between plates = 10cm 11 | lattice_points = 30 # Number of Points in lattice 12 | d = h / lattice_points # Lattice size 13 | boundary_voltage_high = 5.0 # 5 Volts at Positive Plate 14 | boundary_voltage_low = 0.0 # 0 Volts at Negative Plate 15 | epsilon_naught = 8.854e-12 # Permittivity of Vaccum 16 | charge_density = 6e-16 # Coulomb per meter cube 17 | N = 400 # Number of Random Walks 18 | 19 | 20 | def f(x): 21 | # The Function \nabla^2(phi) = f 22 | # For Laplace f = 0 23 | return 0 24 | 25 | 26 | def g(x): 27 | # Two Dimentional Boundary Conditions: two parallel metal plates at x=0,x=h 28 | # the plate at x=h is at high potential and x=0 is low potential 29 | # Assume that there are metal plates along y=0 and y=h (uncharged) 30 | # this is because I dont know how to simulate open boundry conditions 31 | if x[0] <= 0: 32 | return boundary_voltage_low 33 | if x[0] >= h: 34 | return boundary_voltage_high 35 | if x[1] <= 0 or x[1] >= h: 36 | return boundary_voltage_low 37 | 38 | 39 | def f_2(x): 40 | # Alternative charge distribution: A charged Sphere in the centre of metal box 41 | if (h / 2 - x[0]) ** 2 + (h / 2 - x[1]) ** 2 <= (h / 5) ** 2: 42 | return -charge_density * 5 / epsilon_naught 43 | else: 44 | return 0 45 | 46 | 47 | def g_2(x): 48 | # Two Dimentional Alternative Boundary Conditions: uncharged metal box 49 | return 0 50 | 51 | 52 | def f_3(x): 53 | # Alternative charge distribution: TWO charged Sphere in the centre of metal box 54 | if (h / 3 - x[0]) ** 2 + (h / 2 - x[1]) ** 2 <= (h / 5) ** 2: 55 | return -charge_density * 5 / epsilon_naught 56 | if (2 * h / 3 - x[0]) ** 2 + (h / 2 - x[1]) ** 2 <= (h / 5) ** 2: 57 | return charge_density * 5 / epsilon_naught 58 | else: 59 | return 0 60 | 61 | 62 | @np.vectorize 63 | def poisson_approximation_fixed_step(*A): 64 | # Returns the Value of Potential Feild at a given point A with N random walks 65 | result = 0 66 | F = 0 67 | for i in range(N): 68 | x = list(A) 69 | while True: 70 | if x[0] <= 0 or x[0] >= h or x[1] <= 0 or x[1] >= h: 71 | break 72 | random_number = random.randint(0, 3) 73 | if random_number == 0: 74 | x[0] += d 75 | elif random_number == 1: 76 | x[0] -= d 77 | elif random_number == 2: 78 | x[1] += d 79 | elif random_number == 3: 80 | x[1] -= d 81 | F += f(x) * h ** 2 82 | result += g(x) / N 83 | result = result - F 84 | return result 85 | 86 | 87 | def plot(x, y, z): 88 | # Function for plotting the potential 89 | fig = plt.figure() 90 | ax = fig.add_subplot(111, projection="3d") 91 | 92 | ax.plot_surface(x, y, np.array(z), cmap=cm.jet, linewidth=0.1) 93 | plt.xlabel("X (Meters)") 94 | plt.ylabel("Y (Meters)") 95 | ax.set_zlabel("Potential (Volts)") 96 | plt.show() 97 | 98 | 99 | if __name__ == "__main__": 100 | # Experiment E: 2D Capacitor 101 | print( 102 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks" 103 | ) 104 | lattice_x, lattice_y = np.mgrid[ 105 | 0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j 106 | ] 107 | z = poisson_approximation_fixed_step(lattice_x.ravel(), lattice_y.ravel()).reshape( 108 | lattice_x.shape 109 | ) 110 | plot(lattice_x, lattice_y, z) 111 | 112 | # Experiment F: Metal box with positively charged metal ball inside 113 | f = f2 114 | g = g2 115 | print( 116 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for {'Laplace' if laplace else 'Poisson'}" 117 | ) 118 | lattice_x, lattice_y = np.mgrid[ 119 | 0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j 120 | ] 121 | z = poisson_approximation_fixed_step(lattice_x.ravel(), lattice_y.ravel()).reshape( 122 | lattice_x.shape 123 | ) 124 | plot(lattice_x, lattice_y, z) 125 | 126 | # Experiment G: Metal Box with two spheres (positive and negative) 127 | 128 | f = f_3 129 | g = g_2 130 | print( 131 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for {'Laplace' if laplace else 'Poisson'}" 132 | ) 133 | lattice_x, lattice_y = np.mgrid[ 134 | 0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j 135 | ] 136 | z = poisson_approximation_fixed_step(lattice_x.ravel(), lattice_y.ravel()).reshape( 137 | lattice_x.shape 138 | ) 139 | plot(lattice_x, lattice_y, z) 140 | -------------------------------------------------------------------------------- /montecarlo.py: -------------------------------------------------------------------------------- 1 | """ 2 | All calculations in SI units 3 | """ 4 | import random 5 | import matplotlib.pyplot as plt 6 | import gif 7 | import numpy as np 8 | 9 | h = 10e-2 # Distance between plates = 10cm 10 | lattice_points = 15 # Number of Points in lattice 11 | d = h / lattice_points # Lattice size 12 | laplace = False # False-> Poisson, True-> Laplace 13 | boundary_voltage_high = 5.0 # 5 Volts at Positive Plate 14 | boundary_voltage_low = 0.0 # 0 Volts at Negative Plate 15 | epsilon_naught = 8.854e-12 # Permittivity of Vaccum 16 | charge_density = 1e-14 # Coulomb per meter cube 17 | N = 400 # Number of Random Walks 18 | 19 | 20 | def f(x): 21 | # The Function \nabla^2(phi) = f 22 | if laplace: 23 | # For Laplace f = 0 24 | return 0 25 | else: 26 | # For Poisson, assume that there is a constant charge density 27 | # between the plates 28 | # So f= - rho/epsilon 29 | return (x / h - 0.5) * -charge_density / epsilon_naught 30 | 31 | 32 | def g(x): 33 | # One Dimentional Boundary Conditions: 34 | if x <= 0: 35 | return boundary_voltage_low 36 | return boundary_voltage_high 37 | 38 | 39 | def poisson_approximation_fixed_step(A): 40 | # Returns the Value of Potential Feild at a given point A with N random walks 41 | result = 0 42 | F = 0 43 | for i in range(N): 44 | x = A 45 | while True: 46 | if x <= 0 or x >= h: 47 | break 48 | if random.randint(0, 1): 49 | x += d 50 | else: 51 | x -= d 52 | F += f(x) * d ** 2 53 | result += g(x) / N 54 | result = result - F 55 | return result 56 | 57 | 58 | # Function for plotting the potential 59 | 60 | 61 | def plot(x, y, y2=None): 62 | plt.figure(figsize=(7, 5), dpi=100) 63 | plt.plot(x, y, "r.-") 64 | if y2 is not None: 65 | plt.plot(x, y2, "b-") 66 | plt.text(h, 0, f"N = {N}", ha="right") 67 | plt.text(h, 0.4, f"L = {lattice_points}", ha="right") 68 | plt.ylim(-2, 7) 69 | plt.xlabel("Distance from negative plate (Meters)") 70 | plt.ylabel("Potential (Volts)") 71 | 72 | 73 | plotgif = gif.frame(plot) 74 | 75 | if __name__ == "__main__": 76 | # Experiment D: One Dimensional Capacitor with constant charge distribution (Poisson Equation) 77 | laplace = False 78 | print( 79 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Poisson Equation" 80 | ) 81 | lattice = np.linspace(0, h, num=lattice_points, endpoint=True) 82 | plot(lattice, [poisson_approximation_fixed_step(A) for A in lattice]) 83 | plt.show() 84 | 85 | # Experiment A: One Dimensional Capacitor (Laplace Equation) 86 | N = 400 87 | lattice_points = 15 88 | print( 89 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Laplace Equation" 90 | ) 91 | lattice = np.linspace(0, h, num=lattice_points, endpoint=True) 92 | feild_real = (boundary_voltage_high - boundary_voltage_low) / h * lattice 93 | plot(lattice, [poisson_approximation_fixed_step(A) for A in lattice], feild_real) 94 | plt.show() 95 | 96 | # Experiment B: Variation of solution with number of random walks (Laplace Equation) 97 | frames = [] 98 | lattice_points = 15 99 | lattice = np.linspace(0, h, num=lattice_points, endpoint=True) 100 | feild_real = (boundary_voltage_high - boundary_voltage_low) / h * lattice 101 | feild_diff = [] 102 | for N in range(10, 1000, 20): 103 | print( 104 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Laplace Equation" 105 | ) 106 | feild_approx = np.array([poisson_approximation_fixed_step(A) for A in lattice]) 107 | frame = plotgif(lattice, feild_approx, feild_real) 108 | feild_diff.append(abs(feild_real - feild_approx).sum()) 109 | frames.append(frame) 110 | gif.save( 111 | frames, f"Figures/{'Laplace' if laplace else 'Poisson'}_N.gif", duration=100 112 | ) 113 | plt.plot(range(10, 1000, 20), feild_diff, "g.-") 114 | plt.xlabel("Number of Random Walks") 115 | plt.ylabel("Abs Error") 116 | plt.show() 117 | 118 | # Experiment C: Variation of solution with number of lattice points (Laplace Equation) 119 | frames = [] 120 | feild_diff = [] 121 | N = 400 122 | for lattice_points in range(2, 30): 123 | print( 124 | f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Laplace Equation" 125 | ) 126 | d = h / lattice_points 127 | lattice = np.linspace(0, h, num=lattice_points, endpoint=True) 128 | feild_real = (boundary_voltage_high - boundary_voltage_low) / h * lattice 129 | feild_approx = np.array([poisson_approximation_fixed_step(A) for A in lattice]) 130 | frame = plotgif(lattice, feild_approx, feild_real) 131 | feild_diff.append(abs(feild_real - feild_approx).sum()) 132 | frames.append(frame) 133 | gif.save( 134 | frames, 135 | f"Figures/{'Laplace' if laplace else 'Poisson'}_Lattice.gif", 136 | duration=100, 137 | ) 138 | plt.plot(range(2, 30), feild_diff) 139 | plt.xlabel("Number of Lattice Points") 140 | plt.ylabel("Abs Error") 141 | plt.show() 142 | --------------------------------------------------------------------------------