% set the seed for the random number generator
X_init_all = rand(10, 2) * 600; % generate 10 random initial conditions
results = RK4_generic(@derivs_ts, X_init_all(i, :), t_total, dt);
plot(results(:, 1), results(:, 2), 'k', 'DisplayName', 'X' , 'Color', [0, 0, 0]);
plot(results(:, 1), results(:, 3), 'r', 'DisplayName', 'Y' , 'Color', [1, 0, 0]);
legend('X', 'Y', 'Location', 'northeast', 'FontSize', 8);
figure('Units', 'inches', 'Position', [0, 0, 5, 5]); % Adjust the figure size to maintain a 1:1 aspect ratio
results = RK4_generic(@derivs_ts, X_init_all(i, :), t_total, dt);
plot(results(:, 2), results(:, 3), 'k'); % Plot X vs Y with black color
X_all = 0:20:600; % all X grids
Y_all = 0:20:650; % all Y grids
[X_all, Y_all] = meshgrid(X_all, Y_all); % all combinations of X and Y
XY_all = [X_all(:), Y_all(:)]; % reshape the array into a 2D array with 2 columns
% Function to generate vector field
generate_vector_field = @(Xs) [Xs(1), Xs(2), derivs_ts(0, Xs')];
% Apply the function along the specified axis
results = zeros(size(XY_all, 1), 4);
for i = 1:size(XY_all, 1)
results(i, :) = generate_vector_field(XY_all(i, :));
figure('Units', 'inches', 'Position', [0, 0, 5, 5]);
quiver(results(:, 1), results(:, 2), results(:, 3), results(:, 4), 0, 'Color', 'black', 'LineWidth', 1.2);
% Apply the function along the specified axis
results_unit = zeros(size(XY_all, 1), 4);
for i = 1:size(XY_all, 1)
results_unit(i, :) = generate_normalized_vector_field(@derivs_ts, ...
figure('Units', 'inches', 'Position', [0, 0, 5, 5]);
quiver(results_unit(:, 1), results_unit(:, 2), ...
results_unit(:, 3), results_unit(:, 4), ...
0, 'Color', 'black', 'LineWidth', 1.2);
X_all = 0:1:600; % all X grids
Y_all = 0:1:650; % all Y grids
% Define nullcline functions
nullcline1 = @(Y) [(5 + 50 * hill_inh(Y, 100, 4))/ 0.1; Y].';
nullcline2 = @(X) [X; (4 + 40 * hill_inh(X, 150, 4)) / 0.12].';
null1 = nullcline1(Y_all);
null2 = nullcline2(X_all);
figure('Units', 'inches', 'Position', [0, 0, 5, 5]);
quiver(results_unit(:, 1), results_unit(:, 2), ...
results_unit(:, 3), results_unit(:, 4), ...
0, 'Color', 'black', 'LineWidth', 1.2);
plot(null1(:, 1), null1(:, 2), 'r', 'LineWidth', 2, 'DisplayName', 'dX/dt=0');
plot(null2(:, 1), null2(:, 2), 'b', 'LineWidth', 2, 'DisplayName', 'dY/dt=0');
legend('Location', 'northeast');
% all combinations of X and Y
[X_all, Y_all] = meshgrid(X_all, Y_all);
XY_all = [X_all(:), Y_all(:)];
% Apply the function along the specified axis
results = zeros(size(XY_all, 1), 4);
for i = 1:size(XY_all, 1)
results(i, :) = generate_vector_field(XY_all(i, :));
% Note the transposition to match the shape of meshgrid
z_X = reshape(results(:, 3), nY, nX);
z_Y = reshape(results(:, 4), nY, nX);
figure('Units', 'inches', 'Position', [0, 0, 5, 5]);
quiver(results_unit(:, 1), results_unit(:, 2), ...
results_unit(:, 3), results_unit(:, 4), ...
0, 'Color', 'black', 'LineWidth', 1.2);
% Plot contour for z_X (x-nullcline)
contour_plot_X = contour(X_all, Y_all, z_X, 'LevelList', [0], ...
'LineColor', 'red', 'LineWidth', 2, 'DisplayName', 'dX/dt=0');
% Plot contour for z_Y (y-nullcline)
contour_plot_Y = contour(X_all, Y_all, z_Y, 'LevelList', [0], ...
'LineColor', 'blue', 'LineWidth', 2, 'DisplayName', 'dY/dt=0');
legend('Location', 'northeast');
function results = RK4_generic(derivs, X0, t_total, dt, varargin)
% 4th order Runge-Kutta (RK4) for a generic multi-variable system
% derivs: the function of the derivatives
% X0: initial condition, a list of multiple variables
% t_total: total simulation time, assuming t starts from 0 at the beginning
X_all = zeros(n_all, nx);
k1 = dt * derivs(t_0, X_all(i, :), varargin{:});
k2 = dt * derivs(t_0_5, X_all(i, :) + k1 / 2, varargin{:});
k3 = dt * derivs(t_0_5, X_all(i, :) + k2 / 2, varargin{:});
k4 = dt * derivs(t_1, X_all(i, :) + k3, varargin{:});
X_all(i + 1, :) = X_all(i, :) + (k1 + 2 * k2 + 2 * k3 + k4) / 6;
results = [t_all', X_all];