You are on page 1of 8

AEP4380, HW 2, Fall 2014 1

Numerical Integration

Numerical integration techniques will be used to evaluate the following integral:

x4 e x
Z y
D(y) = dx (1)
0 (ex − 1)2

Suppose we wish to integrate from x = x0 to x = xN , with spacings of a constant size h.


The notation here is adapted from chapter 4 of Press [2] et. al.

xi = x0 + ih i = 0, 1, ..., N (2)
f (xi ) = fi (3)

Then the trapezoid rule evaluates this integral using the following formula [2, p. 159]:
Z xN
1 1
f (x) dx = h( f0 + f1 + f2 + ... + fN −1 + fN ) (4)
x0 2 2

Simpson’s rule evaluates this integral using the following formula [2, p. 160]:
Z xN
1 4 2 2 4 1
f (x) dx = h( f0 + f1 + f2 + ... + fN −1 + fN −1 + fN ) (5)
x0 3 3 3 3 3 3

The first two programs in the source code evaluate the integral D(y), doubling the number
of intervals at each iteration. The first program uses the trapezoidal rule while the second uses
Simpson’s rule. n is the number of intervals, while D(y) gives the numerical value of the integral.
The output with the trapezoidal rule for y = 1 is as follows:

n D(y)
4 0.326057
8 0.319446
16 0.317794
32 0.317382
64 0.317278
128 0.317253
256 0.317246
512 0.317245
1024 0.317244
2048 0.317244
4096 0.317244
AEP4380, HW 2, Fall 2014 2

The output with the trapezoidal rule for y = 100 is as follows:

n D(y)
4 0.000135624
8 1.13736
16 19.0558
32 25.9319
64 25.9758
128 25.9758
256 25.9758
512 25.9758
1024 25.9758
2048 25.9758
4096 25.9758

The output with Simpson’s rule for y = 1 is as follows:

n D(y)
4 0.31721
8 0.317242
16 0.317244
32 0.317244
64 0.317244
128 0.317244
256 0.317244
512 0.317244
1024 0.317244
2048 0.317244
4096 0.317244

The output with Simpson’s rule for y = 100 is as follows:

n D(y)
4 0.000180833
8 1.51644
16 25.0286
32 28.2239
64 25.9904
128 25.9758
256 25.9758
512 25.9758
1024 25.9758
2048 25.9758
4096 25.9758
AEP4380, HW 2, Fall 2014 3

We can see clearly that Simpson’s rule converges more quickly to the value of the integral in
general, i.e. it does not need as many points. However, it seems to overestimate the integral quite
significantly for y = 100, n = 32 by chance. Also, as y gets larger (y = 100 in the above runs), the
4
integral approaches the asymptotic value of 4π 15 ≈ 25.9758 (to 6 significant figures) as y → ∞

The next program chooses n = 128 and uses Simpson’s rule to generate a plot of the integral
as a function of y from y = 0.01 to y = 10 with about 200 points in between.

Figure 1: Graph of D(y) from y = 0.01 to y = 10.

We can also automate the search for an optimal number of points using the trapezoid rule or
Simpson’s rule by doubling the number of intervals and evaluating the integral at each such iteration
until the difference between the old and new integral is of a specified tolerance (See section 4.2 of
[2]). This procedure is written as a comment in the Source Code Listing.
The Debye heat capacity is given by
3 Z ΘD /T
T x4 e x

Cv = 9N kB dx (6)
ΘD 0 (ex − 1)2

A few extra lines of code allows for the plotting of the Debye heat capacity as a function of
temperature, as shown in the following graph.
AEP4380, HW 2, Fall 2014 4

Figure 2: Graph of Cv from T = 2 to T = 401.

Source Code Listing

/* AEP 4380 HW 2

Numerical integration with the


trapezoid rule and Simpson’s rule
for a real-valued function.
Run on a core i7 with g++ 4.7.2

Austin Liu
ayl42
2014-09-12
*/

#include <cstdlib>
#include <cmath>

#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

int main(){

int i, n= 1;
double xa=0, xb= 100 , iold, inew, sum, dx, x, psum;
double sum1, sum2, sum4;
double feval( double );
AEP4380, HW 2, Fall 2014 5

ofstream fp1;

fp1.open("numtrap.dat");
if (fp1.fail()){
cout << "cannot open file" << endl;
return (EXIT_SUCCESS);
}

fp1 << setw(15) << ’n’ << setw(15) << "D(y)" << endl;
cout << setw(15)<< ’n’ << setw(15) << "D(y)" << endl;

sum= 0.5*(feval(xa) + feval(xb));


inew= (xb-xa)*sum;
n= 2;
/*
short snippet to evaluate to specified tolerance
replaces "while (n<4096)" if used
int tol= 1e-4; //tolerance
int iter= 0; //iterations
while (fabs(inew-iold)> tol && iter<8){
iter++;
*/
while (n<4096){
n= 2*n;
dx= (xb-xa)/n;
iold= inew;
psum= 0;
for (i=1;i<n;i+=2){
psum= psum+ feval(x+i*dx);
}
sum= sum + psum;
inew= sum*dx;
fp1 << setw(15) << n << setw(15) << inew << endl;
cout << setw(15)<< n << setw(15) << inew << endl;
}

fp1.close();

ofstream fp2;

fp2.open("numsimp.dat");
if (fp2.fail()){
cout << "cannot open file" << endl;
return (EXIT_SUCCESS);
}

fp2 << setw(15) << ’n’ << setw(15) << "D(y)" << endl;
cout << setw(15)<< ’n’ << setw(15) << "D(y)" << endl;
n=2;
sum1= 0 + feval(xb);
sum2= 0;
sum4= feval(0.5*(xa+xb));
inew= 0.5*(xb-xa)*(sum1+4*sum4)/3;
while (n<4096){
/*
short snippet to evaluate to specified tolerance,
replaces "while (n<4096)" if used
int tol= 1e-4; //tolerance
AEP4380, HW 2, Fall 2014 6

int iter= 0; //iterations


while (fabs(inew-iold)> tol && iter<8){
iter++;
*/
n= 2*n;
dx= (xb-xa)/n;
sum2= sum2+sum4;
iold= inew;
sum4= 0;
for (i=1;i<n;i+=2){
sum4= sum4 + feval(x+i*dx);
}
inew= (sum1+2*sum2+4*sum4)*dx/3;

fp2 << setw(15) << n << setw(15) << inew << endl;
cout << setw(15)<< n << setw(15) << inew << endl;
}

fp2.close();
return(EXIT_SUCCESS);
}

// evaluates the value of the integrand


double feval (double x){
double ex= exp(x);
if (x<1e-10) return 0;
else return (pow(x,4.0))*(ex)/(pow((ex-1),2));
}

/* AEP 4380 HW 2

Numerical integration to determine


the integral as a function.
Run on a core i7 with g++ 4.7.2

Austin Liu
ayl42
2014-09-12
*/

#include <cstdlib>
#include <cmath>

#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

int main(){
int i;
double intl, y, ymin= 0.01, ymax= 10, n= 200;
double dy= (ymax-ymin)/(200-1);
double integrate (double, double);
ofstream fp;

fp.open( "numint.dat" );
if( fp.fail() ) {
AEP4380, HW 2, Fall 2014 7

cout << "cannot open file" << endl;


return( 0 );
}

for(i=0; i<200; i++){


y= ymin+i*dy;
intl= integrate(0,y);
cout << setw(15) << y << setw(15) << intl << endl;
fp << setw(15) << y << setw(15) << intl << endl;
}
}// end main

/*
Replaces main() above to compute the
Debye heat capacity as a function of temperature
*/
// int main(){
// int i;
// double heatcap, intl, T, Tmin= 2, Tmax= 401, n= 400;
// double dT= (Tmax-Tmin)/(n-1);
// double integrate (double, double);
// ofstream fp;

// fp.open( "numheatcap.dat" );
// if( fp.fail() ) {
// cout << "cannot open file" << endl;
// return( 0 );
// }

// for(i=0; i<n; i++){


// T= Tmin+i*dT;
// intl= integrate(0, (315/T));
// // use N*k_B = n*R with n= 1 for 1 mole of Cu
// heatcap= 9*8.3145*(pow((T/315),3.0))*intl;
// cout << setw(15) << T << setw(15) << heatcap << endl;
// fp << setw(15) << T << setw(15) << heatcap << endl;
// }
// }

/* Integrates feval from a to b and returns


* the value of the integral.
*/
double integrate(double a, double b){

int i, n= 2;
double xa=a, xb= b , iold, inew, sum1,
sum2, sum4, dx, x;
double feval( double );

sum1= 0 + feval(xb);
sum2= 0;
sum4= feval(0.5*(xa+xb));
inew= 0.5*(xb-xa)*(sum1+4*sum4)/3;
while (n<128){
n= 2*n;
dx= (xb-xa)/n;
sum2= sum2+sum4;
AEP4380, HW 2, Fall 2014 8

iold= inew;
sum4= 0;
for (i=1;i<n;i+=2){
sum4= sum4 + feval(x+i*dx);
}
inew= (sum1+2*sum2+4*sum4)*dx/3;
}
return inew;

// evaluates the value of the integrand


double feval (double x){
double ex= exp(x);
if (x<1e-10) return 0;
else return (pow(x,4.0))*(ex)/(pow((ex-1),2));
}

References

[1] Leslie Lamport, LATEX: A document preparation system. Addison Wesley, Massachusetts, 2nd
edition, 1994.

[2] W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery, Numerical Recipes, The Art
of Scientific Computing. Camb. Univ. Press, 3rd edition, 2007.

You might also like