If I'm to integrate a function
y = -((F+h)M^3(cosh(h*M)+M*beta*sinh(h*M)))/(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))- (alpha*(M^2*(F+h)*(-1+2*h^2*M^2+ cosh(2*h*M)-2*h*M*sinh(2*h*M)))/(8*(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))^2));
with respect to x, where
phi = 0.6;
x = 0.5;
M = 2;
theta = -1:0.5:1.5;
F = theta - 1;
h = 1 + phi*cos(2*pi*x);
alpha = 0.2;beta = 0.0;
I have written an Mfile
function r = parameterIntegrate(F,h,M,beta,alpha,theta,phi)
% defining a nested function that uses one variable
phi = 0.6;
x = 0.5;
r = quad(#testf,0,1 + phi*cos(2*pi*x));
% simpson's rule from 0 to h
function y = testf(x)
h = 1 + phi*cos(2*pi*x);
theta = -1:0.5:1.5;
F = theta - 1;
M = 2;
beta = 0;
alpha = 0;
y = -((F+h)*M^3*(cosh(h*M)+M*beta*sinh(h*M)))/(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))- (alpha*(M^2*(F+h)*(-1+2*h^2*M^2+ cosh(2*h*M)-2*h*M*sinh(2*h*M)))/(8*(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))^2));
end
end
and called the function by
tol = [1e-5 1e-3];
q = quad(#parameterIntegrate, 0, h,tol)
or
q = quad(#parameterIntegrate, 0,1 + phi*cos(2*pi*0.5),tol)
its not working its giving me
Error using ==> plus
Matrix dimensions must agree.
What your error message means is that for some line of code, there are 2 matrices, but the dimensions don't match, so it can't add them. What I suggest you do to solve this is as follows:
Figure out exactly which line of code is causing the problem.
If the line has large numbers of variables, simplify them some.
Remember that if there are any matrixs at all, and you don't want to do matrix multiplication/division, use the .*, ./, and .^.
I suspect that if you change your multiplies/divides with step 3, your problem will go away.
Related
I'm having some issues getting my RK2 algorithm to work for a certain second-order linear differential equation. I have posted my current code (with the provided parameters) below. For some reason, the value of y1 deviates from the true value by a wider margin each iteration. Any input would be greatly appreciated. Thanks!
Code:
f = #(x,y1,y2) [y2; (1+y2)/x];
a = 1;
b = 2;
alpha = 0;
beta = 1;
n = 21;
h = (b-a)/(n-1);
yexact = #(x) 2*log(x)/log(2) - x +1;
ye = yexact((a:h:b)');
s = (beta - alpha)/(b - a);
y0 = [alpha;s];
[y1, y2] = RungeKuttaTwo2D(f, a, b, h, y0);
error = abs(ye - y1);
function [y1, y2] = RungeKuttaTwo2D(f, a, b, h, y0)
n = floor((b-a)/h);
y1 = zeros(n+1,1); y2 = y1;
y1(1) = y0(1); y2(1) = y0(2);
for i=1:n-1
ti = a+(i-1)*h;
fvalue1 = f(ti,y1(i),y2(i));
k1 = h*fvalue1;
fvalue2 = f(ti+h/2,y1(i)+k1(1)/2,y2(i)+k1(2)/2);
k2 = h*fvalue2;
y1(i+1) = y1(i) + k2(1);
y2(i+1) = y2(i) + k2(2);
end
end
Your exact solution is wrong. It is possible that your differential equation is missing a minus sign.
y2'=(1+y2)/x has as its solution y2(x)=C*x-1 and as y1'=y2 then y1(x)=0.5*C*x^2-x+D.
If the sign in the y2 equation were flipped, y2'=-(1+y2)/x, one would get y2(x)=C/x-1 with integral y1(x)=C*log(x)-x+D, which contains the given exact solution.
0=y1(1) = -1+D ==> D=1
1=y1(2) = C*log(2)-1 == C=1/log(2)
Additionally, the arrays in the integration loop have length n+1, so that the loop has to be from i=1 to n. Else the last element remains zero, which gives wrong residuals for the second boundary condition.
Correcting that and enlarging the computation to one secant step finds the correct solution for the discretization, as the ODE is linear. The error to the exact solution is bounded by 0.000285, which is reasonable for a second order method with step size 0.05.
I am generating two different coordinates (x, y) within a loop. In my code, I have just realised that it is saving the last variable from the loop. I am, however, trying to save all the iterations from the setsize variable. I already tried to save using something like:
circleposition = [0:length(setsize) x(i),y(i)];
But, it seems that I am not doing it correctly, getting the following error:
Subscript indices must either be real positive integers or logicals.-
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Here is my original code:
setsize = 9;
r = 340;
cx = 500;
cy = 500;
anglesegment = 2 * pi/setsize;
circleposition = [];
for i = drange (0:setsize)
x = r * cos(i*anglesegment) + cx;
y = r * sin(i*anglesegment) + cy;
circleposition = [x,y];
end
Output:
circleposition =
0 1.0000
840.0000 500.0000
It runs only with the first/last iteration. I need to get 9 x's and 9 y's (depending the setsize, variable).
It's kind of hard to follow, which error message comes from which attempt, but let's have a look.
I don't have access to the Parallel Computing Toolbox, which seems necessary to use the for-loop over distributed range drange, but I assume, this loop can be replaced by for i = 0:setsize for testing.
Now, when starting at i = 0, you would try to access x(0) and y(0), which is not allowed (Subscript indices must either be real positive integers or logicals). Also, you would get 10 values instead of 9, as you stated in your question. So, let's start at i = 1.
To store all 9 pairs of x and y, your circleposition should be an 9 x 2 array So, initialize that by, for example, circleposition = zeros(setsize, 2).
Last, you need to use proper indexing to store [x, y] at the i-th row of circleposition, i.e. circleposition(i, :).
So, the corrected code (attention on the replaced drange part) could look like this:
setsize = 9;
r = 340;
cx = 500;
cy = 500;
anglesegment = 2 * pi/setsize;
circleposition = zeros(setsize, 2); % Initialize circleposition appropriately
for i = 1:setsize % Start at i = 1
x = r * cos(i*anglesegment) + cx;
y = r * sin(i*anglesegment) + cy;
circleposition(i, :) = [x, y]; % Correct indexing of the row
end
circleposition % Output
The output would then be:
circleposition =
760.46 718.55
559.04 834.83
330.00 794.45
180.50 616.29
180.50 383.71
330.00 205.55
559.04 165.17
760.46 281.45
840.00 500.00
On the second error (Error using vertcat. Dimensions of matrices being concatenated are not consistent.): I don't see, where you used vertical concatenation at all!?
Hear is code that works:
setsize = 9;
r = 340;
cx = 500;
cy = 500;
anglesegment = 2 * pi/setsize;
circleposition = zeros(setsize + 1, 2); % Changed from circleposition = []
for i = drange (0:setsize)
x = r * cos(i*anglesegment) + cx;
y = r * sin(i*anglesegment) + cy;
circleposition((i+1),:) = [x,y]; % Changed from circleposition = [x,y];
end
Explanation:
The fix was Changing circleposition = [x,y]; to circleposition((i+1),:) = [x,y]. Without ((i+1),:), you are changing the data of circleposition, not adding to it.
Changing circleposition = []; to circleposition = zeros(setsize + 1, 2); was not required, its just recommended to allocate memory for speed, not an issue for small number of elements.
I am using MATLAB to calculate the numerical integral of a complex function including natural exponent.
I get a warning:
Infinite or Not-a-Number value encountered
if I use the function integral, while another error is thrown:
Output of the function must be the same size as the input
if I use the function quadgk.
I think the reason could be that the integrand is infinite when the variable ep is near zero.
Code shown below. Hope you guys can help me figure it out.
close all
clear
clc
%%
N = 10^5;
edot = 10^8;
yita = N/edot;
kB = 8.6173324*10^(-5);
T = 300;
gamainf = 0.115;
dTol = 3;
K0 = 180;
K = K0/160.21766208;
nu = 3*10^12;
i = 1;
data = [];
%% lambda = ec/ef < 1
for ef = 0.01:0.01:0.1
for lambda = 0.01:0.01:0.08
ec = lambda*ef;
f = #(ep) exp(-((32/3)*pi*gamainf^3*(0.5+0.5*sqrt(1+2*dTol*K*(ep-ec)/gamainf)-dTol*K*(ep-ec)/gamainf).^3/(K*(ep-ec)).^2-16*pi*gamainf^3*(0.5+0.5*sqrt(1+2*dTol*K*(ep-ec)/gamainf)-dTol*K*(ep-ec)/gamainf).^2/((1+dTol*K*(ep-ec)/(gamainf*(0.5+0.5*sqrt(1+2*dTol*K*(ep-ec)/gamainf)-dTol*K*(ep-ec)/gamainf)))*(K*(ep-ec)).^2))/(kB*T));
q = integral(f,0,ef,'ArrayValued',true);
% q = quadgk(f,0,ef);
prob = 1-exp(-yita*nu*q);
data(i,1) = ef;
data(i,2) = lambda;
data(i,3) = q;
i = i+1;
end
end
I've rewritten your equations so that a human can actually understand it:
function integration
N = 1e5;
edot = 1e8;
yita = N/edot;
kB = 8.6173324e-5;
T = 300;
gamainf = 0.115;
dTol = 3;
K0 = 180;
K = K0/160.21766208;
nu = 3e12;
i = 1;
data = [];
%% lambda = ec/ef < 1
for ef = 0.01:0.01:0.1
for lambda = 0.01:0.01:0.08
ec = lambda*ef;
q = integral(#f,0,ef,'ArrayValued',true);
% q = quadgk(f,0,ef);
prob = 1 - exp(-yita*nu*q);
data(i,:) = [ef lambda q];
i = i+1;
end
end
function y = f(ep)
G = K*(ep - ec);
r = dTol*G/gamainf;
S = sqrt(1 + 2*r);
x = (1 + S)/2 - r;
Z = 16*pi*gamainf^3;
y = exp( -Z*x.^2.*( 2*x/(3*G.^2) - 1/(G.^2*(1 + r/x))) ) /...
(kB*T));
end
end
Now, for the first iteration, ep = 0.01, the value of the argument of the exp() function inside f is huge. In fact, if I rework the function to return the argument to the exponent (not the value):
function y = f(ep)
% ... all of the above
% NOTE: removed the exp() to return the argument
y = -Z*x.^2.*( 2*x/(3*G.^2) - 1/(G.^2*(1 + r/x))) ) /...
(kB*T);
end
and print its value at some example nodes like so:
for ef = 0.01 : 0.01 : 0.1
for lambda = 0.01 : 0.01 : 0.08
ec = lambda*ef;
zzz(i,:) = [f(0) f(ef/4) f(ef)];
i = i+1;
end
end
zzz
I get this:
% f(0) f(ef/4) f(ef)
zzz =
7.878426438111721e+07 1.093627454284284e+05 3.091140080273912e+03
1.986962280947140e+07 1.201698288371587e+05 3.187767404903769e+03
8.908646053687230e+06 1.325435523124976e+05 3.288027743119838e+03
5.055141696747510e+06 1.467952125661714e+05 3.392088351112798e+03
...
3.601790797707676e+04 2.897200140791236e+02 2.577170427480841e+01
2.869829209254144e+04 3.673888685004256e+02 2.404148067956737e+01
2.381082059148755e+04 4.671147785149462e+02 2.238181495716831e+01
So, integral() has to deal with things like exp(10^7). This may not be a problem per se if the argument would fall off quickly enough, but as shown above, it doesn't.
So basically you're asking for the integral of a function that ranges in value between exp(~10^7) and exp(~10^3). Needless to say, The d(ef) in the order of 0.01 isn't going to compensate for that, and it'll be non-finite in floating point arithmetic.
I suspect you have a scaling problem. Judging from the names of your variables as well as the equations, I would think that this has something to do with thermodynamics; a reworked form of Planck's law? In that case, I'd check if you're working in nanometers; a few factors of 10^(-9) will creep in, rescaling your integrand to the compfortably computable range.
In any case, it'll be wise to check all your units, because it's something like that that's messing up the numbers.
NB: the maximum exp() you can compute is around exp(709.7827128933840)
Following code throws out an error.
syms z positive;
syms n;
syms m;
N = 10;
Ms = 10;
Es = 1;
pd = 0.9;
pd_dash = 1-pd;
pf = 0.1;
pf_dash = 1-pf;
pr = 0.1;
qr = 1-pr;
p = 0.005
pi = pf_dash*p;
pb = pd_dash*p;
qi = 1-pi;
qb = 1-pb;
sm = symsum( z^((n+1)*Es), n, 0, N-1 );
temp_sum = symsum(z^((n+m+1)*Es)*qr^(n+m)*pr, m, 0, N-1);
z=1; %assume a value of z
x = eval(sm); %works fine
y = eval(temp_sum);
% Error:The expression to the left of the equals sign is not a valid target for an assignment.
Please suggest a way to resolve this.
The problem that I suspect is: the temp_sum comes out to be in piecewise(...) which eval is not capable of evaluating.
What you actually did:
Create a symbolic expression
Create a variable z which is unused
Call a undocumented function sym/eval
I assume you wanted to:
Create a symbolic expression
Substitute z with 1: temp_sum=subs(temp_sum,z,1)
get the result. Here I don't know what you really have because I don't know which variables are symbolic unknowns and which constants. Try simplify(temp_sum). If you substituted all unknowns it should return a number.
In Matlab I want to create the partial derivative of a cost function called J(theta_0, theta_1) (in order to do the calculations necessary to do gradient descent).
The function J(theta_0, theta_1) is defined as:
Lets say h_theta(x) = theta_1 + theta_2*x. Also: alpha is fixed, the starting values of theta_1 and theta_2 are given. Let's say in this example: alpha = 0.1 theta_1 = 0, theta_2 = 1. Also I have all the values for x and y in two different vectors.
VectorOfX =
5
5
6
VectorOfX =
6
6
10
Steps I took to try to solve this in Matlab: I have no clue how to solve this problem in matlab. So I started off with trying to define a function in Matlab and tried this:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*x;
This worked, but is not what I really wanted. I wanted to get x^(i), which is in a vector. The next thing I tried was:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*vectorOfX(1);
This gives the following error:
Error using sym/subsindex (line 672)
Invalid indexing or function definition. When defining a
function, ensure that the body of the function is a SYM
object. When indexing, the input must be numeric, logical or
':'.
Error in prog1>gradientDescent (line 46)
h_theta(x) = theta_1 + theta_2*vectorOfX(x);
I looked up this error and don't know how to solve it for this particular example. I have the feeling that I make matlab work against me instead of using it in my favor.
When I have to perform symbolic computations I prefer to use Mathematica. In that environment this is the code to get the partial derivatives you are looking for.
J[th1_, th2_, m_] := Sum[(th1 + th2*Subscript[x, i] - Subscript[y, i])^2, {i, 1, m}]/(2*m)
D[J[th1, th2, m], th1]
D[J[th1, th2, m], th2]
and gives
Coming back to MATLAB we can solve this problem with the following code
%// Constants.
alpha = 0.1;
theta_1 = 0;
theta_2 = 1;
X = [5 ; 5 ; 6];
Y = [6 ; 6 ; 10];
%// Number of points.
m = length(X);
%// Partial derivatives.
Dtheta1 = #(theta_1, theta_2) sum(2*(theta_1+theta_2*X-Y))/2/m;
Dtheta2 = #(theta_1, theta_2) sum(2*X.*(theta_1+theta_2*X-Y))/2/m;
%// Loop initialization.
toll = 1e-5;
maxIter = 100;
it = 0;
err = 1;
theta_1_Last = theta_1;
theta_2_Last = theta_2;
%// Iterations.
while err>toll && it<maxIter
theta_1 = theta_1 - alpha*Dtheta1(theta_1, theta_2);
theta_2 = theta_2 - alpha*Dtheta2(theta_1, theta_2);
it = it + 1;
err = norm([theta_1-theta_1_Last ; theta_2-theta_2_Last]);
theta_1_Last = theta_1;
theta_2_Last = theta_2;
end
Unfortunately for this case the iterations does not converge.
MATLAB is not very flexible for symbolic computations, however a way to get those partial derivatives is the following
m = 10;
syms th1 th2
x = sym('x', [m 1]);
y = sym('y', [m 1]);
J = #(th1, th2) sum((th1+th2.*x-y).^2)/2/m;
diff(J, th1)
diff(J, th2)