Hi i've been asked to solve SIR model using fsolve command in MATLAB, and Euler 3 point backward. I'm really confused on how to proceed, please help. This is what i have so far. I created a function for 3BDF scheme but i'm not sure how to proceed with fsolve and solve the system of nonlinear ODEs. The SIR model is shown as and 3BDF scheme is formulated as
clc
clear all
gamma=1/7;
beta=1/3;
ode1= #(R,S,I) -(beta*I*S)/(S+I+R);
ode2= #(R,S,I) (beta*I*S)/(S+I+R)-I*gamma;
ode3= #(I) gamma*I;
f(t,[S,I,R]) = [-(beta*I*S)/(S+I+R); (beta*I*S)/(S+I+R)-I*gamma; gamma*I];
R0=0;
I0=10;
S0=8e6;
odes={ode1;ode2;ode3}
fun = #root2d;
x0 = [0,0];
x = fsolve(fun,x0)
function [xs,yb] = ThreePointBDF(f,x0, xmax, h, y0)
% This function should return the numerical solution of y at x = xmax.
% (It should not return the entire time history of y.)
% TO BE COMPLETED
xs=x0:h:xmax;
y=zeros(1,length(xs));
y(1)=y0;
yb(1)=y0+f(x0,y0)*h;
for i=1:length(xs)-1
R =R0;
y1(i+1,:) = fsolve(#(u) u-2*h/3*f(t(i+1),u) - R, y1(i-1,:)+2*h*F(i,:))
S = S0;
y2(i+1,:) = fsolve(#(u) u-2*h/3*f(t(i+1),u) - S, y2(i-1,:)+2*h*F(i,:))
I= I0;
y3(i+1,:) = fsolve(#(u) u-2*h/3*f(t(i+1),u) - I, y3(i-1,:)+2*h*F(i,:))
end
end
You have an implicit equation
y(i+1) - 2*h/3*f(t(i+1),y(i+1)) = G = (4*y(i) - y(i-1))/3
where the right-side term G is constant in the call to fsolve, that is, during the solution of the implicit step equation.
Note that this is for the vector valued system y'(t)=f(t,y(t)) where
f(t,[S,I,R]) = [-(beta*I*S)/(S+I+R); (beta*I*S)/(S+I+R)-I*gamma; gamma*I];
To solve this write
G = (4*y(i,:) - y(i-1,:))/3
y(i+1,:) = fsolve(#(u) u-2*h/3*f(t(i+1),u) - G, y(i-1,:)+2*h*F(i,:))
where a midpoint step is used to get an order 2 approximation as initial guess, F(i,:)=f(t(i),y(i,:)). Add solver options for error tolerances as necessary, you want the error in the implicit equation smaller than the truncation error O(h^3) of the step. One can also keep only a short array of function values, then one has to be careful for the correspondence of the position in the short array to the time index.
Using all that and a reference solution by a higher order standard solver produces the following error graphs for the components
where one can see that the first order error of the constant first step results in a first order global error, while with a second order error in the first step using the Euler method results in a clear second order global error.
Implement the method in general terms
from scipy.optimize import fsolve
def BDF2(f,t,y0,y1):
N, h = len(t)-1, t[1]-t[0];
y = (N+1)*[np.asarray(y0)];
y[1] = y1;
for i in range(1,N):
t1, G = t[i+1], (4*y[i]-y[i-1])/3
y[i+1] = fsolve(lambda u: u-2*h/3*f(t1,u)-G, y[i-1]+2*h*f(t[i],y[i]), xtol=1e-3*h**3)
return np.vstack(y)
Set up the model to be solved
gamma=1/7;
beta=1/3;
print beta, gamma
y0 = np.array([8e6, 10, 0])
P = sum(y0); y0 = y0/P
def f(t,y): S,I,R = y; trns = beta*S*I/(S+I+R); recv=gamma*I; return np.array([-trns, trns-recv, recv])
Compute a reference solution and method solutions for the two initialization variants
from scipy.integrate import odeint
tg = np.linspace(0,120,25*128)
yg = odeint(f,y0,tg,atol=1e-12, rtol=1e-14, tfirst=True)
M = 16; # 8,4
t = tg[::M];
h = t[1]-t[0];
y1 = BDF2(f,t,y0,y0)
e1 = y1-yg[::M]
y2 = BDF2(f,t,y0,y0+h*f(0,y0))
e2 = y2-yg[::M]
Plot the errors, computation as above, but embedded in the plot commands, could be separated in principle by first computing a list of solutions
fig,ax = plt.subplots(3,2,figsize=(12,6))
for M in [16, 8, 4]:
t = tg[::M];
h = t[1]-t[0];
y = BDF2(f,t,y0,y0)
e = (y-yg[::M])
for k in range(3): ax[k,0].plot(t,e[:,k],'-o', ms=1, lw=0.5, label = "h=%.3f"%h)
y = BDF2(f,t,y0,y0+h*f(0,y0))
e = (y-yg[::M])
for k in range(3): ax[k,1].plot(t,e[:,k],'-o', ms=1, lw=0.5, label = "h=%.3f"%h)
for k in range(3):
for j in range(2): ax[k,j].set_ylabel(["$e_S$","$e_I$","$e_R$"][k]); ax[k,j].legend(); ax[k,j].grid()
ax[0,0].set_title("Errors: first step constant");
ax[0,1].set_title("Errors: first step Euler")
Im trying to understand multivariable goal optimization, I will need to optimize complex functions, but to start, I need to optimize the following function:
function ap_phase = objecfun(tau)
f = 1000; %Frequency
w = 2*pi*f; %Angular Frequency
trans_func = #(taux) (1-1i*w*taux)./(1+1i*w*taux); %Transfer function
trans_zero = trans_func(tau(1)); %Transfer function evaluated with the first variable
trans_quad = trans_func(tau(2)); %Transfer function evaluated with the second variable
ap_phase = rad2deg(phase(trans_zero)-phase(trans_quad)); %Phase difference
end
The function objecfun takes one vector of length 2 as an input, computes 2 transfer functions, then substracts the phase of the transfer functions.
My goal is that the phase should be around 90°
The script im using to make the optimization is the following
tau0 = [2E-5, 1E-3]; %Initial Value for tau(1) and tau(2)
lb = [1E-7, 1E-7]; %Lower bound for tau(1) and tau(2)
ub = [1E-2, 1E-2]; %Upper bound for tau(1) and tau(2)
goal = 90; %Optimization goal
weight = 1; %Weight
[x,fval] = fgoalattain(#objecfun,tau0,goal,weight,[],[],[],[],lb,ub)
The optimizer converges but im getting a wrong answer, im getting
x =
0.0100 0.0000
fval =
-178.1044
That's wrong, fval should be near 90°
What am I doing wrong?
I think you need to replace your objective function and goal value so that it fit the problem formulation. You can use as an objective function say the L2 norm of the difference between your function output and your desired angle, and set the goal as some tolerance.
I checked also with "fmincon":
new_goal = 1e-4;
objectfun = #(x) norm(objecfun(x) - goal);
options = optimoptions('fgoalattain');
options.PlotFcns = 'optimplotfval';
[tau_star,fval] = fgoalattain(objectfun,tau0,new_goal,weight,[],[],[],[],lb,ub,[],options);
options = optimoptions('fmincon');
options.PlotFcns = 'optimplotfval';
[tau_star2,fval,exitflag,output] = fmincon(objectfun,tau0,[],[],[],[],lb,ub,[], options);
fgoalattain_solution_phase_diff = objecfun(tau_star)
fmincon_solution_phase_diff = objecfun(tau_star2)
And got:
fgoalattain_solution_phase_diff =
90.0000
fmincon_solution_phase_diff =
90.0006
Note: you can also omit the rad2deg in your function and use as the desired angle its value in [rad].
I have a boundary value problem (specified in the picture below) that is supposed to be solved with shooting method. Note that I am working with MATLAB when doing this question. I'm pretty sure that I have rewritten the differential equation from a 2nd order differential equation to a system of 1st order differential equations and also approximated the missed value for the derivative of this differential equation when x=0 using the secant method correctly, but you could verify this so you'll be sure.
I have done solving this BVP with shooting method and my codes currently for this problem is as follows:
clear, clf;
global I;
I = 0.1; %Strength of the electricity on the wire
L = 0.400; %The length of the wire
xStart = 0; %Start point
xSlut = L/2; %End point
yStart = 10; %Function value when x=0
err = 5e-10; %Error tolerance in calculations
g1 = 128; %First guess on y'(x) when x=0
g2 = 89; %Second guess on y'(x) when x=0
state = 0;
X = [];
Y = [];
[X,Y] = ode45(#calcWithSec,[xStart xSlut],[yStart g1]');
F1 = Y(end,2);
iter = 0;
h = 1;
currentY = Y;
while abs(h)>err && iter<100
[X,Y] = ode45(#calcWithSec,[xStart xSlut],[yStart g2]');
currentY = Y;
F2 = Y(end,2);
Fp = (g2-g1)/(F2-F1);
h = -F2*Fp;
g1 = g2;
g2 = g2 + h;
F1 = F2;
iter = iter + 1;
end
if iter == 100
disp('No convergence')
else
plot(X,Y(:,1))
end
calcWithSec:
function fp = calcWithSec(x,y)
alpha = 0.01; %Constant
beta = 10^13; %Constant
global I;
fp = [y(2) alpha*(y(1)^4)-beta*(I^2)*10^(-8)*(1+y(1)/32.5)]';
end
My problem with this program is that for different given I's in the differential equation, I get strange curves that does not make any sense in physical meaning. For instance, the only "good" graph I get is when I=0.1. The graph to such differential equations is as follows:
But when I set I=0.2, then I get a graph that looks like this:
Again, in physical meaning and according to the given assignment, this should not happen since it gets hotter you closer you get to the middle of the mentioned wire. I want be able to calculate all I between 0.1 and 20, where I is the strength of the electricity.
I have a theory that it has something to do with my guessing values and therefore, my question is about if there is possible to implement an algorithm that forces the program to adjust the guessing values so I can get a graph that is "correct" in physical meaning? Or is it impossible to achieve this? If so, then explain why.
I have struggled with this assignment many days in row now, so all help I can get with this assignment is worth gold to me now.
Thank you all in advance for helping me out of this!
I am trying to compute the value of this integral using Matlab
Here the other parameters have been defined or computed in the earlier part of the program as follows
N = 2;
sigma = [0.01 0.1];
l = [15];
meu = 4*pi*10^(-7);
f = logspace ( 1, 6, 500);
w=2*pi.*f;
for j = 1 : length(f)
q2(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(2));
q1(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(1));
C2(j)= 1/(q2(j));
C1(j)= (q1(j)*C2(j) + tanh(q1(j)*l))/(q1(j)*(1+q1(j)*C2(j)*tanh(q1(j)*l)));
Z(j) = sqrt(-1)*2*pi*f(j)*C1(j);
Apprho(j) = meu*(1/(2*pi*f(j))*(abs(Z(j))^2));
Phi(j) = atan(imag(Z(j))/real(Z(j)));
end
%integration part
c1=w./(2*pi);
rho0=1;
fun = #(x) log(Apprho(x)/rho0)/(x.^2-w^2);
c2= integral(fun,0,Inf);
phin=pi/4-c1.*c2;
I am getting an error like this
could anyone help and tell me where i am going wrong.thanks in advance
Define Apprho in a separate *.m function file, instead of storing it in an array:
function [ result ] = Apprho(x)
%
% Calculate f and Z based on input argument x
%
% ...
%
meu = 4*pi*10^(-7);
result = meu*(1/(2*pi*f)*(abs(Z)^2));
end
How you calculate f and Z is up to you.
MATLAB's integral works by calling the function (in this case, Apprho) repeatedly at many different x values. The x values called by integral don't necessarily correspond to the 1: length(f) values used in your original code, which is why you received errors.
Hello I am relatively new to MATLAB and have received and assignment in which we could use any programming language. I would like to continue MATLAB and have decided to use it for this assignment. The questions has to do with the following formula:
x(t) = A[1+a1*E(t)]*sin{w[1+a2*E(t)]*t+y}(+/-)a3*E(t)
The first question we have is to develop an appropriate discretization of x(t) with a time step h. I think i understand how to do this using step but because there is a +/- in the end I am running into errors. Here is what I have (I have simplified the equation by assigning arbitrary values to each variable):
A = 1;
E = 1;
a1 = 1;
a2 = 2;
a3 = 3;
w = 1;
y = 0;
% ts = .1;
% t = 0:ts:10;
t = 1:1:10;
x1(t) = A*(1+a1*E)*sin(w*(1+a2*E)*t+y);
x2(t) = a3*E;
y(t) = [x1(t)+x2(t), x1(t)-x2(t)]
plot(y)
The problem is I keep getting the following error because of the +/-:
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in Try1 (line 21)
y(t) = [x1(t)+x2(t), x1(t)-x2(t)]
Any help?? Thanks!
You can remove the (t) from the left-hand side of all three assignments.
y = [x1+x2, x1-x2]
MATLAB knows what to do with vectors and matrices.
Or, if you want to write it out the long way, tell MATLAB there will be two columns:
y(t, 1:2) = [x1(t)'+x2(t)', x1(t)'-x2(t)']
or two rows:
y(1:2, t) = [x1(t)+x2(t); x1(t)-x2(t)]
But this won't work when you have fractional values of t. The value in parentheses is required to be the index, not a dependent variable. If you want the whole vector, just leave it out.