Fortran

Личный сайт Go-разработчика из Казани

Fortran is one of the oldest computer languages. It was developed in the 1950s by IBM for numeric calculations (Fortran is an abbreviation of «Formula Translation»). Despite its age, it is still used for high-performance computing such as weather prediction. However, the language has changed considerably over the years, although mostly maintaining backwards compatibility; well known versions are FORTRAN 77, Fortran 90, Fortran 95, Fortran 2003, Fortran 2008, Fortran 2018 and Fortran 2023.

This overview will discuss the features of Fortran 2008 since it is the most widely implemented of the more recent specifications and the later versions are largely similar (by comparison FORTRAN 77 is a very different language).

1! This is a comment. 2 3program example ! declare a program called example. 4 5 ! Code can only exist inside programs, functions, subroutines or modules. 6 ! Using indentation is not required but it is recommended. 7 8 ! Declaring Variables 9 ! =================== 10 11 ! All declarations must come before statements and expressions. 12 13 implicit none ! prevents dynamic declaration of variables 14 ! Recommended! 15 ! Implicit none must be redeclared in every function/program/module... 16 17 ! IMPORTANT - Fortran is case insensitive. 18 real z 19 REAL Z2 20 21 real :: v, x ! WARNING: default initial values are compiler dependent! 22 real :: a = 3, b = 2E12, c = 0.01 23 integer :: i, j, k = 1, m 24 real, parameter :: PI = 3.14159265 ! declare a constant. 25 logical :: y = .TRUE., n = .FALSE. ! boolean type. 26 complex :: w = (0, 1) ! sqrt(-1) 27 character(len=3) :: month ! string of 3 characters. 28 29 ! declare an array of 6 reals. 30 real :: array(6) 31 ! another way to declare an array. 32 real, dimension(4) :: arrayb 33 ! an array with a custom index -10 to 10 (inclusive) 34 integer :: arrayc(-10:10) 35 ! A multidimensional array. 36 real :: array2d(3, 2) 37 38 ! The '::' separators are not always necessary but are recommended. 39 40 ! many other variable attributes also exist: 41 real, pointer :: p ! declare a pointer. 42 43 integer, parameter :: LP = selected_real_kind(20) 44 real(kind=LP) :: d ! long precision variable. 45 46 ! WARNING: initialising variables during declaration causes problems 47 ! in functions since this automatically implies the 'save' attribute 48 ! whereby values are saved between function calls. In general, separate 49 ! declaration and initialisation code except for constants! 50 51 ! Strings 52 ! ======= 53 54 character :: a_char = 'i' 55 character(len=6) :: a_str = "qwerty" 56 character(len=30) :: str_b 57 character(len=*), parameter :: a_long_str = "This is a long string." 58 !can have automatic counting of length using (len=*) but only for constants. 59 60 str_b = a_str//" keyboard" ! concatenate strings using // operator. 61 62 ! Assignment & Arithmetic 63 ! ======================= 64 65 Z = 1 ! assign to variable z declared above 66 j = 10 + 2 - 3 67 a = 11.54/(2.3*3.1) 68 b = 2**3 ! exponentiation 69 70 ! Control Flow Statements & Operators 71 ! =================================== 72 73 ! Single-line if statement 74 if (z == a) b = 4 ! conditions always need parentheses. 75 76 if (z /= a) then ! z not equal to a 77 ! Other symbolic comparisons are < > <= >= == /= 78 b = 4 79 else if (z .GT. a) then ! z greater than a 80 ! Text equivalents to symbol operators are .LT. .GT. .LE. .GE. .EQ. .NE. 81 b = 6 82 else if (z < a) then ! 'then' must be on this line. 83 b = 5 ! execution block must be on a new line. 84 else 85 b = 10 86 end if ! end statement needs the 'if' 87 88 if (.NOT. (x < c .AND. v >= a .OR. z == z)) then ! boolean operators. 89 inner: if (.TRUE.) then ! can name if-construct. 90 b = 1 91 end if inner ! then must name endif statement. 92 endif ! 'endif' is equivalent to 'end if' 93 94 i = 20 95 select case (i) 96 case (0, 1) ! cases i == 0 or i == 1 97 j = 0 98 case (2:10) ! cases i is 2 to 10 inclusive. 99 j = 1 100 case (11:) ! all cases where i>=11 101 j = 2 102 case default 103 j = 3 104 end select 105 106 month = 'jan' 107 ! Condition can be integer, logical or character type. 108 ! Select constructions can also be named. 109 monthly:select case(month) 110 case ("jan") 111 j = 0 112 case default 113 j = -1 114 end select monthly 115 116 do i = 2, 10, 2 ! loops from 2 to 10 (inclusive) in steps of 2. 117 innerloop: do j = 1, 3 ! loops can be named too. 118 exit ! quits the loop. 119 end do innerloop 120 cycle ! jump to next loop iteration. 121 end do 122 123 ! Goto statement exists but it is heavily discouraged. 124 goto 10 125 stop 1 ! stops the program, returns condition code 1. 12610 j = 201 ! this line is labeled as line 10 127 128 ! Arrays 129 ! ====== 130 array = (/1, 2, 3, 4, 5, 6/) 131 array = [1, 2, 3, 4, 5, 6] ! using Fortran 2003 notation. 132 arrayb = [10.2, 3e3, 0.41, 4e-5] 133 array2d = reshape([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [3, 2]) 134 135 ! Fortran array indexing starts from 1. 136 ! (by default but can be defined differently for specific arrays). 137 v = array(1) ! take first element of array. 138 v = array2d(2, 2) 139 140 print *, array(3:5) ! print all elements from 3rd to 5th (inclusive). 141 print *, array2d(1, :) ! print first column of 2d array. 142 143 array = array*3 + 2 ! can apply mathematical expressions to arrays. 144 array = array*array ! array operations occur element-wise. 145 ! array = array*array2d ! these arrays would not be compatible. 146 147 ! There are many built-in functions that operate on arrays. 148 c = dot_product(array, array) ! this is the dot product. 149 ! Use matmul() for matrix maths. 150 c = sum(array) 151 c = maxval(array) 152 print *, minloc(array) 153 c = size(array) 154 print *, shape(array) 155 m = count(array > 0) 156 157 ! Loop over an array (could have used Product() function normally). 158 v = 1 159 do i = 1, size(array) 160 v = v*array(i) 161 end do 162 163 ! Conditionally execute element-wise assignments. 164 array = [1, 2, 3, 4, 5, 6] 165 where (array > 3) 166 array = array + 1 167 elsewhere(array == 2) 168 array = 1 169 elsewhere 170 array = 0 171 end where 172 173 ! Implied-DO loops are a compact way to create arrays. 174 array = [(i, i=1, 6)] ! creates an array of [1,2,3,4,5,6] 175 array = [(i, i=1, 12, 2)] ! creates an array of [1,3,5,7,9,11] 176 array = [(i**2, i=1, 6)] ! creates an array of [1,4,9,16,25,36] 177 array = [(4, 5, i=1, 3)] ! creates an array of [4,5,4,5,4,5] 178 179 ! Input/Output 180 ! ============ 181 182 print *, b ! print the variable 'b' to the command line 183 184 ! We can format our printed output. 185 print "(I6)", 320 ! prints ' 320' 186 print "(I6.4)", 3 ! prints ' 0003' 187 print "(F6.3)", 4.32 ! prints ' 4.320' 188 189 ! The letter indicates the expected type and the number afterwards gives 190 ! the number of characters to use for printing the value. 191 ! Letters can be I (integer), F (real), E (engineering format), 192 ! L (logical), A (characters) ... 193 print "(I3)", 3200 ! print '***' since the number doesn't fit. 194 195 ! we can have multiple format specifications. 196 print "(I5,F6.2,E6.2)", 120, 43.41, 43.41 197 198 ! 3 repeats of integers (field width = 5). 199 print "(3I5)", 10, 20, 30 200 201 ! repeated grouping of formats. 202 print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 203 204 ! We can also read input from the terminal. 205 read (*, *) v 206 read (*, "(2F6.2)") v, x ! read two numbers 207 208 ! To write a file. 209 open (unit=12, file="records.txt", status="replace") 210 ! The file is referred to by a 'unit number', an integer that you pick in 211 ! the range 9:99. Status can be one of {'old','replace','new'}. 212 write (12, "(F10.2,F10.2,F10.2)") c, b, a 213 close (12) 214 215 ! To read a file. 216 open (newunit=m, file="records.txt", status="old") 217 ! The file is referred to by a 'new unit number', 218 ! an integer that the compiler picks for you. 219 220 read (unit=m, fmt="(3F10.2)") a, b, c 221 close (m) 222 223 ! There are more features available than discussed here and alternative 224 ! variants due to backwards compatibility with older Fortran versions. 225 226 ! Built-in Functions 227 ! ================== 228 229 ! Fortran has around 200 functions/subroutines intrinsic to the language. 230 ! Examples - 231 call cpu_time(v) ! sets 'v' to a time in seconds. 232 k = ior(i, j) ! bitwise OR of 2 integers. 233 v = log10(x) ! log base 10. 234 i = floor(b) ! converts b to integer by rounding down. 235 v = aimag(w) ! imaginary part of a complex number. 236 237 ! Functions & Subroutines 238 ! ======================= 239 240 ! A subroutine runs some code on some input values and can cause 241 ! side-effects or modify the input values. 242 243 call routine(a, c, v) ! subroutine call. 244 245 ! A function takes several input parameters and returns a single value. 246 ! However the input parameters may still be modified and side effects 247 ! executed. 248 249 m = func(3, 2, k) ! function call. 250 251 ! Function calls can also be evoked within expressions. 252 print *, func2(3, 2, k) 253 254 ! A pure function is a function that doesn't modify its input 255 ! parameters or cause any side-effects. 256 m = func3(3, 2, k) 257 258contains ! Start defining the program's internal procedures: 259 260 ! Fortran has a couple of slightly different ways to define functions. 261 262 integer function func(a, b, c) ! a function returning an integer value. 263 ! implicit none ! - no longer used in subvariable fields 264 integer, intent(in) :: a, b, c ! type of input parameters 265 ! the return variable defaults to the function name. 266 267 if (a >= 2) then 268 func = a + b + c 269 return ! returns the current value at 'func' 270 end if 271 func = a + c 272 273 ! Don't need a return statement at the end of a function. 274 end function func 275 276 function func2(a, b, c) result(f) ! return variable declared to be 'f'. 277 integer, intent(in) :: a, b ! can declare and enforce that variables 278 !are not modified by the function. 279 integer, intent(inout) :: c 280 integer :: f 281 ! function return type declared inside the function. 282 integer :: cnt = 0 ! GOTCHA - 283 ! assigning a value at initalization 284 ! implies that the variable is 285 ! saved between function calls. 286 287 f = a + b - c 288 c = 4 ! changing value of input variable c. 289 cnt = cnt + 1 ! count number of function calls. 290 291 end function func2 292 293 pure function func3(a, b, c) ! a pure function has no side-effects. 294 integer, intent(in) :: a, b, c 295 integer :: func3 296 297 func3 = a*b*c 298 299 end function func3 300 301 ! a subroutine does not return anything, 302 ! but can change the value of arguments. 303 subroutine routine(d, e, f) 304 real, intent(inout) :: f 305 real, intent(in) :: d, e 306 307 f = 2*d + 3*e + f 308 309 end subroutine routine 310 311end program example 312! End of Program Definition ----------------------- 313 314! Functions and Subroutines declared externally to the program listing need 315! to be declared to the program using an Interface declaration (even if they 316! are in the same source file!) (see below). It is easier to define them within 317! the 'contains' section of a module or program. 318 319elemental real function func4(a) result(res) 320! An elemental function is a Pure function that takes a scalar input variable 321! but can also be used on an array where it will be separately applied to all 322! of the elements of an array and return a new array. 323 real, intent(in) :: a 324 325 res = a**2 + 1.0 326 327end function func4 328 329! Modules 330! ======= 331 332! A module is a useful way to collect related declarations, functions and 333! subroutines together for reusability. 334 335module fruit 336 337 real :: apple 338 real :: pear 339 real :: orange 340 341end module fruit 342 343module fruity 344 ! Declarations must be in the order: modules, interfaces, variables. 345 ! (can declare modules and interfaces in programs too). 346 347 use fruit, only: apple, pear ! use apple and pear from fruit module. 348 implicit none ! comes after module imports. 349 350 ! By default all module data and functions will be public 351 private ! Instead set default to private 352 ! Declare some variables/functions explicitly public. 353 public :: apple, mycar, create_mycar 354 ! Declare some variables/functions private to the module (redundant here). 355 private :: func4 356 357 ! Interfaces 358 ! ========== 359 ! Explicitly declare an external function/procedure within the module 360 ! (better in general to put functions/procedures in the 'contains' section). 361 interface 362 elemental real function func4(a) result(res) 363 real, intent(in) :: a 364 end function func4 365 end interface 366 367 ! Overloaded functions can be defined using named interfaces. 368 interface myabs 369 ! Can use 'module procedure' keyword to include functions already 370 ! defined within the module. 371 module procedure real_abs, complex_abs 372 end interface 373 374 ! Derived Data Types 375 ! ================== 376 ! Can create custom structured data collections. 377 type car 378 character(len=100) :: model 379 real :: weight ! (kg) 380 real :: dimensions(3) ! i.e. length-width-height (metres). 381 character :: colour 382 contains 383 procedure :: info ! bind a procedure to a type. 384 end type car 385 386 type(car) :: mycar ! declare a variable of your custom type. 387 ! See create_mycar() routine for usage. 388 389 ! Note: There are no executable statements in modules. 390 391contains 392 393 subroutine create_mycar(mycar) 394 ! Demonstrates usage of a derived data type. 395 type(car), intent(out) :: mycar 396 397 ! Access type elements using '%' operator. 398 mycar%model = "Ford Prefect" 399 mycar%colour = 'r' 400 mycar%weight = 1400 401 mycar%dimensions(1) = 5.0 ! default indexing starts from 1! 402 mycar%dimensions(2) = 3.0 403 mycar%dimensions(3) = 1.5 404 405 end subroutine create_mycar 406 407 subroutine info(self) 408 class(car), intent(in) :: self 409 ! 'class' keyword used to bind a procedure to a type here. 410 411 print *, "Model : ", self%model 412 print *, "Colour : ", self%colour 413 print *, "Weight : ", self%weight 414 print *, "Dimensions: ", self%dimensions 415 416 end subroutine info 417 418 real pure function real_abs(x) 419 real, intent(in) :: x 420 421 if (x < 0) then 422 real_abs = -x 423 else 424 real_abs = x 425 end if 426 427 end function real_abs 428 429 real pure function complex_abs(z) 430 complex, intent(in) :: z 431 ! long lines can be continued using the continuation character '&' 432 433 complex_abs = sqrt(real(z)**2 + & 434 aimag(z)**2) 435 436 end function complex_abs 437 438end module fruity 439 440! ISO Standard Fortran 2008 introduced the DO CONCURRENT construct to allow you 441! to express loop-level parallelism 442 443integer :: i 444real :: array(10) 445 446DO CONCURRENT (i = 1:size(array)) 447 array(i) = sqrt(real(i)**i) 448END DO 449 450 451! Only calls to pure functions are allowed inside the loop and we can declare 452! multiple indices: 453 454integer :: x, y 455real :: array(8, 16) 456 457do concurrent (x = 1:size(array, 1), y = 1:size(array, 2)) 458 array(x, y) = real(x) 459end do 460 461! loop indices can also declared inside the contruct: 462 463real :: array(8, 16) 464 465do concurrent (integer :: x = 1:size(array, 1), y = 1:size(array, 2)) 466 array(x, y) = real(x) 467end do

More Resources

For more information on Fortran: