mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-06 21:03:14 +02:00
Beautifying RK4Automatic.m
This commit is contained in:
parent
cb42f561f5
commit
3ae8bd014c
@ -1,8 +1,8 @@
|
|||||||
% solve ODE system using RK4 with constant step size
|
% solve ODE system using RK4 with constant step size
|
||||||
function [x, derivativesTable] = rk4(functions, initialValues, interval, stepSize, maxSteps)
|
function [x, derivativesTable] = RK4(equations, initialValues, interval, stepSize, maxSteps)
|
||||||
x = initialValues;
|
x = initialValues;
|
||||||
|
|
||||||
derivativesTable = buildDerivatiesTable(x, functions);
|
derivativesTable = buildDerivatiesTable(x, equations);
|
||||||
|
|
||||||
% Calculate stepCount
|
% Calculate stepCount
|
||||||
stepCount = ceil((interval(2) - interval(1)) / stepSize);
|
stepCount = ceil((interval(2) - interval(1)) / stepSize);
|
||||||
@ -13,35 +13,37 @@ function [x, derivativesTable] = rk4(functions, initialValues, interval, stepSiz
|
|||||||
% then choose smaller number between maxSteps and stepCount and choose
|
% then choose smaller number between maxSteps and stepCount and choose
|
||||||
% it for stepCount
|
% it for stepCount
|
||||||
|
|
||||||
[x, derivativesTable] = rk4Loop(x, stepCount, stepSize, functions, derivativesTable);
|
[x, derivativesTable] = rk4Loop(x, stepCount, stepSize, equations, derivativesTable);
|
||||||
|
|
||||||
|
|
||||||
% append arguments to output
|
% append arguments to output
|
||||||
x = [interval(1):stepSize:(stepCount * stepSize); x];
|
x = [interval(1):stepSize:(stepCount * stepSize); x];
|
||||||
end
|
end
|
||||||
|
|
||||||
function derivativesTable = buildDerivatiesTable(x, functions)
|
function derivativesTable = buildDerivatiesTable(x, equations)
|
||||||
derivativesTable = zeros(size(x));
|
derivativesTable = zeros(size(x));
|
||||||
for eqnum = 1:size(functions, 1)
|
for eqnum = 1:size(equations, 1)
|
||||||
derivativesTable(eqnum, 1) = functions{eqnum}(x(:, 1));
|
derivativesTable(eqnum, 1) = equations{eqnum}(x(:, 1));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function [x, derivativesTable] = rk4Loop(x, stepCount, stepSize, functions, derivativesTable)
|
function [x, derivativesTable] = rk4Loop(x, stepCount, stepSize, equations, derivativesTable)
|
||||||
for step = 1 : stepCount
|
for step = 1 : stepCount
|
||||||
[x, derivativesTable] = rk4stepLoop(x, step, functions, stepSize, derivativesTable);
|
[x, derivativesTable] = rk4stepLoop(x, step, equations, stepSize, derivativesTable);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function [x, derivativesTable] = rk4stepLoop(x, step, functions, stepSize, derivativesTable)
|
function [x, derivativesTable] = rk4stepLoop(x, step, equations, stepSize, derivativesTable)
|
||||||
stepValue = x(:, step);
|
stepValue = x(:, step);
|
||||||
|
[x, derivativesTable] = equationsLoop(x, equations, stepValue, stepSize, step, derivativesTable);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function [x, derivativesTable] = equationsLoop(x, equations, stepValue, stepSize, step, derivativesTable)
|
||||||
for equationNumber = 1 : 2
|
for equationNumber = 1 : 2
|
||||||
% generic single-step iteration
|
Phi = RK4Phi(equations{equationNumber}, stepValue, stepSize);
|
||||||
phi = RK4Phi(functions{equationNumber}, stepValue, stepSize);
|
x(equationNumber, step + 1) = x(equationNumber, step) + stepSize * Phi;
|
||||||
x(equationNumber, step + 1) = x(equationNumber, step) + stepSize * phi;
|
|
||||||
|
|
||||||
% update derivatives table
|
derivativesTable(equationNumber, step + 1) = equations{equationNumber}(x(:, step + 1));
|
||||||
derivativesTable(equationNumber, step + 1) = functions{equationNumber}(x(:, step + 1));
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
92
ENUME/projectC/RK4Automatic.asv
Normal file
92
ENUME/projectC/RK4Automatic.asv
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
% automatic step size variant of RK4
|
||||||
|
function [x, sizes, errors] = RK4Automatic(equations, initialValues, interval, initialStepSize, relativeEpsilon, absoluteEpsilon)
|
||||||
|
|
||||||
|
[functionArguments, x, sizes, errors, stepSize, step, flag] = Initialize(interval, initialValues, initialStepSize);
|
||||||
|
|
||||||
|
[functionArguments, x, sizes, errors] = RK4AutomaticLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag);
|
||||||
|
% append arguments to output
|
||||||
|
x = [functionArguments; x];
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors, stepSize, step, flag] = Initialize(interval, initialValues, initialStepSize)
|
||||||
|
functionArguments = interval(1);
|
||||||
|
x = initialValues;
|
||||||
|
|
||||||
|
sizes = double.empty();
|
||||||
|
errors = double.empty();
|
||||||
|
|
||||||
|
stepSize = initialStepSize;
|
||||||
|
step = 0;
|
||||||
|
flag = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors] = RK4AutomaticLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag)
|
||||||
|
while flag
|
||||||
|
[functionArguments, x, sizes, errors, stepSize, step, interval, flag] = insideWhileLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors, stepSize, step, interval, flag] = insideWhileLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag)
|
||||||
|
[step, stepValue] = initializeSteps(step, x);
|
||||||
|
x = equationsLoop(x, equations, stepValue, stepSize, step);
|
||||||
|
[flag, functionArguments] = stopAlgorithm(functionArguments, stepSize, step, interval);
|
||||||
|
if ~flag
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
stepValue = calculateNextStep(equations, stepValue, stepSize);
|
||||||
|
[stepCorrectionFactor, errors] = calculateStepCorrection(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors);
|
||||||
|
stepSize = 0.9 * stepCorrectionFactor * stepSize;
|
||||||
|
sizes(step) = stepSize;
|
||||||
|
end
|
||||||
|
|
||||||
|
function v
|
||||||
|
|
||||||
|
function [step, stepValue] = initializeSteps(step, x)
|
||||||
|
step = step + 1;
|
||||||
|
stepValue = x(:, step);
|
||||||
|
end
|
||||||
|
|
||||||
|
function x = equationsLoop(x, equations, stepValue, stepSize, step)
|
||||||
|
for equationNumber = 1 : 2
|
||||||
|
Phi = RK4Phi(equations{equationNumber}, stepValue, stepSize);
|
||||||
|
x(equationNumber, step + 1) = x(equationNumber, step) + stepSize * Phi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [flag, functionArguments] = stopAlgorithm(functionArguments, stepSize, step, interval)
|
||||||
|
functionArguments(step + 1) = functionArguments(step) + stepSize;
|
||||||
|
if functionArguments(end) >= interval(2)
|
||||||
|
flag = 0;
|
||||||
|
else
|
||||||
|
flag = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function stepValue = calculateNextStep(equations, stepValue, stepSize)
|
||||||
|
for halfStep = 1 : 2
|
||||||
|
for equationsNumber = 1:size(equations, 1)
|
||||||
|
Phi = RK4Phi(equations{equationsNumber}, stepValue, stepSize / 2);
|
||||||
|
stepValue(equationsNumber) = stepValue(equationsNumber) + (stepSize / 2) * Phi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [stepCorrectionFactor, errors] = calculateStepCorrection(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors)
|
||||||
|
stepCorrectionFactor = Inf; % Initialize stepCorrectionFactor
|
||||||
|
[stepCorrectionFactor, errors] = calculateStepCorrectionLoop(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors, stepCorrectionFactor);
|
||||||
|
stepCorrectionFactor = stepCorrectionFactor ^ (1/5);
|
||||||
|
end
|
||||||
|
|
||||||
|
function [stepCorrectionFactor, errors] = calculateStepCorrectionLoop(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors, stepCorrectionFactor)
|
||||||
|
for equationsNumber = 1 : 2
|
||||||
|
approximationError = abs(stepValue(equationsNumber) - x(equationsNumber, step + 1)) / 15;
|
||||||
|
errors(step) = approximationError;
|
||||||
|
|
||||||
|
epsilon = abs(stepValue(equationsNumber)) * relativeEpsilon + absoluteEpsilon;
|
||||||
|
equationAlpha = epsilon / approximationError;
|
||||||
|
|
||||||
|
if equationAlpha < stepCorrectionFactor
|
||||||
|
stepCorrectionFactor = equationAlpha;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
96
ENUME/projectC/RK4Automatic.m
Normal file
96
ENUME/projectC/RK4Automatic.m
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
function [x, sizes, errors] = RK4Automatic(equations, initialValues, interval, initialStepSize, relativeEpsilon, absoluteEpsilon)
|
||||||
|
[functionArguments, x, sizes, errors, stepSize, step, flag] = Initialize(interval, initialValues, initialStepSize);
|
||||||
|
[functionArguments, x, sizes, errors] = RK4AutomaticLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag);
|
||||||
|
x = [functionArguments; x];
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors, stepSize, step, flag] = Initialize(interval, initialValues, initialStepSize)
|
||||||
|
functionArguments = interval(1);
|
||||||
|
x = initialValues;
|
||||||
|
|
||||||
|
sizes = double.empty();
|
||||||
|
errors = double.empty();
|
||||||
|
|
||||||
|
stepSize = initialStepSize;
|
||||||
|
step = 0;
|
||||||
|
flag = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors] = RK4AutomaticLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag)
|
||||||
|
while flag
|
||||||
|
[functionArguments, x, sizes, errors, stepSize, step, interval, flag] = insideWhileLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [functionArguments, x, sizes, errors, stepSize, step, interval, flag] = insideWhileLoop(functionArguments, x, sizes, errors, stepSize, step, equations, relativeEpsilon, absoluteEpsilon, interval, flag)
|
||||||
|
[step, stepValue, x, functionArguments, flag] = calculateXandFunctionArguments(step, x, equations, stepSize, functionArguments, interval);
|
||||||
|
if ~flag
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
[stepSize, errors] = calculateStepAndErrors(equations, stepValue, stepSize, x, step, relativeEpsilon, absoluteEpsilon, errors);
|
||||||
|
sizes(step) = stepSize;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function [step, stepValue, x, functionArguments, flag] = calculateXandFunctionArguments(step, x, equations, stepSize, functionArguments, interval)
|
||||||
|
[step, stepValue] = initializeSteps(step, x);
|
||||||
|
x = equationsLoop(x, equations, stepValue, stepSize, step);
|
||||||
|
[flag, functionArguments] = stopAlgorithm(functionArguments, stepSize, step, interval);
|
||||||
|
end
|
||||||
|
|
||||||
|
function [stepSize, errors] = calculateStepAndErrors(equations, stepValue, stepSize, x, step, relativeEpsilon, absoluteEpsilon, errors)
|
||||||
|
stepValue = calculateNextStep(equations, stepValue, stepSize);
|
||||||
|
[stepCorrectionFactor, errors] = calculateStepCorrection(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors);
|
||||||
|
stepSize = 0.9 * stepCorrectionFactor * stepSize;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function [step, stepValue] = initializeSteps(step, x)
|
||||||
|
step = step + 1;
|
||||||
|
stepValue = x(:, step);
|
||||||
|
end
|
||||||
|
|
||||||
|
function x = equationsLoop(x, equations, stepValue, stepSize, step)
|
||||||
|
for equationNumber = 1 : 2
|
||||||
|
Phi = RK4Phi(equations{equationNumber}, stepValue, stepSize);
|
||||||
|
x(equationNumber, step + 1) = x(equationNumber, step) + stepSize * Phi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [flag, functionArguments] = stopAlgorithm(functionArguments, stepSize, step, interval)
|
||||||
|
functionArguments(step + 1) = functionArguments(step) + stepSize;
|
||||||
|
if functionArguments(end) >= interval(2)
|
||||||
|
flag = 0;
|
||||||
|
else
|
||||||
|
flag = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function stepValue = calculateNextStep(equations, stepValue, stepSize)
|
||||||
|
for halfStep = 1 : 2
|
||||||
|
for equationsNumber = 1:size(equations, 1)
|
||||||
|
Phi = RK4Phi(equations{equationsNumber}, stepValue, stepSize / 2);
|
||||||
|
stepValue(equationsNumber) = stepValue(equationsNumber) + (stepSize / 2) * Phi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [stepCorrectionFactor, errors] = calculateStepCorrection(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors)
|
||||||
|
stepCorrectionFactor = Inf; % Initialize stepCorrectionFactor
|
||||||
|
[stepCorrectionFactor, errors] = calculateStepCorrectionLoop(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors, stepCorrectionFactor);
|
||||||
|
stepCorrectionFactor = stepCorrectionFactor ^ (1/5);
|
||||||
|
end
|
||||||
|
|
||||||
|
function [stepCorrectionFactor, errors] = calculateStepCorrectionLoop(stepValue, x, step, relativeEpsilon, absoluteEpsilon, errors, stepCorrectionFactor)
|
||||||
|
for equationsNumber = 1 : 2
|
||||||
|
approximationError = abs(stepValue(equationsNumber) - x(equationsNumber, step + 1)) / 15;
|
||||||
|
errors(step) = approximationError;
|
||||||
|
|
||||||
|
epsilon = abs(stepValue(equationsNumber)) * relativeEpsilon + absoluteEpsilon;
|
||||||
|
equationAlpha = epsilon / approximationError;
|
||||||
|
|
||||||
|
if equationAlpha < stepCorrectionFactor
|
||||||
|
stepCorrectionFactor = equationAlpha;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,7 +1,3 @@
|
|||||||
% ENUME MICHAŁ SZOPIŃSKI
|
|
||||||
% PROJECT C NUMBER 60
|
|
||||||
% https://github.com/Lachcim/szopinski-enume
|
|
||||||
|
|
||||||
% coordinate arguments
|
% coordinate arguments
|
||||||
argsx = -1:0.1:1;
|
argsx = -1:0.1:1;
|
||||||
argsy = -2:0.5:12;
|
argsy = -2:0.5:12;
|
||||||
|
|||||||
0
ENUME/projectC/equationsLoop.m
Normal file
0
ENUME/projectC/equationsLoop.m
Normal file
@ -1,5 +1,5 @@
|
|||||||
% solve ODE system using RK4 with constant step size
|
% solve ODE system using RK4 with constant step size
|
||||||
function [x, derivativesTable] = rk4(equations, initialValues, interval, stepSize, maxSteps)
|
function [x, derivativesTable] = RK4(equations, initialValues, interval, stepSize, maxSteps)
|
||||||
x = initialValues;
|
x = initialValues;
|
||||||
|
|
||||||
derivativesTable = buildDerivatiesTable(x, equations);
|
derivativesTable = buildDerivatiesTable(x, equations);
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
% automatic step size variant of RK4
|
% automatic step size variant of RK4
|
||||||
function [x, sizes, errors] = rk4auto(functs, init, interval, initstep, eps_rel, eps_abs)
|
function [x, sizes, errors] = RK4Automatic(equations, initialValues, interval, initialStepSize, relativeEpsilon, absoluteEpsilon)
|
||||||
% set start points of output
|
% set start points of output
|
||||||
args = interval(1);
|
args = interval(1);
|
||||||
x = init;
|
x = initialValues;
|
||||||
|
|
||||||
% initialize output plots
|
% initialize output plots
|
||||||
sizes = double.empty();
|
sizes = double.empty();
|
||||||
errors = double.empty();
|
errors = double.empty();
|
||||||
|
|
||||||
% integrate function until end of interval reached
|
% integrate function until end of interval reached
|
||||||
stepsize = initstep;
|
stepsize = initialStepSize;
|
||||||
step = 0;
|
step = 0;
|
||||||
while 1
|
while 1
|
||||||
% obtain the preceding function values
|
% obtain the preceding function values
|
||||||
@ -17,9 +17,9 @@ function [x, sizes, errors] = rk4auto(functs, init, interval, initstep, eps_rel,
|
|||||||
stepval = x(:, step);
|
stepval = x(:, step);
|
||||||
|
|
||||||
% advance output function
|
% advance output function
|
||||||
for eqnum = 1:size(functs, 1)
|
for eqnum = 1:size(equations, 1)
|
||||||
% generic single-step iteration
|
% generic single-step iteration
|
||||||
phi = RK4Phi(functs{eqnum}, stepval, stepsize);
|
phi = RK4Phi(equations{eqnum}, stepval, stepsize);
|
||||||
x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi;
|
x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -29,21 +29,21 @@ function [x, sizes, errors] = rk4auto(functs, init, interval, initstep, eps_rel,
|
|||||||
|
|
||||||
% also calculate next step using two half-steps
|
% also calculate next step using two half-steps
|
||||||
for substep = 1:2
|
for substep = 1:2
|
||||||
for eqnum = 1:size(functs, 1)
|
for eqnum = 1:size(equations, 1)
|
||||||
phi = RK4Phi(functs{eqnum}, stepval, stepsize / 2);
|
phi = RK4Phi(equations{eqnum}, stepval, stepsize / 2);
|
||||||
stepval(eqnum) = stepval(eqnum) + (stepsize / 2) * phi;
|
stepval(eqnum) = stepval(eqnum) + (stepsize / 2) * phi;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
% calculate step correction factor
|
% calculate step correction factor
|
||||||
alpha = Inf;
|
alpha = Inf;
|
||||||
for eqnum = 1:size(functs, 1)
|
for eqnum = 1:size(equations, 1)
|
||||||
% calculate approximation error
|
% calculate approximation error
|
||||||
delta = abs(stepval(eqnum) - x(eqnum, step + 1)) / 15;
|
delta = abs(stepval(eqnum) - x(eqnum, step + 1)) / 15;
|
||||||
errors(step) = delta;
|
errors(step) = delta;
|
||||||
|
|
||||||
% calculate equation-specific alpha
|
% calculate equation-specific alpha
|
||||||
epsilon = abs(stepval(eqnum)) * eps_rel + eps_abs;
|
epsilon = abs(stepval(eqnum)) * relativeEpsilon + absoluteEpsilon;
|
||||||
eqalpha = epsilon / delta;
|
eqalpha = epsilon / delta;
|
||||||
|
|
||||||
% minimum alpha wins
|
% minimum alpha wins
|
||||||
|
|||||||
@ -8,7 +8,7 @@ interval = [0; 15];
|
|||||||
|
|
||||||
% define available algorithms
|
% define available algorithms
|
||||||
algorithms = {
|
algorithms = {
|
||||||
'RK4', @rk4, [0.01, 0.013408];
|
'RK4', @RK4, [0.01, 0.013408];
|
||||||
'Adams PC', @adamspc, [0.002, 0.01305]
|
'Adams PC', @adamspc, [0.002, 0.01305]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ for alg = 1 : 2
|
|||||||
end
|
end
|
||||||
|
|
||||||
% solve ODE using RK4 with automatic step size
|
% solve ODE using RK4 with automatic step size
|
||||||
[result, sizes, errors] = rk4auto(sysfuncts, initvalues, interval, ...
|
[result, sizes, errors] = RK4Automatic(sysfuncts, initvalues, interval, ...
|
||||||
1e-5, 10e-10, 10e-10);
|
1e-5, 10e-10, 10e-10);
|
||||||
|
|
||||||
% plot trajectory
|
% plot trajectory
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user