Integrating over a constant function - matlab

I am trying to integrate over a constant function in MATLAB 2017a, but I am stuck. First of all when I integrate using the following script, I get the right output. So the script works for a x0 which depends on t.
function E=sol(n,k)
x0 = #(t) t^(2);
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
Where function po(j,k) is as follows,
function A_j = po(j,k) % Adomian polynomials
if j >0
x = sym('x',[1 j]);
syms p; % Assinging a symbolic variable for p
syms x0;
S = x0+ sum(p.^(1:j) .* x) ; % Sum of p*x up to order j
Q =f(S,k); % Taking the k-th power of S, i.e.
A_nc = diff(Q,p,j)/factorial(j); % Taking the j-th order derivative
A_j = subs(A_nc,p,0) ; % Filling in p=0
else
syms x0;
S = x0;
A_j =f(S,k); % Taking the k-th power of S,
end
end
And where f(x,k) is,
function F = f(x,k) % Nonlinear function of k power
F = x^k ;
end
Now when I cal sol(n,k) it does work. But when I try to change my x0 function in sol(n,k) in a constant function like,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
It does not work, As you can see I added *ones(size(t)); just to make it a function of t. But unfortunately it still doesn't work when I call,
K = matlabFunction(subs(po(j,k))) ;
I get,
#()4.0
And then I get an error when I call,
eval(sprintf('x%d = integral(K,0,1);',j+1))
Could anyone help me out trying to integrate over a constant?
The error I get when I call solcon(10,2) is
Error using symengine>#()4.0
Too many input arguments.
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 132)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 75)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 88)
Q = integralCalc(fun,a,b,opstruct);
Error in solcon1 (line 7)
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
EDIT 2
I used the following script,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr= func2str(K)
if fstr(3) == ')';
x{j+1} = K*(1-0)
else x{j+1} = integral(K,0,1)
end
E(j+1,1) = subs(x{j+1},1);
j = j+1
end
end
But the following error occurs,
Undefined operator '*' for input arguments of type 'function_handle'.
Error in solcone1 (line 9)
x{j+1} = K*(1-0);

I am going to ignore the terrible choice of using eval, especially when you can do
x{j+1} = integral(K,0,1);
Read more on why dynamic variables and eval are terrible
Your problem is that matlabFunction is a smartass. When it detects that your function does not have any dependency to x, it gives you a function with empty input arguments #()4.0. As you see, integral does not like that.
A way of solving the problem is detecting this before calling integral. You could check if it has input arguments, and if it does not, then evaluate the integral "by hand"
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if fstr(3)==')'
x{j+1}=K()*(1-0); % evaluate the integral yourself
else
x{j+1} = integral(K,0,1);
end
E(j+1,1) = subs(x{j+1});
j = j+1;
end
...
The problem is considerably more difficult that I though I was. Either rewrite the entire thing, or using eval:
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if j==0
eval(sprintf('x%d = K()*(1-0);;',j+1)) ;
else
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
end
E(j+1,1) = subs(sprintf('x%d',j+1));
j = j+1;
end
...

Related

Find roots using fsolve

Basically I would like to use the fsolve command in order to find the roots of an equation.
I think I should create a function handle that evaluates this equation in the form "right hand side - left hand side =0", but I've been struggling to make this work. Does anyone know how to do this?
The equation itself is 1/sqrt(f) = -1.74log((1.254/((1.27310^8)sqrt(f)))+((110^-3)/3.708)). So I would like to find the point of intersection of the left and right side by solving for 1/sqrt(f)+(1.74log((1.254/((1.27310^8)sqrt(f)))+((110^-3)/3.708))) = 0 using fsolve.
Thanks a lot!
The code so far (not working at all)
f = #(x) friction(x,rho,mu,e,D,Q, tol, maxIter) ;
xguess = [0, 1];
sol = fsolve(x, xguess ) ;
function y = friction(x,rho,mu,e,D,Q, tol, maxIter)
D = 0.1;
L = 100
rho = 1000;
mu = 0.001;
e = 0.0001;
Q = 0.01;
U = (4*Q)/(pi*D^2);
Re = (rho*U*D)/mu ;
y = (1/sqrt(x))-(-1.74*log((1.254/(Re*sqrt(x)))+((e/D)/3.708)))
end
Error message:
Error using lsqfcnchk (line 80)
FUN must be a function, a valid character vector expression, or an inline function object.
Error in fsolve (line 238)
funfcn = lsqfcnchk(FUN,'fsolve',length(varargin),funValCheck,gradflag);
Error in Untitled (line 6)
sol = fsolve(x, xguess ) ;
opt = optimset('Display', 'Iter');
sol = fsolve(#(x) friction(x), 1, opt);
function y = friction(x)
D = 0.1;
L = 100; % note -- unused
rho = 1000;
mu = 0.001;
e = 0.0001;
Q = 0.01;
U = (4*Q)/(pi*D^2);
Re = (rho*U*D)/mu ;
y = (1/sqrt(x))-(-1.74*log((1.254/(Re*sqrt(x)))+((e/D)/3.708)));
end
sol = 0.0054
the first argument of fsolve should be the function not variable. Replace:
sol = fsolve(x, xguess );
with
sol = fsolve(f, xguess );
And define Rho, mu, e etc before you define f (not inside the friction function).

Issue with storing error at each iteration on Matlab - "unrecognized variable"

I've written a modified Newton's method code, and I'm looking to plot the error at each iteration vs the iteration, but after my code runs Matlab does not recognize my error function or the iterations.
function[x,k,e] = mynewton(x0,tol)
f = #(x) (x-1).^5*exp(x);
df = #(x) 5*(x-1).^4*exp(x)+(x-1).^5*exp(x);
kMax = 200;
format long
x=x0;
y=f(x);
e = [];
k = 0;
disp(' k x error')
while abs(y) > tol && k < kMax
k=k+1;
x = x - f(x)/df(x);
y = f(x);
e_k = abs(x-1);
e(k) = e_k;
disp([k x e_k])
end
end
The output will be 3 columns showing k, x, and e_k at each step, but it won't store these values properly into a vector. Instead, it shows
>> k
Unrecognized function or variable 'k'.
What am I doing wrong?
Any suggestions are very appreciated!!
You need to call your function as:
[x, k, e] = mynewton( x0, tol);
After this call, you can enter k at command window and see its value.

Newton's method roots on Matlab

I am not so much experiences with Matlab. I just need it for the sake of solving some lengthy non-linear equations. Instead of using fzero, I wanna use Newton-Raphson's to solve the equation.
newton.m file contains the following code.
function [ x, ex ] = newton( f, df, x0, tol, nmax )
if nargin == 3
tol = 1e-4;
nmax = 1e1;
elseif nargin == 4
nmax = 1e1;
elseif nargin ~= 5
error('newton: invalid input parameters');
end
x(1) = x0 - (f(x0)/df(x0));
ex(1) = abs(x(1)-x0);
k = 2;
while (ex(k-1) >= tol) && (k <= nmax)
x(k) = x(k-1) - (f(x(k-1))/df(x(k-1)));
ex(k) = abs(x(k)-x(k-1));
k = k+1;
end
end
And in the main file, I have called this function as follows:
ext_H = newton( exp(x) + x^3, diff(exp(x) + x^3), 9, 0.5*10^-5, 10);
When I run this function, it gives me the following error.
Error using sym/subsref (line 9)
Error using maplemex
Error, (in MTM:-subsref) Array index out of range
Error in newton (line 37)
x(1) = x0 - (f(x0)/df(x0));
Error in main (line 104)
ext_H = newton( exp(x) + x^3, diff(exp(x) + x^3), 9, 0.5*10^-5, 10);
Could anyone please help me to get through this?
You can probably use Matlab's fsolve (http://uk.mathworks.com/help/optim/ug/fsolve.html) with a couple of options
x0 = 9;
options = optimoptions('fsolve','Algorithm','levenberg-marquardt','TolFun',5*10^-6,'MaxIter',100);
x = fsolve(#(x)(exp(x) + x^3), x0,options);
or just fzero (http://uk.mathworks.com/help/optim/ug/fzero.html) which implements BD algorithm
x = fzero(#(x)(exp(x) + x^3), x0);

Error: `Input argument "N" is undefined`, in simple matlab program

I have this tiny program in Matlab.
laMatriz.m
function k = laMatriz(X)
Y = 9;
A = zeros(X, Y);
for i=1:X
V = elVector(Y);
LimY = length(elVector);
for j=1:LimY
A(i,j) = V(j);
end
end
k = A;
end
elVector.m
function elVector = elVector(N)
%fprintf('largo de elVector %i\n', N);
elVector=1:N;
end
Calling function laMatriz(10) results in this error:
??? Input argument "N" is undefined.
Error in ==> elVector at 3
elVector=1:N;
Error in ==> laMatriz at 11
LimY = length(elVector);
why? how can i fix it?
The problem is in this function:
function k = laMatriz(X)
Y = 9;
A = zeros(X, Y);
for i=1:X
V = elVector(Y);
LimY = length(elVector); <-- here you are calling length(elVector)
for j=1:LimY
A(i,j) = V(j);
end
end
k = A;
end
elVector is a function so you cannot call length with it. Did you mean length(V)? Basically your error is saying the argument N to the function elVector doesn't exist.

variable in solving the equation

I want to solve equations in matlab, eg.
100+a/2=173*cos(b)
sqrt(3)*a/2=173*sin(b)
and the code would be:
[a,b]=solve('100+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
However, if I want to take 100 as a variable, like
for k=1:100
[a,b]=solve('k+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
end
There would be an error, how to make it?
degree=140/1000000;
p=42164000;
a=6378136.5;
b=6356751.8;
x_1=0;
y_1=p;
z_1=0;
for i=451:550
for j=451:550
alpha=(1145-i)*degree;
beta=(1145-j)*degree;
x_2=p/cos(alpha)*tan(beta);
y_2=0;
z_2=p*tan(alpha);
syms x y z x_1 x_2 y_1 y_2 z_1 z_2 a b
eq = [(x-x_1)*(y2-y_1)-(x_2-x_1)*(y-y_1),(x-x_1)*(z_2-z_1)-(x_2-x_1)*(z-z_1), b^2*(x^2+y^2)+a^2*(y^2)-a^2*b^2 ];
sol = solve(eq(1),x,eq(2),y, eq(3),z);
sol.x
sol.y
sol.z
end
end
I got the expression value, how do I get the numeric value of x,y,z?
[['x(1)=';'x(2)='],num2str(double(sol.x))]
not work ,shows
??? Error using ==> mupadmex
Error in MuPAD command: DOUBLE cannot convert the input expression into a double array.
If the input expression contains a symbolic variable, use the VPA function instead.
Error in ==> sym.sym>sym.double at 927
Xstr = mupadmex('mllib::double', S.s, 0);
Error in ==> f2 at 38
[['x(1)=';'x(2)='],num2str(double(sol.x))]
If you have access to the Symbolic Toolkit then you do the following:
syms a b k
eq = [k+a/2-173*cos(b), sqrt(3)*a/2-173*sin(b)];
sol = solve(eq(1),a,eq(2),b);
sol.a = simplify(sol.a);
sol.b = simplify(sol.b);
% There are two solutions for 'a' and 'b'
% check residuals for example k=20
subs(subs(eq,{a,b},{sol.a(1),sol.b(1)}),k,20)
% ans = 0.2e-13
subs(subs(eq,{a,b},{sol.a(2),sol.b(2)}),k,20)
% ans = 0.2e-13
Edit 1
Based on new code by OP the matlab script to solve this is:
clear all
clc
syms alpha beta
degree=140/1000000;
p=42164000;
a=6378136.5;
b=6356751.8;
x_1=0;
y_1=p;
z_1=0;
x_2 = p/cos(alpha)*tan(beta);
y_2 = 0;
z_2 = p*tan(alpha);
syms x y z
eq = [(x-x_1)*(y_2-y_1)-(x_2-x_1)*(y-y_1);...
(x-x_1)*(z_2-z_1)-(x_2-x_1)*(z-z_1); ...
b^2*(x^2+y^2)+a^2*(y^2)-a^2*b^2 ];
sol = solve(eq(1),x,eq(2),y,eq(3),z);
sol.x = simplify(sol.x);
sol.y = simplify(sol.y);
sol.z = simplify(sol.z);
pt_1 = [sol.x(1);sol.y(1);sol.z(1)] % First Solution Point
pt_2 = [sol.x(2);sol.y(2);sol.z(2)] % Second Solution Point
x = zeros(100,100);
y = zeros(100,100);
z = zeros(100,100);
for i=451:550
disp(['i=',num2str(i)])
for j=451:550
res = double(subs(pt_1,{alpha,beta},{(1145-i)*degree,(1145-j)*degree}));
x(i-450, j-450) = res(1);
y(i-450, j-450) = res(2);
z(i-450, j-450) = res(3);
end
end
disp('x=');
disp(x);
disp('y=');
disp(x);
disp('z=');
disp(x);
I would try
for i=1:100
k=num2str(i)
[a,b]=solve('100+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
end
and then solve the equation