Matlab: Orbits of Planetary Bodies - matlab
The below code is something that I am cooking up. I am plotting the orbits of the Sun, Mercury, Earth and the Moon. I have gotten this far into the project but the orbit of Mercury is terrifyingly wrong. This is seen by typing "SunEarthMoon(2,50)" at the command prompt and viewing the bottom left plot. The logic behind the project is utilizing Newton's Second Law toggled with the command "ode45" to find the positions of the bodies during a given time interval. I've been staring at this for far too long. Can anyone help to fix the orbit of Mercury?
function [] = SunEarthMoon(years,framerate)
%% Clean Up
close all
clc
%% Initializaion
x_earth = 147300000000; % [m]
x_mercury = 57.91e9; % [m]
v_earth = 30257; % [m/s]
v_mercury = 47362; % [m/s]
r_sat = 384748000; % earth surface [m]
r_earth = 6367000; % earth radius [m]
v_sat = 1023; % relative velocity from earth [m/s]
a = 5.145; % Angle to vertical (y) axis
b = 90; % Angle to horizontal (x) axis in xz plane
x_earth_o = [x_earth; 0; 0];
x_sun_o = [0; 0; 0];
x_mercury_o = [x_mercury; 0; 0];
x_sat_o = [x_earth+r_sat+r_earth; 0; 0];
v_earth_o = [0; v_earth; 0];
v_sun_o = [0; 0; 0];
v_mercury_o = [0; v_mercury; 0];
v_sat_o = v_sat*[cos(pi/180*b)*sin(pi/180*a); cos(pi/180*a); sin(pi/180*b)*sin(pi/180*a)] + v_earth_o;
interval = years*[0 31536000];
%% Error Control
h = [0.01 36000];
tol = 100000;
Options.AbsTol = tol;
Options.MaxStep = h(2);
Options.InitialStep = h(1);
%% Analysis
ao = [x_earth_o; v_earth_o; x_sun_o; v_sun_o; x_sat_o; v_sat_o; x_mercury_o; v_mercury_o];
[t, x] = ode45(#earthfinal,interval,ao,Options);
for i = 1:length(t)
R1(i) = (x(i,13)-x(i,1));
R2(i) = (x(i,14)-x(i,2));
R3(i) = (x(i,15)-x(i,3));
R(i) = sqrt(R1(i)^2+R2(i)^2+R3(i)^2);
end
T_index_earth = find([1; x(:,4)].*[x(:,4);1]<=0);
T_index_moon = find([1; R2(:)].*[R2(:); 1]<=0);
for i = 4:length(T_index_earth)
T_earth_semi(i-3) = (t(T_index_earth(i)-1)-t(T_index_earth(i-2)-1))/24/60/60;
end
T_earth = mean(T_earth_semi);
for i = 4:length(T_index_moon)
T_moon_semi(i-3) = (t(T_index_moon(i)-1)-t(T_index_moon(i-2)-1))/24/60/60;
end
T_moon = mean(T_moon_semi);
D_earth = 0;
for i = 2:(T_index_earth(4)-1)
D_earth = D_earth + sqrt((x(i,1)-x(i-1,1))^2+(x(i,2)-x(i-1,2))^2+(x(i,3)-x(i-1,3))^2);
end
D_moon = 0;
for i = 2:(T_index_moon(4)-1)
D_moon = D_moon + sqrt((R1(i)-R1(i-1))^2+(R2(i)-R2(i-1))^2+(R3(i)-R3(i-1))^2);
end
%% Plots
q = framerate;
scrsz = get(0,'ScreenSize');
figure('position', [0.05*scrsz(3) 0.05*scrsz(4) 0.75*scrsz(3) 0.85*scrsz(4)])
set(gcf,'name','Sun, Earth, and Moon Orbits')
for i = 1:length(t)/q
subplot(2,2,1)
plot3(x(1:i*q,1),x(1:i*q,2),x(1:i*q,3),'g',x(1:i*q,7),x(1:i*q,8),x(1:i*q,9),'r',x(1:i*q,13),x(1:i*q,14),x(1:i*q,15),'b',x(1:i*q,19),x(1:i*q,20),x(1:i*q,21),'black')
axis(1.1*[min(x(:,1)) max(x(:,1)) min(x(:,2)) max(x(:,2)) 2*min(x(:,15)) 2*max(x(:,15))])
xlabel('Universal X Coordinate (m)')
ylabel('Universal Y Coordinate (m)')
zlabel('Universal Z Coordinate (m)')
title('Relative Orbits')
legend('Earth','Sun','Moon')
hold on
plot3(x(i*q,1),x(i*q,2),x(i*q,3),'g-o',x(i*q,7),x(i*q,8),x(i*q,9),'r-o',x(i*q,13),x(i*q,14),x(i*q,15),'b-o',x(i*q,19),x(i*q,20),x(i*q,21),'black-o')
hold off
subplot(2,2,2)
plot3(R1(1:i*q),R2(1:i*q),R3(1:i*q),'b',zeros(1,i*q),zeros(1,i*q),zeros(1,i*q),'g')
axis(1.5*[min(R1) max(R1) min(R2) max(R2) min(R3) max(R3)])
xlabel('Universal X Coordinate (m)')
ylabel('Universal Y Coordinate (m)')
zlabel('Universal Z Coordinate (m)')
title('Relative Moon Orbit About Earth')
hold on
plot3(R1(i*q),R2(i*q),R3(i*q),'b-o',0,0,0,'g-o')
text(0,1.45*max(R2),1.40*max(R3),sprintf('Orbital Period, T = %3.5g days',T_moon))
text(0,1.45*max(R2),1.15*max(R3),sprintf('Orbital Circumference, D = %3.5g gigameters',D_moon*1e-9))
hold off
subplot(2,2,3)
plot(x(1:i*q,1),x(1:i*q,2),'g',x(1:i*q,7),x(1:i*q,8),'r', x(1:i*q,19),x(1:i*q,20),'black')
axis(1.5*[min(x(:,1)) max(x(:,1)) min(x(:,2)) max(x(:,2))])
xlabel('Universal X Coordinate (m)')
ylabel('Universal Y Coordinate (m)')
title('Relative Earth Orbit About Sun')
hold on
plot(x(i*q,1),x(i*q,2),'g-o',x(i*q,7),x(i*q,8),'r-o',x(i*q,19),x(i*q,20),'black-o')
text(1.45*min(x(:,1)),1.40*max(x(:,2)),sprintf('Orbital Period, T = %3.5g days',T_earth))
text(1.45*min(x(:,1)),1.25*max(x(:,2)),sprintf('Orbital Circumference, D = %3.5g gigameters',D_earth*1e-9))
text(1.45*min(x(:,1)),1.40*min(x(:,2)),sprintf('Time, t = %3.3g days',round(t(q*i)/24/60/60)))
hold off
subplot(2,2,4)
plot(t(1:i*q)/(60*60*24),R(1:i*q)/1000,'b')
axis([t(1)/24/60/60 t(end)/24/60/60 0.999*min(R)/1000 1.001*max(R)/1000])
xlabel('Time,t (days)')
ylabel('Orbit Radius, R (km)')
title('Moon-Earth Distance')
hold on
plot(t(i*q)/(60*60*24),R(i*q)/1000,'b-o')
hold off
drawnow
end
end
%% Differential Equation Function
function [udot]= earthfinal(t,u)
m_earth = 5.9742e24; % [kg]
m_mercury = 3.285e23; % [kg]
m_sun = 1.98892e30; % [kg]
m_sat = 11110; % [kg]
G = 6.67300e-11; %[(m)^3(kg)^-1(s)^-2];
d_earth_sun = sqrt((u( 7,1)-u(1,1))^2+(u( 8,1)-u(2,1))^2+(u( 9,1)-u(3,1))^2);
d_earth_sat = sqrt((u(13,1)-u(1,1))^2+(u(14,1)-u(2,1))^2+(u(15,1)-u(3,1))^2);
d_sun_sat = sqrt((u(13,1)-u(7,1))^2+(u(14,1)-u(8,1))^2+(u(15,1)-u(9,1))^2);
d_mercury_sun = sqrt((u(7,1) -u(19,1))^2 + (u(8,1) - u(20,1))^2 + (u(9,1)-u(21,1))^2);
d_mercury_earth = sqrt((u(1,1) -u(19,1))^2 + (u(2,1) - u(20,1))^2 + (u(3,1)-u(21,1))^2);
d_mercury_sat = sqrt((u(13,1) -u(19,1))^2 + (u(14,1) - u(20,1))^2 + (u(15,1)-u(21,1))^2);
% Earth motion
udot( 1,1) = u(4,1);
udot( 2,1) = u(5,1);
udot( 3,1) = u(6,1);
udot( 4,1) = m_sun*G*(u(7,1)-u(1,1))/d_earth_sun^3 + m_sat*G*(u(13,1)-u(1,1))/d_earth_sat^3 + m_mercury*G*(u(19,1)-u(1,1))/d_mercury_earth^3;
udot( 5,1) = m_sun*G*(u(8,1)-u(2,1))/d_earth_sun^3 + m_sat*G*(u(14,1)-u(2,1))/d_earth_sat^3 + m_mercury*G*(u(20,1)-u(2,1))/d_mercury_earth^3;
udot( 6,1) = m_sun*G*(u(9,1)-u(3,1))/d_earth_sun^3 + m_sat*G*(u(15,1)-u(3,1))/d_earth_sat^3 + m_mercury*G*(u(21,1)-u(3,1))/d_mercury_earth^3;
% Sun Motion
udot( 7,1) = u(10,1);
udot( 8,1) = u(11,1);
udot( 9,1) = u(12,1);
udot(10,1) = m_earth*G*(u(1,1)-u(7,1))/d_earth_sun^3 + m_sat*G*(u(13,1)-u(7,1))/d_sun_sat^3 + m_mercury*G*(u(19,1)-u(7,1))/d_mercury_sun^3;
udot(11,1) = m_earth*G*(u(2,1)-u(8,1))/d_earth_sun^3 + m_sat*G*(u(14,1)-u(8,1))/d_sun_sat^3 + m_mercury*G*(u(20,1)-u(8,1))/d_mercury_sun^3;
udot(12,1) = m_earth*G*(u(3,1)-u(9,1))/d_earth_sun^3 + m_sat*G*(u(15,1)-u(9,1))/d_sun_sat^3 + m_mercury*G*(u(21,1)-u(9,1))/d_mercury_sun^3;
% Satellite Motion
udot(13,1) = u(16,1);
udot(14,1) = u(17,1);
udot(15,1) = u(18,1);
udot(16,1) = m_earth*G*(u(1,1)-u(13,1))/d_earth_sat^3 + m_sun*G*(u(7,1)-u(13,1))/d_sun_sat^3 + m_mercury*G*(u(19,1)-u(13,1))/d_mercury_sat^3;
udot(17,1) = m_earth*G*(u(2,1)-u(14,1))/d_earth_sat^3 + m_sun*G*(u(8,1)-u(14,1))/d_sun_sat^3 + m_mercury*G*(u(20,1)-u(14,1))/d_mercury_sat^3;
udot(18,1) = m_earth*G*(u(3,1)-u(15,1))/d_earth_sat^3 + m_sun*G*(u(9,1)-u(15,1))/d_sun_sat^3 + m_mercury*G*(u(21,1)-u(15,1))/d_mercury_sat^3;
% Mercury Motion
udot(19,1) = u(22,1);
udot(20,1) = u(23,1);
udot(21,1) = u(24,1);
udot(22,1) = m_sun*G*(u(7,1)-u(19,1))/d_mercury_sun^3 + m_earth*G*(u(1,1)-u(19,1))/d_mercury_earth^3 + m_sat*G*(u(13,1)-u(19,1))/d_mercury_sat^3;
udot(23,1) = m_sun*G*(u(8,1)-u(20,1))/d_mercury_sun^3 + m_earth*G*(u(2,1)-u(20,1))/d_mercury_earth^3 + m_sat*G*(u(14,1)-u(20,1))/d_mercury_sat^3;
udot(24,1) = m_sun*G*(u(9,1)-u(21,1))/d_mercury_sun^3 + m_earth*G*(u(3,1)-u(21,1))/d_mercury_earth^3 + m_sat*G*(u(15,1)-u(21,1))/d_mercury_sat^3;
end
Related
Is there a possibility to have a quiver plot with vectors of same length?
I am using a quiver plot in MATLAB to simulate a velocity field. Now I would like the vectors produced by the quiver plot to be all the same length, so that they just indicate the vectors direction. The value of the velocity in each point should be illustrated by different colors then. Is there a possibility to have quiver plotting vectors of same length? That's my current code: %defining parameters: age = 900; vis= 15; turbulences = zeros(9,3); a = 0.01; spacing = 1000; [x,y] = meshgrid(-100000:spacing:100000);%, 0:spacing:10000); u = a; v = 0; n = 0; for i = 1:4 turbulences(i,1) = -80000 + n; turbulences(i,2) = 15000; n = 15000 * i; end n = 0; for i = 5:9 turbulences(i,1) = -15000 + n*5000; turbulences(i,2) = 4000; n = n+1; end for i = 1:4 turbulences(i,3) = -1000; end for i = 5:9 turbulences(i,3) = 800; end %compute velocities in x and y direction for k = 1:9 xc = turbulences(k,1); yc = turbulences(k,2); r1 = ((x-xc).^2 + (y-yc).^2); r2 = ((x-xc).^2 + (y+yc).^2); u = u + turbulences(k,3)/2*pi * (((y-yc)./r1).*(1-exp(-(r1./(4*vis*age)))) - ((y+yc)./r2).*(1-exp(-(r2./(4*vis*age))))); v = v - turbulences(k,3)/2*pi* (((x-xc)./r1).*(1-exp(-(r1./(4*vis*age)))) - ((x-xc)./r2).*(1-exp(-(r2./(4*vis*age))))); end quiver(x,y,u,v); grid on; Thank you for your help!
One way to do this would be to normalize each component of your vectors to +- 1 just to keep their direction. un = u./abs(u); % normalized u vn = v./abs(v); % normalized v quiver(x, y, un, vn)
Servo motor routing according to Matlab x, y, z coordinates
I work to about missile routing. I calculated throuhout the flight x,y,z coordinates of missile . I have data set about missile x,y,z coordinates. My goal is to move the servo motor according to x, y, z coordinates. My input is 3-dimensional(x,y,z). I want to simulate in two dimensions. And for this I use vectoral calculation. The servo motor can take values between 0-1. But the result larger than 1 . When the results are reduced at the same rate, result is smaller than 0. But I get still the error Undefined function 'writePosition' for input arguments of type 'matlab.graphics.chart.primitive.Surface'. I will be grateful if you could help me. My data example: missile_x = 0.015 missile_y = 0.054 missile_z = 0.254 missile_flight = 0.00018794 My flight rotation code: missile_x = vpa(Xval{id}(k)/10,5) missile_y = vpa(Yval{id}(k)/10,5) missile_z = vpa(Zval{id}(k)/10,5) missile_flight = vpa(0.00555556*(missile_x^2+missile_y^2+missile_z^2)^1/2,5) writePosition(s, missile_flight); current_pos = readPosition(s); current_pos = current_pos*missile_flight; fprintf('Current motor position is %d degrees\n', current_pos); pause(2); Missile X,Y,Z calculation code: dt = 0.005; %time step g = 9.81; %gravity ro = 1.2; %air density A = pi*(0.2)^2; % reference area Vmag = 0; % missile velocity vectoral value [m/sn] t = 0; T(1) = t; U(1) = 0; %the missile is initially at rest at t = 0; So the velocity is 0 V(1) = 0; W(1) = 0; X(1) = X0; Y(1) = Y0; Z(1) = Z0; n = 1; h = interp2(x_terrain, y_terrain, h_terrain,X(1), Y(1)); while (Z(n) >= h) [Thx, Thy, Thz] = thrust(t, Thmag0, theta, phi, Tburn, U(n), V(n), W(n)); Vmag = (U(n)^2 + V(n)^2 + W(n)^2)^(1/2); Thmag = (Thx^2 + Thy^2 + Thz^2)^(1/2); m = mass(t, m0, mf, Tburn); [rho,sound_speed] = atmosphere(Z(n)); Cd = drag_coeff(Vmag,sound_speed); U(n+1) = U(n) + (Thx/m - (Cd*rho*A/(2*m))*(U(n)*(U(n)^2+V(n)^2+W(n)^2)^(1/2)))*dt; V(n+1) = V(n) + (Thy/m - (Cd*rho*A/(2*m)*(V(n)*(U(n)^2+V(n)^2+W(n)^2)^(1/2))))*dt; W(n+1) = W(n) + (Thz/m - (Cd*rho*A/(2*m))*(W(n)*(U(n)^2+V(n)^2+W(n)^2)^(1/2)) - g)*dt; X(n+1) = X(n) + U(n+1)*dt; Y(n+1) = Y(n) + V(n+1)*dt; Z(n+1) = Z(n) + W(n+1)*dt; h = interp2(x_terrain, y_terrain, h_terrain, ... X(end), Y(end)); t = t + dt; T(n+1) = t; n = n+1 ; end Tval = T; Xval = X; Yval = Y; Zval = Z;
Matlab 3d projectile secant method with vector
How can I use the secant method in order to calculate the angle b(between the positive x-axis and negative y-axis) I have to throw a ball for it to land on the x-axis, with these conditions: the ball is thrown from origo, at a height z=1.4 m, with the and angle a (for the horizontal plane) 30◦, with a speed of 25 m / s. The air resistance coefficient is c = 0.070 and the wind force is 7 m / s at the ground which increases with the height according to: a(z) = 7 + 0.35z. The motion of the ball is described with the following: x''=−qx', y''=−q(y'−a(z)), z''=−9.81−qz', q=c*sqrt(x'^2+(y'−a(z))^2+z'^2) I did a variable substitution (u) and then used RK4 to calculate the ball's motion, however I can't figure out how to use the secant method to find the angle b. The problem is that when I plot with these start and guessing values is that the ball doesn't land on the x-axis: clear all, close all, clc a = pi/3; %start angle c = 0.07; % air resistance coeff. v0 = 25; %start velocity, 25 m/s t = 0; %start time h = 0.1; % 0.1 second step b = 0 x0 = 0; xPrim = v0*sin(a)*cosd(b); y0 = 0; yPrim = v0*sin(a)*sind(b); z0 = 1.4; zPrim = v0*cos(a); u = [x0 xPrim y0 yPrim z0 zPrim]'; uVek = u'; % Secant method b0 = 270; % Start guess nr 1 b1 = 360; % Start guess nr 2 f0 = funk (b0); db = 1; while abs(db) > 0.5e-8 f1 = funk (b1); db = f1 * (b1 - b0) / (f1 - f0); b0 = b1; % Updates b0 f0 = f1; % Updates f0 b1 = b1 - db % new b end while u(5) >= 0 && u(3)<=0 f1 = FRK4(t,u); f2 = FRK4(t+h/2,u+(h/2)*f1); f3 = FRK4(t+h/2,u+(h/2)*f2); f4 = FRK4(t+h,u+h*f3); f = (f1 + 2*f2 + 2*f3 + f4)/6; u = u + h*f; uVek = [uVek; u']; t = t+h; end x = uVek(:,1)'; y = uVek(:,3)'; z = uVek(:,5)'; plot3(x,y,z) xlabel('X'); ylabel('Y'); zlabel('Z'); grid on where FRK4 is a function: function uPrim = FRK4(t,u) c = 0.07; az = 7+0.35*(u(5)); q = c*sqrt(u(2)^2 +(u(4)- az)^2 + u(6)^2); uPrim = [u(2) -q*u(2) u(4) -q*(u(4) - az) u(6) -9.81-q*u(6)]'; end where funk is a function: function f = funk(b) a = pi/3 v0 = 25 x0 = 0; xPrim = v0*sin(a)*cosd(b); y0 = 0; yPrim = v0*sin(a)*sind(b); z0 = 1.4; zPrim = v0*cos(a); f = [x0 xPrim y0 yPrim z0 zPrim]'; end
Plot equally spaced markers along a spiral
I want to move a red star marker along the spiral trajectory with an equal distance of 5 units between the red star points on its circumference like in the below image. vertspacing = 10; horzspacing = 10; thetamax = 10*pi; % Calculation of (x,y) - underlying archimedean spiral. b = vertspacing/2/pi; theta = 0:0.01:thetamax; x = b*theta.*cos(theta)+50; y = b*theta.*sin(theta)+50; % Calculation of equidistant (xi,yi) points on spiral. smax = 0.5*b*thetamax.*thetamax; s = 0:horzspacing:smax; thetai = sqrt(2*s/b); xi = b*thetai.*cos(thetai); yi = b*thetai.*sin(thetai); plot(x,y,'b-'); hold on I want to get a figure that looks like the following: This is my code for the circle trajectory: % Initialization steps. format long g; format compact; fontSize = 20; r1 = 50; r2 = 35; r3= 20; xc = 50; yc = 50; % Since arclength = radius * (angle in radians), % (angle in radians) = arclength / radius = 5 / radius. deltaAngle1 = 5 / r1; deltaAngle2 = 5 / r2; deltaAngle3 = 5 / r3; theta1 = 0 : deltaAngle1 : (2 * pi); theta2 = 0 : deltaAngle2 : (2 * pi); theta3 = 0 : deltaAngle3 : (2 * pi); x1 = r1*cos(theta1) + xc; y1 = r1*sin(theta1) + yc; x2 = r2*cos(theta2) + xc; y2 = r2*sin(theta2) + yc; x3 = r3*cos(theta3) + xc; y3 = r3*sin(theta3) + yc; plot(x1,y1,'color',[1 0.5 0]) hold on plot(x2,y2,'color',[1 0.5 0]) hold on plot(x3,y3,'color',[1 0.5 0]) hold on % Connecting Line: plot([70 100], [50 50],'color',[1 0.5 0]) % Set up figure properties: % Enlarge figure to full screen. set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]); drawnow; axis square; for i = 1 : length(theta1) plot(x1(i),y1(i),'r*') pause(0.1) end for i = 1 : length(theta2) plot(x2(i),y2(i),'r*') pause(0.1) end for i = 1 : length(theta3) plot(x3(i),y3(i),'r*') pause(0.1) end
I can't think of a way to compute distance along a spiral, so I'm approximating it with circles, in hopes that it will still be useful. My solution relies on the InterX function from FEX, to find the intersection of circles with the spiral. I am providing an animation so it is easier to understand. The code (tested on R2017a): function [x,y,xi,yi] = q44916610(doPlot) %% Input handling: if nargin < 1 || isempty(doPlot) doPlot = false; end %% Initialization: origin = [50,50]; vertspacing = 10; thetamax = 5*(2*pi); %% Calculation of (x,y) - underlying archimedean spiral. b = vertspacing/(2*pi); theta = 0:0.01:thetamax; x = b*theta.*cos(theta) + origin(1); y = b*theta.*sin(theta) + origin(2); %% Calculation of equidistant (xi,yi) points on spiral. DST = 5; cRes = 360; numPts = ceil(vertspacing*thetamax); % Preallocation [xi,yi] = deal(NaN(numPts,1)); if doPlot && isHG2() % Plots are only enabled if the MATLAB version is new enough. figure(); plot(x,y,'b-'); hold on; axis equal; grid on; grid minor; hAx = gca; hAx.XLim = [-5 105]; hAx.YLim = [-5 105]; hP = plot(xi,yi,'r*'); else hP = struct('XData',xi,'YData',yi); end hP.XData(1) = origin(1); hP.YData(1) = origin(2); for ind = 2:numPts P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes)); [~,I] = max(abs(P(1,:)-origin(1)+1i*(P(2,:)-origin(2)))); if doPlot, pause(0.1); end hP.XData(ind) = P(1,I); hP.YData(ind) = P(2,I); if doPlot, pause(0.1); delete(hAx.Children(1)); end end xi = hP.XData(~isnan(hP.XData)); yi = hP.YData(~isnan(hP.YData)); %% Nested function(s): function [XY] = makeCircle(cnt, R, nPts) P = (cnt(1)+1i*cnt(2))+R*exp(linspace(0,1,nPts)*pi*2i); if doPlot, plot(P,'Color',lines(1)); end XY = [real(P); imag(P)]; end end %% Local function(s): function tf = isHG2() try tf = ~verLessThan('MATLAB', '8.4'); catch tf = false; end end function P = InterX(L1,varargin) % DOCUMENTATION REMOVED. For a full version go to: % https://www.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections narginchk(1,2); if nargin == 1 L2 = L1; hF = #lt; %...Avoid the inclusion of common points else L2 = varargin{1}; hF = #le; end %...Preliminary stuff x1 = L1(1,:)'; x2 = L2(1,:); y1 = L1(2,:)'; y2 = L2(2,:); dx1 = diff(x1); dy1 = diff(y1); dx2 = diff(x2); dy2 = diff(y2); %...Determine 'signed distances' S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1); S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1); C1 = feval(hF,D(bsxfun(#times,dx1,y2)-bsxfun(#times,dy1,x2),S1),0); C2 = feval(hF,D((bsxfun(#times,y1,dx2)-bsxfun(#times,x1,dy2))',S2'),0)'; %...Obtain the segments where an intersection is expected [i,j] = find(C1 & C2); if isempty(i), P = zeros(2,0); return; end %...Transpose and prepare for output i=i'; dx2=dx2'; dy2=dy2'; S2 = S2'; L = dy2(j).*dx1(i) - dy1(i).*dx2(j); i = i(L~=0); j=j(L~=0); L=L(L~=0); %...Avoid divisions by 0 %...Solve system of eqs to get the common points P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ... dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')'; function u = D(x,y) u = bsxfun(#minus,x(:,1:end-1),y).*bsxfun(#minus,x(:,2:end),y); end end Result: Note that in the animation above, the diameter of the circle (and hence the distance between the red points) is 10 and not 5.
Output of k3_1 is capped at -3.1445e+24
I'm solving a system of ODEs using RK4. I'm generating a straight line plot that seems to be due to the fact that k3_1 is capped at -3.1445e+24. I don't understand why it is capped. function RK4system_MNModel() parsec = 3.08*10^18; r_1 = 8.5*1000.0*parsec; % in cm z_1 = 0.0; % in cm also theta_1 = 0.0; grav = 6.6720*10^-8; amsun = 1.989*10^33; % in grams amg = 1.5d11*amsun; % in grams gm = grav*amg; % constant q = 0.9; % axial ratio u_1 = 130.0; % in cm/sec w_1 = 95*10^4.0; % in cm/sec v = 180*10^4.0; % in cm/sec vcirc = sqrt(gm/r_1); % circular speed (constant) nsteps = 50000; deltat = 5.0*10^11; % in seconds angmom = r_1*v; % these are the same angmom2 = angmom^2.0; e = -gm/r_1+u_1*u_1/2.0+angmom2/(2.0*r_1*r_1); time=0.0; for i=1:nsteps k3_1 = deltat*u_1 %%%%% THIS LINE k4_1 = deltat*(-gm*r_1/((r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5) + angmom2/(r_1^3.0)); % u'=-dphi_dr+lz^2/(r^3.0) with lz=vi*ri this gives deltau k5_1 = deltat*(angmom/(r_1^2.0)); % theta'=lz/r^2 this gives deltatheta k6_1 = deltat*w_1; k7_1 = deltat*(-gm*z_1*(1+sqrt(1+z_1^2.0))/(sqrt(1+z_1^2.0)*(r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5)); r_2 = r_1+k3_1/2.0; u_2 = u_1+k4_1/2.0; theta_2 = theta_1+k5_1/2.0; z_2 = z_1 + k6_1/2.0; w_2 = w_1 + k7_1/2.0; k3_2 = deltat*u_2; k4_2 = deltat*(-gm*r_2/((r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5)+angmom2/(r_2^3.0)); k5_2 = deltat*(angmom/(r_2^2.0)); % theta'=lz/r^2 =====> deltatheta k6_2 = deltat*w_2; k7_2 = deltat*(-gm*z_2*(1+sqrt(1+z_2^2.0))/(sqrt(1+z_2^2.0)*(r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5)); r_3 = r_1+k3_2/2.0; u_3 = u_1+k4_2/2.0; theta_3 = theta_1+k5_2/2.0; z_3 = z_1 + k6_2/2.0; w_3 = w_1 + k7_2/2.0; k3_3 = deltat*u_3; % r'=u k4_3 = deltat*(-gm*r_3/((r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5)+angmom2/(r_3^3.0));% u'=-dphi_dr+lz^2/(r^3.0) k5_3 = deltat*(angmom/(r_3^2.0)); % theta'=lz/r^2 k6_3 = deltat*w_3; k7_3 = deltat*(-gm*z_3*(1+sqrt(1+z_3^2.0))/(sqrt(1+z_3^2.0)*(r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5)); r_4 = r_1+k3_2; u_4 = u_1+k4_2; theta_4 = theta_1+k5_2; z_4 = z_1 + k6_2; w_4 = w_1 + k7_2; k3_4 = deltat*u_4; % r'=u k4_4 = deltat*(-gm*r_4/((r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5)+angmom2/(r_4^3.0)); % u'=-dphi_dr+lz^2/(r^3.0) k5_4 = deltat*(angmom/(r_4^2.0)); % theta'=lz/r^2 k6_4 = deltat*w_4; k7_4 = deltat*(-gm*z_4*(1+sqrt(1+z_4^2.0))/(sqrt(1+z_4^2.0)*(r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5)); r_1 = r_1+(k3_1+2.0*k3_2+2.0*k3_3+k3_4)/6.0; % New value of R for next step u_1 = u_1+(k4_1+2.0*k4_2+2.0*k4_3+k4_4)/6.0; % New value of U for next step theta_1 = theta_1+(k5_1+2.0*k5_2+2.0*k5_3+k5_4)/6.0; % New value of theta z_1 = z_1+(k6_1+2.0*k6_2+2.0*k6_3+k6_4)/6.0; w_1 = w_1+(k7_1+2.0*k7_2+2.0*k7_3+k7_4)/6.0; e = -gm/r_1+u_1*u_1/2.0+angmom2/(2.0*r_1*r_1); % energy ecc = (1.0+(2.0*e*angmom2)/(gm^2.0))^0.5; % eccentricity x(i) = r_1*cos(theta_1)/(1000.0*parsec); % X for plotting orbit y(i) = r_1*sin(theta_1)/(1000.0*parsec); % Y for plotting orbit time = time+deltat; r(i) = r_1; z(i) = z_1; time1(i)= time; end Note that the anomally occurs on the indicated line.
It's not k3_1 that's capped, it's the calculation of u_1 that returns a value of -3.1445e+24 / deltat (deltat is constant). u_1 is calculated in the line: u_1 = u_1+(k4_1+2.0*k4_2+2.0*k4_3+k4_4)/6.0; After the first iteration, this returns: u_1(1) = 6.500e+13 % Hard coded before the loop u_1(2) = -1.432966614767040e+04 % Calculated using the equation above u_1(3) = -2.878934017859105e+04 % Calculated using the equation above u_1(4) = -4.324903004768405e+04 Based on the equation u_1(n+1) = u_1(n) + du it looks like du represents a relatively small difference. The difference between the two first values is very large, so I'm assuming it is this calculation that's incorrect. If you find that that calculation is correct, then your error is in one of these lines: k4_1 = deltat*(-gm*r_1/((r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5)+angmom2/(r_1^3.0)); % u'=-dphi_dr+lz^2/(r^3.0) with lz=vi*ri this gives delta k4_2 = deltat*(-gm*r_2/((r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5)+angmom2/(r_2^3.0)); k4_3 = deltat*(-gm*r_3/((r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5)+angmom2/(r_3^3.0));% u'=-dphi_dr+lz^2/(r^3.0) k4_4 = deltat*(-gm*r_4/((r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5)+angmom2/(r_4^3.0)); % u'=-dphi_dr+lz^2/(r^3.0)