Computational Lab in Physics: Numerical Integration x L n 1 f ( x ')dx ' x f ( L k x) k 0 Steven Kornreich www.beachlook.com Integration procedure: We will need to define an operator which will take as input a function limits of integration possibly, desired accuracy give as output the result of integrating the function between the two limits 2 From Calculus: x L lim n 1 f ( x ')dx ' x f ( L k x) x 0 k 0 Rectangular rule: Evaluate the function at the left endpoint of each interval. Multiply by the width of the interval. Equivalent to sum of rectangular areas. 3 Alternate: Midpoint rule x n 1 L k 0 f ( x ')dx ' x f ( L (k 0.5)x) Midpoint rule. Evaluate the function at the middle point of each interval. Multiply by the width of the interval. Equivalent to sum of rectangular areas, but has a better discrete error behavior. 4 A first Implementation: Procedural #include <iostream> #include <cmath> using namespace std; double square(double aX) { return aX*aX; } double integrate(double aLeftLimit, double aRightLimit, int aNumberOfIntervals, double integrand(double)) { } int main() { double loLimit, upLimit; int nIntervals; cout << "Enter lower limit and upper limit" << endl; cin >> loLimit >> upLimit; cout << "Enter number of intervals" << endl; cin >> nIntervals; cout << "Integral = " << integrate(loLimit,upLimit,nIntervals, square) << endl; double dx = (aRightLimit - aLeftLimit)/aNumberOfIntervals; double x = aLeftLimit; // bug in the textbook, fixed here! double sum = 0; return 0; for (int i=0; i<aNumberOfIntervals; ++i) { sum+= integrand(x+0.5*dx); // eval function at right endpoint, } increase sum x+=dx; // increase lower limit } return sum*dx; 5 Implementing code with a desired accuracy. int main() { double loLimit, upLimit, epsilon, result; int nIntervals; cout << "Enter lower limit and upper limit" << endl; cin >> loLimit >> upLimit; cout << "Enter initial number of intervals, and maximum allowed error" << endl; cin >> nIntervals >> epsilon; double oldResult = 1.0e30; // large number, at least iterate once int maximumIterations = 25; for (int j=0; j<maximumIterations; ++j) { result = integrate(loLimit,upLimit,nIntervals,square); // if accuracy is reached, end the loop if (fabs(result-oldResult)<epsilon) break; } //update result and increase number of intervals oldResult = result; nIntervals*=2; cout << "Integral of x^2 from " << loLimit << " to " << upLimit << " = " << result << " +/- " << fabs(result-oldResult) << endl; return 0; 6 Using a class: IntegralCalculator.hh #ifndef IntegralCalculator_hh #define IntegralCalculator_hh class IntegralCalculator { public: IntegralCalculator(double aIntegrandFunction(double)); void setNumberOfIntervals(int aNumberOfIntervals) {mNumberOfIntervals=aNumberOfIntervals;} void setLeftLimit(int val) {mLeftLimit=val;} void setRightLimit(int val) {mRightLimit=val;} void readInputData(); void integrate(); void print(); int int int int numberOfIntervals() {return mNumberOfIntervals;} leftLimit() {return mLeftLimit;} rightLimit() {return mRightLimit;} result() {return mResult;} private: int mNumberOfIntervals; double mLeftLimit; double mRightLimit; double mResult; double (*mIntegrandFunction) (double); }; #endif 7 The source file: IntegralCalculator.cc #include "IntegralCalculator.hh" #include <iostream> #include <cmath> using namespace std; IntegralCalculator::IntegralCalculator(double aIntegrandFunction(double)) { mIntegrandFunction = aIntegrandFunction; } void IntegralCalculator::readInputData() { double loLimit, upLimit; int nIntervals; cout << "Enter lower limit and upper limit" << endl; cin >> loLimit >> upLimit; cout << "Enter number of intervals" << endl; cin >> nIntervals; setLeftLimit(loLimit); setRightLimit(upLimit); setNumberOfIntervals(nIntervals); return; } void IntegralCalculator::integrate() { double dx = (mRightLimit mLeftLimit)/mNumberOfIntervals; double x = mLeftLimit; double sum = 0; for (int i=0; i<mNumberOfIntervals; ++i) { sum+= mIntegrandFunction(x+dx); x+=dx; // increase lower limit } mResult = sum*dx; } void IntegralCalculator::print() { cout << "Integral of your function from " << mLeftLimit << " to " << mRightLimit << " = " << mResult << endl; } 8 The new main() using the class. #include "IntegralCalculator.hh" double square(double aX) { } return aX*aX; int main() { IntegralCalculator IC1(square); IC1.readInputData(); IC1.integrate(); IC1.print(); } return 0; 9 Compiling and linking with a class Compiling the class to create a machine readable object file: g++ IntegralCalculator.cc –c Compiling the file containing the main function and linking with the previously created object file: g++ integWithClass.cc –o integWithClass IntegralCalculator.o 10 Monte Carlo methods Statistical Sampling Name “Monte Carlo” was coined in the 1940’s, random numbers → gambling (Stanislaw Ulam’s uncle), probability distributions. Very useful in evaluation of probability distribution functions. Applications in high energy physics: Simulation of high energy collision events. Simulation of detector response. Main idea: analysis of a complicated physical system. evolution of the physical system is governed by a process which is stochastic (probabilistic, non-deterministic) 11 Monte Carlo Integration Commonly applied to multidimensional integration with complicated integrals and boundaries. Example: Overlap volume between two nuclei of radii R1 and R2, separated by a distance b. Model them as spheres: analytic. Realistic model: needs Monte-Carlo. 12 Realistic models: Nuclear density profiles Hard sphere 13 Monte Carlo integration: simple example Integrating a 1-D function between two limits supplied by the user. Algorithm: generate random points (x,y) within a rectangular reference region. Area of rectangle is known: A=bh For each point, check to see if it falls below or above the 1-D function. Make nt total random points, find nb points with 0 < y < f(x) Estimate integral of function via: nb f ( x )dx A nt 14 Monte Carlo integration: Graphically. Throw nt=1000 random points in the 2-D (x,y) space. e.g. sphere of unit radius: Check if the point falls inside our limits -1 < x < 1, b=2 -1 < y < 1, h=2 e.g. if (x2+y2<1) found ni=794 Integral: bh*(ni/nt)=3.176 Statistical uncertainty on ni/nt: 1/ni=0.03. Result = 3.18 ± 0.12 15 Monte Carlo integration of f(x)=x2 Replace integrate function by: void IntegralCalculator::integrate() { double sum = 0; TRandom3 rnd(seed); for (int i=0; i<mNumberOfRealizations; ++i) { double x = rnd.Uniform(mLeftLimit,mRightLimit); double y = rnd.Uniform(mLeftLimit,mRightLimit); if (y<mIntegrandFunction(x)) { sum+=1; } } mResult = sum/mNumberOfRealizations*(mRightLimitmLeftLimit)*(mHiLimitY-mLoLimitY)+mLoLimitY+(mRightLimitmLeftLimit); } Using root random number generator TRandom3. TRandom3 rnd(seed); rnd.Rndm() ; //uniform distribution 0-1 rnd.Uniform(x1,x2); //uniform btw x1-x2 16 For Homework: Numerical Integration Chapter 13, Section 13.4 Assigment (1) Complete the coding of the IntegratorCalculator class using the midpoint rule. Verify the convergence should be quadratic in the step length. In particular, plot graphs of the error against the inverse of the number of points, n, for the integral of x3 from 0 to 1 for both the midpoint rule and the rectangle rule. Assignment (2) Replace the midpoint rule by the Simpson rule, and determine graphically the order of error of this procedure. R L x n 1 xi xi 1 f ( x)dx f ( xi ) 4 f f ( xi 1 ) 6 i 0 2 Chapter 22, Section 22.6 Assignment (1) Use the monte carlo integration program to find the area of a unit circle. You may use symmetry to restrict your calculation to positive x- and y-values. Graph your results for the logarithm of the error as a function of the logarithm of the number of evaluation points. Use 2000, 4000, 8000, … , 210×1000. 17