Plotting a closed interal function MATLAB - matlab

I need a help. I have to generate a curve using MATLAB. The plot is defined by the formula (an analytic expression) :-
where, the meaning of the variables are as follows: R is the distributed resistive function, S is the distributive conductive function, k is the sheet resistance and r(x,y) is the distance between *
(x,y)*, and the perimeter dl with the integration made around all the perimeter of the chip.
A squared foil as shown in the figure with sides (a) 10 arbitrary units long and an unitary unit sheet resistance (k=1 ohm) is used for our consideration. The plot of the function R(x,y) is supposed to come out like this...
I literally have no clue how to plot this function. I could not even get the idea how to define the distance function r(x,y) with respect to dl. On top of that it is complicated further by the closed integral. Please help me. Any help in even simplifying the expression is also welcome. Is there any possible closed form expression for such a square structure ?
Thanks in advance. The link to the paper is here. paper here

Reconstructing the math
The definition of the function R is not particularly clear, but I guess what they mean is:
With dOmega being the boundary of the foil and p a point p = [px,py] on the foil.
Imagine that for a point p on the sheet you are computing R(p) by going around the boundary of the foil (what they call the perimeter), your position being q, and integrating one divided by the distance from you (q) to the point p multiplied by k.
I guess you could analytically compute the integral for this rectangular sheet, but if you just want to plot the function, you could simply approximate the integral by defining a finite number of points on the boundary, evaluating the integrand in those points, then taking the mean and multiplying by the perimeter. [The same way you could approximate integral(f(x), x=0...pi) by pi*(f(0)+f(pi/2)+f(pi))/3]
Alternative representation using coordinates:
If you are only familiar with integrals along the real line in coordinate representation you could write this in the following way, which is frankly quite UGGGLY:
Plotting an approximation
%% Config:
xlen = 10;
ylen = 10;
k = 1;
%% Setting up points on the boundary of the square
x = linspace(0,xlen,50);
y = linspace(0,ylen,50);
perimeter = 2*(xlen+ylen);
boundary = [x(1)*ones(length(y),1), y'
x', y(1)*ones(length(x),1); ...
x(end)*ones(length(y),1), y'; ...
x', y(end)*ones(length(x),1)];
%% Function definition
norm2 = #(X) sqrt(sum(X.^2,2));
R = #(p) 1/(perimeter*mean(1./(k*norm2(bsxfun(#minus,boundary,p)))));
%% Plotting
[X_grid,Y_grid] = ndgrid(x,y);
R_grid = zeros(size(X_grid));
for ii = 1:length(x)
for jj = 1:length(y)
R_grid(ii,jj) = R([x(ii),y(jj)]);
end
end
surf(X_grid, Y_grid, R_grid);
axis vis3d;
This will give you the following plot:

Related

Where did i do wrong when i tried to approximatee this data using polynomial?

I am starting to learn numerical analysis using MATLAB in my course. so far we have covered polynomial interpolation (spline, polyfit, constraint spline, etc.) I was doing this practice question and I can not get the correct answer. I have uploaded the code I used and the question, where did I do wrong? thanks in advance!
close all; clear all; clc;
format long e
x = linspace(0,1,8);
xplot = linspace(0,1);
f = #(x) atan(x.*(x+1));
y_val = f(xplot);
c = polyfit(x,f(x),7);
p = polyval(c,0.7);
err = abs(f(0.7)-p)/(f(0.7))
The question I encountered is seen in the picture
After some playing around, it seems to be a matter of computing the absolute error instead of the relative absolute error.
The code below yields the desired answer. And yes, it is pretty unclear from the question which error is intended.
% Definitions
format long e
x = linspace(0,1,8)';
xplot= linspace(0,1);
f = #(x) atan(x.*(x+1));
y_val = f(xplot);
% Degree of polynomial
n = 7;
% Points to evaluate function
point1 = 0.5;
point2 = 0.7;
% Fit
c= polyfit(x,f(x),n);
% Evaluate
approxPoint1 = polyval(c, point1);
approxPoint2 = polyval(c, point2);
% Absolute errors
errPoint1 = abs( f(point1) - approxPoint1)
errPoint2 = abs( f(point2) - approxPoint2)
What you did wrong was :
mixing absolute and relative values when calculating errors to feed resulting variable err.
incorrectly placing abs() parentheses when calculating err: Your abs() only fixes the numerator, but then the denominator. To obtain |f(0.7)| you also need another abs(f(0.7))
for point x=0.7 instead of
err = abs(f(0.7)-p)/(f(0.7))
could well simply be
err = abs(f(.7)-p));
you only calculate err for assessment point 0.5 . In order to choose among the possible candidates of what seems to be a MATLAB Associate test multichoice answer, one needs err on 0.5 and err on 0.7 and then match the pair in the correct order, among all offered possible answers.
Although it's common practice to approach polynomial approximation of N points with an N-1 degree polynomial, it's often possible to approximate below satisfactory error with lower degree polynomials than N-1.
Lower degree polynomials means less calculations, less time spent approximating points. If one obtains a fair enough approximation with for instance a degree 4 polynomial, why waste time calculating an approximation with a higher degree all the way up to N-1?
Since the question does not tell what degree should have the approximating polynomial, you have to find it sweeping all polynomial degrees from 1 to up to a reasonable order.
The last error I found is that you have used linspace without specifying amount of points, MATLAB then takes by default 100 points hoping it's going to be ok.
Well, in your question 100 points is way too low an amount of points as I am going to show after supplying the following lines, as mentioned in previous point, sweeping all possible approximating polynomials, NOT on default 100 points you tacitly chose.
np=8; % numel(x) amount supplied points
N=1e3; % amount points x grid we build to measure f(x)
x= linspace(0,1,np);
xplot = linspace(0,1,N);
f = #(x) atan(x.*(x+1)); % function to approximate
y_val = f(xplot); % f(x)
xm=[.5 .7]; % points where to asses error
% finding poly coeffs
err1=zeros(2,np+2); % 1st row are errors on x=.5, 2nd row errors on x=.7
figure(1);
ax1=gca
hp1=plot(xplot,y_val)
grid on;
hp1.LineWidth=3;
hp1.Color='r';
hold on
for k=1:1:np+2
c = polyfit(x,f(x),k);
p_01 = polyval(c,xm(1));
err1(1,k) = abs(f(xm(1))-p_01);
% err(1,k) = abs((f(0.5)-p_05)/(f(0.5)))
p_02 = polyval(c,xm(2));
err1(2,k) = abs(f(xm(2))-p_02);
% err(2,k) = abs((f(0.7)-p_07)/(f(0.7)))
plot(x,polyval(c,x),'LineWidth',1.5); %'Color','b');
end
err1
.
.
The only pair of errors matching in the correct order are indeed those of polynomial order 7, but the total smallest error corresponds to the approximating polynomial of order 6.
What happens when taking linspace without defining a large enough amount of points? let's have a look:
np=8; % numel(x) amount supplied points
% N=1e3; % amount points x grid we build to measure f(x)
x= linspace(0,1,np);
xplot = linspace(0,1); %,N);
f = #(x) atan(x.*(x+1)); % function to approximate
y_val = f(xplot); % f(x)
xm=[.5 .7]; % points where to asses error
% finding poly coeffs
err1=zeros(2,np+2); % 1st row are errors on x=.5, 2nd row errors on x=.7
figure(1);
ax1=gca
hp1=plot(xplot,y_val)
grid on;
hp1.LineWidth=3;
hp1.Color='r';
hold on
for k=1:1:np+2
c = polyfit(x,f(x),k);
p_01 = polyval(c,xm(1));
err1(1,k) = abs(f(xm(1))-p_01);
% err(1,k) = abs(f(0.5)-p_05)/abs(f(0.5))
p_02 = polyval(c,xm(2));
err1(2,k) = abs(f(xm(2))-p_02);
% err(2,k) = abs(f(0.7)-p_07)/abs(f(0.7))
plot(x,polyval(c,x),'LineWidth',1.5); %'Color','b');
end
err1
With only 100 points all errors come up way too large, not a single error anywhere near 1e-5 or 1e-6.
This is why one couldn't tell which pair to go for, because all obtained values where at least 5 orders of magnitude away from landing zone.
I was about to include a plot with legend, but the visualization of this particular approach is in this case and in my opinion at best misleading, as in both plots for 100 and 1000 points, at 1st glance, both look as if the errors should be similar regardless of the amount of grid points used.
But as shown above 1e2 points cannot approximate the function,
it's like pitch dark, looking for something and pointing torch 180 from where we should be aiming at, not a chance to spot it.
Yet 1e3 grid points produce a pair of errors matching one of the possible answers, this is option D.
I hope it helps, thanks for reading my answer.

How to calculate the point-by-point radius of curvature of a trajectory that is not a proper function

with Matlab i'm trying to calculate the "radius of curvature" signal of a trajectory obtained using GPS data projected to the local cartesian plane.
The value of the signal onthe n-th point is the one of the osculating circle tangent to the trajectory on that point.
By convention the signal amplitude has to be negative when related to a left turn and viceversa.
With trajectories having a proper function as graph i'm building the "sign" signal evaluating the numeric difference between the y coordinate of the center of the osculating circle:
for i=1:length(yCenter) -1
aux=Y_m(closestIndex_head:closestIndex_tail );
if yCenter(i) - aux(i) > 0
sign(i)=-1;
else
sign(i)=+1;
end
end
yCenter contains x-coordinates of all osculating circles related to each point of the trajectory;
Y_m contain the y-coordinates of every point in trajectory.
The above simple method works as long as the trajectory's graph is a proper function (for every x there is only one y).
The trajectory i'm working on is like that:
and the sign signal got some anomalies:
The sign seems to change within a turn.
I've tried to correct the sign using the sin of the angle between the tangent vector and the trajectory, the sign of the tangent of the angle and other similar stuff, but still i'm looking at some anomalies:
I'm pretty sure that those anomalies came from the fact that the graph is not a proper function and that the solution lies on the angle of the tangent vector, but still something is missing.
Any advice will be really appreciated,
thank you.
Alessandro
To track a 2D curve, you should be using an expression for the curvature that is appropriate for general parametrized 2D functions.
While implementing the equation from Wikipedia, you can use discrete differences to approximate the derivatives. Given the x and y coordinates, this could be implemented as follows:
% approximate 1st derivatives of x & y with discrete differences
dx = 0.5*(x(3:end)-x(1:end-2))
dy = 0.5*(y(3:end)-y(1:end-2))
dl = sqrt(dx.^2 + dy.^2)
xp = dx./dl
yp = dy./dl
% approximate 2nd derivatives of x & y with discrete differences
xpp = (x(3:end)-2*x(2:end-1)+x(1:end-2))./(dl.^2)
ypp = (y(3:end)-2*y(2:end-1)+y(1:end-2))./(dl.^2)
% Compute the curvature
curvature = (xp.*ypp - yp.*xpp) ./ ((xp.^2 + yp.^2).^(1.5))
For demonstration purposes I've also constructed a synthetic test signal (which can be used to recreate the same conditions), but you can obviously use your own data instead:
z1 = linspace(2,1,N).*exp(1i*linspace(0.75*pi,-0.25*pi,N))
z2 = 2*exp(-1i*0.25*pi) + linspace(1,2,N)*exp(1i*linspace(0.75*pi,2.25*pi,N))
z = cat(1,z1,z2)
x = real(z)
y = imag(z)
With the corresponding curvature results:

Matlab horizontal asymptote being calculated incorrectly

From an lsqcurve fit function I am trying to calculate the horizontal asymptote of a sigmoidal curve over the data range. The code I am using to do this and convert the output to double precision works and is as follows:
time = [0,0.166666666666667,0.333333333333333,0.500000000000000,0.666666666666667,0.833333333333333,1,1.16666666666667,1.33333333333333,1.50000000000000,1.66666666666667,1.83333333333333,2,2.16663888888889,2.33330555555556,2.49997222222222,2.66663888888889,2.83330555555556,2.99997222222222,3.16663888888889,3.33330555555556,3.49997222222222,3.66663888888889,3.83330555555556,3.99997222222222,4.16663888888889,4.33330555555556,4.49997222222222,4.66663888888889,4.83330555555556,4.99997222222222,5.16663888888889,5.33327777777778,5.49997222222222,5.66661111111111,5.83327777777778,5.99994444444444,6.16661111111111,6.33327777777778,6.49994444444444,6.66661111111111,6.83327777777778,6.99994444444444,7.16661111111111,7.33327777777778,7.49994444444444,7.66661111111111,7.83327777777778,7.99994444444444,8.16661111111111,8.33327777777778,8.49994444444445,8.66661111111111,8.83325000000000,8.99991666666667,9.16658333333333,9.33325000000000,9.49991666666667,9.66658333333333,9.83325000000000,9.99991666666667,10.1665833333333,10.3332500000000,10.4999166666667,10.6665833333333,10.8332500000000,10.9999166666667,11.1665833333333,11.3332500000000,11.4999166666667,11.6665833333333,11.8332222222222,11.9998888888889,12.1665555555556,12.3332222222222,12.4998888888889,12.6665555555556,12.8332222222222,12.9998888888889,13.1665555555556,13.3332222222222,13.4998888888889,13.6665555555556,13.8332222222222,13.9998888888889,14.1665555555556,14.3332222222222,14.4998888888889,14.6665555555556,14.8332222222222,14.9998611111111,15.1665277777778,15.3331944444444,15.4998611111111];
Abs=[0.0756333346168200,,0.0822666635115941,0.101066668828328,0.125066662828128,0.147433335582415,0.169966672857602,0.192199997603893,0.211166655023893,0.231433339416981,0.256133330365022,0.279866663118203,0.295566670596600,0.309466672440370,0.323400000731150,0.335233343144258,0.348299992581209,0.359700001776218,0.371433332562447,0.383333327869574,0.394433322052161,0.404166663686434,0.413666687905788,0.423499998946985,0.432733344535033,0.443266667425633,0.453899989525477,0.463699989020824,0.475066669285297,0.485300009449323,0.495999989410241,0.504966656366984,0.514033327500025,0.523766654233138,0.532566664119562,0.541033337513606,0.550333333512147,0.559733323752880,0.567733330031236,0.575466672579447,0.583399988710880,0.591433353722096,0.597833327949047,0.604699979225794,0.610233349104722,0.616733354826768,0.622800009946028,0.628666676580906,0.634199996789297,0.638966679573059,0.644799992442131,0.650733329355717,0.654566655556361,0.661333315074444,0.666366661588351,0.671233326196671,0.675699991484483,0.679433315992355,0.682733337084452,0.686333330969016,0.689166650176048,0.693133344252904,0.697366672257582,0.699333322544893,0.702233329415321,0.705400002499422,0.707699996729692,0.709999985992909,0.711533337831497,0.712800003588200,0.713633326192697,0.714666672050953,0.714533333977064,0.713999989132086,0.714266665279865,0.714066684246063,0.714266670246919,0.713733327885469,0.713066659867764,0.712200003365676,0.711600005626679,0.710400002698104,0.710399977862835,0.709799999992053,0.708366667230924,0.706933336953322,0.706766667465369,0.706199998656909,0.704266687234243,0.703333348035812,0.702399998903275,0.701133318245411,0.700166669984659,0.698799995084604,0.697700018684069];
u=linspace(0,15.49986111,500);
v=pchip(time,Abs,u);
p0 = [0.075633335,0.05,0.01]; %First value = Abs value at t=0
options=optimset('MaxFunEvals',10000,'MaxIter',5000,'Display','iter');
[p,error,residual]=lsqcurvefit(#gompertz,p0,time,Abs,[],[],options)
syms x t
f=p(1)*exp(-exp(((p(2)*exp(1))/p(1))*(p(3)-t)+1));
f1=diff(f,t); %Find first derivative of equation W wrt t
f2=diff(f,t,2); %Find second derivative wrt t and to allow inflection point to be defined
crit_pts = solve(f1); %Find local maxima and minima
crit_pts=double(crit_pts);
flimit = limit(f,inf); %Find find horizontal asymptote of function f by taking limit of f as x approaches infinity
function_horizontal_asymptote=double(limit);
The 'gompertz' function called is coded as follows:
function y = gompertz(p,t)
y=p(1)*exp(-exp(((p(2)*exp(1))/p(1))*(p(3)-t)+1));
According to the Matlab documentation I have read
flimit = limit(f,inf);
should yield the correct answer but and appear towards the end of the time course, however the result I get is (shown by the yellow marker):
Am I calculating this incorrectly?
Thank you for your time,
Laura

curve fitting: a number of curves with different length/number of points into one curve in 3D in Matlab

Say I've got a number of curves with different length (number of points in each curve and points distance are all vary). Could I find a curve in 3D space that fit best for this group of lines?
Code example in Matlab would be appreciated.
example data set:
the 1st curve has 10 points.
18.5860 18.4683 18.3576 18.2491 18.0844 17.9016 17.7709 17.6401 17.4617 17.2726
91.6178 91.5711 91.5580 91.5580 91.5701 91.6130 91.5746 91.5050 91.3993 91.2977
90.6253 91.1090 91.5964 92.0845 92.5565 93.0199 93.5010 93.9785 94.4335 94.8851
the 2nd curve has 8 points.
15.2091 15.0894 14.9765 14.8567 14.7360 14.6144 14.4695 14.3017
90.1138 89.9824 89.8683 89.7716 89.6889 89.6040 89.4928 89.3624
99.4393 99.9066 100.3802 100.8559 101.3340 101.8115 102.2770 102.7296
a desired curve is one that could represent these two exist curves.
I have thinking of make these curves as points scatters and fit a line out of them. But only a straight line can I get from many code snippet online.
So did I missing something or could someone provide some hint. Thanks.
Hard to come up with a bulletproof solution without more details, but here's an approach that works for the sample data provided. I found the line of best fit for all the points, and then parameterized all the points along that line of best fit. Then I did least-squares polynomial fitting for each dimension separately. This produced a three-dimensional parametric curve that seems to fit the data just fine.
Note that curve fitting approaches other than polynomial least-squares might be better suited to some cases---just substitute the preferred fitting function for polyfit and polyval.
Hope this is helpful!
clear;
close all;
pts1=[18.5860 18.4683 18.3576 18.2491 18.0844 17.9016 17.7709 17.6401 17.4617 17.2726;
91.6178 91.5711 91.5580 91.5580 91.5701 91.6130 91.5746 91.5050 91.3993 91.2977;
90.6253 91.1090 91.5964 92.0845 92.5565 93.0199 93.5010 93.9785 94.4335 94.8851]';
pts2=[ 15.2091 15.0894 14.9765 14.8567 14.7360 14.6144 14.4695 14.3017;
90.1138 89.9824 89.8683 89.7716 89.6889 89.6040 89.4928 89.3624;
99.4393 99.9066 100.3802 100.8559 101.3340 101.8115 102.2770 102.7296]';
%Combine all of our curves into a single point cloud
X = [pts1;pts2];
%=======================================================
%We want to first find the line of best fit
%This line will provide a parameterization of the points
%See accepted answer to http://stackoverflow.com/questions/10878167/plot-3d-line-matlab
% calculate centroid
x0 = mean(X)';
% form matrix A of translated points
A = [(X(:, 1) - x0(1)) (X(:, 2) - x0(2)) (X(:, 3) - x0(3))];
% calculate the SVD of A
[~, S, V] = svd(A, 0);
% find the largest singular value in S and extract from V the
% corresponding right singular vector
[s, i] = max(diag(S));
a = V(:, i);
%=======================================================
a=a / norm(a);
%OK now 'a' is a unit vector pointing along the line of best fit.
%Now we need to compute a new variable, 't', for each point in the cloud
%This 't' value will parameterize the curve of best fit.
%Essentially what we're doing here is taking the dot product of each
%shifted point (contained in A) with the normal vector 'a'
t = A * a;
tMin = min(t);
tMax = max(t);
%This variable represents the order of our polynomial fit
%Use the smallest number that produces a satisfactory result
polyOrder = 8;
%Polynomial fit all three dimensions separately against t
pX = polyfit(t,X(:,1),polyOrder);
pY = polyfit(t,X(:,2),polyOrder);
pZ = polyfit(t,X(:,3),polyOrder);
%And that's our curve fit: (pX(t),pY(t),pZ(t))
%Now let's plot it.
tFine = tMin:.01:tMax;
fitXFine = polyval(pX,tFine);
fitYFine = polyval(pY,tFine);
fitZFine = polyval(pZ,tFine);
figure;
scatter3(X(:,1),X(:,2),X(:,3));
hold on;
plot3(fitXFine,fitYFine,fitZFine);
hold off;

Limit cycle in Matlab for 2nd order autonomous system

I wish to create a limit cycle in Matlab. A limit cycle looks something like this:
I have no idea how to do it though, I've never done anything like this in Matlab.
The equations to describe the limit cycle are the following:
x_1d=x_2
x_2d=-x_1+x_2-2*(x_1+2*x_2)x_2^2
It is to be centered around the equilibrium which is (0,0)
Can any of you help me?
If you use the partial derivatives of your function to make a vector field, you can then use streamlines to visualize the cycle that you are describing.
For example, the function f = x^2+y^2
Gives me partial derivatives dx = 2x, dy=2y For the visualization, I sample from the partial derivatives over a grid.
[x,y] = meshgrid(0:0.1:1,0:0.1:1);
dx = 2*x;
dy = 2*y;
To visualize the vector field, I use quiver;
figure;
quiver(x, y, dx, dy);
Using streamline, I can visualize the path a particle injected into the vector field would take. In my example, I inject the particle at (0.1, 0.1)
streamline(x,y, dx, dy, 0.1, 0.1);
This produces the following visualization
In your case, you can omit the quiver step to remove the hedgehog arrows at every grid point.
Here's another example that shows the particle converging to an orbit.
Edit: Your function specifically.
So as knedlsepp points out, the function you are interested in is a bit ambiguously stated. In Matlab, * represents the matrix product while .* represents the element-wise multiplication between matrices. Similarly, '^2' represents MM for a matrix M, while .^2 represents taking the element-wise power.
So,
[x_1,x_2] = meshgrid(-4:0.1:4,-4:0.1:4);
dx_1 = x_2;
dx_2 = -x_1+x_2-2*(x_1+2*x_2)*(x_2)^2;
figure; streamline(x_1,x_2, dx_1, dx_2, 0:0.1:4, 0:0.1:4);
Looks like
This function will not show convergence because it doesn't converge.
knedlsepp suggests that the function you are actually interested in is
dx_1 = -1 * x_2;
dx_2 = -1 * -x_1+x_2-2*(x_1+2*x_2).*(x_2).^2;
His post has a nice description of the rest.
This post shows the code to produce the integral lines of your vector field defined by:
dx/dt = y
dy/dt = -x+y-2*(x+2*y)*y^2.
It is important to properly vectorize this function. (i.e. Introducing dots at all the important places)
dxdt = #(x,y) y;
dydt = #(x,y) -x+y-2*(x+2*y).*y.^2;
[X,Y] = meshgrid(linspace(-4,4,100));
[sx,sy] = meshgrid(linspace(-3,3,20));
streamline(stream2(X, Y, ... % Points
dxdt(X,Y), dydt(X,Y),... % Derivatives
sx, sy)); % Starting points
axis equal tight
To get a picture more similar to yours, change the grid size and starting points:
[X,Y] = meshgrid(linspace(-1,1,100));
[sx,sy] = meshgrid(linspace(0,0.75,20),0.2);