I have a mixed set of differential and algebraic equations for which I have found the analytical solution in MATLAB. It concerns a point mass moving along a 2D curve constrained by y=x^2.
How would I go about using an ode-solver in MATLAB (or something else if it's easier) to simulate the ball rolling over the curve? The animation I can do myself, I'm more concerned with finding the velocities, xd yd, for each consecutive step. That's where I kind of get lost.
These are the equations of motion which I've derived using Lagrange multipliers. Hence the lambda. The lambda is the reaction force. I can calculate the accelerations, xdd ydd, but I also need the velocities in the state if I want to properly simulate this, I assume.
% Symbolic functions
syms y x xd yd xdd ydd
syms m g lambda
% Parameters
A = [m 0 -2*x; 0 m 1; -2*x 1 0];
X = [xdd ydd lambda].';
b = [0 -m*g -2*xd^2].';
sol = A\b % these are the states stored in X
So if you work out your problem using the lagrancian you would get the following formula seen below (see https://physics.stackexchange.com/questions/47154/ball-rolling-in-a-parabolic-bowl). The k-value comes from y=kx^2 (can be 1 for your example).
So rewrite this in the following form.
Now you just use
ddx= Formula seen above..
x = x + dx *dt
dx = dx + ddx *dt
t = t + dt
y = k*x*x
You make a loop with a sufficient small dt, and update you x-position velocity and acceleration.
Now you need
to specify the following starting values -> x0 dx0 ddx0 and dt.
I hope this helped
Cheers:)
Related
I tried everything and looked everywhere but can't find any solution for my question.
clc
clear all
%% Solving the Ordinary Differential Equation
G = 6.67408e-11; %Gravitational constant
M = 10; %Mass of the fixed object
r = 1; %Distance between the objects
tspan = [0 100000]; %Time Progression from 0 to 100000s
conditions = [1;0]; %y0= 1m apart, v0=0 m/s
F=#(t,y)var_r(y,G,M,r);
[t,y]=ode45(F,tspan,conditions); %ODE solver algorithm
%%part1: Plotting the Graph
% plot(t,y(:,1)); %Plotting the Graph
% xlabel('time (s)')
% ylabel('distance (m)')
%% part2: Animation of Results
plot(0,0,'b.','MarkerSize', 40);
hold on %to keep the first graph
for i=1:length(t)
k = plot(y(i,1),0,'r.','MarkerSize', 12);
pause(0.05);
axis([-1 2 -2 2]) %Defining the Axis
xlabel('X-axis') %X-Axis Label
ylabel('Y-axis') %Y-Axis Label
delete(k)
end
function yd=var_r(y,G,M,r) %function of variable r
g = (G*M)/(r + y(1))^2;
yd = [y(2); -g];
end
this is the code where I'm trying to replace the ode45 with the runge kutta method but its giving me errors. my runge kutta function:
function y = Runge_Kutta(f,x0,xf,y0,h)
n= (xf-x0)/h;
y=zeros(n+1,1);
x=(x0:h:xf);
y(1) = y0;
for i=1:n
k1 = f(x(i),y(i));
k2= f(x(i)+ h/2 , y(i) +h*(k1)/2);
y(i+1) = y(i)+(h*k2);
end
plot(x,y,'-.M')
legend('RKM')
title ('solution of y(x)');
xlabel('x');
ylabel('y(x)')
hold on
end
Before converting your ode45( ) solution to manually written RK scheme, it doesn't even look like your ode45( ) solution is correct. It appears you have a gravitational problem set up where the initial velocity is 0 so a small object will simply fall into a large mass M on a line (rectilinear motion), and that is why you have scalar position and velocity.
Going with this assumption, r is something you should be calculating on the fly, not using as a fixed input to the derivative function. E.g., I would have expected something like this:
F=#(t,y)var_r(y,G,M); % get rid of r
:
function yd=var_r(y,G,M) % function of current position y(1) and velocity y(2)
g = (G*M)/y(1)^2; % gravity accel based on current position
yd = [y(2); -g]; % assumes y(1) is positive, so acceleration is negative
end
The small object must start with a positive initial position for the derivative code to be valid as you have it written. As the small object falls into the large mass M, the above will only hold until it hits the surface or atmosphere of M. Or if you model M as a point mass, then this scheme will become increasingly difficult to integrate correctly because the acceleration becomes large without bound as the small mass gets very close to the point mass M. You would definitely need a variable step size approach in this case. The solution becomes invalid if it goes "through" mass M. In fact, once the speed gets too large the whole setup becomes invalid because of relativistic effects.
Maybe you could explain in more detail if your system is supposed to be set up this way, and what the purpose of the integration is. If it is really supposed to be a 2D or 3D problem, then more states need to be added.
For your manual Runge-Kutta code, you completely forgot to integrate the velocity so this is going to fail miserably. You need to carry a 2-element state from step to step, not a scalar as you are currently doing. E.g., something like this:
y=zeros(2,n+1); % 2-element state as columns of the y variable
x=(x0:h:xf);
y(:,1) = y0; % initial state is the first 2-element column
% change all the scalar y(i) to column y(:,i)
for i=1:n
k1 = f(x(i),y(:,i));
k2= f(x(i)+ h/2 , y(:,i) +h*(k1)/2);
y(:,i+1) = y(:,i)+(h*k2);
end
plot(x,y(1,:),'-.M') % plot the position part of the solution
This is all assuming the f that gets passed in is the same F you have in your original code.
y(1) is the first scalar element in the data structure of y (this counts in column-first order). You want to generate in y a list of column vectors, as your ODE is a system with state dimension 2. Thus you need to generate y with that format, y=zeros(length(x0),n+1); and then address the list entries as matrix columns y(:,1)=x0 and the same modification in every place where you extract or assign a list entry.
Matlab introduce various short-cuts that, if used consequently, lead to contradictions (I think the script-hater rant (german) is still valid in large parts). Essentially, unlike in other systems, Matlab gives direct access to the underlying data structure of matrices. y(k) is the element of the underlying flat array (that is interpreted column-first in Matlab like in Fortran, unlike, e.g., Numpy where it is row-first).
Only the two-index access is to the matrix with its dimensions. So y(:,k) is the k-th matrix column and y(k,:) the k-th matrix row. The single-index access is nice for row or column vectors, but leads immediately to problems when collecting such vectors in lists, as these lists are automatically matrices.
I have a parametric B-Spline surface, S
S=[x(:);y(:);z(:)];
Right now, I am plotting the surface by just plotting each column of S as a single point:
plot3(S(1,:),S(2,:),S(3,:),'.')
The result is this:
Unfortunately, by plotting individual points, we lose the sense of depth and curvy-ness when we look at this picture.
Any ideas on how to implement SURF or MESH command for a parametric surface? These functions seem to require a matrix representing a meshgrid which I dont think I can use since the X x Y domain of S is not a quadrilateral. However, I like the lighting and color interpolation that can be conveniently included when using these functions, as this would fix the visualization problem shown in figure above.
I am open to any other suggestions as well.
Thanks.
Without seeing your equations it's hard to offer an exact solution, but you can accomplish this by using fsurf (ezsurf if you have an older version of MATLAB).
There are specific sections regarding plotting parametric surfaces using ezsurf and fsurf
syms s t
r = 2 + sin(7*s + 5*t);
x = r*cos(s)*sin(t);
y = r*sin(s)*sin(t);
z = r*cos(t);
fsurf(x, y, z, [0 2*pi 0 pi]) % or ezsurf(x, y, z, [0 2*pi 0 pi])
If you want to have a piece-wise function, you can either write a custom function
function result = xval(s)
if s < 0.5
result = 1 - 2*s;
else
result = 2 * x - 1;
end
end
And pass a function handle to fsurf
fsurf(#xval, ...)
Or you can define x to be piece-wise using a little bit of manipulation of the function
x = (-1)^(s > 0.5) * (1 - 2*s)
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);
I have an unknown non-linear system and I want to model it using another system with some adaptable parameters (for instance, a neural network). So, I want to fix an online learning structure of the unknown system without knowing its dynamics, I can only interact with it through inputs-outputs. My problem is that I can not make it work in MATLAB using ode solvers. Lets say that we have this real system (my actual system is more complicated, but I will give a simple example in order to be understood):
function dx = realsystem(t, x)
u = 2;
dx = -3*x+6*u;
end
and we solve the equations like this:
[t,x_real] = ode15s(#(t,x)realsystem(t,x), [0 1], 0)
We suppose that is an unknown system and we do not know the coefficients 3 and 6 so we take an adaptive system with the 2 adaptive laws:
dx(t) = -p1(t)*x(t) + p2(t)*u(t)
dp1(t) = -e(t)*x(t)
dp2(t) = e(t)*u(t)
with e(t) the error e(t) = x(t) - x_real(t).
The thing is that I cannot find a way to feed the real values for each t to the ode solver in order to have online learning.
I tried with something like this but it didn't work:
function dx = adaptivesystem(t, x, x_real)
dx = zeros(3,1);
e = x_real - x;
u = 2;
dx(1) = -x(2)*x(1)+x(3)*u;
dx(2) = -e*x(1); %dx(2) = dp1(t)
dx(3) = e*u; %dx(3) = dp2(t)
end
You should be aware that your problem is ill-posed as it is. Given any trajectory x(t) obtained via sampling and smoothing/interpolating, you can choose p1(t) at will and set
p2(t) = ( x'(t) - p1(t)*x(t) ) / u.
So you have to formulate restrictions. One obvious is that the functions p1 and p2 should be valid for all trajectories of the black-box system. Do you have different trajectories available?
Another variant is to demand that p1 and p2 are constants. Actually, in this case and if you have equally spaced samples available, it would be easier to first find a good difference equation for the data. With the samples x[n] for time t[n]=t0+n*dt form a matrix X with rows
[ -u, x[n], x[n+1], ... ,x[n+k] ] for n=0, ... , N-k
and apply QR decomposition or SVD to X to determine the right hand kernel vectors. QR may fail to show a usable rank deficiency, so use the SVD on the top square part of R = USV^T, S diagonal, ordered as usual, U,V square and orthogonal, and use the last row of V, with coefficients
[b, a[0], ..., a[k] ],
corresponding to the smallest eigenvalue, to form the difference equation
a[0]*x[n]+a[1]*x[n-1]+...+a[k]*x[n-k]=b*u.
If the effective rank of R resp. S is not (k-1), then reduce k to be the effective rank plus one and start again.
If in the end k=1 is found, then you can make a differential equation out of it. Reformulate the difference equation as
a[0]*(x[n]-x[n-1])/dt = -(a[0]+a[1])/dt * x[n-1] + b/dt * u
and read off the differential equation
x'(t) = -(a[0]+a[1])/(a[0]*dt) * x(t) + b/(a[0]*dt) * u
One may reject this equation if the coefficients become uncomfortably large.
I need to draw an elliptic curve over the finite field F17(in other words, I want to draw some specific dots on the curve), but somehow I don't get it right.
The curve is defined by the equation:
y^2 = x^3 +x + 1 (mod 17)
I tried the way below, but it can't work.
for x = 0:16, plot(x, mod(sqrt(x^3+x+1), 16),'r')', end
Can someone help ?
[Update]
According to Nathan and Bill's suggestions, here is a slightly modified version.
x = 0:18
plot(mod(x,16), mod(sqrt(x.^3+x+1), 16),'ro')
However, I feel the figure is WRONG , e.g.,y is not an integer when x=4 .
You have to test all points that fulfill the equation y^2 = x^3 +x + 1 (mod 17). Since it is a finite field, you cannot simply take the square root on the right side.
This is how I would go about it:
a=0:16 %all points of your finite field
left_side = mod(a.^2,17) %left side of the equation
right_side = mod(a.^3+a+1,17) %right side of the equation
points = [];
%testing if left and right side are the same
%(you could probably do something nicer here)
for i = 1:length(right_side)
I = find(left_side == right_side(i));
for j=1:length(I)
points = [points;a(i),a(I(j))];
end
end
plot(points(:,1),points(:,2),'ro')
set(gca,'XTick',0:1:16)
set(gca,'YTick',0:1:16)
grid on;
Matlab works with vectors natively.
your syntax was close, but needs to be vectorized:
x = 0:16
plot(x, mod(sqrt(x.^3+x+1), 16),'r')
Note the . in x.^3. This tells Matlab to cube each element of x individually, as opposed to raising the vector x to the 3rd power, which doesn't mean anything.
You can use this code if you want to plot on Real numbers:
syms x y;
v=y^2-x^3-x-1;
ezplot(v, [-1,3,-5,5]);
But, for plot in modulo, at first you can write below code;
X=[]; for x=[0:16], z=[x; mod(x^3+x+1,17)]; X=[X, z]; end, X,
Then, you can plot X with a coordinate matrix.