We are trying to plot the orbit of the moon around the earth, which in turn is orbiting the sun. We are employing the Euler-Cromer method. This code works for a simulation of the planets. And it should work given the right initial conditions, for a more complicated set up such as what we are trying now with three bodies. Our code is this:
function [xe, ye, xm, ym] = earth_moon(me, mm)
% Constants
ms = 2e30;
ntsteps = 12;
dt = 0.001;
% Variables: Earth
xe = 1 : dt : ntsteps;
xe(1) = 1; % Initial x pos (AU)
ye = 1 : dt : ntsteps;
ye(1) = 0; % Initial y pos (AU)
vex = 0;
vey = 6.27; % AU/yr
% Variables: Moon
xm = 1 : dt : ntsteps;
xm(1) = 1.0027; % Initial x pos (AU)
ym = 1 : dt : ntsteps;
ym(1) = 0; % Initial y pos (AU)
vmx = 0;
vmy = 0.215 + vey; % AU/yr
% Calculations
for i = 1 : ntsteps / dt
rm = sqrt(xm(i)^2 + ym(i)^2);
re = sqrt(xe(i)^2 + ye(i)^2);
rme = sqrt((xm(i) - xe(i))^2 + (ym(i) - ye(i))^2);
vex = vex - 4 * pi^2 * xe(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (xe(i) - xm(i))/rme^3 * dt;
vey = vey - 4 * pi^2 * ye(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (ye(i) - xm(i))/rme^3 * dt;
vmx = vmx - 4 * pi^2 * xm(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (xm(i) - xe(i))/rme^3 * dt;
vmy = vmy - 4 * pi^2 * ym(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (ym(i) - ye(i))/rme^3 * dt;
xm(i + 1) = xm(i) + vmx * dt;
ym(i + 1) = ym(i) + vmy * dt;
xe(i + 1) = xe(i) + vex * dt;
ye(i + 1) = ye(i) + vey * dt;
end
end
And the script is as follows:
clear
clc
me = 5.97237e24;
mm = 7.3477e22;
[xe, ye, xm, ym] = earth_moon(me, mm);
hold on;
plot(xm, ym, 'r');
plot(xe, ye, 'b');
plot(0, 0, 'r.', 'Markersize', 50);
plot(0, 0, 'y.', 'Markersize', 40);
grid on;
axis square;
xlabel('X position (AU)');
ylabel('Y position (AU)');
ylim([-2, 2])
xlim([-2, 2])
title('Three-body orbit: Sun, Earth, Moon');
text(2, 5.5, strcat('Earth: ', num2str(me), ' kg'));
text(3.5, 4.5, strcat('Moon: ', num2str(mm), ' kg'));
legend('Moon', 'Earth', 'Location', 'eastoutside');
But we just cant get the moon to cooperate. Any suggestions?
Thanks!
Related
I have the next code: BD_MACRO, but when rum, I obtain this answer in command window in matlab
BD_MACROPA
Subscript indices must either be real positive integers or
logicals.
Error in BD_MACROPA (line 27)
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) -
alphaH * Z(i-1);
[![% MODELO BASICO
dt=0.01; % pasos en el tiempo
tiempo=2000; % anos de evolucion
%CONDICIONES INICIALES
H(1)=100; h(1)=250; Z(1)=200; t(1)=0;
%PARAMETROS
%ADULTOS Y PREADULTOS
aH = 147.9;
ah = 34.25;
bh = 0.20;
bH = 0.20;
phi= 0.25;
ro = 34.24;
muZ = 0.15;
H0 = 10.0;
alphaH = 0.000001;
alphah = 0.000001;
lambda = 6.0;
betaH = 0.095;
betah = 0.095;
rand('state',sum(100*clock)); % semilla de generador de numeros aleatorios,
%
numreps=5000; % numero de realizaciones
for j=1:numreps
for i=2:tiempo
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
dh = betah((ah - bh) * h(i-1) + ro * H(i-1)) - alphah * Z(i-1);
dZ = Z(i-1) * (lambda * H(i-1)./(H0 + H(i-1)) + (r - mu + (bH + bh)) - alpha * (H(i-1) + Z(i-1))./H(i-1));
H(i) = H(i-1) + dt * dH;
h(i) = h(i-1) + dt * dh;
Z(i) = Z(i-1) + dt * dZ;
t(i) = t(i-1) + dt;
end
end
% Create figure
figure1 = figure;
% Create axes
axes1 = axes('Parent',figure1);
hold(axes1,'on');
% Create multiple lines using matrix input to plot
plot1 = plot(t,H,t,P,t,Z,'LineWidth',2);
set(plot1(1),'DisplayName','H');
set(plot1(2),'DisplayName','P','LineStyle','--');
set(plot1(3),'DisplayName','Z','LineStyle','.-');
%plot(t,H,t,P)
% Create xlabel
xlabel('Tiempo');
% Create ylabel
ylabel('Tamaño de la Población');
box(axes1,'on');
grid(axes1,'on');
% Set the remaining axes properties
set(axes1,'FontSize',12);
% Create legend
legend1 = legend(axes1,'show');
set(legend1,'FontSize',20);
legend('Hospederos Adultos', 'Hospederos Preadultos','Zoosporas');][1]][1]
You are probably missing a * sign in the statement
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
Right now, this is trying to access 14833-th element of dH whereas you define dH as a scalar. I think what you want is
dH = betaH*((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
Same issue with dH. You also have undeclared variables alpha, mu and r in the statement
dZ = Z(i-1) * (lambda * H(i-1)./(H0 + H(i-1)) + (r - mu + (bH + bh)) - alpha * (H(i-1) + Z(i-1))./H(i-1));
Consider the following code.
Wx = zeros(N, N);
for ii = 1 : 1 : N
x_ref = X(ii); y_ref = Y(ii);
nghlst_Local = nghlst(ii, find(nghlst(ii, :))); Nl = length(nghlst_Local);
x_Local = X(nghlst_Local, 1); y_Local = Y(nghlst_Local, 1);
PhiU = ones(Nl+1, Nl+1); PhiU(end, end) = 0;
Phi = ones(Nl+1, Nl+1); Phi(end, end) = 0;
Bx = zeros(Nl+1,1);
for jj = 1 : 1 : Nl
for kk = 1 : 1 : Nl
rx = x_Local(jj,1) - x_Local(kk,1);
ry = y_Local(jj,1) - y_Local(kk,1);
PhiU(jj, kk) = (1 - U(1,1))) / sqrt(rx^2 + ry^2 + c^2);
end
rx = x_ref - x_Local(jj);
ry = y_ref - y_Local(jj);
Bx(jj, 1) = ( (Beta * pi * U(1,1)/(2*r_0*norm(U))) * cos( (pi/2) * (-rx * U(1,1) - ry * U(2,1)) / (r_0 * norm(U)) ) ) / sqrt(rx^2 + ry^2 + c^2) - rx * (1 - Beta * sin( (pi/2) * (-rx * U(1,1) - ry * U(2,1)) / (r_0 * norm(U)) ))/ (rx^2 + ry^2 + c^2)^(3/2);
end
invPhiU = inv(PhiU);
CX = Bx' * invPhiU; CX = CX (1, 1:end-1); Wx (ii, nghlst_Local) = CX;
end
I want to convert the first for loop into parfor loop. The rest of the code works fine, but the following assignment statement does not work when I change for to parfor.
Wx (ii, nghlst_Local) = CX;
I want to know what is this is wrong and how to remove such errors. Thank you.
i'm trying to solve a boundary value problem of an system q' = f(q(t), a(t)) with an input a using bvp4c in Matlab. Where q = [q1, q2, q1_dot, q2_dot]'
My Matlab Code does not work properly. Does anyone know how to solve this?
img: System Equation of the One Pendulum
a is a input function.
the initial state: q1(0) = pi, q2(0) = 0, q1_dot(0) = 0, q2_dot(0) = 0.
the end state: q1(te) = 0, q2(te) = 0, q1_dot(te) = 0, q2_dot(te) = 0.
input initial state: a(0) = 0, and the end state: a(te) = 0.
i've in total 10 boundaries. one_pendulum_bc can take only 5 and not more and fewer.
function one_pendulum
options = []; % place holder
solinit = bvpinit(linspace(0,1,1000),[pi, 0, 0, 0],0);
sol = bvp4c(#one_pendulum_ode,#one_pendulum_bc,solinit,options);
t = sol.x;
plot(t, sol.y(1,:))
figure(2)
plot(t, sol.y(2,:))
figure(3)
plot(t, sol.y(3,:))
figure(4)
plot(t, sol.y(4,:))
% --------------------------------------------------------------------------
function dydx = one_pendulum_ode(x,y,a)
% Parameter of the One-Pendulum
m1 = 0.3583; % weight of the pendulum [kg]
J1 = 0.03799; % moment of inertia [Nms^2]
a1 = 0.43; % center of gravity [m]
d1 = 0.006588; % coefficient of friction [Nms]
g = 9.81; % gravity [m/s^2]
dydx = [ y(3)
y(4)
(a*a1*m1*cos(y(1)) + a1*g*m1*sin(y(1)) - d1*y(3))/(J1 + a1^2 *m1)
a ];
% --------------------------------------------------------------------------
function res = one_pendulum_bc(ya,yb,a)
res = [ya(1) - pi
ya(2)
ya(4)
yb(1)
yb(3)];
img: The result should look like this
i just solved it with a model function.
function one_pendulum
options = bvpset('stats', 'on', 'NMax', 3000);
T = 2.5;
sol0 = [
-5.3649
119.5379
-187.3080
91.6670];
solinit = bvpinit(linspace(0, T, T/0.002),[pi, 0, 0, 0], sol0);
sol = bvp4c(#one_pendulum_ode,#one_pendulum_bc,solinit,options, T);
t = sol.x;
ax1 = subplot(2,2,1);
ax2 = subplot(2,2,2);
ax3 = subplot(2,2,3);
ax4 = subplot(2,2,4);
plot(ax1, t, sol.y(1,:))
title(ax1, 'phi');
plot(ax2, t, sol.y(2,:))
title(ax2, 'x');
plot(ax3, t, sol.y(3,:))
title(ax3, 'phi_d');
plot(ax4, t, sol.y(4,:))
title(ax4, 'x_d');
length = size(t)
k = sol.parameters
for i=1:length(2)
k5 = -(k(1) * sin(pi) + k(2) * sin(2*pi) + k(3) * sin(3*pi) + k(4) * sin(4*pi))/sin(5*pi);
x = t(i);
acc(i)=k(1) * sin(pi*x/T) + k(2) * sin(2*pi*x/T) + k(3) * sin(3*pi*x/T) + k(4) * sin(4*pi*x/T) + k5* sin(5*pi*x/T);
end
figure(2)
plot(t,acc)
% --------------------------------------------------------------------------
function dydx = one_pendulum_ode(x,y,k,T)
% Parameter of the One-Pendulum
m1 = 0.3583; % weight of the pendulum [kg]
J1 = 0.03799; % moment of inertia [Nms^2]
a1 = 0.43; % center of gravity [m]
d1 = 0.006588; % coefficient of friction [Nms]
g = 9.81; % gravity [m/s^2]
% Ansatzfunktion
k5 = -(k(1) * sin(pi) + k(2) * sin(2*pi) + k(3) * sin(3*pi) + k(4) * sin(4*pi))/sin(5*pi);
a = k(1) * sin(pi*x/T) + k(2) * sin(2*pi*x/T) + k(3) * sin(3*pi*x/T) + k(4) * sin(4*pi*x/T) + k5* sin(5*pi*x/T);
dydx = [ y(3)
y(4)
(a*a1*m1*cos(y(1)) + a1*g*m1*sin(y(1)) - d1*y(3))/(J1 + a1^2 *m1)
a ];
% --------------------------------------------------------------------------
function res = one_pendulum_bc(ya,yb,k,T)
res = [ya(1) - pi
ya(2)
ya(3)
ya(4)
yb(1)
yb(2)
yb(3)
yb(4)];
I have seen that there was an interest in custom interpolation kernels for resize (MATLAB imresize with a custom interpolation kernel). Did anyone implemented the parametric Mitchell-Netravali kernel [1] that is used as default in ImageMagick and is willing to share the Matlab code? Thank you very much!
[1] http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch24.html
// Mitchell Netravali Reconstruction Filter
// B = 0 C = 0 - Hermite B-Spline interpolator
// B = 1, C = 0 - cubic B-spline
// B = 0, C = 1/2 - Catmull-Rom spline
// B = 1/3, C = 1/3 - recommended
float MitchellNetravali(float x, float B, float C)
{
float ax = fabs(x);
if (ax < 1) {
return ((12 - 9 * B - 6 * C) * ax * ax * ax +
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
} else if ((ax >= 1) && (ax < 2)) {
return ((-B - 6 * C) * ax * ax * ax +
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
ax + (8 * B + 24 * C)) / 6;
} else {
return 0;
}
}
Here I got another approach with vectorization; according to my tests with upscaling (1000x1000 -> 3000x3000) this is faster than the standard bicubic even with a large Mitchell radius = 6:
function [outputs] = Mitchell_vect(x,M_B,M_C)
outputs= zeros(size(x,1),size(x,2));
ax = abs(x);
temp = ((12-9*M_B-6*M_C) .* ax.^3 + (-18+12*M_B+6*M_C) .* ax.^2 + (6-2*M_B))./6;
temp2 = ((-M_B-6*M_C) .* ax.^3 + (6*M_B+30*M_C) .* ax.^2 + (-12*M_B-48*M_C) .* ax + (8*M_B + 24*M_C))./6;
index = find(ax<1);
outputs(index)=temp(index);
index = find(ax>=1 & ax<2);
outputs(index)=temp2(index);
end
I got the following proposal for the Mitchel kernel called by imresize with the parameters B and C and a kernel radius using for-loops (and preallocation):
img_resize = imresize(img, [h w], {#(x)Mitchell(x,B,C),radius});
function [outputs] = Mitchell(x,B,C)
outputs= zeros(size(x,1),size(x,2));
for i = 1 : size(x,1)
for j = 1 : size(x,2)
ax = abs(x(i,j));
if ax < 1
outputs(i,j) = ((12-9*B-6*C) * ax^3 + (-18+12*B+6*C) * ax^2 + (6-2*B))/6;
elseif (ax >= 1) && (ax < 2)
outputs(i,j) = ((-B-6*C) * ax^3 + (6*B+30*C) * ax^2 + (-12*B-48*C) * ax + (8*B + 24*C))/6;
else
outputs(i,j) = 0;
end
end
end
end
Based on this question, I can confirm that horizontal patterns can be imposed onto a matrix (which in this case is an image), by multiplying it with a modulation signal created with this:
vModulationSignal = 1 + (0.5 * cos(2 * pi * (signalFreq / numRows) * [0:(numRows - 1)].'));
It would also be great if someone could explain to why the above modulation signal works.
Now I want to create diagonal patterns such as :
And criss-cross (checkered) patterns such as this:
using a similar vModulationSignal
Code Excerpt where the modulation signal is created
numRows = size(mInputImage, 1);
numCols = size(mInputImage, 2);
signalFreq = floor(numRows / 1.25);
vModulationSignal = 1 + (0.5 * cos(2 * pi * (signalFreq / numRows) * [0:(numRows - 1)].'));
mOutputImage = bsxfun(#times, mInputImage, vModulationSignal);
Code Excerpt where I'm trying to create the criss cross signal
numRows = size(mInputImage, 1);
numCols = size(mInputImage, 2);
signalFreq1 = floor(numRows / 1.25);
signalFreq2 = floor(numCols / 1.25);
vModulationSignal1 = 1 + (0.5 * cos(2 * pi * (signalFreq / numRows) * [0:(numRows - 1)].'));
vModulationSignal2 = 1 + (0.5 * cos(2 * pi * (signalFreq / numRows) * [0:(numRows - 1)].'));
mOutputImage = bsxfun(#times, mInputImage, vModulationSignal);
figure();
imshow(mOutputImage);
For horizontal, vertical, diagonal stripes:
fx = 1 / 20; % 1 / period in x direction
fy = 1 / 20; % 1 / period in y direction
Nx = 200; % image dimension in x direction
Ny = 200; % image dimension in y direction
[xi, yi] = ndgrid(1 : Nx, 1 : Ny);
mask = sin(2 * pi * (fx * xi + fy * yi)) > 0; % for binary mask
mask = (sin(2 * pi * (fx * xi + fy * yi)) + 1) / 2; % for gradual [0,1] mask
imagesc(mask); % only if you want to see it
just choose fx and fy accordingly (set fy=0 for horizontal stripes, fx=0 for vertical stripes and fx,fy equal for diagonal stripes). Btw. the period of the stripes (in pixels) is exactly
period_in_pixel = 1 / sqrt(fx^2 + fy^2);
For checkerboard patterns:
f = 1 / 20; % 1 / period
Nx = 200;
Ny = 200;
[xi, yi] = ndgrid(1 : Nx, 1 : Ny);
mask = sin(2 * pi * f * xi) .* sin(2 * pi * f * yi) > 0; % for binary mask
mask = (sin(2 * pi * f * xi) .* sin(2 * pi * f * yi) + 1) / 2; % for more gradual mask
imagesc(mask);
Here the number of black and white squares per x, y direction is:
number_squares_x = 2 * f * Nx
number_squares_y = 2 * f * Ny
And if you know the size of your image and the number of squares that you want, you can use this to calculate the parameter f.
Multiplying the mask with the image:
Now that is easy. The mask is a logical (white = true, black = false). Now you only have to decide which part you want to keep (the white or the black part).
Multiply your image with the mask
masked_image = original_image .* mask;
to keep the white areas in the mask and
masked_image = original_image .* ~mask;
for the opposite.
This is actually an extension of Trilarion's answer that gives better control on stripes appearance:
function out = diagStripes( outSize, stripeAngle, stripeDistance, stripeThickness )
stripeAngle = wrapTo2Pi(-stripeAngle+pi/2);
if (stripeAngle == pi/2) || (stripeAngle == 3*pi/2)
f = #(fx, fy, xi, yi) cos(2 * pi * (fy * yi)); % vertical stripes
elseif (stripeAngle == 0)||(stripeAngle == pi)
f = #(fx, fy, xi, yi) cos(2 * pi * (fx * xi)); % horizontal stripes
else
f = #(fx, fy, xi, yi) cos(2 * pi * (fx * xi + fy * yi)); % diagonal stripes
end
if numel(outSize) == 1
outSize = [outSize outSize];
end;
fx = cos(stripeAngle) / stripeDistance; % period in x direction
fy = sin(stripeAngle) / stripeDistance; % period in y direction
Nx = outSize(2); % image dimension in x direction
Ny = outSize(1); % image dimension in y direction
[yi, xi] = ndgrid((1 : Ny)-Ny/2, (1 : Nx)-Nx/2);
mask = (f(fx, fy, xi, yi)+1)/2; % for gradual [0,1] mask
out = mask < (cos(pi*stripeThickness)+1)/2; % for binary mask
end
outSize is a two or one element vector that gives the dimensions of output image in pixels, stripeAngle gives the slope of stripes in radians, stripeDistance is the distance between centers of stripes in pixels and stripeDistance is a float value in [0 .. 1] that gives the percent of coverage of (black) stripes in (white) background.
There're also answers to the other question for generating customized checkerboard patterns.