Matlab simulating winnowing using Euler and RK4

33 Views Asked by At

I am trying to make a winnowing simulator using matlab. Here is my code.

My Euler simulation works as expected but I am unable to figure out the error in rk4 code. Here is my full code for reference. My rk4 output doesnt show grain trajectory and chaff is in freefall. Absolute noobie with matlab so please help. I am unfamiliar with most of the concepts and trying to learn so sometimes I miss out understanding. So even pointers to where I am missing stuff would be great.

% Simulation parameters
t_start = 0;
dt = 0.01;
t_end = 10;

time = t_start:dt:t_end;

v_0 = 0;
w_0 = 0;
global u_0;
u_0 = 0.5; % Increased horizontal force
x_0 = 0.5;
y_0 = 0.5;
x_c = 0.55;
y_c = -0.5;

% Allocate arrays
y_pos = zeros(length(time));
v_vel = zeros(length(time));
x_pos = zeros(length(time));
w_vel = zeros(length(time));

% Initial conditions
y_pos(1) = y_0; 
v_vel(1) = v_0; 
x_pos(1) = x_0; 
w_vel(1) = 0;

% Constants and parameters
h_slot = 0.1; 
density_air = 1.2; 
density_particle_grain = 750;
viscosity_air = 1.8 * 10^-5;
diameter_particle_grain = 0.0025; 
density_particle_chaff = 50; 
diameter_particle_chaff = 0.00325;

gravity = -9.81; velocity_final = 0;

volume_particle_grain = ((pi/6) * diameter_particle_grain^3);
volume_particle_chaff = ((pi/6) * diameter_particle_chaff^3);

% Compute grain trajectory using Euler's method
for i = 1:numel(time)-1
    if y_pos(i) < y_c
        break; % Stop loop when y_pos(i) < y_c
    end
    
    % Equations for grain
    force_gravity_grain = density_particle_grain * volume_particle_grain * gravity;
    force_buoyancy_grain = (-density_air * volume_particle_grain * gravity);
    mass_grain = density_particle_grain * volume_particle_grain;
    fluid_velocity = 6.2 * u_0 * exp(-50 * ((y_pos(i) / x_pos(i))^2)) * sqrt(h_slot / x_pos(i));

    Reynolds_number_grain = density_air * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * diameter_particle_grain / viscosity_air;
    if Reynolds_number_grain < 800
        drag_coefficient = (24 / Reynolds_number_grain) * (1 + (0.15 * (Reynolds_number_grain)^(0.687)));
    else 
        drag_coefficient = 0.44;
    end 
    drag_force_x = (0.5 * pi * density_air * (diameter_particle_grain^2) * drag_coefficient * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * (fluid_velocity - w_vel(i)));
    drag_force_y = (0.5 * pi * density_air * (diameter_particle_grain^2) * drag_coefficient * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * (velocity_final - v_vel(i)));

    force_tangential = drag_force_x / mass_grain;
    force_vertical = (force_gravity_grain + force_buoyancy_grain + drag_force_y) / mass_grain;

    y_pos(i+1) = y_pos(i) + dt * v_vel(i);
    x_pos(i+1) = x_pos(i) + dt * w_vel(i);
    v_vel(i+1) = v_vel(i) + dt * force_vertical;
    w_vel(i+1) = w_vel(i) + dt * force_tangential;
end

xg_euler = x_pos(1:i); % Grain x positions for Euler
yg_euler = y_pos(1:i); % Grain y positions for Euler

% Compute chaff trajectory using Euler's method
y_pos = zeros(length(time));
v_vel = zeros(length(time));
x_pos = zeros(length(time));
w_vel = zeros(length(time));

y_pos(1) = y_0;
v_vel(1) = v_0; 
x_pos(1) = x_0; 
w_vel(1) = 0;

for i = 1:numel(time)-1
    if y_pos(i) < y_c
        break; % Stop loop when y_pos(i) < y_c
    end
    
    % Equations for chaff
    force_gravity_chaff = density_particle_chaff * volume_particle_chaff * gravity;
    force_buoyancy_chaff = (-density_air * volume_particle_chaff * gravity);
    mass_chaff = density_particle_chaff * volume_particle_chaff;
    fluid_velocity = 6.2 * u_0 * exp(-50 * ((y_pos(i) / x_pos(i))^2)) * sqrt(h_slot / x_pos(i));

    Reynolds_number_chaff = density_air * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * diameter_particle_chaff / viscosity_air;
    if Reynolds_number_chaff < 800
        drag_coefficient = (24 / Reynolds_number_chaff) * (1 + (0.15 * (Reynolds_number_chaff)^(0.687)));
    else 
        drag_coefficient = 0.44;
    end 
    drag_force_x = (0.5 * pi * density_air * (diameter_particle_chaff^2) * drag_coefficient * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * (fluid_velocity - w_vel(i)));
    drag_force_y = (0.5 * pi * density_air * (diameter_particle_chaff^2) * drag_coefficient * sqrt((fluid_velocity - w_vel(i))^2 + (velocity_final - v_vel(i))^2) * (velocity_final - v_vel(i)));

    force_tangential = drag_force_x / mass_chaff;
    force_vertical = (force_gravity_chaff + force_buoyancy_chaff + drag_force_y) / mass_chaff;

    y_pos(i+1) = y_pos(i) + dt * v_vel(i);
    x_pos(i+1) = x_pos(i) + dt * w_vel(i);
    v_vel(i+1) = v_vel(i) + dt * force_vertical;
    w_vel(i+1) = w_vel(i) + dt * force_tangential;
end

xch_euler = x_pos(1:i); % Chaff x positions for Euler
ych_euler = y_pos(1:i); % Chaff y positions for Euler

% Compute grain trajectory using RK4 method
[yg_rk4, xg_rk4] = rungeKutta4(@computeTrajectory, time, [y_0, v_0, x_0, w_0], y_c, density_air, u_0, h_slot, density_particle_grain, diameter_particle_grain, viscosity_air, gravity, volume_particle_grain);
% Compute chaff trajectory using RK4 method
[ych_rk4, xch_rk4] = rungeKutta4(@computeTrajectory, time, [y_0, v_0, x_0, w_0], y_c, density_air, u_0, h_slot, density_particle_chaff, diameter_particle_chaff, viscosity_air, gravity, volume_particle_chaff);

% Plotting
figure;

% Euler Method
subplot(1, 2, 1);
plot(xg_euler, yg_euler, 'r-', 'LineWidth', 1.5);
hold on;
plot(xch_euler, ych_euler, 'g--', 'LineWidth', 1.5);
scatter(x_c + 0.05, y_c, 50, 'b', 'filled'); % Separation point
plot([x_c - 0.05, x_c + 0.05], [y_c, y_c], 'k--', 'LineWidth', 1.5); % Denote Bin1 and Bin2 region with black dashed line
text(x_c - 0.075, y_c - 0.05, 'Bin1', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top');
text(x_c + 0.075, y_c - 0.05, 'Bin2', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top');
xlabel('x (m)');
ylabel('y (m)');
title('Euler Method');
legend('Grain', 'Chaff', 'Separation Point', 'Location', 'Best');
axis equal;
grid on;
hold off;

% RK4 Method
subplot(1, 2, 2);
plot(xg_rk4, yg_rk4, 'r-', 'LineWidth', 1.5);
hold on;
plot(xch_rk4, ych_rk4, 'g--', 'LineWidth', 1.5);
scatter(x_c + 0.05, y_c, 50, 'b', 'filled'); % Separation point
plot([x_c - 0.05, x_c + 0.05], [y_c, y_c], 'k--', 'LineWidth', 1.5); % Denote Bin1 and Bin2 region with black dashed line
text(x_c - 0.075, y_c - 0.05, 'Bin1', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top');
text(x_c + 0.075, y_c - 0.05, 'Bin2', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'top');
xlabel('x (m)');
ylabel('y (m)');
title('RK4 Method');
legend('Grain', 'Chaff', 'Separation Point', 'Location', 'Best');
axis equal;
grid on;
hold off;

% Function defining the particle motion equations for RK4
function dydt = computeTrajectory(t, y, yc, denf, u0, h, denp, dp, visf, g, Vp)
    % Extracting variables
    y_particle = y(1);
    v_particle = y(2);
    x_particle = y(3);
    w_particle = y(4);

    % Equations of motion
    Fg = denp * Vp * g;
    Fb = -denf * Vp * g;
    m_particle = denp * Vp;
    uf = 6.2 * u0 * exp(-50 * ((y_particle / x_particle)^2)) * sqrt(h / x_particle);

    Rep = denf * sqrt((uf - w_particle)^2 + v_particle^2) * dp / visf;
    if Rep < 800
        Cd = (24 / Rep) * (1 + (0.15 * Rep^(0.687)));
    else 
        Cd = 0.44;
    end

    Fdrag_x = (0.5 * pi * denf * dp^2 * Cd * sqrt((uf - w_particle)^2 + v_particle^2) * (uf - w_particle));
    Fdrag_y = (0.5 * pi * denf * dp^2 * Cd * sqrt((uf - w_particle)^2 + v_particle^2) * v_particle);

    F_tw = Fdrag_x / m_particle;
    F_tv = (Fg + Fb + Fdrag_y) / m_particle;

    dydt = [v_particle; F_tv; w_particle; F_tw];
end

% 4th order Runge-Kutta method for particle motion
function [y, x] = rungeKutta4(func, t, initial_conditions, yc, denf, u0, h, denp, dp, visf, g, Vp)
    dt = t(2) - t(1);
    y = zeros(length(t), 1);
    x = zeros(length(t), 1);
    
    y(1) = initial_conditions(1);
    v = initial_conditions(2);
    x(1) = initial_conditions(3);
    w = initial_conditions(4);

    for i = 1:numel(t)-1
        if y(i) < yc
            break; % Stop loop when y(i) < yc
        end

        k1 = func(t(i), [y(i), v, x(i), w], yc, denf, u0, h, denp, dp, visf, g, Vp);
        k2 = func(t(i) + dt/2, [y(i), v, x(i), w] + dt/2 * k1', yc, denf, u0, h, denp, dp, visf, g, Vp);
        k3 = func(t(i) + dt/2, [y(i), v, x(i), w] + dt/2 * k2', yc, denf, u0, h, denp, dp, visf, g, Vp);
        k4 = func(t(i) + dt, [y(i), v, x(i), w] + dt * k3', yc, denf, u0, h, denp, dp, visf, g, Vp);

        y(i+1) = y(i) + dt/6 * (k1(1) + 2*k2(1) + 2*k3(1) + k4(1));
        v = v + dt/6 * (k1(2) + 2*k2(2) + 2*k3(2) + k4(2));
        x(i+1) = x(i) + dt/6 * (k1(3) + 2*k2(3) + 2*k3(3) + k4(3));
        w = w + dt/6 * (k1(4) + 2*k2(4) + 2*k3(4) + k4(4));
    end

    y = y(1:i); % Particle y positions
    x = x(1:i); % Particle x positions
end

I have tried playing around with the code. I am only trying to learn this now suing a tutorial and this was one of the problems listed there with no solution. I am unfamiliar with most of the concepts and trying to learn so sometimes I miss out understanding. So even pointers to where I am missing stuff would be great.

0

There are 0 best solutions below