2nd year computational physics week 1 (standard): …part2/online/labnotes/week_1_standard.pdf......

35
2nd Year Computational Physics Week 1 (standard): Getting acquainted with C Last compiled September 28, 2017 1

Upload: vonhu

Post on 19-Mar-2018

217 views

Category:

Documents


3 download

TRANSCRIPT

2nd Year Computational PhysicsWeek 1 (standard): Getting acquainted with C

Last compiled September 28, 2017

1

Contents

1 Introduction 4

1.1 Getting Acquainted . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.2 Introduction to Program Logic and Flow Charts . . . . . . . . . . . 5

2 Prelab Questions 7

3 Hello, world! 8

3.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.1.1 Introduction to Linux . . . . . . . . . . . . . . . . . . . . . 8

3.1.2 Program Structure . . . . . . . . . . . . . . . . . . . . . . . 8

3.1.3 Program Compilation . . . . . . . . . . . . . . . . . . . . . 12

3.1.4 Standard Libraries and Basic Data Output . . . . . . . . . . 13

3.2 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.3 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4 Evaluating a Simple Function 14

4.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4.1.1 Data Types and Precision . . . . . . . . . . . . . . . . . . . 14

4.1.2 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.1.3 User Input . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4.2 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4.3 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

5 Data Files and Plotting 18

5.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

5.1.1 Exporting Data in C . . . . . . . . . . . . . . . . . . . . . . 18

2

5.1.2 Plotting Data . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5.2 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

5.3 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6 Loops and Logic Statements 22

6.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

6.1.1 If Function and Boolean Objects . . . . . . . . . . . . . . . 22

6.1.2 Loops in C . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

6.1.3 Series and Sequences . . . . . . . . . . . . . . . . . . . . . . 24

6.2 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

6.3 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

7 Bonus Section: Special Functions and Recurrence Relations 32

7.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

7.1.1 Series Representations of Bessel Functions . . . . . . . . . . 32

7.2 Procedure (One Bonus Mark) . . . . . . . . . . . . . . . . . . . . . 32

7.3 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3

1 Introduction

Computation is of fundamental importance in physics. While many physical sys-tems can be described by simple analytical rules, there are yet many more thatare analytically intractable. Even seemingly simple systems blow up in complexitywhen they contain any more than one or two elements. Computational and nu-merical techniques make these previously difficult or impossible to solve systemswithin reach, and as a result are at the foundation of modern physics.

The purpose of these labs is to introduce you to some of the basics of computerprogramming, as well as some of most important techniques in computationalphysics. At the end of these labs you will be able to perform a host of tasks usingnumerical techniques, including solving systems of equations, series expansions,differentiation and integration, root finding and solving ordinary differential equa-tions, among other things. The language of choice for these labs is C, though thetechniques and logic are universal.

The course consists of four 6 hour lab sessions, broken up into 3 hour slots. You willbe expected to have read through the lab in detail and answered the prelab ques-tions before arrival (prelabs are marked). During the session you will work throughthe assigned problems, with the guidance of your lab demonstrators. Although youare not working in groups, communication with your peers is encouraged, but codecopying is frowned upon. You must submit all hand drawn and printed figures inhard copy with your lab book. Make sure you finish the prelabs, includingall of the flowcharts, before the lab session. You will have to submit yourlab book at the end of the day of your lab session. Your code must also be emailedto Laurence at [email protected] by 5pm on the day of your session.

For further information on common mistakes and proper style when drawingflowcharts and coding in C, and how to code C at home, it is highly recommendedthat you read the documents on the second year labs website. READ THESE.

1.1 Getting Acquainted

You can’t build a house until you can swing a hammer. This week we will workthrough some of the most important building blocks in any program. We workthrough the use of the Linux system terminal and program compilation, basicprogram flow and logic, data types, input and output operations and loops. Wewill use these in the context of mathematical series and sequences, and end withan interesting example of series solutions to differential equations.

4

1.2 Introduction to Program Logic and Flow Charts

At its most basic level, a program is simply a chain of simple logical operationswhich you get a computer to work though sequentially. While most programs arefar from simple in their entirety, this complexity is a result of scale, and theycan still be decomposed into a sequence of simple operations. Given that theprogrammer is building complicated algorithms from simple rules, planning is key,else you are likely to find yourself in, I think the technical term is ‘a big horriblemess’.

It is of paramount importance when writing a program that the core stream oflogic behind the program is sound. To this end, it is common practice to employthe use of flow charts to describe the flow of a program, from its execution to itscompletion. The basic (and rather obvious) flow of pretty much every programever goes as follows:

start program

do stuff

end program

where do stuff can contain many iterations of this same pattern. The basic op-erations that make up programming are presented in Table 1, along with theirconventional flow chart representation.

As a slightly less trivial example consider the following flow chart:

5

Symbol Purpose Description→ Flow Line Used to indicate flow of logic by con-

necting symbols.

Start/Stop Used to represent the start and end offlow chart.

Input/Output Used to indicate input or output oper-ation.

Processing Used to indicate arithmetic operationsand data manipulation.

Decision Used to indicate true false discrimina-tion.

Table 1:

Start

Declare variables num1, num2 and sum

read num1 and num2 from user input

sum←a+b

Display sum

Stop

which sums two numbers input by the user and displays the result on screen. (Note:don’t worry too much about the step under Start for now, it will be explainedlater...). As another example consider:

6

Start

Declare variables a, b and c

read a, b and c

is a>b?

is b>c? is a>c?

Print b Print c Print a

Stop

False True

True False True

which finds the largest of the three numbers input by the user.

2 Prelab Questions

Note: You should read through the entirety of the lab before attempting thepre-lab questions.

1. Draw a flow chart to print the numbers 1-10 in order.

2. Draw a flow chart for how you would recursively compute the factorial, n!for a given integer n. Hint: There should be a termination condition whenn = 1.

3. Draw a flow-chart for question 3 of the procedure in section 6.2 showing howyou use the Euler Method to find a series expression for π.

7

3 Hello, world!

3.1 Background

3.1.1 Introduction to Linux

The part 2 lab computers are running Linux operating systems. While having agraphical interface, the advantage of Linux over Windows is access to the terminal,in which you can access all elements of the operating system via command-lineinputs. This is extremely useful when compiling and running simple programs, asit makes such tasks simple one line inputs, and removes the need for 3rd partysoftware with graphical interfaces.

Command Descriptioncd Move to new directory

mkdir Create new directorycp Copy filemv Move filerm Remove filels View contents of current directory

touch Create filepwd Display working directory/ Location of home directory; End of line

Table 2: List of basic Linux terminal commands.

Table 2 contains a list of basic terminal commands; remember them, as you will usethem often. As an example, if I were to create a working directory ‘/home/Lab_1’containing the file ‘Lab_1.c’ and open it in the default text editor, I would write:

1mkdir ˜/Lab1; cd Lab_1; touch Lab_1.c; gedit Lab_1.c;

3.1.2 Program Structure

The language of choice for these labs is C. All C programs are built around one mainfile, which we will call, surprise surprise, main.c. This file must contain a functioncalled ‘main’ which returns an integer. The execution of the ‘main’ function defines

8

the execution of the C program. The syntax for declaring a function in C is thefollowing:

9

1// main.c2

3int main()4{5// do stuff here6return(0);7}

where round brackets encapsulate the required function inputs, and curly bracketsencapsulate the functions execution. This function takes no inputs and returns0. Note the semi-colon, this tells the compiler that there is a line-break in theprogram. You must include a semi-colon at the end of every action within theprogram or it will not compile. C does not have restrictions on number of lines orvariable names, but is case sensitive.

Of course we are not limited to just one function; within main() we can call otherfunctions, which in turn can call further functions etc. To use a new function wemust do 2 things, declare it and define it.

To Declare a function you simply write its name and type, as well as the typeof the inputs, for example int function(int);. You must do this so that thecompiler knows the function exists, and doesn’t complain when you reference itlater in your code.

To Define a function you write it out in full, as for main() above. You can ofcourse (as with main() above) do both of these stages at once, though they shouldbe conceptually separated, as we will discuss below.

No function can be declared or defined within another function, so must be de-clared/defined before main(). One method is to simply declare/define new func-tions above main() in main.c i.e.

1// main.c2int do_more_stuff(int input)3{4// do more stuff, define some_integer.5return(some_integer);6}7//////////////////////8int main()9{10// do stuff here, define input

10

11do_more_stuff(input);12return(0);13}

where do_more_stuff(int input) takes an integer as an input and returns aninteger. Alternatively we can write our non-main() functions in another C filecalled a library file, for example

1// do_more_stuff.c2int do_more_stuff(int input)3{4// do more stuff, define some_integer.5return(some_integer);6}

We can then compile this file along with main.c into an executable as we willdiscuss shortly. Files ending with .c are referred collectively as source files. Thisconvention is desirable as our file naming scheme now matches our file functionality(and clean code = good code...). This introduces a new problem however, asnowhere in main.c is there a declaration/definition of int do_more_stuff(intinput) before it is used. Thus when we call this function in main.c, it looks likean unknown entity, and the program will not compile. The solution is to use whatis known as a header file, which conventionally has file type do_more_stuff.h.This file contains just the deceleration of the function name, not the functioncontents, and it is included at the top of main.c with the #include command,so that everywhere in main.c is it clear that int do_more_stuff(int input)exists. Thus int do_more_stuff(int input) is declared in do_more_stuff.h,but defined in do_more_stuff.c. Explicitly:

1// do_more_stuff.h2int do_more_stuff(int);

1// do_more_stuff.c2int do_more_stuff(int input)3{4// do more stuff, define some_integer.5return(some_integer);6}

1// main.c2#include "do_more_stuff.h"

11

3

4int main()5{6// do stuff here, define input7do_more_stuff(input);8return(0);9}

3.1.3 Program Compilation

Now that we have the basic structure of our code, we need to compile it into anexecutable program. This is done by a program called a compiler, which acts onour code in several stages:

1. Pre-processing is the first stage of compilation. It reads all #includestatements in all source files, and takes note of all declared functions andvariables. Note that the pre-processing stage must include declarations ofall functions and global variables used in any source code functions, else thenext stage will fail.

2. Compilation takes the output of the pre-processor and all source code files(.c) and compiles them into object files (.o), which are machine readable.

3. Linking takes all object files and links them together into one executable.

While it is important to know how the process works, and it is possible to separatethe stages of compilation, producing intermediary files, it is not necessary for ourpurposes. We will be using the compiler gcc, which takes care of all these stagesbehind the scenes. To run gcc from terminal and compile a program, we simplynavigate to the directory containing the source code files, and enter:

1gcc list_of_source_files -o executable_name;

where -o just tells the compiler to perform the above stages without outputtingany intermediary files. To compile the above example we would enter:

1gcc main.c do_more_stuff.c -o executable;

leaving us with an executable which we can run in the current directory by entering./executable in terminal.

12

3.1.4 Standard Libraries and Basic Data Output

As fun as it is writing your own libraries of functions to use in your main() function,there exist a host of pre-existing libraries of functions which can be used to makeyour life easier. In fact when people talk about ‘writing in C’, they really mean‘writing in C using the standard library set’. So important are standard libraries,that when updated they can fundamentally change the way programming is donein any given language.

The first library we will use is stdio, accessed by including <stdio.h> in therelevant source files. This library contains functions which deals with data inputand output, including the function printf, which takes a string of characters insidedouble parentheses, and prints them in the command line. Note: the newlinecharacter is given by “\n”.We are now ready to write our first program!

3.2 Procedure

1. Write a program in the default text editor which prints to screen a simple”Hello, world!” statement.

2. Compile and run this program in terminal.

3.3 Example Code

1// Example Code for Hello, world!2

3// Include standard library for input and output.4#include <stdio.h>5

6// Begin main program.7int main()8{9// Print text to terminal.10printf("Hello, world! \n");11// Finish program execution and return 0.12return(0);13}

13

4 Evaluating a Simple Function

4.1 Background

4.1.1 Data Types and Precision

There are several basic data types in C, each having a different amount of memoryallocation associated with them. The three types we will employ in this lab areintegers (int), floating point numbers (float), and long double precision numbers(long double). Similar to functions, variables of a particular data type in C mustbe declared and assigned. This doesn’t have to, but usually happens at once, forexample a function might contain the lines

1int i;2i=5;

which declares the int t in line 1, and assigns the value 5 to it on line 2. Alter-natively we can save lines by writing

1int i=5;

which does both at once. Note: you cannot use a variable, (say i in this example)as an algebraic entity, it just is a name for a value. If you have not assigned avalue to the name, it will have some unpredictable value automatically assigned.

A variable declared within a function, is only declared within that function. Whenthe function finishes evaluating the variable goes ‘out of scope’, meaning its allo-cated memory is cleared and the variable needs to be pre-declared/assigned. Wecan also define global constants at the beginning of our file. These are constantswhich are fixed throughout the program, and are visible to all functions. We dothis by using the #define command at the pre-processor stage, for example

1#define X 5

could be written under your #include statements. X is now defined for all func-tions.A little more about these data types:

Integers can have either sign, and have a memory allocation of 2 bytes if under≃ 3×104, over which they take around 4 bytes. Integers have a maximum value of≃ 1×1010. Arithmetic with integers can lead to decimal numbers. When assigning

14

a decimal number to an integer variable, the number will in general be roundeddown to the nearest integer.

A floating point number has a precision of 6 digits and can be either sign. It has4 bytes of storage assigned to it, and can be anywhere in the range 1.2× 10−38 →1.2 × 1038. It is important to be aware that floating point arithmetic can lead torounding errors of order 10−7.

A long double precision number is like a float but has a precision of 80 bitsand has between 12 and 16 bytes of storage assigned to it depending on its value.It can also be of either sign. Similarly to floating point arithmetic, long doublearithmetic can lead to rounding errors of order 10−80.

Given the limited memory allocated to C data types, it is important to be carefulthat your functions do not rely on data which exceeds the size limitations above.If unavoidable (as is often the case in physics applications!) make sure you re-scaleyour data so as not to exceed the limitations of your data type, but remember toscale your results back to the correct order of magnitude.

4.1.2 Operators

Functions are the stage, data types are the actors, but operators are the ac-tion...um...anyway, here are a list of basic C arithmetic operators...

Operator Name Descriptiona=b Assignment Assigns value b to data type a.

a +/- b Addition/Subtraction Adds/Subtracts a and ba*b Multiplication Multiplies a and ba/b Division Divides a and ba+=b Addition Assignment a=a+ba-=b Subtraction Assignment a=a-ba*=b Multiplication Assignment a=a*ba/=b Division Assignment a=a/b++a Prefix Increment Increases a by one then returns aa++ Postfix Increment Returns a then increases by one--a Prefix Decrement Decreases a by one then returns aa-- Postfix Decrement Returns a then decreases by one

Table 3: List of basic C arithmetic operators.

15

4.1.3 User Input

Also within stdio is the function scanf, which reads data from user input andstores it in a variable of the appropriate type. It takes as function parametersscanf("%x", reference_to_variable), where ‘x’ depends on the input datatype (d for integer, f for float). The parameter ‘reference_to_variable’ refersto the memory location of a declared variable. You don’t need to worry about thistoo much yet, but the basic idea is that when a variable is declared, some amountof memory is put aside to store it. This memory has a location in your systemmemory, and it is this location which is the input to the function. The memoryreference of a variable is recalled with the & operator, for example

1int i; // Allocates 2 bytes of memory to i.2i=5; // Assigns value of 5 to i.3i; // Returns 5.4&i; // Returns the location of the memory used to store i.

We can also use the notation of scanf to introduce some new functionality to ourprintf function, by including a variable assigned in our code in our output char-acter string. Using similar syntax to scanf, we can write printf("some string%x \n", variable), where as for scanf x is of the type ‘variable’, and is d for aninteger or f for a float (note that in this case ‘variable’ is the variable itself, notthe memory location).

Lets put this together into an example. See section 4.3 for an example programthat takes two integers from user input, and adds them together, returning theresult

4.2 Procedure

1. Write a simple function quadratic(a,b,c,x), which returns y(x) = ax2 +bx+ c.

2. Extend this program such that a, b, c and x are entered into the terminalby the user, and the result y(x) is returned and displayed.

16

4.3 Example Code

1// Example Code for Evaluating a Simple Function2// Author: Ahmad Galea3// Date: 01/03/20164

5#include <stdio.h>6

7int main()8{9// declare integers a and b.10int a, b;11// print user input prompt to terminal12printf("Enter integer value of a: \n");13// assign user input to integer a.14scanf("%d", &a);15// print user input prompt to terminal16printf("Enter integer value of b: \n");17// assign user input to integer b.18scanf("%d", &b);19// assign the sum of a and b to integer c.20int c = a+b;21// print c to terminal.22printf("a+b=%d \n",c);23

24return(0);25}

17

5 Data Files and Plotting

5.1 Background

5.1.1 Exporting Data in C

Just as we used printf to write to the terminal in earlier sections, we can use thestdio function fprintf to write to a file. First we must open a new file. This isdone by first creating an object of type FILE

1FILE *my_file;

don’t worry too much about the star preceding my_file (for those with somebackground this is technically a pointer to an object of type FILE, not the objectitself). We then use the function fopen to open a new file and assign it to my_file,

1my_file = fopen("my_file.dat", "w");

where the "w" means the file has writing permissions. The other options can beseen in Table 4 We can then write to the file using fprintf and the following

Option Meaningr Open for readingw Open for writing (file need not exist)a Open for appending (file need not exist)

r+ Open for reading and writing, start at beginningw+ Open for reading and writing (overwrite file)a+ Open for reading and writing (append if file exists)

Table 4: fopen options.

syntax

1int i = 1;2fprintf(my_file, "%d is and integer.", i);

and finally close the file with

1fclose(my_file);

18

It is usually good procedure to use a file extension which reflects the contents of afile, for example ".dat" for data and ".txt" for text.

Just as as fprintf can be used to print data to a file (analogously to printf forprinting to terminal), fscanf can be used to read data from a file (analogously toscanf user input). The syntax is the similar to scanf, for example

1int j;2FILE * my_file;3my_file = fopen("my_file.dat", "r");4

5fscanf(my_file, "%d", &j);6

7fclose(my_file);

opens "my_file.dat" for reading, and assigns the first integer in the file to j.

5.1.2 Plotting Data

In these labs we will use the plotting program PGPLOT, which is a multi plat-form library for plotting scientific data. It is loaded and used like any other Clibrary, by including the appropriate .h file in the relevant .c files, i.e. #include<cpgplot.h>. Recall from Section 3.1.3 though that we also need to link the ob-ject files of the PGPLOT library with our programs object files in our executablein order for the PGPLOT functions to be defined as well as declared. Given thatPGPLOT is installed in the system directory we can do this simply by enteringthe command -lcpgplot before the -o when compiling our program in terminal.

Below are some useful PGPLOT functions

cpgbeg is called to initiate PGPLOT and open the output device. It will promptthe user to supply the device name and type. It is called with

1cpgbeg(0, "/XWINDOW", 1,1);

Use “?” instead of “/XWINDOW” to bring up a list of display options.

cpgenv is called to specify the range of the axes and to draw the box which willcontain the plot. Following this cpglab is called to label the axes, for example

1cpgenv(0.0, 5.0, 0.0, 10.0, 0, 1);2cpglab("(x)", "(y)", "PGPLOT Example 1: y(x) = 2x");

19

specifies axes x and y, run from 0-5, and 0-10 respectively.

cpgpt draws points in the plot. It takes C arrays of x and y data values as input,along with the symbol used for the point, for example the following

1float y_values[4] = {2.0, 4.0, 6.0, 8.0};2float x_values[4] = {1.0, 2.0, 3.0, 4.0};3cpgpt(3, x_values, y_values, 9);

plots the first 3 elements of y_values, as a function of x_values, using symbolnumber nine.

cpgline takes number of points, y_values, and x_values as inputs and plots aline between the points, for example

1float y_values[4] = {2.0, 4.0, 6.0, 8.0};2float x_values[4] = {1.0, 2.0, 3.0, 4.0};3cpgline(3, x_values, y_values);

creates the linear y(x) = 2x line plot.

Finally, calling cpgend(); terminates PGPlot properly. We put all this togetherin the example below, using some further functions for prettier plots.

5.2 Procedure

1. Evaluate a simple function such as quadratic(a,b,c,x) over the range 1 ≤ x ≤5, with 5 equally-spaced data points.

2. Export a table of arguments and function values to an external file such as‘quadratic.dat’.

3. Read the data from ‘quadratic.dat’ and use PGPLOT to graph and print thisdata. (It is OK to copy the PGPLOT segment directly form the examplecode. Read and understand the comments in the file. Try playing aroundwith the settings.)

5.3 Example Code

1// Author: Julia McCoey2// Date: 01/03/2016

20

3// This program writes the function 'quadratic' to a data file"quadratic.dat".

4

5

6#include <stdlib.h>7#include <stdio.h>8

9// Declare functions signatures.10// This provides the compiler the input parameter and return types

before it actually reads the function DEFINITION defined below main.11float quadratic(float a, float b, float c, float x);12

13// This the main program14

15int main()16{17

18FILE *dataFile; // File pointer for data file19float a = 2.0; // Arbitrary value a20float b = 3.0; // Arbitrary value b21float c = 5.0; // Arbitrary value c22

23dataFile=fopen("quadratic.dat", "w"); // Open the data file24

25// Write 5 data points to file.26fprintf(dataFile, "%0.1f %0.1f\n", 1.0, quadratic(a,b,c,1.0));27fprintf(dataFile, "%0.1f %0.1f\n", 2.0, quadratic(a,b,c,2.0));28fprintf(dataFile, "%0.1f %0.1f\n", 3.0, quadratic(a,b,c,3.0));29fprintf(dataFile, "%0.1f %0.1f\n", 4.0, quadratic(a,b,c,4.0));30fprintf(dataFile, "%0.1f %0.1f\n", 5.0, quadratic(a,b,c,5.0));31

32

33

34return 0;35}36

37

38//The 'quadratic' function is defined here:39

40float quadratic(float a, float b, float c, float x)41{42return (a*x*x)+(b*x)+c;43}

21

6 Loops and Logic Statements

6.1 Background

6.1.1 If Function and Boolean Objects

Discrimination between variables is of fundamental importance in any program.The if function is the core mode of assertion testing in C. Unlike regular functions,if can be inlined in any function, and has the following syntax:

1if(test==true)2{3\\ Do stuff.4}

taking a Boolean (bool) type object as an argument.

Boolean objects are defined such that they can have either true or false astheir value. Table 5 shows a list of common comparison operators which result inBoolean values.

Operator Namea == b Equal toa != b Not equal toa > b Greater thana < b Less thana >= b Greater than or equal toa <= b Less than or equal to

Table 5: List of basic C comparison operators. Note that a and b can be of anytype, including bool.

Boolean values can be operated on using the operators in Table 6.

6.1.2 Loops in C

A loop is, in basic terms, an operation or series of operations, that is repeatedwhile a particular assertion holds true. In flow chart language

22

Operator Name Descriptiona && b AND Returns true if a and b are true.a || b OR Returns true if a or b are true.!a NOT Returns true if a is false.

Table 6: List of basic C Boolean operators.

Start

Test assertionDo operations

Stop

False

True

There are several loop types in C:

while loops are the simplest loop type. The while loop has the same format asif, but will repeat until the Boolean argument becomes false, e.g.:

1while(test==true)2{3\\ Do stuff.4}

do while loops are the same as while loops, but the assertion is tested after theoperation rather than before, i.e.

1do2{

23

3\\ Do stuff.4}5while(test==true);

for loops perform a given operation while an iterator spans a range. They havethis basic functionality:

1int i=0;2while(i<i_max)3{4\\ Do stuff.5i++;6}

but expressed in a compact form. They have a similar syntax to while loops,but take 3 arguments: the definition of the iterator, the Boolean value setting theupper bound, and the iteration of the value. For example

1for(int i=0; i<i_max; i++)2{3\\ Do stuff.4}

There is clearly some overlap in the functionality of these loops, though usuallyone is the best tool for the job. Be clear and try to think about your applicationbefore choosing.

6.1.3 Series and Sequences

Series expressions are extremely useful in mathematics and physics, and are oftenthe only solution to a system of equations. By truncating a series at order N , wecan find a numerical approximation of the solution, which gets more accurate asN increases. Such is the case for the Gregory Series expansion of π, which can beobtained from Machins Formula

1

4π = 4 tan−1

(1

5

)− tan−1

(1

239

)(1)

and can be seen in Table 7, along with other valid expansions.

The Hayashi expansion uses the Fibonacci sequence Fn, given byFn = Fn−1 + Fn−2 (2)

24

Name DefinitionGregory 4

∑∞k=1

(−1)k+1

2k−1

Wallis 2∏N

k=1(2k)2

(2k−1)(2k+1)

Newton/Euler∑∞

k=0(k!)22k+1

(2k+1)!

Hayashi 4∑∞

k=1 arctan(

1F2k+1

)Table 7: Series expression for π

where the sequence is seeded by the values F1 = F2 = 1.

Given their iterative nature, the numerical evaluation of series should be donewith loops. Specifically, given the incremental increase of the summed variable,for loops are the most convenient to use.

6.2 Procedure

1. Write a program which uses a loop to print integers 1-10 in the terminal.

2. Write a loop which calculates the first 10 Fibonacci numbers, and print themto the terminal.

3. Write a function which uses a loop to calculate the series expression for πup to order N , using the Euler Method.

4. Investigate the convergence of the formulae for π in Table 7 (by comparisonto its exact value) as a function of series truncation N, and produce a tableof results. You can copy the methods directly from the example code forthis section.

5. Order these series formulae from most to least convergent.

6.3 Example Code

1// Author: William Lawrie2// Date: 01/03/20163

4#include <stdio.h>5#include <stdlib.h>

25

6#include <math.h>7

8#define NMAX 10009

10//Declare global variables:11

12//Declare functions:13double Gregory(int iteration);14double Wallis( int Iteration);15double Euler(int Iteration);16double Hayashi(int Iteration);17

18double factorial(double number);19double fibonaci(int number);20

21//The main part of the code. Functions that approximate pi22//are called from here, in a loop that determines the number23//of iterations used to approximate.24int main()25{26///////////////////////27// Declare Variables //28///////////////////////29

30double pi_Gregory; //These keep track of the approximation31double pi_Wallis;32double pi_Euler;33double pi_Hayashi;34

35double del_Gregory; //These keep track of the error in theapproximation

36double del_Wallis;37double del_Euler;38double del_Hayashi;39

40int N; // This is the variable that counts the number of iterations41// to use42

43//Here are the guts of the program. We feed in a number N,44//which determines the number of iterations to use in the45//relevant approximation. We loop over values of N between46// 1 and 100 to get an idea of how quickly different47//approximations converge with number of iterations.

26

48

49printf("N\tPi\t\tGregory\t\tDelGregory\n");50for( N = 0; N < NMAX; N++){51/*The values in the if statement below can be changed at will, these

are simply the values of interest52for N number of iterations in the various approximations.*/53if(N==1 || N==10 || N==100 || N==1000 || N==NMAX-1){54pi_Gregory = Gregory(N); //Calls the Gregory approximation for N

iterations55del_Gregory = fabs(pi_Gregory - M_PI); //These calculate the error

by taking the absolute value56printf("%d\t%4.6f\t%4.6f\t%4.6f\n",N,M_PI,pi_Gregory,del_Gregory);57}58}59

60

61

62printf("N\tPi\t\tWallis\t\tDelWallis\n");63for( N = 0; N < NMAX; N++){64/*The values in the if statement below can be changed at will, these

are simply the values of interest65for N number of iterations in the various approximations.*/66if(N==1 || N==10 || N==100 || N==1000 || N==NMAX-1){67pi_Wallis = Wallis(N); //Calls the Wallis approximation for N

iterations68del_Wallis = fabs(pi_Wallis - M_PI); //These calculate the error

by taking the absolute value69printf("%d\t%4.6f\t%4.6f\t%4.6f\n",N,M_PI,pi_Wallis,del_Wallis);70}71}72

73

74printf("N\tPi\t\tHayashi\t\tDelHayashi\n");75for( N = 0; N < NMAX; N++){76if(N==1 || N==10 || N==50 || N==90){77pi_Hayashi = Hayashi(N); // '' '' Hayashi '' '' ''78del_Hayashi = fabs(pi_Hayashi - M_PI);//the actual value of pi

(M_PI)79printf("%d\t%4.6f\t%4.6f\t%4.6f\n",N,M_PI,pi_Hayashi,del_Hayashi);80}81}82

83}

27

84

85

86///////////////////////////////////////////87//// DEFINE FUNCTIONS: ////////////////////88///////////////////////////////////////////89

90//This is the Gregory approximation. It takes a number of iterations91//over which to loop, thus improving upon the approximation92double Gregory(int iteration){93///////////////////////////94//Declare local variables//95///////////////////////////96double pi_new = 0.;97int i = 0;98double j = 0.;99///////////////////////////100

101for(i=1;i<iteration+1;i++){102pi_new+=(pow(-1, i+1)/(2*i-1));103}104

105pi_new = 4.*pi_new;106return pi_new;107}108

109//This is the Wallis approximation. It takes a number of iterations110//over which to loop, thus improving upon the approximation. This111//Approximation is given in full. Note the structure, particularly the112// way the approximation pi_new constantly updates itself inside the

loop113double Wallis(int iteration){114///////////////////////////115//Declare local variables//116///////////////////////////117

118double pi_new=1.; //Since the Wallis approx is a multiplicative sum,119//We set the approximation initially to 1.120

121int i = 0; //i is an integer, that keeps track of the number122//of iterations being done in the loop123

124double j = 0.; // j is a double type: its purpose is to convert the125//value of the integer 'i' as a double, so it can be

28

126//used in calculations. The take home message here is127//that you should never try to perform operations on128//variables stored as different types.129

130///////////////////////////131

132

133//Begin the loop:134for(i=1;i<iteration+1;i++){135j = (double)i; //As mentioned before, we convert the integer136//i into a double type and store it as j137

138pi_new = pi_new * (2.*j * 2.*j) / ((2.*j - 1.)*(2.*j+1.));139//This is Wallis approximationˆˆ140}141

142pi_new = 2.*pi_new; //Since the Wallis approx technically approximates143//pi/2 , we multiply out to get the final value144return pi_new; //We return the approximation to the main() section145}146

147

148

149/*This is the Euler approximation. It takes a number of iterations150over which to loop, thus improving upon the approximation.151You'll need to write this and subsequent ones yourself.152Some tips:153-Euler uses a conventional sum, so make sure you set your154initial value to 0.155-to update your approximation inside a loop, you can either156write pi_approx = pi_approx + next term157or pi_approx += next term158-Euler requires using a factorial function, which is already159written for you below. just call "factorial(k)" where k is a160double you want to calculate the factorial of. don't try to calculate161the factorial of a negative number or decimal.162*/163double Euler(int iteration){164///////////////////////////165//Declare local variables//166///////////////////////////167

168///////////////////////////

29

169//Begin your for loop /////170///////////////////////////171

172////////////////////////////173//Return your approximation/174////////////////////////////175}176

177//This is the Hayashi approximation. It takes a number of iterations178//over which to loop, thus improving upon the approximation179double Hayashi(int iteration){180///////////////////////////181//Declare local variables//182///////////////////////////183double pi_new = 0.;184int i = 0;185double j = 0.;186///////////////////////////187

188for(i=1;i<iteration+1;i++){189pi_new+=atan(1./fibonaci(2*i+1));190}191

192pi_new = 4.*pi_new;193return pi_new;194}195

196

197

198//Calculates the Factorial of the number 'n'199double factorial(double n){200///////////////////////////201//Declare local variables//202///////////////////////////203

204int i;205double fact = 1.;206///////////////////////////207

208if(n==0){209fact=1.;210}211else if(n<0){

30

212fact = 1.;213printf("\nError! Negative input to Factorial Function!\n");214}215else{216for(i = 0; i < n; i++){217fact = fact*(n-i);218}219}220return fact;221}222

223

224//Calculates the k'th fibonaci number225double fibonaci(int k){226///////////////////////////227//Declare local variables//228///////////////////////////229int i;230double fib2;231double fib1=1.; //F(1) = 1232double fib0=1.; //F(2) = 1233double j;234///////////////////////////235

236for(i=2;i<k;i++){ //i = 2 since k237fib2 = fib1 + fib0; //will be 3 or greater,238fib0 = fib1; //and F(1) and F(2) are239fib1 = fib2; //already defined240}241return fib2;242}

31

7 Bonus Section: Special Functions and Recur-rence Relations

7.1 Background

7.1.1 Series Representations of Bessel Functions

As an interesting application of numerical evaluation of series expansions, we willnow look at the solutions to Bessel’s equation, specifically, at Bessel Functions ofthe First Kind.

Bessel’s differential equation is given by

x2 d2y

dx2+ x

dy

dx+ (x2 − n2)y = 0 (3)

It is a 2-dimensional wave equation, and has many applications in physics includingthe notable examples: description of electromagnetic waves in a cylindrical wave-guide, solutions to the radial Schrodinger Equation for a free particle, and modesof vibration on a circular drum. (refs)For integer n it has the series solutions

Jn(x) =N∑l=0

(−1)l

22l+nl!(n+ l)!x2l+n (4)

where N →∞.

7.2 Procedure (One Bonus Mark)

1. Use the series solution for Jn(x) of arbitrary integer order n ≥ 1 to write afunction bessj(n,x)

2. Generate and plot a data file bessjn.dat for the zeroth- and first-order Besselfunctions J0(x) and J1(x) between 0 ≤ x ≤ 10 with 1000 data points, usingeach of N = {10, 50, 200} .

3. Repeat the above step for all Bessel functions of the first kind, Jn(x), up ton = 6, using N = 200 terms in the series. (This will require a nested loop).Plot the results.

32

7.3 Example Code

1// Example Code for Series Representation of Bessel Functions2// Author: Chia-Ling Hsu3// Date: 23/02/20164

5#include <math.h>6#include <stdio.h>7#include <stdlib.h>8/*9This program needs to use long double for the factorial function,

since the result will10be over the limit of double precision when iterations is close to 200.11*/12// Declare functions which will use later13long double factorial(int);14double bessel_n(int, double);15

16#define MAX_ARRAY 100117

18int main(void){19

20// Open a file21FILE *fp = fopen("bessel.dat","w");22// Check if the file is open, if not print out error message and quit

the program23if (fp == NULL)24{25printf("Error opening file!");26exit(1);27}28// Declare variable29double j0;30double j1;31double x = 0;32// Array for pgplot (pgplot only accepts float type)33float j0p[MAX_ARRAY];34float j1p[MAX_ARRAY];35float xp[MAX_ARRAY];36

37// Loop for x iteration ( 0 <= x <= 10 )38int i;39for (i = 0; i < 1001; i++)

33

40{41// Calculate x position for this step42x = 0.01*i;43xp[i] = x;44// Assign return values with the present x position to j1, j245j0 = bessel_n(0, x);46j1 = bessel_n(1, x);47// Fill in values to array48j0p[i] = j0;49j1p[i] = j1;50// Print out result to file51fprintf(fp, " %f %f\n", j0, j1);52

53}54// Close the file55fclose(fp);56return (0);57}58

59long double factorial(int n)60{61// Calculate factorial with given n62// NOTE: if n = 0, the function will skip the loop and return the

initial value63// Declare local variable for this function64long double fact = 1;65for (int c = 1; c <= n; c++)66{67fact = fact * c;68}69return fact;70}71

72double bessel_n(int n, double x)73{74// Declare local variables for this function75long double f_k = 0;76long double f_kn = 0;77int k;78double frac = 1;79double a_k = 0;80for (k = 0; k<=200; k++)81{

34

82// Determine the factor of (-1)ˆk83if (k%2 == 0)84{85frac = 1;86}87else88{89frac = -1;90}91// Assign k! and (k+n)! for f_k and f_kn92f_k = factorial(k);93f_kn = factorial(k+n);94long double power = 1;95// Calculate Exponential function with the base x/296for (int i = 1; i<=2*k+n; i++)97{98// Iteratively increase the power of exponential99power *= (0.5*x);100}101// Sum up each term in the series102a_k += (frac/(f_k*f_kn))*power;103}104// Return value105return a_k;106}

35