Matlab: evaluate a symbolic function with vector and matrix arguments - matlab

I want to do something like this:
syms x1 x2 h11 h12 h21 h22
x = [x1 x2]
matrix = [h11 h12; h21 h22]
And then create my function as:
f(x, matrix) = ((2*matrix)^(-1/2))*(x');
But I must be doing something wrong because I get:
Error using sym/cat>checkDimensions (line 75) CAT arguments dimensions
are not consistent.
Error in sym/cat>catMany (line 38) [resz, ranges] =
checkDimensions(sz,dim);
Error in sym/cat (line 27)
ySym = catMany(dim, strs);
Error in sym/horzcat (line 19)
ySym = cat(2,args{:});
Error in sym/subsasgn (line 1639)
C = symfun(B,[inds{:}]);

The error is in your function definition. See this link for how to correctly declare a function in MATLAB.
Put this in a separate file named "your_function_name.m"
function result = your_function_name(x, matrix)
result = ((2*matrix)^(-1/2))*(x');
Then you can call your function like this:
x = [x1 x2];
matrix = [h11 h12; h21 h22];
your_function_name(x, matrix);
Or you can use an anonymous function.
x = [x1 x2];
matrix = [h11 h12; h21 h22];
f = #(x, m) ((2*m)^(-1/2))*(x');
f(x, matrix);

Related

how to create a surface in matlab using interpolation

I have x y z data which looks like the following:
How do i create a surface across the lines using z values in matlab (interpolated surface)?
I tried this method but i am getting following error:
[fn,pn] = uigetfile('*.xyz','Open the file');
I = importdata([pn,fn], ',', 16);
x = I.data(:,1);
y = I.data(:,2);
z = I.data(:,3);
%%
spX = min(x):3:max(x);
spY = min(y):3:max(y);
[xC,yC] = meshgrid(spX,spY);
Vq = interp2(x,y,z,xC,yC);
Error using griddedInterpolant
The grid vectors must be strictly monotonically increasing.
Error in interp2>makegriddedinterp (line 229)
F = griddedInterpolant(varargin{:});
Error in interp2 (line 129)
F = makegriddedinterp({X, Y}, V, method,extrap);
Try griddata
spX = min(x):3:max(x);
spY = min(y):3:max(y);
[xC,yC] = meshgrid(spX,spY);
zC = griddata(x,y,z,xC,yC);
surf(xC,yC,zC)

Error using vertcat-Dimensions of matrices being concatenated are not consistent

I'm new to Matlab and am trying to implement this scheme.
Scheme: Un+1 = Minv*((1+2theta)*Un + *Un-1 +bn+1 + fn+1
Given the following equation:
ut(x; t) = cuxx(x; t) + f(x; t)
where x belongs to ]0; 1[: t belongs to ]0; T[, T > 0 and c>0
with Dirichlet boundaries
conditions:
u(0; t) = alpha(t)
u(1; t) = beta(t)
t belongs to [0; T]
The goal of the function in the code is to determine the error(defined in the code).
I keep getting:
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in wave1d_func11910448 (line 60)
uh=[UL;U;UR];
The code:
function [ h,err ] = wave1d_func11910448( nx )
a=0.0; b=1.0;
nx=20;
c=1.0;
tfinal=1;
h=(b-a)/(nx-1);
dt=0.5*h*h/c;
lambda=c*dt/h/h;
theta=1;
x=linspace(a,b,nx);
%defining the function f(x,t)
f = #(x,t) (pi^2-1)*exp(-t)*cos(pi*x)+4*x-2;
Fh=zeros(nx-2,1);%filling the vector f(n+1)
%defining the function g(x,t):initial condition-filling the vector U0
u = #(x) x.^2+cos(pi*x);
U0=u(x(2:end-1));
%defining the exact solution exact(x,t)
exact=#(x,t) x.^2+4*x*t+cos(pi*x)*exp(-t);
%filling the vector u1
U1=exact(x(2:end-1),1);
%defining the functions alpha(t) and beta(t)
alpha = #(t) exp(-t);
beta = #(t) -exp(-t)+4*t+1;
%filling the matrix Mh
Ah=diag(0.0*ones(1,nx-2),0)+diag(1.0*ones(1,nx-3),1)+diag(1.0*ones(1,nx-
3),-1);
Mh=eye(nx-2,nx-2)*(1+theta+2*lambda)-lambda*Ah;
Minv=inv(Mh);
Bh = zeros(nx-2,1);%filling the vector b
time=0.0;
i=0.0;
U2=Minv.*((1+2*theta )*U1-theta*U0+Bh+ dt*Fh);
while(time<tfinal)
time=time+dt;
i=i+1;
Bh(1)=lambda*alpha(time);Bh(nx-2)=lambda*beta(time);
Fh=f(x(2:end-1),time);
U=Minv.*((1+2*theta )*U1-theta*U0+Bh+ dt*Fh);
U0=U1;
U1=U2;
UL=alpha(time);
UR=beta(time);
uh=[UL;U;UR];
error(i) = norm(uh - exact(x,time),inf);
end
err=max(error);
expected results: err= a positive number <1
error message:
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in wave1d_func11910448 (line 60)
uh=[UL;U;UR];

Error when taking gradient of symbolic function

I get an error when taking the gradient of a symbolic function. Can anyone tell me why I get this error?
syms x1 x2 R
L0=0; %[m]
k1=8; %[N/m]
k2=4; %[N/m]
F1=5; %[N]
F2=10; %[N]
F = 0.5*k1*(sqrt(x1^2 + (L0-x2)^2) - L0)^2 + 0.5*k2*(sqrt(x1^2 + (L0+x2)^2)
- L0)^2 - F1*x1 - F2*x2;
f = matlabFunction(F);
R = 0.1;
GI = x1^2 + x2^2 - R^2;
gi = matlabFunction(GI);
epsilon=0.001;
xo=[0,0]';
k = 0;
r = (sqrt(5)-1) / 2;
rpe=0.01;
Merit_pe = #(x1,x2) f(x1,x2) + rpe*(max(0,gi(x1,x2)))^2;
g = gradient(Merit_pe, [x1 x2]);
Error:
Error using sym/max (line 97)
Input arguments must be convertible to
floating-point numbers.
Error in
Ex>#(x1,x2)f(x1,x2)+rpe*(max(0,gi(x1,x2)))^2
Error in sym>funchandle2ref (line 1249)
S = x(S{:});
Error in sym>tomupad (line 1154)
x = funchandle2ref(x);
Error in sym (line 163)
S.s = tomupad(x);
Error in sym/gradient (line 17)
args = privResolveArgs(sym(f));
Error in Ex (line 31)
g = gradient(Merit_pe, [x1 x2])
I think the max part is causing me trouble, but I still need to determine the gradient of this function. Any advise? (I could do it by hand I guess, but I'd rather not if I don't have to)
Directly taking the gradient of max(0,gi(x1,x2)) is not possible in matlab. Instead the function should be defined according to the following definition.
The function Merit_pe can then be defined as follows:
if gi(xo(1,1),xo(2,1)) > 0
Merit_pe = #(x1,x2) f(x1,x2) + rpe*(gi(x1,x2))^2;
else
Merit_pe = #(x1,x2) f(x1,x2);
end
The gradient can then be determined using:
g = gradient(Merit_pe, [x1 x2]);

Evaluate symbolic function in Matlab

I've defined a function in Matlab like this:
clg = 2*pi*(alpha-alphai+0.5*A(1));
where A is an array which depends on alpha.
I want to evaluate clg for aplha=0.53.
I've tried subs(clg, alpha, 0.53), but It gives me a bunch of weird errors:
Error using sym/subs>normalize (line 210)
Entries in second argument must be scalar.
Error in sym/subs>mupadsubs (line 136)
[X2,Y2,symX,symY] = normalize(X,Y); %#ok
Error in sym/subs (line 124)
G = mupadsubs(F,X,Y);
Error in integral (line 45)
subs(clg, alpha, 0.53)
Any idea on how to achieve that?
Thanks!
I have no problem about your question.
>> syms x x1 x2
>> clg = 2*pi*(x-x1+0.5*x2);
>> subs(clg,x,0.53)
ans =
2*pi*(x2/2 - x1 + 53/100)
I am trying to reproduce the problem, but this works:
syms x
%A is a symbolic matrix that depends on x
A = inv([10*x, 2*x, 3*x;
4*x, 10, 6*x;
7*x, 8*x, 10*x])
%y is a symbolic expression defined such that
%it depends on A, but collapses to an expression of x
y = x + 0.5*A(2,2)
%subs returns a symbolic (in this case fraction) evaluation:
subs(y, x, 3)
%eval returns a numeric evaluation:
x = 3
eval(y)
(I have encountered the same error message as you in my own code, but have not yet hunted down its source.)

MATLAB strange error Gamma function numerical integration

i try to run the following in order to integrate numerically:
nu = 8;
psi=-0.2;
lambda = 1;
git = #(u) tpdf((0 - lambda * skewtdis_inverse(u, nu, psi)), nu);
g(t,i) = integral(git,1e-10,1-1e-10,'AbsTol',1e-16);
where tpdf is a matlab function and skewtdis:inverse looks like this:
function inv = skewtdis_inverse(u, nu, lambda)
% PURPOSE: returns the inverse cdf at u of Hansen's (1994) 'skewed t' distribution
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
a = 4*lambda*c*((nu-2)/(nu-1));
b = sqrt(1 + 3*lambda^2 - a^2);
if (u<(1-lambda)/2);
inv = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u/(1-lambda),nu)-a/b;
elseif (u>=(1-lambda)/2);
inv = (1+lambda)/b*sqrt((nu-2)./nu).*tinv(0.5+1/(1+lambda)*(u-(1-lambda)/2),nu)-a/b;
end
What i get out is:
Error in skewtdis_inverse (line 6)
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
Output argument "inv" (and maybe others) not assigned during call to "F:\Xyz\skewtdis_inverse.m>skewtdis_inverse".
Error in #(u)tpdf((0-lambda*skewtdis_inverse(u,nu,psi)),nu)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
If i , however call the function in thr handle directly there are no Problems:
tpdf((0 - lambda * skewtdis_inverse(1e-10, nu, psi)), nu)
ans =
1.4092e-11
tpdf((0 - lambda * skewtdis_inverse(1-1e-10, nu, psi)), nu)
ans =
7.0108e-10
Your effort is highly appreciated!
By default, integral expects the function handle to take a vector input.
In your code, the if-statement creates a complication since the condition will evaluate to true only if all elements of u satisfy it.
So, if u is a vector that has elements both greater than and less than (1-lambda)/2, inv will never be assigned.
There are two options:
Put the if-statement in a for-loop and iterate over all of the elements of u.
Use logical indexes for the assignment.
The second option is faster for large element count and, in my opinion, cleaner:
inv = u; % Allocation
IsBelow = u < (1-lambda)/2; % Below the threshold
IsAbove = ~IsBelow ; % Above the threshold
inv(IsBelow) = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u(IsBelow)/(1-lambda),nu)-a/b;
inv(IsAbove) = (1+lambda)/b*sqrt((nu-2)./nu)*tinv(0.5+1/(1+lambda)*(u(IsAbove)-(1-lambda)/2),nu)-a/b;