## module trapezoid ''' Inew = trapezoid(f,a,b,Iold,k). Recursive trapezoidal rule: Iold = Integral of f(x) from x = a to b computed by trapezoidal rule with 2^(k-1) panels. Inew = Same integral computed with 2^k panels. ''' def trapezoid(f,a,b,Iold,k): if k == 1:Inew = (f(a) + f(b))*(b - a)/2.0 else: n = 2**(k -2 ) # Number of new points h = (b - a)/n # Spacing of new points x = a + h/2.0 # Coord. of 1st new point sum = 0.0 for i in range(n): sum = sum + f(x) x = x + h Inew = (Iold + h*sum)/2.0 return Inew
## example6_4 # Use the recursive trapezoidal rule to evaluate # int_0_π # sqrt(x) cosx dx to six decimal places and determine # how many panels are needed to achieve this result import math from trapezoid import * def f(x): return math.sqrt(x)*math.cos(x) Iold = 0.0 for k in range(1,21): Inew = trapezoid(f,0.0,math.pi,Iold,k) if (k > 1) and (abs(Inew - Iold)) < 1.0e-6: break Iold = Inew print("Integral =",Inew) print("nPanels =",2**(k-1)) input("\nPress return to exit")
## module romberg ''' I,nPanels = romberg(f,a,b,tol=1.0e-6). Romberg intergration of f(x) from x = a to b. Returns the integral and the number of panels used. ''' import numpy as np from trapezoid import * def romberg(f,a,b,tol=1.0e-6): def richardson(r,k): for j in range(k-1,0,-1): const = 4.0**(k-j) r[j] = (const*r[j+1] - r[j])/(const - 1.0) return r r = np.zeros(21) r[1] = trapezoid(f,a,b,0.0,1) r_old = r[1] for k in range(2,21): r[k] = trapezoid(f,a,b,r[k-1],k) r = richardson(r,k) if abs(r[1]-r_old) < tol*max(abs(r[1]),1.0): return r[1],2**(k-1) r_old = r[1] print("Romberg quadrature did not converge")
Use Romberg integration to evaluate \(\int_{0}^{\sqrt{\pi }}2x^{2}\,\textup{cos}\,x^{2}\:dx \)
## example6_7 # Use Romberg integration to evaluate integ_0_√π 2x^2 cos x^2 dx import math from romberg import * def f(x): return 2.0*(x**2)*math.cos(x**2) I,n = romberg(f,0,math.sqrt(math.pi)) print("Integral =",I) print("numEvals =",n) input("\nPress return to exit")
## module gaussNodes ''' x,A = gaussNodes(m,tol=10e-9) Returns nodal abscissas {x} and weights {A} of Gauss-Legendre m-point quadrature. ''' import math import numpy as np def gaussNodes(m,tol=10e-9): def legendre(t,m): p0 = 1.0; p1 = t for k in range(1,m): p = ((2.0*k + 1.0)*t*p1 - k*p0)/(1.0 + k ) p0 = p1; p1 = p dp = m*(p0 - t*p1)/(1.0 - t**2) return p,dp A = np.zeros(m) x = np.zeros(m) nRoots = int((m + 1)/2) # Number of non-neg. roots for i in range(nRoots): t = math.cos(math.pi*(i + 0.75)/(m + 0.5))# Approx. root for j in range(30): p,dp = legendre(t,m) # Newton-Raphson dt = -p/dp; t = t + dt # method if abs(dt) < tol: x[i] = t; x[m-i-1] = -t A[i] = 2.0/(1.0 - t**2)/(dp**2) # Eq.(6.25) A[m-i-1] = A[i] break return x,A
## module gaussQuad ''' I = gaussQuad(f,a,b,m). Computes the integral of f(x) from x = a to b with Gauss-Legendre quadrature using m nodes. ''' from gaussNodes import * def gaussQuad(f,a,b,m): c1 = (b + a)/2.0 c2 = (b - a)/2.0 x,A = gaussNodes(m) sum = 0.0 for i in range(len(x)): sum = sum + A[i]*f(c1 + c2*x[i]) return c2*sum
Determine how many nodes are required to evaluate \(\int_{a}^{\pi }\left ( \frac{\textup{sin}\,x}{x} \right )^{2}\:dx\) with Gauss-Legendre quadrature to six decimal places. The exact integral, rounded to six places, is 1.41815
import math from gaussQuad import * def f(x): return (math.sin(x)/x)**2 a = 0.0; b = math.pi; Iexact = 1.41815 for m in range(2,12): I = gaussQuad(f,a,b,m) if abs(I - Iexact) < 0.00001: print("Number of nodes =",m) print("Integral =", gaussQuad(f,a,b,m)) break input("\nPress return to exit")
## module gaussQuad2 ''' I = gaussQuad2(f,xc,yc,m). Gauss-Legendre integration of f(x,y) over a quadrilateral using integration order m. {xc},{yc} are the corner coordinates of the quadrilateral. ''' from gaussNodes import * import numpy as np def gaussQuad2(f,x,y,m): def jac(x,y,s,t): J = np.zeros((2,2)) J[0,0] = -(1.0 - t)*x[0] + (1.0 - t)*x[1] \ + (1.0 + t)*x[2] - (1.0 + t)*x[3] J[0,1] = -(1.0 - t)*y[0] + (1.0 - t)*y[1] \ + (1.0 + t)*y[2] - (1.0 + t)*y[3] J[1,0] = -(1.0 - s)*x[0] - (1.0 + s)*x[1] \ + (1.0 + s)*x[2] + (1.0 - s)*x[3] J[1,1] = -(1.0 - s)*y[0] - (1.0 + s)*y[1] \ + (1.0 + s)*y[2] + (1.0 - s)*y[3] return (J[0,0]*J[1,1] - J[0,1]*J[1,0])/16.0 def map(x,y,s,t): N = np.zeros(4) N[0] = (1.0 - s)*(1.0 - t)/4.0 N[1] = (1.0 + s)*(1.0 - t)/4.0 N[2] = (1.0 + s)*(1.0 + t)/4.0 N[3] = (1.0 - s)*(1.0 + t)/4.0 xCoord = np.dot(N,x) yCoord = np.dot(N,y) return xCoord,yCoord s,A = gaussNodes(m) sum = 0.0 for i in range(m): for j in range(m): xCoord,yCoord = map(x,y,s[i],s[j]) sum = sum + A[i]*A[j]*jac(x,y,s[i],s[j]) \ *f(xCoord,yCoord) return sum
Use gaussQuad2 to evaluate \(\iint_{A}^{}f(x,y)\,dx\, dy \) over the quadrilateral shown below where \(f(x)= (x-2)^{2}(y-2)^{2} \). Use enough integration points for an "exact" answer
from gaussQuad2 import * import numpy as np def f(x,y): return ((x - 2.0)**2)*((y - 2.0)**2) x = np.array([0.0, 4.0, 4.0, 1.0]) y = np.array([0.0, 1.0, 4.0, 3.0]) m = eval(input("Integration order ==> ")) print("Integral =", gaussQuad2(f,x,y,m)) input("\nPress return to exit")
## module triangleQuad ''' integral = triangleQuad(f,xc,yc). Integration of f(x,y) over a triangle using the cubic formula. {xc},{yc} are the corner coordinates of the triangle. ''' import numpy as np def triangleQuad(f,xc,yc): alpha = np.array([[1.0/3, 1.0/3.0, 1.0/3.0], \ [0.2, 0.2, 0.6], \ [0.6, 0.2, 0.2], \ [0.2, 0.6, 0.2]]) W = np.array([-27.0/48.0,25.0/48.0,25.0/48.0,25.0/48.0]) x = np.dot(alpha,xc) y = np.dot(alpha,yc) A = (xc[1]*yc[2] - xc[2]*yc[1] \ - xc[0]*yc[2] + xc[2]*yc[0] \ + xc[0]*yc[1] - xc[1]*yc[0])/2.0 sum = 0.0 for i in range(4): sum = sum + W[i] * f(x[i],y[i]) return A*sum
Evaluate \(\iint_{A}^{}f(x,y)\,dx\, dy \) over the equilateral triangle shown below where \(f(x)= \frac{1}{2}(x^{2}+y^{2})-\frac{1}{6}(x^{3}-3xy^{2})-\frac{2}{3} \). Use the quadrature formulas for (1) a quadrilateral and (2) a triangle
## example6_16a from gaussQuad2 import * import numpy as np import math def f(x,y): return (x**2 + y**2)/2.0 \ - (x**3 - 3.0*x*y**2)/6.0 \ - 2.0/3.0 x = np.array([-1.0,-1.0,2.0,2.0]) y = np.array([math.sqrt(3.0),-math.sqrt(3.0),0.0,0.0]) m = eval(input("Integration order ==> ")) print("Integral =", gaussQuad2(f,x,y,m)) input("\nPress return to exit") ## example6_16b import numpy as np import math from triangleQuad import * def f(x,y): return (x**2 + y**2)/2.0 \ -(x**3 - 3.0*x*y**2)/6.0 \ -2.0/3.0 xCorner = np.array([-1.0, -1.0, 2.0]) yCorner = np.array([math.sqrt(3.0), -math.sqrt(3.0), 0.0]) print("Integral =",triangleQuad(f,xCorner,yCorner)) input("Press return to exit")<