4th order Runge Kutta method for differential equations using a tolerance
Show older comments
I am trying to plot three separate graphs: mass vs density, radius vs density, and mass vs radius. I have given the following differential equations
1. Equation of State
2. 
3. 
4. 

5. 
For the equation of state, du/dR and dt/dR need to be simultaneously integrated using the intial conditions u = 0, t = t0 = 0.5, and R = 0. I need to use a 4th order Runge-Kutta method to calculate u and t as R increases. The integration needs to stop when n or dP/dt goes negative. This will give the maximum t0 value and the values of u and R correspond to the mass and radius for that value of t0.
dP/dt = dP/dn * dn/dt
In order to integrate dt/dR, dP/dt needs to be calculated. in order to calculate dP/dt, dn/dt, dP/dt and dE/dt need to be calculated.
Please see the attached code.
c = 3*10^10; % speed of light [cm/s]
h0 = 6.6261*10^-21; % Planck's constant [cm^2 g s^-1]
m_n = 1.675*10^-24; % Mass of neutron [g]
h_bar = h0/(2*pi*m_n); % Reduced Planck's constant
e_d = 6.48*10^36; % energy density [erg/cm^-3]
Msun = 1.9891*10^33; % mass of Sun in [g]
Mx = 2.9*Msun; %new unit of mass in solar masses
rx = 13.69*10^5; % new unit of length in [cm]
G = 6.674*10^-8;
% KK93 fitting functions for E(n)
% EOS 1. AV14+UVII
% syms n t R
% E_AV14 = (2.6511 + 76.744*n - 183.611*n^2 + 459.906*n^3 - 122.832*n^4)/624151; % [erg]
% dE_dn = int(E_AV14,n)
% % Pressure as a function of n
% P_n = (n^2*(dE_dn))
% n1 = (sin(h0^3*(t/4)))/(3*pi^2*(h_bar/m_n*c)^3)/(1*10^13) % [cm]
% dn_dt = int(n1,t)
% dp_dn = int(P_n,n)
% dP_dt = dp_dn*dn_dt
% R = 0;
% u = 0
% t = 0.5;
% du_dR = 4*pi*e_d*R^2
% dt_dR = -4*pi*r*((dP_dt)^-1)*((P_n+e_d)/(1-2*u/R))*((P_n+u)/(4*pi*R^2))
% 4th Order Runga Kutta Method to calculate u and t and R increases
h = 0.5; % set the step size
t = 0.5:0.5:100; % set the interval of x
u = zeros(1,length(t));
r = zeros(1,length(t));
t_o = 0.5; % set the intial value for y
n = length(t)-1;
f =@(r,t)(du_dR); %insert function to be solved
f2 =@(r,t,u)(dt_dR);
for i = 1:n
k1_1 = h*f(r(i),t(i));
k2_1 = h*f(r(i)+.5*h,t(i)+.5*k1_1*h);
k3_1 = h*f(r(i)+.5*h,t(i)+.5*k2_1*h);
k4_1 = h*f(r(i)+h,t(i)+k3_1*h);
u(i+1) = u(i)+((k1_1+2*k2_1+2*k3_1+k4_1)/6)*h
k1_2 = h*f2(r(i),u(i),t(i));
k2_2 = h*f2(r(i)+.5*h,u(i) +0.5*K1_1,t(i)+.5*k1_2*h);
k3_2 = h*f2(r(i)+.5*h,u(i) + 0.5*K2_1,t(i)+.5*k2_2*h);
k4_2 = h*f2(r(i)+h,u(i) + K3_1,t(i)+k3_2*h);
t(i+1) = u(i)+((k1_2+2*k2_2+2*k3_2+k4_2)/6)*h
tol = dP_dt;
if tol < 0
break
end
tol2 = n;
if n < 0
break
end
end
syms n t
E_AV14 = (2.6511 + 76.744*n - 183.611*n^2 + 459.906*n^3 - 122.832*n^4)/624151; % [erg]
dE_dn = int(E_AV14,n);
% Pressure as a function of n
P_n = (n^2*(dE_dn));
syms n t
n1 = (sin(h0^3*(t/4)))/(3*pi^2*(h_bar/m_n*c)^3)/(1*10^13); % [cm]
dn_dt = int(n1,t);
dp_dn = int(P_n,n);
dp_dt = dp_dn*dn_dt;
du_dR = 4*pi*e_d*R^2;
dt_dR = -4*pi*r*((dP_dt)^-1)*((P_n+e_d)/(1-2*u/R))*((P_n+u)/(4*pi*R^2));
16 Comments
Torsten
on 24 Apr 2022
And what is your question ?
Caroline Kenemer
on 24 Apr 2022
Torsten
on 24 Apr 2022
What is the independent variable of all your functions ? Is it "t" ?
Caroline Kenemer
on 24 Apr 2022
Then the first thing to do is to write all differential equations with respect to t:
dP/dt = dP/dn * dn/dt = (2n*dE/dn + n^2*d^2E/dn^2)*dn/dt = ...
du/dt = du/dR * dR/dt = 4*pi*eps*R^2*dR/dt
dR/dt = 1/(-4*pi*R*(dP/dt)^(-1)*(P+eps)/(1-2*u/R)*(P+u/(4*pi*R^2)))
Remains to calculate dn/dt, dE/dt, and d^2E/dn^2 as functions of t.
Then you can try to solve these 2 differential equations for u and R with the Runge-Kutta code.
Caroline Kenemer
on 24 Apr 2022
t is the independent variable. You prescribe t, you don't integrate it.
The variables to be integrated are u and R.
And if you want to use symbolic calculations to get derivatives, you will have to do them before invoking Runge-Kutta because the functions are needed there.
Caroline Kenemer
on 24 Apr 2022
Caroline Kenemer
on 24 Apr 2022
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
@Caroline Kenemer: Whenever you mention in the forum, that you get an error, attach a copy of the complete error message. It is much easier to solve an error than to guess, what the error is.
Answers (2)
Jan
on 25 Apr 2022
A bold guess:
du_dR = 4*pi*e_d*R.^2;
dt_dR = -4*pi*R.*((dP_dt).^-1)*((P_n+e_d)./(1-2*u./R))*((P_n+u)./(4*pi*R.^2));
% Now du_dR and dtdR are constants
f = @(R,u,t) [du_dR,dt_dR];
% f does not depend on R,u,t, but is a [1 x 2] constant vector
Try this:
f = @(R,u,t) [4*pi*e_d*R.^2, -4*pi*R.*((dP_dt).^-1)*((P_n+e_d)./(1-2*u./R))*((P_n+u)./(4*pi*R.^2))];
But here dP_dt is a contant also, which will cause the next troubles.
I suggest to omit the cute function handles and to write a function instead. This reduces the level of confusion.
If your code:
E_AV14 = (2.6511 + 76.744*n - 183.611*n^2 + 459.906*n^3 - 122.832*n^4)/624151;
the variable n is undefined.
A general hint to improve the processing speed: h0 = 6.6261*10^-21 is a mutliplication and an expensive power operation, while h0 = 6.6261e-21 is a cheap constant.
I made the best of your code I could, but study carefully. There must be something wrong - I guess with the units.
c = 3*10^10; % speed of light [cm/s]
h0 = 6.6261*10^-21; % Planck's constant [cm^2 g s^-1]
m_n = 1.675*10^-24; % Mass of neutron [g]
h_bar = h0/(2*pi*m_n); % Reduced Planck's constant
e_d = 6.48*10^36; % energy density [erg/cm^-3]
Msun = 1.9891*10^33; % mass of Sun in [g]
Mx = 2.9*Msun; %new unit of mass in solar masses
rx = 13.69*10^5; % new unit of length in [cm]
G = 6.674*10^-8;
syms t R n u
%Define E(n)
E_AV14 = (2.6511 + 76.744*n - 183.611*n^2 + 459.906*n^3 - 122.832*n^4)/624151; % [erg]
% Define P
P = n^2*diff(E_AV14,n);
% Differentiate P with respect to n
dP_dn = diff(P,n);
% Define n as a function of t
n1 = (sin(h0^3*(t/4)))/(3*pi^2*(h_bar/m_n*c)^3)/(1*10^13); % [cm]
% Differentiate n with respect to t
dn1_dt = diff(n1,t);
% Differentiate P with respect to t
dP_dt = dP_dn*dn1_dt;
% Express P in terms of t alone (Substitute n by its function of t)
P = subs(P,n,n1);
% Express dP/dt with respect to t alone (Substitute n by its function of t)
dP_dt = subs(dP_dt,n,n1);
% Your dt/dR expression
dt_dR = -4*pi*R*(dP_dt)^(-1)*(P+e_d)/(1-2*u/R)*(P+u/(4*pi*R^2));
% Substitute u by 4/3*pi*e_d*R^3
dt_dR = subs(dt_dR,u,4/3*pi*e_d*R^3)
% Your du/dR expression (actually superfluous since u has already been integrated)
du_dR = 4*pi*e_d*R^2;
% Define the symbolic vector of derivatives du/dR and dt/dR
f = [du_dR,dt_dR];
% Convert symbolic vector into function handle
f = matlabFunction(f,'Vars',{R,u,t})
f = @(R,y)f(R,y(1),y(2))
% Convert symbolic expressions for n, P and dP/dt into function handles as fiunctions of t
n = matlabFunction(n1)
P = matlabFunction(P)
dP_dt = matlabFunction(dP_dt)
% Define interval of integration
rstart = 1e-8;
rend = 1.0e-1;
% Define stepsize
h = (rend - rstart)/20;
% Define R values where u and t shall be supplied
R = (rstart:h:rend).';
% Define vector of initial values for u and t
Y0 = [0 0.5];
% Get the number of R-steps (number of elements of R-vector)
N = numel(R);
% Get the number of functions to be integrated
node = numel(Y0);
% Initialize solution vector
Y = zeros(N,node);
% Define solution vector at r=rstart
Y(1,:) = Y0;
% Runge-Kutta method
for i = 2:N
r = R(i-1);
y = Y(i-1,:);
h = R(i) - R(i-1);
k0 = f(r,y);
k1 = f(r+0.5*h,y+k0*0.5*h);
k2 = f(r+0.5*h,y+k1*0.5*h);
k3 = f(r+h,y+k2*h);
Y(i,:) = y + h/6*(k0+2*k1+2*k2+k3)
P(Y(i,2))
dP_dt(Y(i,2))
n(Y(i,2))
pause()
end
% Plot results
plot(R,[Y(:,1),Y(:,2)])
10 Comments
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
Torsten
on 25 Apr 2022
Why all these while's and if's ? Check at the end of each time step (when Y(i,:) is computed) whether the conditions dP/dt > 0, P> 0 and n> 0 hold. If not, stop.
And why did you delete the creation of the matlabFunctions ? All your computations in the Runge-Kutta part don't work with symbolic variables - you have to convert the expressions into numerical functions. That's what the command "matlabFunction" is for.
Caroline Kenemer
on 25 Apr 2022
By converting the expressions
P(Y(i,2))
dP_dt(Y(i,2))
n(Y(i,2))
of the code I posted into if-statements.
Caroline Kenemer
on 25 Apr 2022
Torsten
on 25 Apr 2022
if P(Y(i,2)) < 0 || dP_dt(Y(i,2)) < 0 || n(Y(i,2)) < 0
break
end
Caroline Kenemer
on 25 Apr 2022
Caroline Kenemer
on 25 Apr 2022
I included comments in the code.
Nevertheless, the best way to learn about "subs", "numel" and "matlabFunction" is to read the MATLAB documentation:
"node" is just a variable name I chose (long format: number of ordinary differential equations)
The coefficients occuring in the function handle for du/dR and dt/dR are of an unbelievable magnitude. I don't know which modifications you did to your code after units checking, but you should keep this in mind as the most probable source of error.
You might want to set
sympref('FloatingPointOutput',true)
to get floating point output within your function handles.
Categories
Find more on Solver Outputs and Iterative Display in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!