CU Mechanical EngineeringFluid Mechanics Matlab tutorials |
Writing Matlab Functions: integration with different parameters
In this example, we will write a function that integrates the equation
using the trapezoidal rule, Simpson’s rule, and adaptive quadrature algorithm based on the trapezoidal rule.
To begin, all functions within matlab must begin by declaring that m-file is a function. This is accomplished by having the first line of the m-file having the word 'function' followed by the name of the variable that will be returned. This is consequently set equal to the name of the name of the file with the quantities that are passed to the function in parenthesis. For the purpose of this exercise, the name of the function will be 'cp4' and the first lines of the function is as follows:
function cp4 global isub syms f t close all figure(1)
After naming the function, we define the global variable 'isub'. Ordinarily, each MATLAB function, defined by an M-file, has its own local variables, which are separate from those of other functions, and from those of the base workspace. However, if several functions, and possibly the base workspace, all declare a particular name as global, they all share a single copy of that variable. Any assignment to that variable, in any function, is available to all the functions declaring it global. The line 'syms f t' is short-hand notation for:
f = sym('f'); t = sym('t'); ...
'close all' deletes all figures whose handles are not hidden. figure(1) does one of two things, depending on whether or not a figure with handle 1 exists. If 1 is the handle to an existing figure, figure(1) makes the figure identified by 1 the current figure, makes it visible, and raises it above all other figures on the screen. The current figure is the target for graphics output. If 1 is not the handle to an existing figure, but is an integer, figure(1) creates a figure and assigns it the handle 1. figure(1) where 1 is not the handle to a figure, and is not an integer, is an error.
The following sets up the initial conditions for both cases:
for cs = 1:2 if cs ==1 alpha = 2; beta = 0.2; I_ex= 0.0095499658265276; f = t^alpha*(6/5-t)*(1-exp(beta*(t-1))); subplot(2,2,1) elseif cs == 2 alpha = 0.2; beta = 2; I_ex= 0.3457273592825; f = t^alpha*(6/5-t)*(1-exp(beta*(t-1))); subplot(2,2,2) end
The next step is block of code it as follows:
xvec=linspace(0,1,101); fvec=subs(f,xvec); plot(xvec,fvec,'r-'); grid on if cs == 1 del=[1.e-1,1.e-2,1.e-3,1.e-4,1.e-5,1.e-6,1.e-7,1.e-8,1.e-9,1.e-10,1.e-11] ; n=[20,40,80,160,320,640,1280]; ttl='Case a'; else del=[1.e-1,1.e-2,1.e-3,1.e-4,1.e-5,1.e-6,1.e-7,1.e-8] ; n=[20,40,80,160,320,640,1280,2560,5120,10240]; ttl='Case b'; end
The linspace function generates linearly spaced vectors. It is similar to the colon operator ":", but gives direct control over the number of points. 'y = linspace(a,b,n)' generates a row vector 'y' of n points linearly spaced between and including a and b. In the next line of code, subs(f,xvec) replaces the default symbolic variable in f with xvec. 'grid on' adds major grid lines to the current axes. The following conditional 'if' statement defines the array of intervals and tolerances.
The next few lines of code create arrays of all zeros.
err_Simpson=zeros(size(n)); n_adapt=zeros(size(del)); err_adapt=zeros(size(del)); title(ttl); disp(ttl);
The command 'B = zeros(size(A))' returns an array the same size as A consisting of all zeros.
Next we have to integrate. For this step, we need two other functions: one using the adaptive quadrature algorithm based on the trapezoidal rule and the other using Simpson’s rule. First we'll create the function integrate_Simpson:
function I=integrate_Simpson(f,a,b,n) xvec=linspace(a,b,n+1); fvec=subs(f,xvec); h = (b-a)/n; I=h/3*(fvec(1)+4*sum(fvec(2:2:n))+2*sum(fvec(3:2:n-1))+fvec(n+1));
To begin, as with all functions within matlab, it must begin by declaring that the m-file is a function. This is accomplished by having the first line of this m-file having the word 'function' followed by the name of the variable that will be returned. This is consequently set equal to the name of the name of the file with the quantities that are passed to the function in parenthesis. Within the parenthesis are the defining parameters, which are: f, which is the symbolically defined function of one variable; a, the lower limit of integration; b, the upper limit of integreation; and n, the number of subintercals. The fourth line of this function, 'h = (b-a)/n', describes the grid spacing. The last line is the integral itself.
Next we create the function adaptive_quadrature:
function I = adaptive_quadrature(f,a,b,delta) global isub I2=integrate_Simpson(f,a,b,2); I4=integrate_Simpson(f,a,b,4); err=abs(I2-I4)/15; isub = isub + 1; if err < delta I=I4; else I=adaptive_quadrature(f,a,(a+b)/2,delta/2)+adaptive_quadrature(f,(a+b)/2,b,delta/2); end
Again, we begin by having the first line of this m-file having the word 'function' followed by the name of the variable that will be returned. This is consequently set equal to the name of the name of the file with the quantities that are passed to the function in parenthesis. Within the parenthesis are the defining parameters, which are: f, which is the symbolically defined function of one variable; a, the lower limit of integration; b, the upper limit of integreation; and delta, which corresponds to the desired tolerance. The second line defines 'isub' as a global variable. In the next line, we use Simpson's integration rule over interval [a,b] using 3 points, and the next line uses Simpson's integration rule over interval [a,b] using 5 points. The next line, 'err=abs(I2-I4)/15' is the error estimate. Line six calculates the number of times the quadrature is called. The conditional 'if' statement tells the function to stop if the error is below the desired tolerance, and otherwise to refine the interval and call the same function again.
Back to the fucntion cp4, we can now put these functions to use:
for i=1:length(n) disp(['Simpson integration with ',num2str(n(i)),' points']); I_Simpson=integrate_Simpson(f,0,1,n(i)); err_Simpson(i)=abs(I_Simpson-I_ex); end for i=1:length(del) isub = 1; disp(['Adaptive quadrature with ',num2str(del(i)),' tolerance']); I_adapt=adaptive_quadrature(f,0,1,del(i)); err_adapt(i)=abs(I_adapt-I_ex); n_adapt(i)=2*isub; end
This block of code evaluates the external functions. The command 'disp(X)' displays an array, without printing the array name. If X contains a text string, the string is displayed.
To finish the function and obtain the desired plots, we input the following:
if cs == 1 subplot(2,2,3) elseif cs == 2 subplot(2,2,4) end loglog(n,err_Simpson,'r-') grid on set(gca,'xlim',[10,1e4],'XMinorGrid','off','YMinorGrid','off') set(gca,'xTick',[10 10^2 10^3 10^4 10^5]) set(gca,'yTick',[1e-16 1e-14 1e-12 1e-10 1e-8 1e-6 1e-4 1e-2 1 10]) hold on plot(n_adapt,err_adapt,'k-') legend('Simpson','Ad. Quadr.') legend boxon end
The command subplot divides the current figure into rectangular panes that are numbered rowwise. Each pane contains an axes object. Subsequent plots are output to the current pane. 'h = subplot(m,n,p)' or 'subplot(mnp)' breaks the figure window into an m-by-n matrix of small axes, selects the path axes object for the current plot, and returns the axes handle. The axes are counted along the top row of the figure window, then the second row, etc. Next, 'loglog(X1,Y1,...)' plots all Xn versus Yn pairs. If only Xn or Yn is a matrix, loglog plots the vector argument versus the rows or columns of the matrix, depending on whether the vector's row or column dimension matches the matrix. We already discussed the 'grid on' command. 'set(H,'PropertyName',PropertyValue,...)' sets the named properties to the specified values on the object(s) identified by H. H can be a vector of handles, in which case set sets the properties' values for all the objects. The 'hold' function determines whether new graphics objects are added to the graph or replace objects in the graph. 'hold on' retains the current plot and certain axes properties so that subsequent graphing commands add to the existing graph. 'legend' places a legend on various types of graphs (line plots, bar graphs, pie charts, etc.). For each line plotted, the legend shows a sample of the line type, marker symbol, and color beside the text label you specify. When plotting filled areas (patch or surface objects), the legend contains a sample of the face color next to the text label.
The m-file can now be saved as 'cp4.m' The following are several sample outputs from the code illustrating the ways to call the function with different types of return arguments.
>> cp4 Case a Simpson integration with 20 points Simpson integration with 40 points Simpson integration with 80 points Simpson integration with 160 points Simpson integration with 320 points Simpson integration with 640 points Simpson integration with 1280 points Adaptive quadrature with 0.1 tolerance Adaptive quadrature with 0.01 tolerance Adaptive quadrature with 0.001 tolerance Adaptive quadrature with 0.0001 tolerance Adaptive quadrature with 1e-005 tolerance Adaptive quadrature with 1e-006 tolerance Adaptive quadrature with 1e-007 tolerance Adaptive quadrature with 1e-008 tolerance Adaptive quadrature with 1e-009 tolerance Adaptive quadrature with 1e-010 tolerance Adaptive quadrature with 1e-011 tolerance Case b Simpson integration with 20 points Simpson integration with 40 points Simpson integration with 80 points Simpson integration with 160 points Simpson integration with 320 points Simpson integration with 640 points Simpson integration with 1280 points Simpson integration with 2560 points Simpson integration with 5120 points Simpson integration with 10240 points Adaptive quadrature with 0.1 tolerance Adaptive quadrature with 0.01 tolerance Adaptive quadrature with 0.001 tolerance Adaptive quadrature with 0.0001 tolerance Adaptive quadrature with 1e-005 tolerance Adaptive quadrature with 1e-006 tolerance Adaptive quadrature with 1e-007 tolerance Adaptive quadrature with 1e-008 tolerance
The entire matlab script can be seen below or downloaded here (right-click to save):
function cp4 global isub syms f t close all figure(1) for cs = 1:2 if cs ==1 alpha = 2; beta = 0.2; I_ex= 0.0095499658265276; f = t^alpha*(6/5-t)*(1-exp(beta*(t-1))); subplot(2,2,1) elseif cs == 2 alpha = 0.2; beta = 2; I_ex= 0.3457273592825; f = t^alpha*(6/5-t)*(1-exp(beta*(t-1))); subplot(2,2,2) end xvec=linspace(0,1,101); fvec=subs(f,xvec); plot(xvec,fvec,'r-'); grid on if cs == 1 del=[1.e-1,1.e-2,1.e-3,1.e-4,1.e-5,1.e-6,1.e-7,1.e-8,1.e-9,1.e-10,1.e-11] ; n=[20,40,80,160,320,640,1280]; ttl='Case a'; else del=[1.e-1,1.e-2,1.e-3,1.e-4,1.e-5,1.e-6,1.e-7,1.e-8] ; n=[20,40,80,160,320,640,1280,2560,5120,10240]; ttl='Case b'; end err_Simpson=zeros(size(n)); n_adapt=zeros(size(del)); err_adapt=zeros(size(del)); title(ttl); disp(ttl); for i=1:length(n) disp(['Simpson integration with ',num2str(n(i)),' points']); I_Simpson=integrate_Simpson(f,0,1,n(i)); err_Simpson(i)=abs(I_Simpson-I_ex); end for i=1:length(del) isub = 1; disp(['Adaptive quadrature with ',num2str(del(i)),' tolerance']); I_adapt=adaptive_quadrature(f,0,1,del(i)); err_adapt(i)=abs(I_adapt-I_ex); n_adapt(i)=2*isub; end if cs == 1 subplot(2,2,3) elseif cs == 2 subplot(2,2,4) end loglog(n,err_Simpson,'r-') grid on set(gca,'xlim',[10,1e4],'XMinorGrid','off','YMinorGrid','off') set(gca,'xTick',[10 10^2 10^3 10^4 10^5]) set(gca,'yTick',[1e-16 1e-14 1e-12 1e-10 1e-8 1e-6 1e-4 1e-2 1 10]) hold on plot(n_adapt,err_adapt,'k-') legend('Simpson','Ad. Quadr.') legend boxon end %--------------------------------------------------------- %integrate_Simpson function I=integrate_Simpson(f,a,b,n) xvec=linspace(a,b,n+1); fvec=subs(f,xvec); h = (b-a)/n; I=h/3*(fvec(1)+4*sum(fvec(2:2:n))+2*sum(fvec(3:2:n-1))+fvec(n+1)); %------------------------------------------------------ %adaptive_quadrature function I = adaptive_quadrature(f,a,b,delta) global isub I2=integrate_Simpson(f,a,b,2); I4=integrate_Simpson(f,a,b,4); err=abs(I2-I4)/15; isub = isub + 1; if err < delta I=I4; else I=adaptive_quadrature(f,a,(a+b)/2,delta/2)+adaptive_quadrature(f,(a+b)/2,b,delta/2); end