Lösningsförslag till inlämningsuppgift 5 i Beräkningsprogrammering Problem 1 function prob1 %Integrationsgränserna a = 0; b = 0.8; %Antalet olika n-värden np = 19; %Referensvärdet på integralen Iref = 0.6576698563283957; %En vektor med antalet punkter i integrationsintervallet nvec = 2.^(2:np+1) + 1; %En vektor för att spara resultaten från den sammansatta trapetsregeln I = zeros(np,1); %En vektor att spara exekveringstiderna i timetrap = zeros(np,1); for i = 1:np end %Starta tidtagning tic %Aktuellt n-värde n = nvec(i); %En vektor med x-punkterna xvec = linspace(a,b,n); %Avståndet mellan varje punkt h = (b-a)/(n-1); %En vektor med bredderna på staplarna (vikterna) w = h*[0.5; ones(n-2,1); 0.5]; %Integralens värde enligt den sammansatta trapetsregeln I(i) = g(xvec)*w; %Avsluta tidtagning timetrap(i) = toc; 1
%De relativa felen relerr = abs((i-iref)/iref); %Plotta loglog(nvec,relerr, * ) xlabel( Antalet punkter n ); ylabel( Relativfel ); grid on disp([ Relativfel med trapetsregeln ( num2str(nvec(np))... punkter) : num2str(relerr(np)), beräkningen tog... num2str(timetrap(np)) sekunder. ]) %Integralen beräknad med quad tic Iquad = quad(@g,a,b,1e-11); timequad = toc; disp([ Relativfel med quad : num2str(abs(iref-iquad)/iref)..., beräkningen tog num2str(timequad) sekunder. ]); function gout = g(x) gout = exp(-x.^2); I figuren kan man se att om antalet noder n ökas från 10 1 till 10 6 (ett steg av storlek 5 i exponenterna) så minskar det relativa felet från ungefär 10 3 till 10 13 (ett steg av storlek 10 i exponenterna). Av formeln relerr I c n p fås p ( 13 ( 3))/(6 1) = 2, det vill säga p 2. Felet avtar alltså som c. quad är smidig att använda och är oftast snabbare n 2 än sammansatta trapetsregeln, eftersom den använder en noggrannare metod (Simpsons regel) samt är adaptiv. Den önskade noggrannheten kan hos quad styras med en extra inparameter, se programmet ovan där vi önskar en precision på 10 11. 2
Figur 1: Det relativa felet i uppskattningen av I plottat mot antalet punkter n. Problem 2 function broms %r-värdena är ekvidistanta så vi kan skriva r = linspace(9.38,14.58,11) ; T = [338 423 474 506 557 573 601 622 651 661 671] ; %Antalet punkter n = length(t); %Vikter för sammansatta trapetsregeln h = (r(n)-r(1))/(n-1); wtrap = h*[1/2;ones(n-2,1);1/2]; %Beräkna integralen i nämnaren med sammansatta trapetsregeln namnaretrapets = r *wtrap % Beräkna integralen i täljaren med sammansatta trapetsregeln taljaretrapets = (r.*t) *wtrap %Medeltemperaturen beräknad med den sammansatta trapetsregeln TmedTrapets = taljaretrapets/namnaretrapets %Det analytiska uttrycket för nämnaren och felet i uppskattningen från %sammansatta trapetsregeln namnareanalytisk = r(n)^2/2-r(1)^2/2 namnarefel = abs(namnaretrapets-namnareanalytisk) 3
%Vikter för Simpsons regel m = (n-1)/2; hs = (r(n)-r(1))/m; wsimp = ones(n,1); wsimp(2:2:n-1) = 4; wsimp(3:2:n-2) = 2; wsimp = hs/6*wsimp; % % Kortare men svårläsligt sätt att skapa viktvektorn: % wsimp = hs/6*[1, 2*rem(1:n-2,2)+2, 1] ; % % Man kan också bara skriva upp vikterna: % wsimp = hs/6*[1;4;2;4;2;4;2;4;2;4;1]; %Täljaren beräknad med Simpsons regel taljaresimp = (r.*t) *wsimp; %Medeltemperaturen beräknad med det analytiska uttrycket för nämnaren och %med uppskattningen av täljaren gjord med Simpsons regel TmedSimpAnalytisk = taljaresimp/namnareanalytisk %Skillnaden mellan de beräknade medeltemperaturerna: skillnad = abs(tmedsimpanalytisk-tmedtrapets) Att vi kan använda den sammansatta trapetsregeln beror på att r-värdena är ekvidistanta (avståndet mellan två punkter på r-axeln är konstant i integrationsintervallet), vilket gör att vi kan definiera ett h. Nämnaren blir väldigt noggrann. Detta beror på att förstagradspolynom integreras exakt med trapetsregeln. Medeltemperaturen beräknad analytiskt och med Simpsons regel skiljer sig med ungefär 0.4 C från medeltemperaturen beräknad helt med trapetsregeln. Mätdata är givna med tre värdesiffror. Siffrorna till och med entalssiffran bör alltså tas med: T med 568 C. Problem 3 Överkurs function dblint close all %Skapa en x- och en y-vektor N = 50; xhat = linspace(-2,2,n); yhat = linspace(-2,2,n); %Skapa en matris att spara dubbelintegralens värden i P = zeros(n); for j = 1:N 4
end for i = 1:N P(i,j) = dblquad(@pot,-1,1,-1,1,0.0001,@quad,xhat(j),yhat(i)); %Eller med en anonym funktion: %P(i,j) = dblquad(@(x,y) pot(x,y,xhat(j),yhat(i)),-1,1,-1,1,0.0001,@quad); end %Skapa griden och plotta funktionen [X,Y] = meshgrid(xhat,yhat); [cs,h] = contour(x,y,p); clabel(cs,h, labelspacing,3000); xlabel( xhat ) ylabel( yhat ) function potout = pot(x,y,xhat,yhat) %Integranden potout = 1./sqrt((xhat-x).^2 + (yhat-y).^2); Figur 2: Nivåkurvor för funktionen Φ. 5