Weird error Matlab with piecewise elements in matrix - matlab

I'm trying to solve a differential equation that has the form Y'(t)=A(t)*Y(t), where Y and Y' is a column with 4 elements, A is a 4x4 matrix. In the A(t) matrix I'm using the functions m(t) and f(t) to compute each value of the matrix. However, when I put a simple value to m(t) and f(t) (ex: a constant value or a t^2...) the function solvedPmWithTime returns a 4x1 matrix, which is what I expect, but when I use the m(t) and /or function f(t) that I want, which is computed by the compute_m_and_f function, it returns a 1x1 matrix. I can't find my error. If someone could help it would be very much appreciated :). Here are the codes of the functions and the code of the live script that I use to compute the differential equation:
function [m,f] = compute_m_and_f()
syms m(t) f(t)
Bm =600000;
sigmam =2.5;
tm =6;
tf =6;
sigmaf = 2;
Bf = 600000;
eqnM = diff(m,t) == Bm / sqrt(2*pi*sigmam^2)*exp(-((t-tm)^2)/(2*sigmam^2));
condM = m(0)==0;
eqnF = diff(f,t) == Bf / sqrt(2*pi*sigmaf^2)*exp(-((t-tf)^2)/(2*sigmaf^2));
condF = f(0)==0;
M(t) = dsolve(eqnM, condM);
F(t) = dsolve(eqnF, condF);
taum = 4;
tauf = 5;
m(t) = piecewise(t>taum, M(t)-M(t-taum),M(t));
f(t) = piecewise(t>tauf, F(t)-F(t-taum),F(t));
end
function solvedPmWithTime= solvedPmWithTime(~, y)
[m, f] = compute_m_and_f;
alpha = 480;
beta = 0.0011;
sigma = 0.0634;
epsilon = 0.0725;
a = (alpha * (f + m)) / (1 + alpha * beta * (f + m));
b11 =- (1 - (m / (f + m)) ^ sigma);
b12 = (1 - (f / (f + m)) ^ epsilon);
b13 = (1 - (f / (f + m)) ^ epsilon);
b14 = (1 - (f / (f + m)) ^ epsilon);
b21 = (1 - (m / (f + m)) ^ sigma);
b22 = -1;
b23 = 0;
b24 = 0;
b31 = 0;
b32 = (f / (f + m)) ^ epsilon;
b33 = -1;
b34 = 0;
b41 = 0;
b42 = 0;
b43 = (f / (f + m)) ^ epsilon;
b44 =- (1 - (f / (f + m)) ^ epsilon);
b = [b11, b12, b13, b14; b21, b22, b23, b24; b31, b32, b33, b34; b41, b42, b43, b44];
A = a * b;
solvedPmWithTime = A * y;
end
clear all
rho = 6;
Bf = 600000;
Pm1_0 = 0;
Pm2_0 = 0;
Pm3_0 = 0;
Pf_0 = 3600;
[t, Pm] = ode45(#solvedPmWithTime, [0, 100], [Pm1_0; Pm2_0; Pm3_0; Pf_0]); %this returns an error because the size of the matrix is not 4x1
Pm1 = Pm(:, 1);
Pm2 = Pm(:, 2);
Pm3 = Pm(:, 3);
Pf = Pm(:, 4);
hold off
plot(t, Pm1, t, Pm2, t, Pm3, t, Pf)
legend('Pm1', 'Pm2', 'Pm3', 'Pf')
n = solvedPmWithTime([0, 100], [Pm1_0; Pm2_0; Pm3_0; Pf_0]);
size(n)

Related

I'm getting an error "Undefined function 'Romberg' for input arguments of type 'char'." I'm trying to code the romberg integration method

I'm trying to code the romberg integration method on matlab. I think I coded it right but I'm not getting why I have this error.
This is the function.
function[t , r] = Romberg (fun, a, b, nmax)
f = inline(fun);
r(1, 1) = (b - a) * (f(a) + f(b)) / 2;
for i = 1 : nmax
h(i) = (b-a) /2^(i) ;
m = 0;
for k = 1 : (2^(i))-1
m = m + f (a+k*h(i));
end
r(i + 1, 1) = (h(i) / 2) * (f(a) + f(b) + 2*m);
for j = 2 : i
r(i, j) = r(i, j-1) + (r(i, j-1) - r(i - 1, j - 1)) / (4^(j-1) - 1);
end
end
t = r (i, j)
This is its call
clc; clear all; close all;
a = 0;
b = pi;
nmax = 3;
fun ='sin (x)' ;
[t, r]= Romberg (fun, a, b, nmax)
And this is the error:
Undefined function 'Romberg' for input arguments of type 'char'.

Code Horner’s Method for Polynomial Evaluation

I am trying to code Horner’s Method for Polynomial Evaluation but for some reason its not working for me and I'm not sure where I am getting it wrong.
These are the data I have:
nodes = [-2, -1, 1]
x = 2
c (coefficients) = [-3, 3, -1]
The code I have so far is:
function y = horner(x, nodes, c)
n = length(c);
y = c(1);
for i = 2:n
y = y * ((x - nodes(i - 1)) + c(i));
end
end
I am supposed to end up with a polynomial such as (−1)·(x+2)(x+1)+3·(x+2)−3·1 and if x =2 then I am supposed to get -3. But for some reason I don't know where I am going wrong.
Edit:
So I changed my code. I think it works but I am not sure:
function y = horner(x, nodes, c)
n = length(c);
y = c(n);
for k = n-1:-1:1
y = c(k) + y * (x - nodes((n - k) + 1));
end
end
This works:
function y = horner(x, nodes, c)
n = length(c);
y = 0;
for i = 1:n % We iterate over `c`
tmp = c(i);
for j = 1:i-1 % We iterate over the relevant elements of `nodes`
tmp *= x - nodes(j); % We multiply `c(i) * (x - nodes(1)) * (x -nodes(2)) * (x- nodes(3)) * ... * (x - nodes(i -1))
end
y += tmp; % We added each product to y
end
% Here `y` is as following:
% c(1) + c(2) * (x - nodes(1)) + c(3) * (x - nodes(1)) * (x - nodes(2)) + ... + c(n) * (x - nodes(1)) * ... * (x - nodes(n - 1))
end
(I'm sorry this isn't python but I don't know python)
In the case where we didn't have nodes, horner's method works like this:
p = c[n]
for i=n-1 .. 1
p = x*p + c[i]
for example for a quadratic (with coeffs a,b,c) this is
p = x*(x*a+b)+c
Note that if your language supports fma
fma(x,y,x) = x*y+z
then horner's method can be written
p = c[n]
for i=n-1 .. 1
p = fma( x, p, c[i])
When you do have nodes, the change is simple:
p = c[n]
for i=n-1 .. 1
p = (x-nodes[i])*p + c[i]
Or, using fma
p = c[n]
for i=n-1 .. 1
p = fma( (x-nodes[i]), p, c[i])
For the quadratic above this leads to
p = (x-nodes[1]*((x-nodes[2])*a+b)+c

Why do i get "Error using vertcat" in Matlab ode45 solver?

I have the following function to be solved by ODE45 solver of Matlab:
function f = odefun(t, y)
global mu ft
% y = [a, h, k, p, q, L, lla, lh, lk, lp, lq, lL];
a = y(1);
h = y(2);
k = y(3);
p = y(4);
q = y(5);
L = y(6);
lla = y(7);
lh = y(8);
lk = y(9);
lp = y(10);
lq = y(11);
lL = y(12);
n = sqrt(mu./a.^3); % mean motion
G = sqrt(1-h.^2-k.^2);
K = 1+p.^2+q.^2;
sL = sin(L);
cL = cos(L);
r = (a.*G.^2)./(1+h.*sL+k.*cL);
% components of B Matrix
B11 = 2.*(n.^-1).*(G.^-1).*(k.*sL-h.*cL);
B12 = 2.*(n.^-1).*a.*(r.^-1).*G;
B13 = 0;
B21 = -(n.^-1).*(a.^-1).*G.*cL;
B22 = (n.^-1).*(a^-2).*r.*(G.^-1).*(h+sL)+(n.^-1).*(a.^-1).*G.*sL;
B23 = -(n.^-1).*(a.^-2).*r.*(G.^-1).*k.*(p.*cL-q.*sL);
B31 = (n.^-1).*(a.^-1).*G.*sL;
B32 = (n.^-1).*(a.^-2).*r.*(G.^-1).*(k+cL)+(n.^-1).*(a.^-1).*G.*cL;
B33 = (n.^-1).*(a.^-2).*r.*(G.^-1).*h.*(p.*cL-q.*sL);
B41 = 0;
B42 = 0;
B43 = 0.5.*(n.^-1).*(a.^-2).*r.*(G.^-1).*K.*sL;
B51 = 0;
B52 = 0;
B53 = 0.5.*(n.^-1).*(a.^-2).*r.*(G.^-1).*K.*cL;
B61 = 0;
B62 = 0;
B63 = n.*(a.^2).*(r.^-2).*G+(n.^-1).*(a.^-2).*r.*(G.^-1).*(q.*sL-p.*cL);
B = [B11 B12 B13;
B21 B22 B23;
B31 B32 B33;
B41 B42 B43;
B51 B52 B53;
B61 B62 B63];
% costate vector
lambdaVec = [lla lh lk lp lq lL];
% control law vector
uvec = lambdaVec * B;
unorm = norm(uvec);
u = uvec./unorm;
u = u';
z_ = (B*u).*ft;
C = [0; 0; 0; 0; 0; n.*(a.^2)*(r.^-2).*G];
zdot = z_+C;
which should solve a system of 12 ODEs with 12 initial conditions, however when i run the code i get the following error:
Error using vertcat
Dimensions of arrays being concatenated are not consistent.
Error in odefun (line 49)
B = [B11 B12 B13;
which refers to matrix B. what possibly goes wrong here?
B11, B12, ... are the components of the matrix which are defined based on function variables e.g. "y" vector.

How can I get a proper double form for a symbolic matrix?

How can I get a proper double form from this symbolic Matrix in MatLab? I've tried everything but I prefer not using feval or inline function as they're not recommended
This is the code to get the matrix
function T = Romberg (a, b, m, f)
T = zeros(m, m);
T = sym(T);
syms f(x) c h;
f(x) = f;
c = (subs(f,a)+subs(f,b)) / 2;
h = b - a;
T(1,1) = h * c;
som = 0 ;
n = 2;
for i = 2 : m
h = h / 2;
for r = 1 : n/2
som = som + subs(f,(a + 2*(r-1)*h));
T(i,1) = h * (c + som);
n = 2*n;
end
end
r = 1;
for j = 2 : m
r = 4*r;
for i = j : m
T(i,j) = (r * T(i, j-1) - T(i-1,j-1)/(r-1));
end
end
end
And with an input like this
Romberg(0, 1, 4, '2*x')
I get a symbolic matrix output with all the
3 * f(3)/2 + f(1)/2 + f(5)/2
I would like to have a double output.
Can you please help me?
Thank you very much in advance!

How can I fix the link between the multiplier and eqn(x)?

I am right now stuck on a problem in matlab. What I have done is that I have an equation that is passed on into another function which works by the bisection-method.
But I have a multiplier that I am trying to implement which somehow leads to the function crashing.
Before I introduced the multiplier it all worked, I tried breaking it down by entering the multiplier value manually and it didn't work
P_{1} = 0.6;
P_{2} = 0.2;
P_{3} = 0.2;
a_1 = 4/3;
a_2 = -7/3;
b_1 = -1/3;
b_2 = 4/3;
persistent multiplier
multiplier = exp(a_1 * 44 + a_2 * 14 + 0);
eqn = #(x) ((a_1 * x + b_1)^a_1) * ((a_2 * x + b_2)^a_2) * x ...
-(P_{1}^a_1) * (P_{2}^a_2) * P_{3} * multiplier;
Q_{3} = Bisectionmethod(a_1, a_2, b_1, b_2, eqn);
Here is the calculating part of the bisection method.
x_lower = max(0, -b_1 / a_1);
x_upper = -b_2 / a_2;
x_mid = (x_lower + x_upper)/2;
Conditional statement encompassing the method of bisection
while abs(eqn(x_mid)) > 10^(-10)
if (eqn(x_mid) * eqn(x_upper)) < 0
x_lower = x_mid;
else
x_upper = x_mid;
end
x_mid = (x_lower + x_upper)/2;
end
Based on the information you provided this is what I came up with
function Q = Stackoverflow
persistent multiplier
P{1} = 0.6;
P{2} = 0.2;
P{3} = 0.2;
a1 = 4/3;
a2 = -7/3;
b1 = -1/3;
b2 = 4/3;
multiplier = exp(a1 * 44 + a2 * 14 + 0);
eqn = #(x) ((a1 .* x + b1).^a1) .* ((a2 .* x + b2).^a2) .* x -(P{1}.^a1) .* (P{2}.^a2) .* P{3} .* multiplier;
Q{3} = Bisectionmethod(eqn, max([0, -b1/a1]), -b2/a2, 1E-10);
end
function XOut = Bisectionmethod(f, xL, xH, EPS)
if sign(f(xL)) == sign(f(xH))
XOut = [];
error('Cannot bisect interval because can''t ensure the function crosses 0.')
end
x = [xL, xH];
while abs(diff(x)) > EPS
x(sign(f(mean(x))) == sign(f(x))) = mean(x);
end
XOut = mean(x);
end