MP520 – Computer Systems in Medicine
Fortran Mini-lab 1: The Shortest Path Between Two Points
Introduction
For your first programming assignment with Fortran, you're going to make a lightweight application that linearly interpolates (lerp) between two data points.
We'll do the design together, here in this document, and then you will be responsible for the coding, testing, and debugging of the application.
A linear interpolation literally describes a line between two points, and then returns a value on that line based on the point of interpolation. The graph below describes a linear interpolation between (x1, y1) and (x2, y2).
The x-values describe the quantity that you know: for instance, if you were interpolating field sizes to get a TMR, the x-values represent field sizes, as you know the field size for which you are trying to get a TMR. You input x0 to the lerp, which is itself just the equation of the line drawn in the graph. Remember that the actual curve that describes the data does not necessarily have the shape of a line—this is why the lerp is an approximation.
The actual equation you will be implementing is laid out like this:
y0 = y2 - y1/x2 - x1 (x0 - x1)+y1
This equation does not correspond exactly to the graph above, but the idea is the same.
Incidentally, it is very easy to verify that you've written the correct equation. First, let x0 = x1, and see if y0 = y1. Then, let x0 = x2, and see if y0 = y2. I have always found this invaluable for remembering the lerp equation.
Lesson / Design
So, let's begin to design our program. We are going to need variables to represent the five inputs (x0, and then the four values we will be interpolating between). They are all floating point numbers, so they should be declared as REALs, which are what Fortran calls floating point type variables. We might as well use REALs of kind (8). The kind parameter is fairly unique to Fortran—it is a secondary specifier of the size of a type. For instance, REAL can come in (1) (2) (4) or (8) byte kinds. To declare a variable, simply enter the following:
REAL(8) :: variable
or
LOGICAL(4) :: anothervar
or
INTEGER(4) :: integervar
Note that LOGICAL is the type name for boolean in Fortran. Logicals should always be of kind (4). Integers will usually be kind (8) or (4), and the same goes for REALs.
You can initialize a variable by adding an equals sign and the initial value of the variable after the variable's name in its declaration. This ensures that the variable's memory address has a value that you've specified entered into it when the program first starts. If you don't initialize a variable, and then try to use it before you assign it a value, the uninitialized value of the variable will be meaningless junk. Remember, initialization ONLY sets the value of the variable ONCE at the start of the program. That is, this happens right after you type the name of your executable. (Modules, subs, and functions work differently, but don't worry about that right now.) Initialization is important if you might use a variable before you store anything into it, or if your first use of the variable is to add something to what's already in it. For instance, you would probably want to initialize the variable alpha in the following code block, if this was your first use of alpha:
alpha = alpha + 1
It is a good practice to store the result of the calculation in another variable, so you should declare yourself a y0 variable to store your results in.
The flow of the program is straightforward. The simplest possible program would prompt the user for all five values, calculate the result, print it to the screen, and then terminate.
The simplest way to print to the screen is the use of the PRINT *, text statement. There are ways of printing with special formatting (e.g. printing numbers in pretty formats) that we will worry about later. You should replace text either with a variable or with a block of text in quotation marks. You can even make a list, separated by commas, of what you would like to stick on the same line of output. For instance...
INTEGER(4) result = 0
PRINT *, “The result is”, result, “in units of Gy.”
… would write to the screen
The result is 0 in units of Gy.
To read input from the keyboard, use a READ(*,*) variable statement. Replace variable with a single variable or list of variables into which you want to read input. Although you can read in more than one variable at a time, I encourage you to prompt your user for each variable by putting a PRINT line before a READ line, like the following:
PRINT *, “Enter x coordinate:”
READ(*,*) xc
PRINT *, “”
PRINT *, “Enter y coordinate:”
READ(*,*) yc
… as opposed to...
PRINT *, “Enter x and y coordinate:”
READ(*,*) xc, yc
The former helps to prevent invalid input on the part of a user. It's more clear what is expected of them, and they don't need to know the niceties of how input works in Fortran in order to successfully use your program. The less your user has to guess at, the better.
You can use WRITE(*,*) by itself or PRINT *, “” to insert a blank line in your program output.
The last thing you really need to worry about is arithmetic. Arithmetic in FORTRAN works much like other computer math packages. The order of operations is no different from standard algebra. The operators are:
+ Add
- Subtract
* Multiply
/ Divide (that is a forward slash)
** Exponentiate (e.g. 3**2 is equal to 9)
That's really most of what there is to it. Since this is your first assignment in the course, we won't worry about niceties like looping, storing results, error handling, and so on. However, try making a header comment for the program. Make the first few lines of your program comments (the first character of the line should be an exclamation point—everything on a given line that comes after one is a comment). The first line should include MP520, the assignment number, and your name—do this for every program you make for this course. The next few lines should very briefly describe what the program does, what it expects as inputs, and what it returns as outputs. In the future, every program, module, or subroutine that we write will include a header comment such as this one to describe the interface of the routine. The interface is just what inputs the program expects, what outputs it gives back, and the order of the arguments.
Get to Work
Your assignment is as follows:
- Code the linear interpolation program.
- It must obtain the five necessary inputs listed above.
- It must print at least one output: the correct result of the interpolation.
- The inputs and outputs are floating point numbers.
- Use comments to document the code and create the header.
- Successfully compile and run the program.
- Show that you have tested the program for at least two representative cases, and that the results of the test are in accord with hand calculations that you are also to provide.
As long as your program accomplishes all the goals listed above, the details of how it does so are largely up to you. You are free to add reasonable additional features, but the goals listed above are sufficient for full credit.
Your program must be free of logic errors—that is, it must actually give the correct answer for any interpolation that you can think of (within the operating parameters of the program).
You should test your program for several different cases. This means, for this program, to try interpolating between data points that have different properties. It is obvious to check to data points with all positive values, but you need to think a little deeper about how the program might be used. Try two negative data points, and also one negative and one positive.
There may be other cases you can think of that might need special handling. What happens if the user accidentally puts in two points that have the same y value? The same x value? In your program, these cases are not handled gracefully. That is to say, the program will give unexpected results, and might even crash. Generally, your program should never do anything unexpected, or if it has to it should explain to the user what just happened. We will worry about error handling, boundary checks, and so on in another lab. For now, though, be thinking about cases that could cause problems.