Help in Matlab Laplace Equation - matlab

I have tried to implement Laplace equation in my matlab code sequence as shown below. I created this LaplaceExplicit.m and thus used another function numgrid in the same. However, it shows error as "Input variable n is undefined". What should be done? The code is as below-
function [x,y,T]= LaplaceExplicit(n,m,Dx,Dy)
echo off;
numgrid(n,m);
R = 5.0;
T = R*ones(n+1,m+1); % All T(i,j) = 1 includes all boundary conditions
x = [0:Dx:n*Dx];y=[0:Dy:m*Dy]; % x and y vectors
for i = 1:n % Boundary conditions at j = m+1 and j = 1
6
T(i,m+1) = T(i,m+1)+ R*x(i)*(1-x(i));
T(i,1) = T(i,1) + R*x(i)*(x(i)-1);
end;
TN = T; % TN = new iteration for solution
err = TN-T;
% Parameters in the solution
beta = Dx/Dy;
denom = 2*(1+beta^2);
% Iterative procedure
epsilon = 1e-5; % tolerance for convergence
imax = 1000; % maximum number of iterations allowed
k = 1; % initial index value for iteration
% Calculation loop
while k<= imax
for i = 2:n
for j = 2:m
TN(i,j)=(T(i-1,j)+T(i+1,j)+beta^2*(T(i,j-1)+T(i,j+1)))/denom;
err(i,j) = abs(TN(i,j)-T(i,j));
end;
end;
T = TN; k = k + 1;
errmax = max(max(err));
if errmax < epsilon
[X,Y] = meshgrid(x,y);
figure(2);contour(X,Y,T',20);xlabel('x');ylabel('y');
title('Laplace equation solution - Dirichlet boundary conditions Explicit');
figure(3);surfc(X,Y,T');xlabel('x');ylabel('y');zlabel('T(x,y)');
title('Laplace equation solution - Dirichlet boundary conditions Explicit');
fprintf('Convergence achieved after %i iterations.\n',k);
fprintf('See the following figures:\n');
fprintf('==========================\n');
fprintf('Figure 1 - sketch of computational grid \n');
fprintf('Figure 2 - contour plot of temperature \n');
fprintf('Figure 3 - surface plot of temperature \n');
return
end;
end;
fprintf('\n No convergence after %i iterations.',k);

MATLAB will go through a standard look-up procedure to work out what it represents. First, is it a local variable? If not, is a function or script (command)? This also requires looking in a prescribed set of places. The simple version is: first look in the current directory, then look in the directories specified by the MATLAB path (in order).
Hence, if you write square_table.m and save it in C:\work\Moe\MATLAB then that directory needs to be either the current working directory on on the MATLAB path. Otherwise you will get an error ("undefined function or variable").

Sorry people, got my questions answered.. it was just some problem with initialisation and calling a function defined in another .m file. Resolved it and now the code's working fine.. :)

Related

MATLAB to Scilab conversion: mfile2sci error "File contains no instruction"

I am very new to Scilab, but so far have not been able to find an answer (either here or via google) to my question. I'm sure it's a simple solution, but I'm at a loss. I have a lot of MATLAB scripts I wrote in grad school, but now that I'm out of school, I no longer have access to MATLAB (and can't justify the cost). Scilab looked like the best open alternative. I'm trying to convert my .m files to Scilab compatible versions using mfile2sci, but when running the mfile2sci GUI, I get the error/message shown below. Attached is the original code from the M-file, in case it's relevant.
I Searched Stack Overflow and companion sites, Google, Scilab documentation.
The M-file code follows (it's a super basic MATLAB script as part of an old homework question -- I chose it as it's the shortest, most straightforward M-file I had):
Mmax = 15;
N = 20;
T = 2000;
%define upper limit for sparsity of signal
smax = 15;
mNE = zeros(smax,Mmax);
mESR= zeros(smax,Mmax);
for M = 1:Mmax
aNormErr = zeros(smax,1);
aSz = zeros(smax,1);
ESR = zeros(smax,1);
for s=1:smax % for-loop to loop script smax times
normErr = zeros(1,T);
vESR = zeros(1,T);
sz = zeros(1,T);
for t=1:T %for-loop to carry out 2000 trials per s-value
esr = 0;
A = randn(M,N); % generate random MxN matrix
[M,N] = size(A);
An = zeros(M,N); % initialize normalized matrix
for h = 1:size(A,2) % normalize columns of matrix A
V = A(:,h)/norm(A(:,h));
An(:,h) = V;
end
A = An; % replace A with its column-normalized counterpart
c = randperm(N,s); % create random support vector with s entries
x = zeros(N,1); % initialize vector x
for i = 1:size(c,2)
val = (10-1)*rand + 1;% generate interval [1,10]
neg = mod(randi(10),2); % include [-10,-1]
if neg~=0
val = -1*val;
end
x(c(i)) = val; %replace c(i)th value of x with the nonzero value
end
y = A*x; % generate measurement vector (y)
R = y;
S = []; % initialize array to store selected columns of A
indx = []; % vector to store indices of selected columns
coeff = zeros(1,s); % vector to store coefficients of approx.
stop = 10; % init. stop condition
in = 0; % index variable
esr = 0;
xhat = zeros(N,1); % intialize estimated x signal
while (stop>0.5 && size(S,2)<smax)
%MAX = abs(A(:,1)'*R);
maxV = zeros(1,N);
for i = 1:size(A,2)
maxV(i) = abs(A(:,i)'*R);
end
in = find(maxV == max(maxV));
indx = [indx in];
S = [S A(:,in)];
coeff = [coeff R'*S(:,size(S,2))]; % update coefficient vector
for w=1:size(S,2)
r = y - ((R'*S(:,w))*S(:,w)); % update residuals
if norm(r)<norm(R)
index = w;
end
R = r;
stop = norm(R); % update stop condition
end
for j=1:size(S,2) % place coefficients into xhat at correct indices
xhat(indx(j))=coeff(j);
end
nE = norm(x-xhat)/norm(x); % calculate normalized error for this estimate
%esr = 0;
indx = sort(indx);
c = sort(c);
if isequal(indx,c)
esr = esr+1;
end
end
vESR(t) = esr;
sz(t) = size(S,2);
normErr(t) = nE;
end
%avsz = sum(sz)/T;
aSz(s) = sum(sz)/T;
%aESR = sum(vESR)/T;
ESR(s) = sum(vESR)/T;
%avnormErr = sum(normErr)/T; % produce average normalized error for these run
aNormErr(s) = sum(normErr)/T; % add new avnormErr to vector of all av norm errors
end
% just put this here to view the vector
mNE(:,M) = aNormErr;
mESR(:,M) = ESR;
% had an 'end' placed here, might've been unmatched
mNE%reshape(mNE,[],Mmax)
mESR%reshape(mESR,[],Mmax)]
figure
dimx = [1 Mmax];
dimy = [1 smax];
imagesc(dimx,dimy,mESR)
colormap gray
strESR = sprintf('Average ESR, N=%d',N);
title(strESR);
xlabel('M');
ylabel('s');
strNE = sprintf('Average Normed Error, N=%d',N);
figure
imagesc(dimx,dimy,mNE)
colormap gray
title(strNE)
xlabel('M');
ylabel('s');
The command used (and results) follow:
--> mfile2sci
ans =
[]
****** Beginning of mfile2sci() session ******
File to convert: C:/Users/User/Downloads/WTF_new.m
Result file path: C:/Users/User/DOWNLO~1/
Recursive mode: OFF
Only double values used in M-file: NO
Verbose mode: 3
Generate formatted code: NO
M-file reading...
M-file reading: Done
Syntax modification...
Syntax modification: Done
File contains no instruction, no translation made...
****** End of mfile2sci() session ******
To convert the foo.m file one has to enter
mfile2sci <path>/foo.m
where stands for the path of the directoty where foo.m is. The result is written in /foo.sci
Remove the ```` at the begining of each line, the conversion will proceed normally ?. However, don't expect to obtain a working .sci file as the m2sci converter is (to me) still an experimental tool !

Finding the nth root of the bessel function of the first kind (J0(x)) using bisection

First of all, I would just like to clarify that this is an assignment for school, so I am not looking for a solution. I simply want to be pushed in the right direction.
Now, for the problem.
We have code for finding the root of a polynomial using bisection:
function [root, niter, rlist] = bisection2( func, xint, tol )
% BISECTION2: Bisection algorithm for solving a nonlinear equation
% (non-recursive).
%
% Sample usage:
% [root, niter, rlist] = bisection2( func, xint, tol )
%
% Input:
% func - function to be solved
% xint - interval [xleft,xright] bracketing the root
% tol - convergence tolerance (OPTIONAL, defaults to 1e-6)
%
% Output:
% root - final estimate of the root
% niter - number of iterations needed
% rlist - list of midpoint values obtained in each iteration.
% First, do some error checking on parameters.
if nargin < 2
fprintf( 1, 'BISECTION2: must be called with at least two arguments' );
error( 'Usage: [root, niter, rlist] = bisection( func, xint, [tol])' );
end
if length(xint) ~= 2, error( 'Parameter ''xint'' must be a vector of length 2.' ), end
if nargin < 3, tol = 1e-6; end
% fcnchk(...) allows a string function to be sent as a parameter, and
% coverts it to the correct type to allow evaluation by feval().
func = fcnchk( func );
done = 0;
rlist = [xint(1); xint(2)];
niter = 0;
while ~done
% The next line is a more accurate way of computing
% xmid = (x(1) + x(2)) / 2 that avoids cancellation error.
xmid = xint(1) + (xint(2) - xint(1)) / 2;
fmid = feval(func,xmid);
if fmid * feval(func,xint(1)) < 0
xint(2) = xmid;
else
xint(1) = xmid;
end
rlist = [rlist; xmid];
niter = niter + 1;
if abs(xint(2)-xint(1)) < 2*tol || abs(fmid) < tol
done = 1;
end
end
root = xmid;
%END bisection2.
We must use this code to find the nth zero of a Bessel function of the first kind (J0(x)). It is quite simple to insert a range and then find the specific root we are looking for. However, we must plot Xn vs. n and for that, we would need to be able to calculate a large number of roots in relation to n. So for that, I wrote this code:
bound = 1000;
x = linspace(0, bound, 1000);
for i=0:bound
for j=1:bound
y = bisection2(#(x) besselj(0,x), [i,j], 1e-6)
end
end
I believed this would work, but the roots it provides are not in order and keep repeating. The problem I believe is my range when I call bisection2. I know [i,j] is not the best way to do it and was hoping someone could lead me in the right direction on how to fix this problem.
Thank you.
Your implementation is in the right direction but it isn't completely correct.
bound = 1000;
% x = linspace(0, bound, 1000); No need of this line.
x_ini = 0; n =1;
Root = zeros(bound+1,100); % Assuming there are 100 roots in [1,1000] range
for i=0:bound
for j=1:bound
y = bisection2(#(x) besselj(i,x), [x_ini,j], 1e-6); % besselj(i,x) = Ji(x); i = 0,1,2,3,...
if abs(bessel(i,y)) < 1e-6
x_ini = y; % Finds nth root
Root(i+1,n) = y;
n = n+1;
end
end
n = 1;
end
I have replaced besselj(0,x) in your code with besselj(i,x). This gives you roots for not only J0(x) but also for J1(x), J2(x), J3(x), .....so on. (i=0,1,2,... )
Another change I made in your code is replacing [i,j] by [x_ini,j]. Initially x_ini=0 & j=1. This tries to find root in the interval [0,1]. Since the 1st root for J0 occurs at 2.4, the root your bisection function calculates (0.999) isn't actually the first root. The lines between if.....end will check if the root found by Bisection function is actually a root or not. If it is, x_ini will take the value of the root as the next root will occur after x = x_ini (or y).

parfor doesn't consider information about vectors which are used in it

This is a part of my code in Matlab. I tried to make it parallel but there is an error:
The variable gax in a parfor cannot be classified.
I know why the error occurs. because I should tell Matlab that v is an incresing vector which doesn't contain repeated elements. Could anyone help me to use this information to parallelize the code?
v=[1,3,6,8];
ggx=5.*ones(15,14);
gax=ones(15,14);
for m=v
if m > 1
parfor j=1:m-1
gax(j,m-1) = ggx(j,m-1);
end
end
if m<nn
parfor jo=m+1:15
gax(jo,m) = ggx(jo,m);
end
end
end
Optimizing a code should be closely related to its purpose, especially when you use parfor. The code you wrote in the question can be written in a much more efficient way, and definitely, do not need to be parallelized.
However, I understand that you tried to simplify the problem, just to get the idea of how to slice your variables, so here is a fixed version the can run with parfor. But this is surely not the way to write this code:
v = [1,3,6,8];
ggx = 5.*ones(15,14);
gax = ones(15,14);
nn = 5;
for m = v
if m > 1
temp_end = m-1;
temp = ggx(:,temp_end);
parfor ja = 1:temp_end
gax(ja,temp_end) = temp(ja);
end
end
if m < nn
temp = ggx(:,m);
parfor jo = m+1:15
gax(jo,m) = temp(jo);
end
end
end
A vectorized implementation will look like this:
v = [1,3,6,8];
ggx = 5.*ones(15,14);
gax = ones(15,14);
nn = 5;
m1 = v>1; % first condition with logical indexing
temp = v(m1)-1; % get the values from v
r = ones(1,sum(temp)); % generate a vector of indicies
r(cumsum(temp)) = -temp+1; % place the reseting locations
r = cumsum(r); % calculate the indecies
r(cumsum(temp)) = temp; % place the ending points
c = repelem(temp,temp); % create an indecies vector for the columns
inds1 = sub2ind(size(gax),r,c); % convert the indecies to linear
mnn = v<nn; % second condition with logical indexing
temp = v(mnn)+1; % get the values from v
r_max = size(gax,1); % get the height of gax
r_count = r_max-temp+1; % calculate no. of rows per value in v
r = ones(1,sum(r_count)); % generate a vector of indicies
r([1 r_count(1:end-1)+1]) = temp; % set the t indicies
r(cumsum(r_count)+1) = -(r_count-temp)+1; % place the reseting locations
r = cumsum(r(1:end-1)); % calculate the indecies
c = repelem(temp-1,r_count); % create an indecies vector for the columns
inds2 = sub2ind(size(gax),r,c); % convert the indecies to linear
gax([inds1 inds2]) = ggx([inds1 inds2]); % assgin the relevant values
This is indeed quite complicated, and not always necessary. A good thing to remember, though, is that nested for loop are much slower than a single loop, so in some cases (depend on the size of the output), this will may be the fastest solution:
for m = v
if m > 1
gax(1:m-1,m-1) = ggx(1:m-1,m-1);
end
if m<nn
gax(m+1:15,m) = ggx(m+1:15,m);
end
end

Gauss-Seidel Method in MATLAB

I am trying to implement the Gauss-Seidel method in MATLAB. But there are two major mistakes in my code, and I could not fix them:
My code converges very well on small matrices, but it never converges on large matrices.
The code makes redundant iterations. How can I prevent from redundant iterations?
Gauss-Seidel Method on wikipedia.
N=5;
A=rand(N,N);
b=rand(N,1);
x = zeros(N,1);
sum = 0;
xold = x;
tic
for n_iter=1:1000
for i = 1:N
for j = 1:N
if (j ~= i)
sum = sum + (A(i,j)/A(i,i)) * xold(j);
else
continue;
end
end
x(i) = -sum + b(i)/A(i,i);
sum = 0;
end
if(abs(x(i)-xold(j))<0.001)
break;
end
xold = x;
end
gs_time=toc;
prompt1='Gauss-Seidel Method Time';
prompt2='x Matrix';
disp(prompt2);
disp(x);
disp(prompt1);
disp(gs_time);
First off, a generality. The Gauß-Seidel and Jacobi methods only apply to diagonally dominant matrices, not generic random ones. So to get correct test examples, you need to actually constructively ensure that condition, for instance via
A = rand(N,N)+N*eye(N)
or similar.
Else the method will diverge towards infinity in some or all components.
Now to some other strangeness in your implementation. What does
if(abs(x(i)-xold(j))<0.001)
mean? Note that this instruction is outside the loops where i and j are the iteration variables, so potentially, the index values are undefined. By inertia they will accidentally both have the value N, so this criterion makes at least a little sense.
What you want to test is some norm of the difference of the vectors as a whole, thus using sum(abs(x-xold))/N or max(abs(x-xold)). On the right side you might want to multiply with the same norm construction applied to x so that the test is for the relative error, taking the scale of the problem into account.
By the instructions in the given code, you are implementing the Jacobi iteration, computing all the updates first and then advancing the iteration vector. For the Gauß-Seidel variant you would need to replace the single components in-place, so that newly computed values are immediately used.
Also, you could shorten/simplify the inner loop
xold = x;
for i = 1:N
sum = b(i);
for j = 1:N
if (j ~= i)
sum = sum - A(i,j) * x(j);
end
end
x(i) = sum/A(i,i);
end
err = norm(x-xold)
or even shorter using the language features of matlab
xold = x
for i = 1:N
J = [1:(i-1) (i+1):N];
x(i) = ( b(i) - A(i,J)*x(J) )/A(i,i);
end
err = norm(x-xold)
%Gauss-seidal method for three equations
clc;
x1=0;
x2=0;
x3=0;
m=input('Enter number of iteration');
for i=1:1:m
x1(i+1)=(-0.01-0.52*x2(i)-x3(i))/0.3
x2(i+1)=0.67-1.9*x3(i)-0.5*x1(i+1)
x3(i+1)=(0.44-0.1*x1(i+1)-0.3*x2(i+1))/0.5
er1=abs((x1(i+1)-x1(i))/x1(i+1))*100
er2=abs((x2(i+1)-x2(i))/x2(i+1))*100
er3=abs((x3(i+1)-x3(i))/x3(i+1))*100
if er1<=0.01
er2<=0.01
er3<=0.01
break;
end
end

Matlab: Repeat iteration until condition is met

I am trying to learn Matlab as someone with an R background. I have the following program written for an iteration that I would like to repeat until the specified condition is met. I believe that I have all of code written for Matlab, except for the command that the iteration should repeat infinitely times until the condition is met (denoted below).
Would someone be able to tell me how to translate this to Matlab syntax? I think that I should be using a while-loop, but I'm not sure since the iterations should continue until a condition is met rather than continuing while some condition is met. Is there an until equivalent? Thank you!
function xn = newton_v2(f,fd,x0,tol)
% newton iteration
xn = x0;
repeat{ %%% 'This is how I would begin the repeat command in R'
% evaluate function and derivative
fxn = feval(f,xn);
fdxn = feval(fd,xn);
% newton iteration step
xnp1 = xn - fxn/fdxn;
if(abs(xnp1 - xn)/abs(xnp1) < tol)
xn<-xnp1
end
% update
xn = xnp1;
} %%% 'This is how I would end the repeat command in R'
end
Also, please let me know if you see anything else wrong in my Matlab code.
I'm not great with R syntax, but you would have two options 1.pass in an array of values to a matlab for loop and iterate through them. Then graph it to find the best solution and try to get more precise from there 2. Set a condition on a while loop. I think you are looking more for a while loop, so you'll put your condition in there. It may be more computationally heavy, but depending on the funct. may be fine.
I do the Newton method with a while loop though the recursive version in the answer by hamaney is interesting. I do this by passing a function handle, initial guess and tolerance to a function.
function x1 = NewtonMethod(f,x,tol)
% dtol is calculated from eps based on the function handle...not shown
xi = f(x); % initial guess
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
while (abs(x1 - x) < tol)
x = x1;
xi = f(x);
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
end
end
There is a problem with this approach. If the initial guess is poorly conditioned or the function unbounded it is possible for this to be an infinite loop. Because of this I include a loop counter and normally break when that counter reaches a maxSteps value.
Adding the inifinite loop protection looks something like this.
xi = f(x); % initial guess
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
loopCounter = 0;
while (abs(x1 - x) < tol)
x = x1;
xi = f(x);
dxi = (f(x+dtol) - f(x-dtol)) / (2 * dtol);
x1 = x - xi / dxi;
loopCounter = loopCounter + 1;
if loopCounter > maxSteps
% include warning message
break
end
end
Do you mean the syntax for the for loop?
If you are trying to create Newton's method, see my own implementation script
y is the function
x0 - first initial value
n - # of xns to approximate
function Xn = newtonsMethod (y,x0,n,startDomain,endDomain)
%the tangent line at any point on the curve
y1 = matlabFunction(diff(sym(y)));
Xn = x0;
x= linspace(startDomain,endDomain,1000);
%recursive call for the newton formula
for i = 1 : n
%find the tangent line
L =#(x)(y1(Xn).*(x-Xn)+y(Xn));
%find the root
Xn = Xn - (y(Xn)./y1(Xn));
end
end
This might be not the best way to do it. but it could help!