[re] 매틀랩 예제입니다.
- 글쓴이
- 사색자
- 등록일
- 2002-11-08 09:35
- 조회
- 8,070회
- 추천
- 1건
- 댓글
- 5건
관련링크
=======================================================
function []=Derivatives(input_num)
% made by Dong-Youn Shin, UMIST
% 2002-11-08
% You can use this function free but you must keep the above lines
close all
clc
figure;
switch input_num
case 1
disp('Bessel');
% ================== Bessel ==================
x=linspace(0,20,50);y_temp=besselj(0,x);
xx=linspace(min(x),max(x),max(size(x))*2-1);
h=xx(2)-xx(1);
% Would you like to put some noise on your data?
% Then input a small number instead of 0.0 below
y=y_temp+0.0*(rand(size(x))-.5);
for loop=1:1:max(size(xx))
a_dydx(loop)=-besselj(1,xx(loop));
a_d2ydx2(loop)=-besselj(0,xx(loop))+besselj(1,xx(loop))/xx(loop);
a_d3ydx3(loop)=besselj(1,xx(loop))-2*besselj(1,xx(loop))/xx(loop)^2+besselj(0,xx(loop))/xx(loop);
end
case 2
disp('Sinusoidal');
% ================== sinusoidal==================
x=linspace(0,2*pi,50);y_temp=sin(x);
xx=linspace(min(x),max(x),max(size(x))*2-1);
h=xx(2)-xx(1);
% Would you like to put some noise on your data?
% Then input a small number instead of 0.0 below
y=y_temp+0.0*(rand(size(x))-.5);
for loop=1:1:max(size(xx))
a_dydx(loop)=cos(xx(loop));
a_d2ydx2(loop)=-sin(xx(loop));
a_d3ydx3(loop)=-cos(xx(loop));
end
case 3
disp('Parabolic');
% ================== Parabolic ==================
r=10;
Multiplier=1;
x=linspace(0,r*0.99,100);
xx=linspace(min(x),max(x),max(size(x))*2-1);
h=xx(2)-xx(1);
for loop=1:1:max(size(x));
y(loop)=sqrt(r-x(loop));
end
for loop=1:1:max(size(xx));
a_dydx(loop)=-1/(2*sqrt(r-xx(loop)));
a_d2ydx2(loop)=1/(4*(xx(loop)-r)*sqrt(r-xx(loop)));
a_d3ydx3(loop)=-3/(8*(xx(loop)-r)^2*sqrt(r-xx(loop)));
end
case 4
% ================== Circle ==================
r=10;
Multiplier=1;
x=linspace(0,2*r*0.99,100);
xx=linspace(min(x),max(x),max(size(x))*2-1);
h=xx(2)-xx(1);
for loop=1:1:max(size(x));
if x(loop)<r
y(loop)=r;
else
y(loop)=sqrt(r^2-(x(loop)-r)^2);
end
end
for loop=1:1:max(size(xx));
if xx(loop)<r
a_dydx(loop)=0;
a_d2ydx2(loop)=0;
a_d3ydx3(loop)=0;
else
m_x=xx(loop)-r;
a_dydx(loop)=-m_x/sqrt(r^2-m_x^2);
a_d2ydx2(loop)=r^2/((m_x^2-r^2)*sqrt(r^2-m_x^2));
a_d3ydx3(loop)=-3*m_x*r^2/((m_x^2-r^2)^2*sqrt(r^2-m_x^2));
end
end
otherwise
disp('You must choose 1 to 4');
close all;
return;
end
start=cputime;
y1=interp1(x,y,xx,'pchip');
subplot(2,2,1);
hold on;
plot(xx,y1,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(x,y,'ob','MarkerSize',2,'MarkerFaceColor','b');
legend('pchip - Noisy',0);
hold off;
finish=cputime-start;
disp('interp1 takes'),disp(finish)
start=cputime;
y1=spline(x,y,xx);
subplot(2,2,2);
hold on;
plot(xx,y1,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(x,y,'ob','MarkerSize',2,'MarkerFaceColor','b');
legend('spline - Noisy',0);
hold off;
finish=cputime-start;
disp('spline takes'),disp(finish)
start=cputime;
[y1,y2]=f_CurveSmoothing(x,y,xx,60,0);
subplot(2,2,3);
hold on;
plot(xx,y2,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(x,y,'ob','MarkerSize',2,'MarkerFaceColor','b');
legend('CurveSmoothing - Noisy',0);
hold off;
finish=cputime-start;
disp('CurveSmoothing takes'),disp(finish)
start=cputime;
[y1,p] = csaps(x,y,0.99,xx);
subplot(2,2,4);
hold on;
plot(xx,y1,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(x,y,'ob','MarkerSize',2,'MarkerFaceColor','b');
legend('csaps - Noisy',0);
hold off;
finish=cputime-start;
disp('csaps takes'),disp(finish)
% Polynomial fitting numerical derivatives
% If there is a noise, then activate the lines below deactivated by '%'
n_dydx=f_deriv_new(xx,y1,1);
% [n_dydx,p]=csaps(xx,n_dydx,0.99,xx);
n_d2ydx2=f_deriv_new(xx,n_dydx,1);
% [n_d2ydx2,p]=csaps(xx,n_d2ydx2,0.99,xx);
n_d3ydx3=f_deriv_new(xx,n_d2ydx2,1);
% [n_d3ydx3,p]=csaps(xx,n_d3ydx3,0.99,xx);
% 5 point numerical derivatives
% If there is a noise, then activate the lines below deactivated by '%'
o_dydx=f_deriv_old(y1,h);
% [o_dydx,p]=csaps(xx,o_dydx,0.99,xx);
o_d2ydx2=f_deriv_old(o_dydx,h);
% [o_d2ydx2,p]=csaps(xx,o_d2ydx2,0.99,xx);
o_d3ydx3=f_deriv_old(o_d2ydx2,h);
% [o_d3ydx3,p]=csaps(xx,o_d3ydx3,0.99,xx);
figure;
subplot(3,1,1);
hold on;
plot(xx,n_dydx,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(xx,o_dydx,'-ob','MarkerSize',2,'MarkerFaceColor','b');
plot(xx,a_dydx,'-ok','MarkerSize',2,'MarkerFaceColor','k');
legend('Polynomial fitted','5 point','Analytic',0);
title('1st derivative');
hold off;
subplot(3,1,2);
hold on;
plot(xx,n_d2ydx2,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(xx,o_d2ydx2,'-ob','MarkerSize',2,'MarkerFaceColor','b');
plot(xx,a_d2ydx2,'-ok','MarkerSize',2,'MarkerFaceColor','k');
legend('Polynomial fitted','5 point','Analytic',0);
title('2nd derivative');
hold off;
subplot(3,1,3);
hold on;
plot(xx,n_d3ydx3,'-or','MarkerSize',2,'MarkerFaceColor','r');
plot(xx,o_d3ydx3,'-ob','MarkerSize',2,'MarkerFaceColor','b');
plot(xx,a_d3ydx3,'-ok','MarkerSize',2,'MarkerFaceColor','k');
legend('Polynomial fitted','5 point','Analytic',0);
title('3rd derivative');
hold off;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Numerical derivative using polynomial curve fitting
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function dydx=f_deriv_new(x,y,m_Multiplier)
% Numerical derivative using polynomial curve fitting
% made by Dong-Youn Shin, UMIST
% 2002-11-08
% You can use this function free but you must keep the above
% lines
x=x*m_Multiplier;
y=y*m_Multiplier;
% 5 point polynomial curve fitting
N=5;
Break=1;
array_size=max(size(y));
dydx=zeros(1,array_size);
for loop=3:3:array_size
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
k=polyder(p);
dydx_temp=polyval(k,x(loop-2:loop+2));
if loop==3
dydx(loop-2:loop+1)=dydx_temp(loop-2:loop+1);
elseif loop+2==array_size
dydx(loop-1:loop+1)=dydx_temp(2:4);
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
k=polyder(p);
dydx_temp=polyval(k,x(loop-2:loop+2));
dydx(loop+2)=dydx_temp(5);
break;
elseif loop+4==array_size
dydx(loop-1:loop+1)=dydx_temp(2:4);
loop=loop+2;
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
k=polyder(p);
dydx_temp=polyval(k,x(loop-2:loop+2));
dydx(loop:loop+2)=dydx_temp(3:5);
break;
elseif loop+3==array_size
dydx(loop-1:loop+1)=dydx_temp(2:4);
loop=loop+1;
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
k=polyder(p);
dydx_temp=polyval(k,x(loop-2:loop+2));
dydx(loop+1:loop+2)=dydx_temp(4:5);
break;
else
dydx(loop-1:loop+1)=dydx_temp(2:4);
end
end
y=y/m_Multiplier;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Numerical derivative using 5 points
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function V = f_deriv_old(U,h)
% get derivatives
% U = y values
% h = uniform step size
% DERIV Column-wise derivative estimation.
% Computes 5-point discrete derivative estimates for each column
% of the input matrix U.
% V = DERIV(U) Returns a matrix V of the same size as U each
% element containing the estimates of the column-wise derivative of
% a function sampled at unit intervals in U.
%
% DERIV Uses 5 points both in the interior and at the edges.
% If size of the matrix U is less than 5 use simpler 3-point
% or 2-point estimate.
%
% If you want to go really fancy, you may even use a 7-point formulae:
% [-1/60 3/20 -3/4 0 3/4 -3/20 1/60] - in the interior,
% [-49/20 6 -7.5 20/3 -15/4 6/5 1/6] - for edge point
%
% See also DIFF, GRADIENT, DEL2
% Kirill K. Pankratov, kirill@plume.mit.edu
% March 22, 1994
% 5-point coefficients for derivatives ..................................
% Edges (1st, 2nd pts):
Cde = [-25/12 4 -3 4/3 -1/4; -1/4 -5/6 3/2 -1/2 1/12];
% Interior
Cd = [1/12 -2/3 0 2/3 -1/12];
% Determine the size of the input and make column if vector .............
ist = 0;
ly = size(U,1);
if ly==1, ist = 1; U = U(:); ly = length(U); end
% If only 2 points - simple difference ..................................
if ly==2
V(1,:) = U(2,:)-U(1,:);
V(2,:) = V(1,:);
if ist, V = V'; end % Transpose output if necessary
return
end
% Now if more than 2 points - more complicated procedure ...............
if ly<5 % If less than 5 points
V(2:ly-1,:) = (U(3:ly,:)-U(1:ly-2,:))/2; % First
V(1,:) = 2*U(2,:)-1.5*U(1,:)-.5*U(3,:); % Last
V(ly,:) = 1.5*U(ly,:)-2*U(ly-1,:)+.5*U(ly-2,:); % Interior
else % If 5 points or more - regular, more accurate estimation
% Edges ............
V(1:2,:) = Cde*U(1:5,:);
V([ly ly-1],:) = -fliplr(Cde)*U(ly-4:ly,:);
% Interior .........
V(3:ly-2,:) = Cd(1)*U(1:ly-4,:)+Cd(2)*U(2:ly-3,:)+Cd(3)*U(3:ly-2,:);
V(3:ly-2,:) = V(3:ly-2,:)+Cd(4)*U(4:ly-1,:)+Cd(5)*U(5:ly,:);
end
V=V/h;
if ist, V = V'; end % Transpose output if necessary
% Curve smoothing function
function [y,yy] = f_CurveSmoothing(x,y,xx,m_Error,m_drawoption)
% Curve smoothing function
% made by Dong-Youn Shin, UMIST
% 2002-11-08
% You can use this function free but you must keep the above lines
Break=1;
while Break==1
yold=y;
for loop=3:3:max(size(x))-2
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
ytemp=polyval(p,x(loop-2:loop+2));
y(loop-1:loop+1)=ytemp(2:4);
for loop1=1:1:max(size(xx))
if x(loop-2)<=xx(loop1)
Min=loop1;
break;
end
end
for loop1=max(size(xx)):-1:1
if x(loop+2)>=xx(loop1)
Max=loop1;
break;
end
end
ytemp=polyval(p,xx(Min:Max));
yy(Min:Max)=ytemp;
if m_drawoption==1
set(gcf,'DoubleBuffer','on');
plot(x,y,'-ob',x(loop-1:loop+1),y(loop-1:loop+1),'-*r');
drawnow;
pause(0.1);
end
end
for loop=max(size(x))-2:-2:3
p=polyfit(x(loop-2:loop+2),y(loop-2:loop+2),2);
ytemp=polyval(p,x(loop-2:loop+2));
y(loop-1:loop+1)=ytemp(2:4);
for loop1=1:1:max(size(xx))
if x(loop-2)<=xx(loop1)
Min=loop1;
break;
end
end
for loop1=max(size(xx)):-1:1
if x(loop+2)>=xx(loop1)
Max=loop1;
break;
end
end
ytemp=polyval(p,xx(Min:Max));
yy(Min:Max)=ytemp;
if m_drawoption==1
set(gcf,'DoubleBuffer','on');
plot(x,y,'-ob',x(loop-1:loop+1),y(loop-1:loop+1),'-*r');
drawnow;
pause(0.1);
end
end
Break=0;
for loop=1:1:max(size(x))
if yold(loop)~=0
Error=abs((y(loop)-yold(loop))/yold(loop)*100);
elseif y(loop)~=0
Error=abs((yold(loop)-y(loop))/y(loop)*100);
else
Error=0;
end
if Error>m_Error*100
Break=1;
end
end
end
다른 사람들 의견
-
푸푸
()
제가 오늘은 바쁜 관계로 내일 저녁이나 일요일(한국시간)에 답변해 드리겠습니다.
-
사색자
()
오늘 수계산으로 확인해보니깐 Kirill의 에지부분 coefficient가 Cde = [-25/12 4 -3 4/3 -1/4; -3/10 -19/30 6/5 -3/10 1/30];로 정정되어야하는거 같은데요...제가 잘못계산한건지 아니면 이 사람이 실수한건지...
-
푸푸
()
제가 MATLAB을 쓸지 몰라서 님께서 넣어주신 코드는 실행해 보지 않았습니다만 간단하게 포트란으로 작성해서 확인만 해 보았습니다. 그런데 대체 무슨 계산을 하시길래 4차정확도의 scheme을 사용하시는지 궁금하군요. 저도 high order는 사용해 보지 않아서.... 그리고 경계 부분에서의 계수는 원저자가 맞는거 같습니다.
-
사색자
()
7 point를 쓸까 싶었는데 그건 너무 오바하는거 같아서 그냥 5 point로 할려다가 이것도 uniformly spaced가 아니면 곤란하기에 지금은 polynomial fitted된 커브로 미분값을 추측하고자 합니다. 실문제에서는 도메인의 한쪽 end point 혹은 양쪽에서 singularity가 발생합니다만 이는 수학적으로 트릭을 써서 극복가능합니다. finite difference method를 통한 free surface flow를 끄적거리고 있습니다. 개인적으로 볼때 볼품없는 코드지만 정확도보다는 생산성을 중시합니다. 물처럼 아주 low viscosity에다가 velocity도 낮으면 계산상 unphysical oscillation이 발생/증폭되기에, 정확한 미분값을 구할려고 노력중입니다.
-
사색자
()
그런데 경계부분 계수를 구할때, f(x-h), f(x), f(x+h), f(x+2h), f(x+3h) 로 놓고 볼때 f(x+h)와 f(x+2h)를 한 페어로, f(x-h)와 f(x+3h)를 한 페어로 놓고 계산한후 이 두 페어를 연립해서 미분값을 근사하는데 계수가 몇번 확인해봐도 원 저자와는 같게 나오지 않네요. Cde에서 첫번째 행의 계수는 맞습니다만 (x, x+h, x+2h, x+3h, x+4h일 경우), 두번째 행 계수는 아직도 제 실수인지 원저자 실수인지 잘 모르겠군요. 사인이나 베셀로 계산해보면 수정계수가 더 정확하게 나올겁니다.