Beruflich Dokumente
Kultur Dokumente
Octave
revision pack
FOR MATH, SCIENCE, AND ENGINEERING STUDENTS
CONTENTS
1. INTRODUCTION 2. ASSIGNMENTS AND VARIABLES 3. VECTORS, RANGES, AND MATRICES 4. GRAPHS 5. LOOPS AND CONDITIONALS 6. SCRIPTS AND FUNCTIONS 7. APPLICATION 1. ROOT FINDING 8. APPLICATION 2. SPARSE MATRICES AND DERIVATIVES 9. APPLICATION 3. THE VAN DER POL OSCILLATOR 10. APPLICATION 4. CELLULAR AUTOMATA
PROBLEM SET REFERENCES 2 3 4 6 8 10 14 18 21 26 29 31
INTRODUCTION
+, -, *, /, ^, pi, i, inf, eps, format, sin, cos, tan, asin, acos, atan, asinh, acosh, exp, log, log10, log2, abs, sqrt, sign, round, ceil, floor, fix, max, min, help.
The simplest way to use Octave is to do arithmetic as you would do with a common calculator. Addition, subtraction, multiplication, division, and exponentiation are represented by the operators +, -, *, /, ^ respectively. For instance, type at the prompt the following expression
> (3 + 2^(-1)) / 0.5 ans = 7
Note that white spaces are ignored by Octave and the example above could be equivalently written as
> (3+2^(-1))/0.5 ans = 7
Octave displays the answer and assigns the resulting value to the variable ans. To change the format in which numbers are displayed, use the format function with basic arguments short (default) and long.
> pi ans = 3.1416 > format long > pi ans = 3.14159265358979
! ! ! !
where the variable pi represents the mathematical constant !=3.14... . Octave knows most (if not all) of the standard mathematical functions. A function is invoked with its name followed by the arguments in round brackets.
> sin (2.7)^2 + cos (2.7)^2 ans = 1 > log (exp (2)) ans = 2
! ! !
where we note that the trigonometric functions work with radians, and the natural logarithm is represented by the function log. A complex number is one that can be written in the form z=x+yi where i=(-1)1/2 is the imaginary unit, x=Re(z) is the real part of z, and y=Im(z) the imaginary part. In Octave, the imaginary unit is represented by the symbol i (or j). The complex number 1+2.3i is entered as
> 1 + 2.3i ans = 1.0000 + 2.3000i > 1+2.3j
! !
ans =
1.0000 + 2.3000i
The magnitude |z|=(x2+y2)1/2 of a complex number z with x=Re(z) and y=Im(z) can be calculated by the function abs (or norm); moreover you can use the functions real and imag to retrieve the real and imaginary part respectively. To get detailed information about a function func, type help func, whereas you can search for functions related to a keyword key by typing lookfor key. Moreover, two autocompletion shortcuts are provided. The TAB key tries to autocomplete a function name based on Octaves knowledge, while the UP-ARROW key tries to autocomplete based on user input (history).
=, ,, ;, ..., #, %, #{<>#}, %{<>%}, who, whos, exist, clear, global, isglobal, persistent.
Variables are symbolic names associated with values. The name of a variable must be a sequence of letters, digits, and underscores, but it must not begin with a digit. Octave does not enforce a limit on the length of variable names. Case is significant in variable names. The symbols x and X can be used as distinct variable names. In Octave, the assignment operator is the equal sign (=). Some valid assignments are
! ! ! ! ! ! > x = 1 x = 1 > distance = sqrt (4^2 + 3^2) distance = 5 > i_am_a_long_variable_name = 25 i_am_a_long_variable_name = 25
where semicolons (;) are used to separate multiple instructions and suppress the output, whereas # (or % for both Octave and Matlab) initializes a single line comment. To get a list showing the user defined variables we type who, whereas we can check a variables value by typing its name. Octave does not forget assignments unless instructed to do so. To clear a previous assignment we use the clear command.
! ! ! ! ! ! ! ! ! > clear x y > x error: `x' undefined near line 9 column 1 > y error: `y' undefined near line 9 column 1 > d d = 5 > exist ('x') ans = 0 # this is false GNU OCTAVE/MATLAB REVISION PACK | 3
! ! ! !
zeros, ones, eye, diag, rand, full, sparse, toeplitz, norm, det, trace, inv, lu, qr, eig, svd, cond, expm.
A vector is an ordered set of numbers. To enter a row vector type a set of numbers separated by commas (,) or white spaces inside square brackets.
! ! ! > v = [ 7, 3, 9, 0, 2, 4, 1 ] v = 7 3 9 0 2 4 1
We can enter a column vector by typing a set of numbers separated by semicolons (;) inside square brackets.
! ! ! ! ! > w = [ 7; 3; 9 ] w = 7 3 9
A range is a row vector with evenly spaced elements. Ranges are created by instructions of the form <first>:<step>:<last>, where the <step> can be omitted (the default is 1).
! ! ! ! ! ! > a = 0:5 a = 0 1 2 3 4 5 > b = 0:0.2:0.6 b = 0.00000 0.20000
0.40000
0.60000
To change v from row to column vector we ask from Octave for its transpose by typing v.', while for the conjugate transpose we omit the period v'. Another way to to get a column vector is by typing v(:). We can perform several operations on vectors. For instance, to square the elements of the vector v we type
! ! ! > v.^2 ans = 49 9
81
16
The period in the above instruction says that the numbers in v should be squared individually. Typing v^2 would tell Octave to use matrix multiplication to multiply v by itself and would have produce an error. Similarly, we must use .* and ./ for element-wise multiplication and division respectively. Most Octave functions are, by default, performed
element by element. For example, we type exp(v) to get the exponential of each number in v. The ith element of a vector can be specified through Octaves indexing rules, that is by typing the vector variable followed by the position index inside round brackets. If v=[7,3,9,0,2,4,1] we have v(1)==7, v(2)==3, v(3)==9, v(4)==0, v(5)==2, v(6)==4, and v(7)==v(end)==7. To extract a vector containing the first, the third, and the seventh element of v we type
> v([ 1, 2, 3 ]) ans = 7 3 9
! !
Elements of vectors can be extracted with ranges. For instance, v(4:length(v)) is the same as v(4:end) and as v([4,5,6,7]), where the length function returns the number of elements in v. Entering matrices in Octave is as easy. For example, the matrix
! A=# 1 1 # # # 2 2 "
is entered in Octave by typing
! ! ! ! > A = [ 1, 1; 2, 2 ] A = 1 1 2 2
For that specific example we could compose the matrix A by two column vectors [1;2].
! ! ! ! ! ! ! ! > v = [ 1; 2 ] v = 1 2 > A = [ v, v ] A = 1 1 2 2
The individual elements are extracted by typing A(row,column), we have A(1,1)==A(1,2) ==1, A(2,1)==A(2,2)==2, whereas an entire row or column is denoted by a colon (:).
! ! ! ! ! ! ! ! ! > A(:, 1) ans = 1 2 > A(:, 2) ans = 1 2 > A(1, :) GNU OCTAVE/MATLAB REVISION PACK | 5
! ! ! ! !
GRAPHS
plot, contour, polar, quiver, bar, plot3, surf, mesh, imagesc, meshgrid, xlabel, ylabel, zlabel, title, grid, axis, hold, subplot, figure, print, set, gcf.
The basic plotting function is plot. To plot the graph of the function f:X!Y we define a discrete version of the domain X as follows.
! > x = 0:0.01:2*pi;
We can modify a graph in a number of ways. To add axes labels and title we use the functions xlabel, ylabel, and title.
1 1 f(x)=sin(x)
0.5
0.5
-0.5
-1
-0.5
-1
We would also like to change the font size, the font style, and the axes limits to fit exactly the plotted function. To permanently enforce the changes we use the following statements in the file .octaverc. WARNING! All the graphics of this document have been plotted using the following statements in .octaverc and printed as eps using the option -deps in the print function.
set set set set (0, (0, (0, (0, 'defaultaxesfontsize', 'defaulttextfontsize', 'defaultaxesfontname', 'defaultaxesfontname', 26); 26); 'Times-Roman'); 'Times-Roman');
! ! !
Often we want to overlay two (or more) plots on the same set of axes. The way to do it is shown below.
> x = 0:0.01:2*pi; > plot (x, sin (x), 'g', x, cos (x), 'm')
This example also shows how to control the line color. To change the color replace g and m in the above instruction with k, b, y, r. Apart from color we can use different markers instead of a continuous line.
> x = 0:0.1:2*pi; > plot (x, sin (x), 'xg', x, cos (x), 'om')
1
!
1
0.5
0.5
-0.5
-0.5
-1
-1
Below we give a complete example in which several different properties of a plot are changed in order to achieve a publication quality result.
> > > > > > x = 0:0.1:40; f = besselj (0, x); d = f + rand (1, length(x)) - 0.5; u = f + 0.5; l = f - 0.5; plot (x, f, 'k', 'linewidth', 5, ... GNU OCTAVE/MATLAB REVISION PACK | 7
! ! ! ! !
! ! ! !
x, d, '*k', 'markersize', 1, ... x, u, 'm', 'linewidth', 5, ... x, l, 'g', 'linewidth', 5) xlabel ('x') > ylabel ('J_0(x)') grid on legend ('Bessel function', 'Measured data', ... ! ! 'Upper bound', 'Lower bound')
1.5 Measured data Upper bound Lower bound boxon
0.5
J0(x)
-0.5
-1
10
15
20 x
25
30
35
40
&, |, ~, !, ==, ~=, !=, <, >, <=, >=, if, elseif, else, endif, for, while, switch, break, continue, pause.
In Octave, control flow statements operate like those in common computer languages. Indenting the instructions of a loop or conditional statement is optional, but helps readability.
! ! ! ! ! ! ! ! ! ! ! ! ! > > > > > > > > > > > > > if v < 0.25 !! x = -1; !! y = 0; elseif v < 0.5 !! x = +1; !! y = 0; elseif v < 0.75 !! x = 0; !! y = -1; else !! x = 0; !! y = +1; endif
The if statement evaluates a logical expression and executes a group of instructions when the expression is true (=1). Alternative instructions can be executed by using the optional keywords elseif and else. In the example above a random number is generated using the function rand and a conditional decides the direction of a step.
8 | FOTIOS KASOLIS 2010 - 2011
Octave includes for and while loops. To make the above example more interesting we modify it as follows.
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! > N = 10000; > x = zeros (1, N); > y = zeros (1, N); > for i = 1:N-1 >! ! v = rand (1); >! ! if v > 0.75 >! ! ! x(i+1) = x(i) - 1; >! ! ! y(i+1) = y(i); >! ! elseif v > 0.5 >! ! ! x(i+1) = x(i) + 1; >! ! ! y(i+1) = y(i); >! ! elseif v > 0.25 >! ! ! x(i+1) = x(i); >! ! ! y(i+1) = y(i) - 1; >! ! else >! ! ! x(i+1) = x(i); >! ! ! y(i+1) = y(i) + 1; >! ! endif > end > plot (x, y)
y
60 40 20 0 0 20 40 60 80 100 120
WARNING! In Matlab, loops and conditionals end with the same end statement. A simple end is an accepted end of block statement for Octave. It is a coding style guideline to use specific end of block statements (endif, endswitch) rather than the generic end that is used only in case of for loops. COMPARISON AND BOOLEAN OPERATORS
x < y
x <= y x == y x > y x >= y (Octave) x != y (Octave and Matlab) x ~= y b1 & b2 b1 | b2 (Octave) ! b (Octave and Matlab) ~ b
True if x is less than or equal to y. True if x is equal to y. True if x is greater than y. True if x is greater than or equal to y. True if x is not equal to y. True if both b1 and b2 are true. True if either of b1 and b2 are true. True if the b is false (=0).
function, endfunction, return, nargin, nargout, varargin, varargout, feval, eval, tic, toc, keyboard, dbcont, dbquit.
We can execute a sequence of regular Octave instructions stored in simple text files called scripts. Apart from regular statements we can create new function files specific to the problem we want to solve. Script and function files are sometimes called m-files since they have the extension .m. To write our first script, we open our favorite (simple) text editor (nano, vim, emacs, etc.) and we type the instructions shown below.
# A b x example 1: xmpl.m = [ 1, 2; 2, 2]; = [3; 2]; = A \ b
We save the file as xmpl.m. To execute the contents of the created script we move to the directory we saved the file (for instance ~/Desktop) using
> cd ~/Desktop
and then we type the name of the file without the extension .m and hit enter.
! ! ! ! > xmpl x = -1 2
where endfunction denotes the end of the function and should be avoided if you want Matlab compatible code. To invoke a function we type the function name followed by its argument in round brackets. Preferably the <function_name> and the name of the .m file that defines the function are the same.
f ''(x) f '''(x) ! ih 3 +! 2! 3!
f '(x) =
that is an O(h2) estimate of the derivative of the function f at x. This method is implemented in Octave as follows.
function [ dfdx ] = complexStepDeriv (f, x0, h) dfdx = imag (f (x0 + i * h)) ./ h; endfunction
To call this function we have to define the mathematical function f which we want differentiate. To do so, we could create another function file, but for simple cases we can use anonymous functions, for instance if f(x)=sinx we type
> f = @(x) sin (x); # anonymous function definition
! ! ! ! ! ! ! ! ! ! ! ! ! !
The complexStepDeriv function accepts vectors as input for x0 or h as shown in the following example.
! ! ! ! ! ! ! > > > > > > > n = -7:0; h = 10.^n; dfdx = complexStepDeriv (f, pi, h); loglog (h, abs (-1-dfdx), 'linewidth', 5); xlabel h; ylabel '|-1-df(\pi)/dx|'; grid on; axis equal;
100 10-2 10-4 10-6
|-1-df( )/dx|
10-8
10-6
10-5
10-4
10-3
10-2
10-1
100
When writing a function you can easily define default values for input arguments.
function [ dfdx ] = complexStepDeriv (f, x0, h = 10^-7) dfdx = imag (f (x0 + i * h)) ./ h; endfunction
WARNING! Defining default values as in the example above is valid only in Octave. The above function could be called with only two arguments.
> dfdx = complexStepDeriv (f, pi) dfdx = -1.00000000000000
Variables in a function file are local, meaning that unlike the variables defined in script files, these variables are completely unrelated to any of the variables with the same names that are defined in the command line, and Octave does not remember their values after executing the function. Time can be measured by the tic - toc functions (tic starts the timer and toc prints the elapsed time since tic was used).
! ! > tic; complexStepDeriv (f, 0:10^-6:2*pi); toc Elapsed time is 2.8265950679779 seconds.
Below we give a script that could be used to check how Octave compares to Matlab with respect to efficiency (a sloppy benchmark!).
clear all; f = @(x) sin (x); time = zeros (1, 7); for i = 1:7 step = 10^-i; tic; complexStepDeriv (f, 0:step:2*pi); time(i) = toc; end
Debugging
Often (or very often!) your code does not work at all, or has some strange behavior. You can debug Octave code using the function keyboard. The function keyboard stops the execution and gives control to the user. The debugging status is indicated by the keyword
GNU OCTAVE/MATLAB REVISION PACK | 13
(or K in Matlab) appearing before the prompt. In debugging mode you can examine variables and use any valid Octave command. As an example we modify the complexStepDeriv function as shown below.
debug
102 Octave vs Matlab
101
100
Time in secs
10-1
10-2
10-4 1
function [ dfdx ] = complexStepDeriv (f, x0, h = 10^-3) keyboard; dfdx = imag (f (x0 + i*h)) ./ h; endfunction ! ! ! ! ! ! ! ! ! > complexStepDeriv (f, pi) keyboard: stopped in /Users/fotios/Desktop/complexStepDeriv.m debug> h h = 0.00100000000000000 debug> h = 10^-7; debug> h h = 1.00000000000000e-07 debug> dbcont ans = -1.00000000000000
where dbcont is used to terminate the debugging mode and continue execution (alternatively you can use return). If you enter debug mode in a long for loop, it will probably be enough to check some iterations and then stop, to do so use dbquit.
7
Brief theory
roots, polyval, polyfit, polyder, polyint, fzero, optimset, optimget, fminunc, gls, sqp.
The problem of finding analytically the roots of a non-linear equation f(x)=0 is difficult or not feasible, while with a few lines of code we can find numerical solutions instantly. A
14 | FOTIOS KASOLIS 2010 - 2011
slow but yet robust method is the bisection method. This method approximates the root guaranteed by Bolzanos theorem. (Bolzano) Let D=[a,b] and f:D! . If f is continuous on D and f(a)f(b)<0 then, there is at least one !"(a,b) such that f(!)=0. If f:D! is continuous on D and f(x)"0 for all x"D, then f(x)>0 or f(x)<0 for all x"D. The sign of a continuous function f:D! does not change between two subsequent zeros. If f(a)f(b)>0, there may or may not be a root between a and b. If f(a)f(b)<0 there could be more than one roots between a and b. The inverse of Bolzanos theorem is not always true. The bisection method is always convergent. Since the method brackets the root, it is guaranteed to converge (assuming existence). As iterations are conducted, the interval gets halved. So one can guarantee the error in the solution. The convergence of the bisection method is slow as it is simply based on halving the working interval. If one of the initial guesses is close to the root, the method requires more iterations in order to converge.
Algorithm
1. Bisect [a,b] into two halves [a,c] and [c,b] where c=(a+b)/2. 2. Identify the interval containing the root by checking the signs of f(a)f(c) and f(c)f(b). 3. If f(a)f(c)<0 then interval [a,c] has the root. Otherwise the other interval [c,b] has the root. 4. Bisect the new interval that contains the root and repeat steps 1-3. 5. At each step take the midpoint of the interval as the most updated approximation of the root. 6. Stop the procedure after a specified number of iterations or when the width of the interval containing the root is less than a given tolerance ".
Built-in functions
Polynomials are represented in Octave by their coefficients in descending order of powers. For instance, the polynomial
p(x) =
is entered in Octave by typing
! > p = [ 1/24, 0, -1/2, 0, 1]
1 4 1 2 x ! x +1 24 2
To check the correctness of this answer we evaluate the polynomial values at the roots.
! ! ! ! ! ! > f = polyval (p, r) f = 1.3323e-15 1.1102e-15 1.3323e-15 4.4409e-16
The more general problem of finding the zeros of a transcendental function of a single variable is solved in Octave by the command fzero. Suppose we are interested in finding the zeros of f(x)=cosx-x2, to do so we type
! ! ! ! ! ! ! > f = @(x) cos (x) - x.^2; > z = fzero (f, 0.5) z = 0.82413 > fz = f (z) fz = 1.2212e-15 > x = 0:0.01:1; > plot (x, f (x), 'k', 'linewidth', 5, z, fz, 'or')
where the second argument in the fzero function is a starting point. In one dimensional problems a good starting point (a point relatively close to the root) can be found by plotting the function.
4 1
3 0.5
p(x)
f(x)
1 0 -3 -2 -1 0 x 1 2 3 4
-0.5
-1 -4
-1
0.2
0.4
0.6
0.8
Octaves function fsolve can be used to solve systems of non-linear equations. Consider the following set of three equations in three unknowns (x, y, z).
where info=1 means that the relative residual error is less than specified by TolFun.
Sparse matrices
A sparse matrix is a matrix dominated by zeros, so that special techniques can be used for storing instead of storing every single element. One well-known sparse (banded, tridiagonal) matrix comes from the finite difference approximation to the second derivative of a function. By Taylors expansion we have that
h2 f ''(x) 2
f ''(x i ) !
or in matrix form
1 h2
(f
i+1
f '' =
where
1 h2
Tf
% ' ' ' ' ' ' ' ' ' ' ' ' ' ' &
! ! ! ! ! !
T = -2 1 0 0 0
1 -2 1 0 0
0 1 -2 1 0
0 0 1 -2 1
0 0 0 1 -2
Since this is a sparse matrix (as its size grows it is dominated by zeros) we only need to store the non-zero entries. The storing technique used by Octave is the compressed column format meaning that it stores a position index and the values of the non-zero entries in a column-wise manner.
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! > T = sparse (T) T = Compressed Column Sparse (rows = 5, cols = 5, nnz = 13 [52%]) (1, 1) -> -2 (2, 1) -> 1 (1, 2) -> 1 (2, 2) -> -2 (3, 2) -> 1 (2, 3) -> 1 (3, 3) -> -2 (4, 3) -> 1 (3, 4) -> 1 (4, 4) -> -2 (5, 4) -> 1 (4, 5) -> 1 (5, 5) -> -2
Finally, Octave offers the possibility to plot the sparsity pattern, that is the structure of the non-zero elements of a matrix.
! > spy (T)
0
u '' =
thus the discrete problem can be written as
1 h2
Tu
1 h
2
This system can be solved in Octave by using the backslash operator \ as shown below.
function [ u ] = boundaryValueProb (h) n = 1 / h - 1; I = -h^2 * diag (ones (n)); T = toeplitz ([ -2, 1, zeros(1, n - 2) ]); u = T \ I; u = [ 0; u; 0]; endfunction
Then we define h and the domain [0,1] and we call our function.
! ! ! ! ! ! ! > > > > > > > > h = 0.1; x = 0:h:1; u = boundaryValueProb (h); plot (x, u, 'linewidth', 5, x, u, 'ok'); xlabel x; ylabel u(x); title 'd^2u(x)/dx^2=1, u(0)=u(1)=0'; grid on
To make our problem slightly more interesting we let u''(x)=-cos(0.5!x) for all x in (0,1). To change the rhs in our function we modify it as shown below.
function [ u ] = boundaryValueProb (h) n = 1 / h - 1; x = h:h:1-h; rhs = cos (0.5*pi*x(:)); I = -h^2 * rhs; T = toeplitz ([ -2, 1, zeros(1, n - 2) ]); u = T \ I; u = [ 0; u; 0]; endfunction
Try it!
0.16 0.14 0.12 0.1
u(x)
d2u(x)/dx2=1, u(0)=u(1)=0
0.2
0.4
0.6
0.8
9
Brief theory
!! ! x + f(x)x + g(x) = 0
This second order differential equation includes the van der Pol equation
2 !! ! x + (x ! 1)x + x = 0
(where ##0) that arose in connection with non-linear electrical circuits. The van der Pol equation looks like a simple harmonic oscillator, but with a non-linear factor $=#(x2-1). For x>1 the factor $ is positive and acts like regular damping, while for x<1 it becomes negative and amplifies the oscillations. Before we study the van der Pol oscillator in Octave we introduce the basics of dynamical systems theory. By setting
! x=y
the van der Pol equation becomes a system of two first order equations
! x = y,
2 ! y = !x ! (x ! 1)y
To qualitatively analyze the behavior of the system we find the fixed points, that is the points at which the velocities are zero.
(x * , y* ) = (0, 0)
Given a fixed point we are interested in its stability properties. Using (linear) stability analysis we find what is the future of small perturbations around the fixed point.
x = x * + u,
y = y* + v
By using Taylors expansion and keeping only the first order terms we get for the general system
! x = f(x, y),
! y = g(x, y)
two linear differential equations that predict the future of the perturbations (u,v).
! u $ ! df(x * , y* ) / dx df(x * , y* ) / dy # ! &=# & # # # v & # dg(x , y ) / dx dg(x , y ) / dy " ! & # % # " * * * *
$! &# u $ & & &# & &# & &" v & % & %
The evolution of the perturbed system is completely defined by the eigenvalues of the Jacobian matrix
The eigenvalues of the Jacobian are negative real numbers, or complex numbers with negative real part. In that case (u(t),v(t))!(0,0) as t!$ and the fixed point (0,0) is said to be stable. At least one of the eigenvalues of the Jacobian is positive, or in the case of complex eigenvalues at least one has positive real part. Then (u(t),v(t))!($,$) as t!$ and the fixed point (0,0) is said to be unstable. The eigenvalues of the Jacobian are imaginary. In that case the functions u(t) and v(t) are periodic and they do not approach zero or infinity as t!$. The fixed point (0,0) is said to be Lyapunov stable. The Jacobian of the van der Pol system is
J(0, 0) = $ $
with eigenvalues
!1,2 =
"4 4
which are positive for ##2, or complex with positive real part for #<2, thus the origin is always unstable.
Implementation
We choose the initial displacement x0, the integration time, and the damping # as our experimental variables and we define the van der Pol system as follows.
function [ xp ] = vdp (x, t, mu) xp = [x(2); - x(1) - mu*(x(1)^2 - 1)*x(2)]; endfunction
Moreover, we define the function solvevdp that uses an anonymous function to pass the parameter # and solves the system using lsode (with default options lsode_options). WARNING! Matlab uses different integration routines, try help ode15s, ode23s, ode23t, or ode23tb.
function [ sol ] = solveVdp (x0, tint, mu) vdpode = @(x, t) vdp (x, t, mu); sol = lsode (vdpode, x0, tint); endfunction ode45, ode23, ode113,
Lets start the experimental study with the weak damping case, #=0.1, initial displacement x(0)=0.5, y(0)=0 and x(0)=3, y(0)=0, and integrate from 0 to 60, that is some periods of the free oscillation T0=2!/%0%6.28.
! ! ! ! ! > > > > > x1 = solveVdp ([ 0.5; 0.0 ], 0:0.1:60, 0.1); x2 = solveVdp ([ 3.0; 0.0 ], 0:0.1:60, 0.1); plot (0:0.1:60, x1(:,1), 'k', 0:0.1:60, x2(:,1), 'm'); xlabel ('t'); ylabel ('x(t)');
3
x(t)
-1
-2
-3
10
20
30 t
40
50
60
The conclusion from that first result is that independently of the initial condition our oscillator settles to a constant amplitude (close to 2) oscillation of (almost) the same period as if there was no damping. What is more interesting to see is the phase space x-y. To plot the phase space we type
! ! ! ! > > > > plot (x1(:,1), x1(:,2), 'k', x2(:,1), x2(:,2), 'm'); axis tight equal; xlabel ('x'); ylabel ('y');
-1
-2
-2
-1
and the conclusion is of course the same. Both phase trajectories settle to the same closed orbit, which in that case is called limit cycle (since it is isolated). A limit cycle is nothing more than the geometrical equivalent to periodic motion. An even better graphical result could be obtained by plotting the vector field (phase flow, velocity field) using the quiver function.
! ! ! ! ! ! ! ! ! ! > > > > > > > > > > [ x, y ] = meshgrid (-3:0.25:3, -3:0.25:3); u = y; v = - x - 0.1 * (x.^2 - 1) .* y; quiver (x, y, u, v, 'k'); hold on; plot (x1(:,1), x1(:,2), 'k', x2(:,1), x2(:,2), 'm'); hold off; axis tight equal; xlabel ('x'); ylabel ('y');
Lets repeat the experiment, but this time change the damping factor from 0.1 to 0.7.
! ! ! ! ! ! ! ! ! ! > > > > > > > > > > x1 = solveVdp ([ 0.5; 0.0 ], 0:0.1:60, 0.7); x2 = solveVdp ([ 3.0; 0.0 ], 0:0.1:60, 0.7); v = - x - 0.7 * (x.^2 - 1) .* y; quiver (x, y, u, v, 'k'); hold on; plot (x1(:,1), x1(:,2), 'k', x2(:,1), x2(:,2), 'm'); hold off; axis tight equal; xlabel ('x'); ylabel ('y');
-1
-2
-3 -3 -2 -1 0 x 1 2 3
-1
-2
-3 -3 -2 -1 0 x 1 2 3
10
Brief theory
+, -, *, /, ^, pi, i, inf, eps, format, sin, cos, tan, asin, acos, atan, asinh, acosh, exp, log, log10, log2, abs, sqrt, sign, round, ceil, floor, fix, max, min, help.
A cellular automaton is a mathematical machine that consists of cells that get their state from a finite set according to a local rule. The rule is said to be local because it only uses the neighborhood of each cell as its input. Two commonly used 2d neighborhoods are the von Neumann neighborhood NN={(0,-1),(-1,0),(0,0),(+1,0),(0,+1)} and the Moore neighborhood NM=NN{(-1,-1),(-1,+1),(+1,-1),(+1,+1)} and their representation is shown in the figure below.
(-1,+1)
(0,+1)
(+1,+1)
(-1,0)
(0,0)
(+1,0)
(-1,-1)
(0,-1)
(+1,-1)
To model forest fire we allow three different states for each cell. If a cell is empty its state is 0, if a cell is burning its state is 1, and if a cell represents a tree its state is 2. Moreover we assume that the array is toroidly connected, meaning that fire which burns to the left side of the forest will start fire on the right side and the same is true for the top and bottom sides. To continue we must define the local rules. To do so we choose a von Neumann neighborhood and we represent an empty cell with black color, a burning cell with pink color, and a tree with gray color. If one or more of the four neighbors of a cell is in burning state and the cell represents a tree (2), then its new state is burning.
There is a low probability (1%) for an empty cell to become a tree cell.
There is a very low probability (0.0005%) for a tree cell to start burning because of natural cause (like lightning or human irresponsibility).
Implementation
We choose the number of cells and the number of iterations to be our experimental variables. Keep in mind that the problem should not be programmed with for loops running through the cells, because it will be extremely slow in every (pure) interpreted language for big problem size (big number of cells). To resolve the looping problem we must combine the matrix manipulation capabilities of Octave together with logicals. Here is an example
! ! ! ! ! ! ! ! ! ! > a = round (10 * rand (3, 3)) a = 6 4 4 4 4 0 6 5 1 > a == 4 ans = 0 1 1 1 1 0 0 0 0
The function that solves the fire forest problem is shown below. Let us first comment on the variable s. Each line checks if there are any burning cells and returns a matrix with ones at the burning cells and zeros everywhere else. Moreover, the toroidal symmetry is enforced by the indexing. Consider the matrix
GNU OCTAVE/MATLAB REVISION PACK | 27
! 0 1 0 # # 1 0 1 # #" 0 0 0
that is it contains the number of neighbors in burning state for every cell.
function [ v ] = caForestFire (n = 100, iter = 100) z = zeros (n, n); v = z; s = z; pl = 0.000005; pg = 0.01; h = imagesc (cat (3, z, z, z)); axis equal off; for i = 1:iter s = (v(1:n, [ n, 1:n-1 ]) == 1) + ... (v(1:n, [ 2:n, 1 ]) == 1) + ... (v([ n, 1:n-1 ], 1:n) == 1) + ... (v([ 2:n, 1 ], 1:n) == 1); v = 2*(v == 2) - ... ((v == 2) & (s > 0 | (rand (n, n) < pl))) + ... 2*((v == 0) & rand (n, n) < pg); set (h, 'cdata', cat(3, v == 1, v == 2, z)); drawnow end endfunction
Regarding the variable v, its first line checks for tree cells and sets them to 2, meaning that it keeps them as tree cells. The second line subtracts 1 if a cell is in tree state and it has burning neighbors or exists natural cause (first and last rule). The last line applies the rule for empty cells to become trees. Notice that burning cells become automatically zeros since v==2 and v==0 return matrices with zeros at the cells v==1.
04.
(a) Set the variable x equal to 1 and suppress the output. (b) Set the variable y equal to 7 using the line continuation operator after the assignment operator. (c) Set the variable z equal to 3.1 and in the same line set the variable w equal to true.
08.
Given the matrix A=[2,7,9,7;3,1,5,6;8,1,2,5], explain the results of the following instructions. (a) A', (b) A(:,[1 4]), (c) A(:), (d) reshape(A,2,6), and length(A).
Make a good plot of the tan function over the domain [0,4!].
! ! !
12.
(a)
Evaluate the vector x in the following Octave code fragments and use Octave to verify your answers.
(b) n = 1; m = 2; for i = 1:10 if n == m x(i) = n^2 + m^2; n = m + 1; else x(i) = n / m; n = m; end end (c) n = 1; m = 2; for i = 1:10 if n == m x(i) = n^2 + m^2; n = m + 1; else x(i) = n / m; n = n * m; end end
Study the following scripts. In all cases the resulting vector is the same column vector. What is the problem with the cases (a) and (b)?
(b) clear x tic for i = 1:10^5 x(i) = sin (i); end toc (c) clear x tic x = zeros (10^5,1); for i = 1:10^5 x(i) = sin (i); end toc
14.
by
Write a function that returns a vector with the Fibonacci numbers which are given
x n = x n!1 + x n!2
with initial conditions x0=0 and x1=1, and n=0,1,2,...N. Use the number N as user input. Execute your function for N=100 and plot the resulting values (vs position index). For the first 50 Fibonacci numbers, compute the ratio xn/xn-1.
15.
Write two function that return the roots of the quadratic equation ax2+bx+c=0 given a, b, and c. In the first function use the formulas
x! =
!b !
b ! 4ac
!b +
b ! 4ac 2a
x! =
2c !b + b ! 4ac
2
x+ =
2c !b ! b ! 4ac
2
Invoke both functions for a=10-5, b=105, and c=-10-5 and compare the solutions with respect to accuracy.
16.
Make sure that you know how to use the functions given below each chapter title. Use help to find the syntax of the functions that are not used in the text.
04.
Applied numerical methods using Matlab. Won Young Yang, Wenwu Cao, Tae-Sang Chung, John Morris. John Wiley & Sons. 2005. *****
05.
Numerical methods in engineering with Matlab. Jaan Kiusalaas. Cambridge university press. 2005. ****
A brief introduction to Scilab. Fotios Kasolis. 2010. **** Essential Matlab for scientists and engineers. Brian D. Hahn. Elsevier. 2002. *** A brief introduction to Matlab. Fotios Kasolis. 2008. ***