From b5ff3688db0d656b49cb0c74fd41cc3714c38cc8 Mon Sep 17 00:00:00 2001 From: Martin Delcourt <martin.delcourt@uclouvain.be> Date: Fri, 22 Nov 2019 09:19:12 +0100 Subject: [PATCH] Updating Chapter 9 --- Chapter_9/capacitor.py | 8 +++--- Chapter_9/ex1.py | 33 +++++++++++++++++++++++ Chapter_9/integrator.py | 59 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 Chapter_9/ex1.py diff --git a/Chapter_9/capacitor.py b/Chapter_9/capacitor.py index 8372cec..04c8ec3 100644 --- a/Chapter_9/capacitor.py +++ b/Chapter_9/capacitor.py @@ -36,11 +36,11 @@ distance = 0.1 potential = V(0,0,distance) theory = distance*8*math.pi -print("In the center : potential = {} - theory = {}; diff = {:.2f}%".format(potential,theory, 200*(potential-theory)/(potential + theory))) +print("In the center : potential = {} - theory = {}; diff = {:.2f}%".format(potential,theory, 100*(potential-theory)/(theory))) -potential = V(10,10,distance) -print("In the corner : potential = {} - theory = {}; diff = {:.2f}%".format(potential,theory, 200*(potential-theory)/(potential + theory))) - +potential = V(9.5,9.5,distance) +print("In the corner : potential = {} - theory = {}; diff = {:.2f}%".format(potential,theory, 100*(potential-theory)/(theory))) +print("The two values are different because the assumption that we have a finite uniformly charged conductor is not physical.") diff --git a/Chapter_9/ex1.py b/Chapter_9/ex1.py new file mode 100644 index 0000000..6b9d896 --- /dev/null +++ b/Chapter_9/ex1.py @@ -0,0 +1,33 @@ +import random +import math + + +class my_random_vector: + def __init__(self,N_dim,min_value = -5, max_value = 5): + self.vec = [min_value + (max_value-min_value)*random.random() for i in range(N_dim)] + + def norm_squared(self): + nn = 0 + for x in self.vec: + nn+= x**2 + return nn + +def pdf(vec): + return math.exp(-0.5*vec.norm_squared()) + + +def integrate_normal(n_dim, n_tests, n_sigma = 5): + n_tests = int(n_tests) + integral = 0 + for test in range(n_tests): + integral += pdf(my_random_vector(n_dim,-n_sigma,n_sigma)) + return 1./n_tests * integral * (2*n_sigma)**n_dim + + + +for n_dim in [1,2,5,15]: + mc = integrate_normal(n_dim,1e5,3) + truth = math.sqrt((2*math.pi)**n_dim) + print("N_dim = {}".format(n_dim)) + print("Truth = {}, Monte-Carlo = {}".format(truth,mc)) + print("Difference : {:.2f}%".format(100*(truth-mc)/truth)) diff --git a/Chapter_9/integrator.py b/Chapter_9/integrator.py index e7a568f..4534823 100644 --- a/Chapter_9/integrator.py +++ b/Chapter_9/integrator.py @@ -32,7 +32,7 @@ def TrapezeIntegrator(function, x_min, x_max, precision=1e-9, step_min = 3, step return integral -def RombergIntegrator(function, x_min, x_max, precision=1e-9, step_min = 3, step_max = 20, silent = True): +def RombergIntegrator(function, x_min, x_max, precision=1e-9, step_min = 3, step_max = 25, silent = True): r = [TrapezeStep(function, x_min, x_max, 1, 0)] @@ -45,8 +45,10 @@ def RombergIntegrator(function, x_min, x_max, precision=1e-9, step_min = 3, step if not silent: print("Step {} : precision of {}".format(k, error)) r = new_r - if error < precision and k > step_min: + if error < precision and k >= step_min: break + if k == step_max-1: + print("Warning, integral didn't converge after {} iterations with a precision of {}.".format(k, error)) return r[-1] #self.integrals.append(self.r[-1]) @@ -55,9 +57,54 @@ def RombergIntegrator(function, x_min, x_max, precision=1e-9, step_min = 3, step if __name__ == "__main__": - def my_func(x): - return math.exp(-0.5*x**2) + print("### Trying with a gaussian function. The integral is expected to be {}".format(math.sqrt(2*math.pi))) + print("gaus [-5,5] : {}".format(RombergIntegrator(lambda x: math.exp(-0.5*x**2) , -5, 5 ))) + print("gaus [-100,100] : {}".format(RombergIntegrator(lambda x: math.exp(-0.5*x**2), -100, 100 ))) + print("\n\n### Trying with sin^2(x), should converge towards pi={}".format(math.pi)) + print("Sin^2 with no minimum steps : {}".format(RombergIntegrator(lambda x : math.sin(x)**2, -math.pi, math.pi ,step_min = 0))) + print("This first integral converged towards a wrong value.") + print("It was expected since the first steps of Romberg are :") + print(" * evaluate R11 = (f(b) + f(a)) * (b-a)/2 = 0 since sin²(-pi) = sin²(pi) = 0") + print(" * evaluate R21 = previous_integral/2 + f( (b-a)/2 )/2 = 0/2 + 0/2 = 0") + print(" * compute R22 = 1/(4^2 -1) * (4^2 * R21 - R11) = 0") + print("Since the first and second steps yield the same integral (0), the difference is < 1e-9 and the process stops") + print("This same integral converges correctly if we ask at least 3 steps: ") + print("Sin^2 : {}".format(RombergIntegrator(lambda x : math.sin(x)**2, -math.pi, math.pi))) + + + def test_1(x): + if x == 0: + return 0 + return 1./math.sqrt(abs(x)) + + print("\n\n### 1/sqrt(|x|) should converge towards 2") + print("1/sqrt(|x|) : {}".format(RombergIntegrator(test_1, -1, 1))) + print("We can see that it is indeed starting to converge towards the correct value, but very slowly...") + + + def test_2(x): + if x == 0: + return 0 + return 1./x**2 - 1 + + print("\n\n### 1/x^2 should diverge") + print("1/x^2 - 1 : {}".format(RombergIntegrator(test_2, -1 , 1 ))) + print("And it is indeed the case") + - ii = RombergIntegrator(my_func, -5, 5 , silent = False) - print (ii) + def regular(x): + r = x - int(x) + if r == 0: + return 0 + return r**-2 + + print("\n\n### Finally, with the weird 'regular' function :") + print("regular [-256; 256] : {}".format(RombergIntegrator(regular, -256, 256))) + print("It converges towards 0 if we integrate on the whole range") + print("regular [0,1] : {}".format(RombergIntegrator(regular, 0, 1))) + print("But diverges when computing over [0,1]") + print("This is expected since :") + print("The first ten steps of Romberg will always evaluate on integer numbers yielding the same '0' value, thus returning a null integral") + print("But we know that it diverges if the integral is computed correctly (on the [0,1] interval for example)") + -- GitLab