Calculating numerical integral using MATLAB - matlab

I have an equation of the following form:
where A,B,C, and q are 3-by-3 matrix and Tr[...] represent trace. And
here b is a constant. The explicit form of A,B(x,y,E),C(x,y,E), q(x,y) matrices is written in the below MATLAB code. I am trying to solve it using the integral3() function of MATLAB. But it is giving me errors.
I wrote the function for the integrant in two different ways. And run the script:
integral3(#fun1,-pi,pi,-pi,pi,-inf,inf)
function file 1:
function out = fun1(x,y,E)
%=============just some constants==========
DbyJ = 2/sqrt(3);
T = 1e-2;
eta = 1e-3;
b = 1/T;
D = 1+1i*DbyJ;
fk1 = 1+exp(1i*x);
fk2 = 1+exp(1i*y);
fk1k2 = 1+exp(1i*(x-y));
%=============Matrices==========
A = eye(3); A(1,1) = 1;
q = [0, 1i*D*exp(-1i*x), 0 ;
-1i*conj(D)*exp(1i*x), 0,-1i*D*exp(1i*(x-y));
0,1i*conj(D)*exp(1i*(y-x)),0];
h = [0 -D*conj(fk1) -conj(D)*conj(fk2);
-conj(D)*fk1 0 -D*fk1k2;
-D*fk2 -conj(D)*conj(fk1k2) 0];
B = ((E-1i*eta)*eye(3) - h)^(-1);
C = conj(B);
Term1 = A*(B-C)*q*(B-C);
trc = trace(Term1);
N = -b*exp(b*E)/((exp(b*E)-1)^2);
out = trc*E*N;
It gave me the following error:
Error using horzcat
Dimensions of arrays being concatenated are not consistent.
Error in fun1 (line 19)
q = [0, 1i*D*exp(-1i*x), 0 ;
Then I tried to solve Tr[...] part symbolically and removed the matrices from integrant. The function file is very large for this, so, I am not putting it here. Anyway, it give me error that
Error using *
Incorrect dimensions for matrix multiplication. Check that the number of columns in the first matrix matches the number of rows in the second matrix. To perform elementwise multiplication, use '.*'.
Error in fun1 (line 33)
trc = (D*exp(-x*1i)*((exp(conj(x ... (it is a very long expression that I calculated symbolically to remove matrices.)
Question:
Why integral3() is not working?
Is there any other way to solve this kind of integrals numerically? (In Python or in any other software/language).
Thank you for reading.
TLDD:
How can I solve the above given integral numerically?

Related

Having difficulties in finding error: Matrix dimensions must agree

My aim is to call this function into the pso code for minimization.
actually im calling this code into another program(mfile),here
v=0.1*x0; % initial velocity
for i=1:n
f0(i,1)=ofun(x0(i,:));
end
so what should i do, could anyone plz write me a code, so i can remove this problem. my aim is to minimize error using ITEA code, which im trying to do, im trying to find a that every time code runs, e_t have last updated value, not e_t=0.001 .
I don't have e_t. If I'm going to initialize it, it will remain constant, but I need to change its value in the code.
Second, I'm getting this error
Error using .* Matrix dimensions must agree.
Error in ofun (line 10), f = sum(t'.*abs(e_t)*dt);
function f=ofun(x)
Kp= x(1);
Ki= x(2);
e_t;
d=0.001;
I_ref=-1.1:d:1;
dt = 0.01;
t = 0:dt:1;
e_t= I_ref - (Kp.*e_t +Ki.*sum(t'.*abs(e_t)*dt));
f = sum(t'.*abs(e_t)*dt); % line 10
I want to write code for following equations
error= I_ref - (kp * error + ki*(integration of error));
I want to set I-ref=-1.1-1.1;
Here e_t get's the same size as I_ref
e_t= I_ref - (Kp.*e_t +Ki.*sum(t'.*abs(e_t)*dt));
Then you want to multiply it with t
f = sum(t'.*abs(e_t)*dt);
But t is of a different size as I_ref. t has length 101, I_ref has length 2101.
"Matrix dimensions must agree" is an error message that appears in this case in line 10 because matrix t cannot be multiplied elementwise with the e_t. Whichever matrix is smaller, I would probably add ones to the rest of it so that the result matrix is still able tone populated. Why are you transposing matrix t though? Good luck with your project!
function f=ofun(x)
%Define variables and constants- when you define e_t, why are you not multiplying dt elementwise? Also why do you transpose matrix t?
Kp = x(1); Ki = x(2); d = 0.001; I_ref = [-1.1 : d : 1]; dt = 0.01; t = [0 : dt : 1]; e_t = I_ref - (Kp.*e_t + Ki.*sum(t'.*abs(e_t)*dt));
f = sum(t'.*abs(e_t)*dt);% line 10
end

Why I am getting matrix dimension error in the line while calculating n?

Can you please tell me what's wrong with the following code?
function [n]=calculate_n(p,delta)
e = 1.6*power(10,-19);
k = 1.38*power(10,-23);
T = 298;
co = 3.25*power(10,13)*e*power(10,4);
er=12.5;
eo=1.0;
Nv=3*power(10,13);
us = log((p*e)/sqrt(2*k*T*er*eo*Nv))*2*k*T;
tmp = delta+(e*e*p)/co+us;
n = 1/(exp((tmp))+1);
end
I am getting matrix dimension error while calculating n. Please help me.
Caller:
e = 1.6*power(10,-19);
x = logspace(13,18);
y=calculate_n(x,0.2*e);
semilogx(x,y,'-s');
grid on;
Just replace n = 1/(exp((tmp))+1); with n = 1./(exp(tmp)+1);. But beware, tmp is so small for these values that exp(tmp) will always be 1. Also, there is a surplus bracket around tmp, you might want to check if you put them correctly.
Edit:
The reason is that A/B tries to solve the system of linear equations A*x = B for x which is not what you wanted. It threw an error because it requires both variables to have the same number of columns. A./B performs element-wise matrix division which is what you wanted. However, if A and B are singular A/B = A./B. See the documentation for more info.

How do I define parameters in a convolution equation?

I am trying to compute the convolution of a sound signal without using the built in conv function but instead using arrays. x is the input signal and h is are the impulse responses. However, when I run my other main function to call onto my_conv I am getting these errors:
Undefined function or variable 'nx'.**
Error in my_conv (line 6)
ly=nx+nh-1;
Error in main_stereo (line 66)
leftchannel = my_conv(leftimp, mono); % convolution of left ear impulse response and mono
This is my function my_conv:
function [y]=my_conv(x,h)
x=x(:);
h=h(:);
lx=length(x);
lh=length(h);
ly=nx+nh-1;
Y=zeros(nh,ny);
for i =1:nh
Y((1:nx)+(i-1),i)=x;
end
y=Y*h;
What changes should I make to fix these errors and get this code running?
I am trying to immplement the function into this code:
input_filename = 'speech.wav';
stereo_filename = 'stereo2.wav';
imp_filename = 'H0e090a.dat';
len_imp = 128;
fp = fopen(imp_filename, 'r', 'ieee-be');
data = fread(fp, 2*len_imp, 'short');
fclose(fp);
[mono,Fs] = audioread(input_filename);
if (Fs~=44100)
end
len_mono = length(mono);
leftimp = data(1:2:2*len_imp);
rightimp = data(2:2:2*len_imp);
leftchannel = my_conv(leftimp, mono);
rightchannel = my_conv(rightimp, mono);
leftchannel = reshape(leftchannel , length(leftchannel ), 1);
rightchannel = reshape(rightchannel, length(rightchannel), 1);
norml = max(abs([leftchannel; rightchannel]))*1.05;
audiowrite(stereo_filename, [leftchannel rightchannel]/norml, Fs);
As pointed out by #SardarUsama in comments, the error
Undefined function or variable 'nx'.
Error in my_conv (line 6) ly=nx+nh-1;
tells you that the variable nx has not been defined before before its usage on the line ly=nx+nh-1. Given the naming of the variables and their usage, it looks like what you intended to do was:
nx = length(x);
nh = length(h);
ny = nx+nh-1;
After making these modifications and solving the first error, you are likely going to get another error telling you that
error: my_conv: operator *: nonconformant arguments
This error is due to an inversion in the specified size of the Y matrix. This can be fixed by initializing Y with Y = zeros(ny, nh);. The resulting my_conv function follows:
function [y]=my_conv(x,h)
nx=length(x);
nh=length(h);
ny=nx+nh-1;
Y=zeros(ny,nh);
for i =1:nh
Y((1:nx)+(i-1),i)=x;
end
y=Y*h;
Note that storing every possible shifts of one of the input vectors in the matrix Y to compute the convolution as a matrix multiplication is not very memory efficient (requiring O(NM) storage). A more memory efficient implementation would compute each element of the output vector directly:
function [y]=my_conv(x,h)
nx=length(x);
nh=length(h);
if (nx < nh)
y = my_conv(h,x);
else
ny=nx+nh-1;
y = zeros(1,ny);
for i =1:ny
idh = [max(i-(ny-nh),1):min(i,nh)]
idx = [min(i,nx):-1:max(nx-(ny-i),1)]
y(i) = sum(x(idx).*h(idh));
end
end
An alternate implementation which can be more computationally efficient for large arrays would make use of the convolution theorem and use the Fast Fourier Transform (FFT):
function [y]=my_conv2(x,h)
nx=length(x);
nh=length(h);
ny=nx+nh-1;
if (size(x,1)>size(x,2))
x = transpose(x);
end
if (size(h,1)>size(h,2))
h = transpose(h);
end
Xf = fft([x zeros(size(x,1),ny-nx)]);
Hf = fft([h zeros(size(h,1),ny-nh)]);
y = ifft(Xf .* Hf);

Bessel's integral implementation

I'm trying to implement this integral representation of Bessel function of the first kind of order n.
here is what I tried:
t = -pi:0.1:pi;
n = 1;
x = 0:5:20;
A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
B(t) = integral(A(t),-pi,pi);
plot(A(t),x)
the plot i'm trying to get is as shown in the wikipedia page.
it said:
Error using * Inner matrix dimensions must agree.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
so i tried putting x-5;
and the output was:
Subscript indices must either be real positive integers or logicals.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
How to get this correct? what am I missing?
To present an anonymous function in MATLAB you can use (NOT A(t)=...)
A = #(t) exp(sqrt(-1)*(n*t-x.*sin(t)));
with element-by-element operations (here I used .*).
Additional comments:
You can use 1i instead of sqrt(-1).
B(t) cannot be the function of the t argument, because t is the internal variable for integration.
There are two independent variables in plot(A(t),x). Thus you can display plot just if t and x have the same size. May be you meant something like this plot(x,A(x)) to display the function A(x) or plot(A(x),x) to display the inverse function of A(x).
Finally you code can be like this:
n = 1;
x = 0:.1:20;
A = #(x,t) exp(sqrt(-1)*(n*t-x.*sin(t)));
B = #(x) integral(#(t) A(x,t),-pi,pi);
for n_x=1:length(x)
B_x(n_x) = B(x(n_x));
end
plot(x,real(B_x))

Fitting model to data in matlab

i have some experimental data and a theoretical model which i would like to try and fit. i have made a function file with the model - the code is shown below
function [ Q,P ] = RodFit(k,C )
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
R = 10; % radius in Å
L = 1000; % length in Å
Q = 0.001:0.0001:0.5;
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
end
with Q being the x-values and P being the y-values. I can call the function fine from the matlab command line and it works fine e.g. [Q,P] = RodFit(1,0.001) gives me a result i can plot using plot(Q,P)
But i cannot figure how to best find the fit to some experimental data. Ideally, i would like to use the optimization toolbox and lsqcurvefit since i would then also be able to optimize the R and L parameters. but i do not know how to pass (x,y) data to lsqcurvefit. i have attempted it with the code below but it does not work
File = 30; % the specific observation you want to fit the model to
ydata = DataFiles{1,File}.data(:,2)';
% RAdius = linspace(10,1000,length(ydata));
% LEngth = linspace(100,10000,length(ydata));
Multiplier = linspace(1e-3,1e3,length(ydata));
Constant = linspace(0,1,length(ydata));
xdata = [Multiplier; Constant]; % RAdius; LEngth;
L = lsqcurvefit(#RodFit,[1;0],xdata,ydata);
it gives me the error message:
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have tried i) making all vectors/matrices the same length and ii) tried using .* instead. nothing works and i am giving the same error message
Any kind of help would be greatly appreciated, whether it is suggestion regading what method is should use, suggestions to my code or something third.
EDIT TO ANSWER Osmoses:
A really good point but i do not think that is the problem. just checked the size of the all the vectors/matrices and they should be alright
>> size(Q)
ans =
1 1780
>> size(P)
ans =
1 1780
>> size(xdata)
ans =
2 1780
>> size([1;0.001]) - the initial guess/start point for xdata (x0)
ans =
2 1
>> size(ydata)
ans =
1 1780
UPDATE
I think i have identified the problem. the function RodFit works fine when i specify the input directly e.g. [Q,P] = RodFit(1,0.001);.
however, if i define x0 as x0 = [1,0.001] i cannot pass x0 to the function
>> x0 = [1;0.001]
x0 =
1.0000
0.0010
>> RodFit(x0);
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
The same happens if i use x0 = [1,0.001]
clearly, matlab is interpreting x0 as input for k only and attempts to multiplay a vector of length(ydata) and a vector of length(x0) which obviously fails.
So my problem is that i need to code so that lsqcurvefit understands that the first column of xdata and x0 is the k variable and the second column of xdata and x0 is the C variable. According to the documentation - Passing Matrix Arguments - i should be able to pass x0 as a matrix to the solver. The solver should then also pass the xdata in the same format as x0.
Have you tried (that's sometimes the mistake) looking at the orientation of your input data (e.g. if xdata & ydata are both row/column vectors?). Other than that your code looks like it should work.
I have been able to solve some of the problems. One mistake in my code was that the objective function did not use of vector a variables but instead took in two variables - k and C. changing the code to accept a vector solved this problem
function [ Q,P ] = RodFit(X)
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
% Q = 0.001:0.0001:0.5;
Q = linspace(0.11198,4.46904,1780);
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*X(1)+X(2);
with the code above, i can define x0 as x0 = [1 0.001];, and pass that into RodFit and get a result. i can also pass xdata into the function and get a result e.g. [Q,P] = RodFit(xdata(2,:));
Notice i have changed the orientation of all vectors so that they are now row-vectors and xdata has size size(xdata) = 1780 2
so i thought i had solved the problem completely but i still run into problems when i run lsqcurvefit. i get the error message
Error using RodFit
Too many input arguments.
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have no idea why - does anyone have any idea about why Rodfit recieves to many input arguments when i call lsqcurvefit but not when i run the function manual using xdata?