Newton Raphson in MATLAB - matlab

I would like to implement the following: ive written a script that executes the Newton Raphson algorithm for my specific function. Now I would like to write a script that repeats itself using the previous found zero as my next intial starting point:
x=zeros(1,31);
for i=1:31
x(i)=(i-1)/10;
end
y0=0;
for i=1:length(x)
y0=newton(x(i),y0)
end
So, I want this script to execute newton(x,y0). So it will start with newton(0,0), it will find a new value y0 and then I want the script to execute newton(0.1,y0) etc. I want these values to be displayed in a table together with the number of iterates that was needed to find the value y0.
I hope my question is clear. Thanks in regards.
Again: I have a vector x with elements 0, 0.1, 0.2, ...,3
When I implement x(i) with initial value y0 newton(x,y) will give me a value. Then I want the script to execute newton(x,y) again with value x(2) for x and the previous found y0.So I need some kind of loop, but I can't get it done .. :(
EDIT
This is my newton-function:
function nulpunt=newton(x,y0)
tolerantie=1e-8;
iteraties=0;
while (abs(functie1(y0,x))>tolerantie)
y0=y0-functie1(y0,x)/afgeleide_functie1(y0);
iteraties=iteraties+1;
end
if iteraties==100;
fprintf('Maximaal aantal iteraties bereikt')
else
fprintf('De benadering van het nulpunt y*(%.2f) is %.4f gevonden in %d iteraties.\n',x,y0,iteraties)
end
end

Your loop should already use the previous y0 every consecutive time it operates.
If you want to display the y0 and the number of iterations in the Matlab command window, you first need to change the newton-function to return not just y0 but also the number of iterations, iteraties:
function [nulpunt, iteraties]=newton(x,y0)
Also, your function should actually return the final y0as nulpunt:
if iteraties==100;
fprintf('Maximaal aantal iteraties bereikt')
nulpunt = 0; % in this case, no solution was found, return the baseline value;
else
fprintf('De benadering van het nulpunt y*(%.2f) is %.4f gevonden in %d iteraties.\n',x,y0,iteraties)
nulpunt = y0;
end
to display the number of iterations and y0 after each execution of newton, add these two lines after you call the function:
[y0, iteraties] = newton(x(i),y0);
disp(['This point was found: ',num2str(y0)])
disp(['It took ',num2str(iteraties),' iterations.'])
This may actually be redundant, as your function already outputs which y0 it found and how long that took.

Related

Implementing forward Euler method in matlab

I'm trying to implement the forward Euler method using matlab, but don't understand the error I'm getting. This is what I have written:
function y = ForwardEulerMethod(f,y0,T,N)
h=T/N;
t=zeros(N+1,1);
for i=0:N
t(i)=i.*h; %line 5
end
y=zeros(N+1,1);
y(0)=y0;
for i=1:N
y(i)=y(i-1)+h.*f(t(i-1),y(i-1));
end
end
My error is with line 5 and says, "Subscript indices must either be real positive integers or logicals." I am familiar with this rule, but don't see how I'm breaking it. I'm just trying to replace a zero at each location in t with a numerical value. What am I missing?
Agree with #vijoc above. You are indexing with 0 at multiple places. You could either change how you are indexing the values or get rid of the for loop altogether, like below:
function y = ForwardEulerMethod(f,y0,T,N)
h=T/N;
t=0:N .* h; % this takes the place of the first for-loop
y=zeros(N+1,1);
y(1)=y0;
for i=2:N+1
y(i)=y(i-1)+h.*f(t(i-1),y(i-1));
end
end
You could even replace the second loop if the function f takes vector inputs like so:
y(1) = y0;
y(2:end) = y(1:end-1) + h .* f(t(1:end-1), y(1:end-1));
You're iterating over i = 0:N and using it as t(i)=i.*h, so you're trying to access t(0) during the first iteration. Matlab indexing starts from 1, hence the error.
You also have other lines which will cause the same error, once the execution gets that far.

Matlab: Creating a while loop which stops a Taylor Series approximation after it reaches a specified error?

Say I take the taylor series of e^x, for n terms, centered at a=0 for some random value until the error reaches a specified value.
The error is error=(exp(x)-approx)/(exp(x)) and the specified value the error should reach is err=0.01
I have managed to generate a taylor series
x=2;
j=1;
for s=[0:1:10]
approx=approx+(x^s)/(factorial(s))
end
However, I am unable to integrate a while loop which extends the series until the statement error>err is false.
I tried
x=2;
j=1;
err=0.01
error=(exp(x)-approx)/(exp(x));
while error>err
for s=[0:1:10]
approx=approx+(x^s)/(factorial(s))
end
end
and
x=2;
j=1;
err=0.01;
s=-1
error=(exp(x)-approx)/(exp(x));
while error>err
s=s+1
approx=approx+(x^s)/(factorial(s))
end
None of them give the correct answer.
How can I solve the problem.
Make sure your error calculation is within the for loop and initialize the terms:
x=2;
j=1;
err=0.01;
s=0;
error = 1e10;
approx = 0;
while error>err
approx=approx+(x^s)/(factorial(s));
error=(exp(x)-approx)/(exp(x));
s=s+1
end

How solve a system of ordinary differntial equation with time-dependent parameters

How solve a system of ordinary differential equation ..an initial value problem ....with parameters dependent on time or independent variable?
say the equation I have
Dy(1)/dt=a(t)*y(1)+b(t)*y(2);
Dy(2)/dt=-a(t)*y(3)+b(t)*y(1);
Dy(3)/dt=a(t)*y(2);
where a(t) is a vector and b(t) =c*a(t); where the value of a and b are changing with time not in monotone way and each time step.
I tried to solve this using this post....but when I applied the same principle ...I got the error message
"Error using griddedInterpolant The point coordinates are not
sequenced in strict monotonic order."
Can someone please help me out?
Please read until the end to see whether the first part or second part of the answer is relevant to you:
Part 1:
First create an .m file with a function that describe your calculation and functions that will give a and b. For example: create a file called fun_name.m that will contain the following code:
function Dy = fun_name(t,y)
Dy=[ a(t)*y(1)+b(t)*y(2); ...
-a(t)*y(3)+b(t)*y(1); ...
a(t)*y(2)] ;
end
function fa=a(t);
fa=cos(t); % or place whatever you want to place for a(t)..
end
function fb=b(t);
fb=sin(t); % or place whatever you want to place for b(t)..
end
Then use a second file with the following code:
t_values=linspace(0,10,101); % the time vector you want to use, or use tspan type vector, [0 10]
initial_cond=[1 ; 0 ; 0];
[tv,Yv]=ode45('fun_name',t_values,initial_cond);
plot(tv,Yv(:,1),'+',tv,Yv(:,2),'x',tv,Yv(:,3),'o');
legend('y1','y2','y3');
Of course for the fun_name.m case I wrote you need not use sub functions for a(t) and b(t), you can just use the explicit functional form in Dy if that is possible (like cos(t) etc).
Part 2: If a(t) , b(t) are just vectors of numbers you happen to have that cannot be expressed as a function of t (as in part 1), then you'll need to have also a time vector for which each of them happens, this can be of course the same time you'll use for the ODE, but it need not be, as long as an interpolation will work. I'll treat the general case, when they have different time spans or resolutions. Then you can do something of the following, create the fun_name.m file:
function Dy = fun_name(t, y, at, a, bt, b)
a = interp1(at, a, t); % Interpolate the data set (at, a) at times t
b = interp1(at, b, t); % Interpolate the data set (bt, b) at times t
Dy=[ a*y(1)+b*y(2); ...
-a*y(3)+b*y(1); ...
a*y(2)] ;
In order to use it, see the following script:
%generate bogus `a` ad `b` function vectors with different time vectors `at` and `bt`
at= linspace(-1, 11, 74); % Generate t for a in a generic case where their time span and sampling can be different
bt= linspace(-3, 33, 122); % Generate t for b
a=rand(numel(at,1));
b=rand(numel(bt,1));
% or use those you have, but you also need to pass their time info...
t_values=linspace(0,10,101); % the time vector you want to use
initial_cond=[1 ; 0 ; 0];
[tv,Yv]= ode45(#(t,y) fun_name(t, y, at, a, bt, b), t_values, initial_cond); %
plot(tv,Yv(:,1),'+',tv,Yv(:,2),'x',tv,Yv(:,3),'o');
legend('y1','y2','y3');

nlfilter taking same values twice

I used nlfilter for a test function of mine as follows:
function funct
clear all;
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
A = nlfilter(I, [7 7], #dirvar);
% Subfunction
function [h] = dirvar(I)
c = (size(I)+1)/2
EW = I(c(1),c(2):end)
h = length(EW) - ld
end
end
The function works fine but it is expected that nlfilter progresses element by element, but in first two iterations the values of EW will be same 0.2089 0.4162 0.9398 0.1058. But then onwards for all iterations the next element is selected, for 3rd it is 0.4162 0.9398 0.1058 0.1920, for 4th it is 0.9398 0.1058 0.1920 0.5201 and so on. Why is it so?
This is nothing to worry about. It happens because nlfilter needs to evaluate your function to know what kind of output to create. So it uses feval once before starting to move across the image. The output from this feval call is what you see the first time.
From the nlfilter code:
% Find out what output type to make.
rows = 0:(nhood(1)-1);
cols = 0:(nhood(2)-1);
b = mkconstarray(class(feval(fun,aa(1+rows,1+cols),params{:})), 0, size(a));
% Apply fun to each neighborhood of a
f = waitbar(0,'Applying neighborhood operation...');
for i=1:ma,
for j=1:na,
x = aa(i+rows,j+cols);
b(i,j) = feval(fun,x,params{:});
end
waitbar(i/ma)
end
The 4th line call to eval is what you observe as the first output from EW, but it is not used to anything other than making the b matrix the right class. All the proper iterations happen in the for loop below. This means that the "duplicate" values you observe does not affect your final output matrix, and you need not worry.
I hope you know what the length function does? It does not give you the Euclidean length of a vector, but rather the largest dimension of a vector (so in your case, that should be 4). If you want the Euclidean length (or 2-norm), use the function norm instead. If your code does the right thing, you might want to use something like:
sz = size(I,2);
h = sz - (sz+1)/2 - ld;
In your example, this means that depending on the lag you provide, the output should be constant. Also note that you might want to put semicolons after each line in your subfunction and that using clear all as the first line of a function is useless since a function will always be executed in its own workspace (that will however clear persistent or global variables, but you don't use them in your code).

Metropolis algorithm in MATLAB -->> error with function handles

i have a piece of metropolis algorithm:
mB=5.79*10^(-9); %Bohr magnetone in eV*G^-1
kB=0.86*10^(-4); %Boltzmann in eV*K^-1
%system parameters
L=60; %side square grid
L2=L*L; % total number grid position
Tstep=5; %step in temperature change (K)
Maxstep=10; %max number of steps
nmcs=5; % cycle numberof Metropolis algorithm
magnet=NaN(1,Maxstep);%store magnetization in "monte carlo images" of sample
%Creation initial point arrangement of magnetic spins
%Outer parameters
H=100000; %Gauss
T=20; % Kelvin
%Energy alteration in spin-reverse
de =# (i,j) (2*mB*H).*mlat(i,j);
%Metropolis probability
pmetro=# (i,j) exp(-de(i,j)./(kB*T));
%Creation and display of initial lattice
mlat=2*round(rand(L,L))-1;
mtotal=sum(mlat(:))./L2
% Alteration of system with time
for ii=1:Maxstep
for imc=1:nmcs
for i=1:L
for j=1:L
if pmetro(i,j)>=1
mlat(i,j)=-mlat(i,j);
elseif rand<pmetro(i,j)
mlat(i,j)=-mlat(i,j);
end
end
end
end
magnet(:,ii)=sum(mlat(:))./L2;
%figure(ii);
%pcolor(mlat);
% shading interp;
end
m1=mean(magnet)
error=std(magnet) ./sqrt(numel(magnet))
fprintf('Temperature = %d K',T)
figure(13)
plot(magnet(1,:),'b.')
axis([0 10 0 0.5])
grid on
xlabel('i (Configuration) ')
ylabel('M/(N*mB)')
Now,the problem is in figure(13).The values it gives me are around zero (0.05,0.02..).It supposes to give me values around 0.3..
Generally,the graph its ok,It gives me the right "shape"(it has points) but as i said around zero.
I really don't know how to put this post in order to be understood.Maybe i have some mistake in the "magnet"matrix ,i don't know.
Anyway,i don't demand from anybody to check it thoroughly ,i am just asking if with a quick look anyone can help.
ΕDIT--->> Also,sometimes when i run the program ,it gives me :
Undefined function or method 'mlat'
for input arguments of type 'double'.
Error in ==> #(i,j)(2*mB*H).*mlat(i,j)
Error in ==>
#(i,j)exp(-de(i,j)./(kB*T))
Error in ==> metropolis at 39
if pmetro(i,j)>=1
EDIT--->>> I found the "mistake" .In my code in the loops where i have the function "pmetro" i replaced it with the "exp(-(2*mB*H).*mlat(i,j)./(kB*T))" and the program worked just fine!!!
Why it didn't work with calling the "pmetro"??How can i overcome this?Is there a problem with function handles in loops?
Blockquote
I very strongly suggest that you try writing code without using any function handles until you're really familiar with Matlab.
The line
de =# (i,j) (2*mB*H).*mlat(i,j);
is what causes your problems. In Matlab, when you define a function handle that refers to, say, an array, the function handle will use the array as it was at the time of definition. In other words, even though mlat changes inside your loop, mlat(i,j) inside the function de is always the same. In fact, you cannot even run this code unless you have previously defined mlat in the workspace.
You should therefore rewrite the main loop as follows
for iStep = 1:maxStep
for imc = 1:mcs
pmetro = $some function of mlat - this can be calculated using the
entire array as input
%# for each element in mlat (and thus pmetro), decide whether
%# you have to switch the spin
switchIdx = pmetro > 1 | pmetro < rand(size(mlat));
mlat(switchIdx) = -mlat(switchIdx);
end
$calculate magnetization$
end
Also, note that there is a command mean to take the average. No need to sum and then divide by the number of elements.