160 likes | 294 Views
How to Write a Fortran Jiffy. (C)2005 Mark Rould University of Vermont. Fortran has a few idiosyncrasies. • Lines with a "C" or "!" in column 1 are comments (ignored) • Lines which start with something in column 6 are continuations of the previous line
E N D
How to Write a Fortran Jiffy (C)2005 Mark Rould University of Vermont
Fortran has a few idiosyncrasies... • Lines with a "C" or "!" in column 1 are comments (ignored) • Lines which start with something in column 6 are continuations of the previous line • All other lines should begin in column 7 or later 123456789012345678901234567890123456789012345678901234567890... c This line is a comment ! This line is too. write( 6, *) 'This is a normal line (aka, a statement)' do i = 1, 3 write( 6, *) 'This statement continues ', & 'on the next line.' end do end 123456789012345678901234567890123456789012345678901234567890...
Programs Play with Data; Data is stored in Variables 3 types of variables will get you far in Fortran: • INTEGER for holding whole numbers: 43, -9843, 0 • REAL for holding numbers with decimal fractions and/or exponents: 43.546, 3.14159, -1.6180339, 6.0221E23 • CHARACTER for holding anything alphanumeric: "I love Fortran!", "Nothing from nothing leaves 0" Other notables: • LOGICAL variables hold values of either TRUE or FALSE • COMPLEX variables are really two REALs (a real part and an imaginary part) • Any of these variables can be used in arrays • All of the numeric variables are also available as DOUBLE PRECISION (at least twice as many significant digits)
Do you have any variables to declare? It's always a good idea to have an implicit none statement as the first line of your program -- It forces you to declare your variables at the beginning of the program, but it also helps catch a lot of typos. implicit none integer Hin, Kin, Lin, & Hout, Kout, Lout, & m11, m12, m13, m21, m22, m23, m31, m32, m33, determinant, & endOfFileFlag, & nreflectionsRead, nreflectionsWritten, nsysAbsencesTossed character filename*200, headerLine*100, restOfReflectionLine*32 All of these variables are declared to be integers These are declared as character variables; the # after the * indicates how many characters long they are. real detector_width, wavelength, & min_xtl_detector_dist, max_xtl_detector_dist, & xtl_detector_dist_increment, xtl_detector_dist, & twoTheta_max_radians, twoTheta_max_degrees, highest_resolution These variables will hold real numbers.
Getting Data In and Out Display on the terminal write( 6, *) 'Width of detector (in mm)?' read( 5, *) detector_width Take input from the user and store it in this variable
Could you get me that file? Open an existing (old) file whose name is stored in the character variable filename write( 6, *) 'Input .sca file:' read( 5, '(a)') filename open( unit=1, file=filename, status='old') read( 1, '(i4,i4,i4,a32)', iostat = endOfFileFlag ) Hin, Kin, Lin, restOfReflectionLine If we run out of data while trying to read from this file, then the variable endOfFileFlag will be set to a non-zero value; otherwise it will be set to 0. Read a line from that file, take the integer number in the first 4 columns and store it in variable Hin, take the number in the next 4 columns and store it in Kin, the next 4 in Lin, and store the next 32 columns as alphanumeric data in the character variable restOfReflectionLine.
File This Away write( 6, *) 'Output .sca file:' read( 5, '(a)') filename open( unit=2, file=filename, status='unknown') Open this file, regardless of whether or not it already exists. write( 2, '(i4,i4,i4,a32)') Hout, Kout, Lout, restOfReflectionLine Write the values in these variables to the file in the specified format. Section of output file: 9 5 12 2259.5 138.0 2355.5 108.8 9 5 13 679.9 134.7 766.4 68.5 9 5 14 1477.4 119.0 1237.8 78.5 9 5 15 2163.2 149.2 2511.8 171.4 9 5 16 544.5 138.7 480.1 131.1
Data Games nreflectionsRead = 0 Store a 0 in this variable nreflectionsRead = nreflectionsRead + 1 Take the amount stored in this variable, add 1 to it, and store the result back in the same variable.
More Fun with Variables Variables Hout = m11 * Hin + m12 * Kin + m13 * Lin Calculate the sine of the following expression in parentheses highest_resolution = wavelength / ( 2. * sin( 0.5 * twoTheta_max_radians)) + - * / sin( ) asin( ) cos( ) acos( ) tan( ) atan( ) mod( a, b) -- remainder of a/b Use parentheses liberally to force the order of evaluation
Decisions Decisions Only if the expression in parentheses is true will the statements in between be executed. if ( min_xtl_detector_dist .le. 0.0 ) then write( 6, *) 'This distance must be greater than 0.0 mm.' stop end if .eq. = .lt. < .gt. > .le. < or = .ge. > or = .ne. not =
Tough Decisions Only if all 3 of these conditions are met will the statements between the then and else be executed; else if not, the statements between the else and end if will be executed if ( ( Hout .eq. 0 ) .and. ( Kout .eq. 0 ) .and. ( mod( Lout, 2) .ne. 0 ) ) then write( 6, '( " ** Tossed ** ", 3i4, a32)' ) Hout, Kout, Lout, restOfReflectionLine nsysAbsencesTossed = nsysAbsencesTossed + 1 else write( 2, '(3i4,a32)') Hout, Kout, Lout, restOfReflectionLine nreflectionsWritten = nreflectionsWritten + 1 end if .and. .or. .not.
Loop-de-Loop A simple loop: "Begin by setting the variable i to 10. Execute all statements up to the end do, then go back up to the beginning of the loop, increment i by 2, and repeat until i exceeds 20." do i = 10, 20, 2 write( 6, *) i end do 10 12 14 16 18 20
Loop-de-Loop, part Deux do xtl_detector_dist = min_xtl_detector_dist, max_xtl_detector_dist, xtl_detector_dist_increment twoTheta_max_radians = atan( 0.5 * detector_width / xtl_detector_dist) twoTheta_max_degrees = twoTheta_max_radians * 180. / 3.14159 highest_resolution = wavelength / ( 2. * sin( 0.5 * twoTheta_max_radians)) write( 6, '(5x, f6.1, 19x, f5.2, 21x, f5.1)') xtl_detector_dist, highest_resolution, twoTheta_max_degrees end do When this loop is reached, the variable xtl_detector_dist will be set to the value in variable min_xtl_detector_dist. Do (execute) all statements up to the end of the loop, indicated by end do. At the bottom of the loop, xtl_detector_dist_increment is added to xtl_detector_dist. As long as xtl_detector_dist does not exceed max_xtl_detector_distance, the loop repeats.
How long do I have to keep doing this? Repeat this loop as long as the condition in parentheses is true endOfFileFlag = 0 do while ( endOfFileFlag .eq. 0 ) read( 1, '(3i4,a32)', iostat = endOfFileFlag ) Hin, Kin, Lin, restOfReflectionLine if ( endOfFileFlag .eq. 0 ) then nreflectionsRead = nreflectionsRead + 1 Hout = m11 * Hin + m12 * Kin + m13 * Lin Kout = m21 * Hin + m22 * Kin + m23 * Lin Lout = m31 * Hin + m32 * Kin + m33 * Lin . . . end if end do Note: The indenting is not required, but helps make the program more legible.
How do you want that written? write( 6, '(a)') ' Xtl-Det Dist (mm) Highest Resolution (A) 2theta_max (deg)' write( 6, '(a)') ' ----------------- ---------------------- ----------------' ! '.....####.#...................##.##.....................###.#' write( 6, '(5x, f6.1, 19x, f5.2, 21x, f5.1)') xtl_detector_dist, highest_resolution, twoTheta_max_degrees 5x -- skip 5 spaces f6.1 -- write a real value in a total of 6 spaces, with 1 decimal digit i5 -- write an integer value in 5 spaces a7 -- write 7 characters of a character variable The same format specifiers can be used for reading too.
Compiling and Running your Jiffy To compile (ie, convert your program into the computer's native tongue) g77 yourProgam.f -o yourProgram -ffixed-line-length-255 To run: yourProgram