This is a simple cheatsheet and some performance comparison for scientific programmers who are interested in discover Julia. It is not an exhaustive list. This page is inspired from A Cheatsheet for Fortran 2008 Syntax: Comparison with Python 3.
Fortran | Julia | |
Top-level constructs | ||
the main program |
program my_program
...
end program |
function my_program()
...
end
my_program() |
modules |
module my_module
...
end module my_module |
module MyModule
...
end |
subroutines |
subroutine my_subroutine
...
end subroutine my_subroutine |
function my_subroutine!
...
end |
functions |
function f(x) result(res)
res = ...
end function f |
function my_function(x)
...
return res
end |
Generic interface |
module cube_root_functions
interface cube_root
function s_cube_root(x)
real :: s_cube_root
real, intent(in) :: x
end function s_cube_root
function d_cube_root(x)
double precision :: d_cube_root
double precision, intent(in) :: x
end function d_cube_root
end interface
end module cube_root_functions
function s_cube_root(x)
real :: s_cube_root
real, intent(in) :: x
s_cube_root = x ** (1.0/3.0)
end function s_cube_root
function d_cube_root(x)
double precision :: d_cube_root
double precision, intent(in) :: x
d_cube_root = x ** (1.0d0/3.0d0)
end function d_cube_root |
cube_root( x :: Float32 ) :: Float32 = x^(1/3)
cube_root( x :: Float64 ) :: Float64 = x^(1/3) |
submodules |
module main_module
...
contains
<submodule statements>
end module main_module |
module MainModule
...
module SubModule
...
end
end |
import statement |
use my_module
use my_module, only : fun1, var1 |
using MyModule
import MyModule: fun1, var1 |
call subroutines and functions |
call my_subroutine(args)
my_function(args) |
my_function(args) |
abort a program |
stop |
exit() |
inline comments |
! This is a comment |
# This is a comment |
include external source files |
include 'source_file_name' |
include("source_file_name") |
Control flow patterns | ||
if construct |
if <logical expr> then
...
else if <logical expr> then
...
else
...
end if |
if <logical expr>
...
elseif <logical expr>
...
else
...
end |
case construct |
select case <expr>
case <value>
...
case <value>
...
case default
...
end select |
Not supported. Possible alternative is to use the ternary ? :syntax: function case(x)
x == 1 ? println(1) :
x + 1 == 3 ? println(2) :
x == 3 ? println(3) :
println("greater than 3")
end |
do construct |
do i = start_value, end_value, step
...
end do |
for i in start:step:end
...
end |
do while construct |
do while <logical expr>
...
end do |
while <logical expr>
...
end |
break from a loop |
exit |
break |
leave this iteration and continue to the next iteration |
cycle |
continue |
Data types | ||
declaration |
integer(kind=8) :: n = 0
real(kind=8) :: x = 0. |
n = 0
n :: Int64 = 0
x = 0.
x :: Float64 = 0. |
named constants |
integer, parameter :: answer = 42
real(8), parameter :: pi = 4d0 * atan(1d0) |
const answer = 42 |
complex number |
complex :: z = (1., -1.) |
z = 1 - 1im
z = complex(1, -1) |
string |
character(len=10) :: str_fixed_length
character(len=:), allocatable :: str_var_length |
string = "this is a string" |
pointer |
real, pointer :: p
real, target :: r
p => r |
p = Ref(r) |
boolean |
.true.
.false. |
true
false |
logical operators |
.not.
.and.
.or.
.eqv.
.neqv. |
!
&&
|| |
equal to |
==, .eq. |
== |
not equal to |
/=, .ne. |
!== |
greater than |
>, .gt. |
> |
less than |
<, .lt. |
< |
greater than or equal to |
>=, .ge. |
>= |
less than or equal to |
<=, .ge. |
<= |
array declaration |
real(8), dimension(3) :: a = [1., 2., 3.] |
a = [1., 2., 3.] |
string array declaration |
character(len=20), dimension(3, 4) :: char_arr |
char_arr = String[]
push!(char_arr, new_string) |
elementwise array operations |
a op b op can be +, -, *, /, **, =, == , etc.This is supported since the Fortran 90 standard. |
Supported by using the broadcast operator `.`and the `f.(x)` syntax |
first element |
a(1) |
a[1] (or a[begin] for general indexing) |
slicing |
a(1:5) a(5) .
|
a[1:5] (or @view(a[1:5]) for non-allocating slicing) a[5] .
|
slicing with steps |
a(1:100:2) |
a[1:2:100] |
size |
size(a) |
length(a) |
shape |
shape(a) |
size(a) |
shape along a dimension |
size(a, dim) |
size(a, dim) |
Type conversion | ||
to integer by truncation |
int(x) |
trunc(Int, x ) |
to integer by rounding |
nint() |
round() |
integer to float |
real(a[, kind]) |
float() |
complex to real |
real(z[, kind]) |
real() |
to complex |
cmplx(x [, y [, kind]]) |
complex() |
to boolean |
logical() |
Bool() |
Derived data types | ||
definition |
type Point
real(8) :: x, y
end type Point |
struct Point
x :: Float64
y :: Float64
end |
instantiation |
type(Point) :: point1 = Point(-1., 1.) |
point1 = Point(-1., 1.) |
get attributes |
point1%x
point1%y |
point1.x
point1.y |
array of derived type |
type(Point), dimension(:), allocatable :: point_arr |
point_arr = Vector{Point} |
type bound procedures (aka class method) | Assume that Circle has a type bound procedure (subroutine) print_area .
type(Circle) :: c
call c%print_area |
Assume that Circle has a method print_area(c :: Circle) .
c = Circle()
print_area(c) |
Built-in mathematical functions | ||
functions with the same names |
abs(), cos(), cosh(), exp(), floor(), log(),
log10(), max(), min(), sin(), sinh(), sqrt(),
sum(), tan(), tanh(), acos(), asin(), atan() |
Have the same name in Julia. |
functions with different names |
aimag()
atan2(x, y)
ceiling()
conjg(z)
modulo()
call random_number() |
imag()
atan(x, y)
ceil()
conj()
mod(), %
Random.rand() |
Built-in string functions | ||
string length |
len() |
length() |
string to ASCII code |
iachar() |
Int() |
ASCII code to string |
achar() |
String() |
string slicing | Same as 1D array slicing. | Same as 1D array slicing. |
find the position of a substring |
index(string, substring) |
findfirst(substring, string) |
string concatenation |
"hello" // "world" |
"hello" * "world"
string("hello", "world") |
Array constructs | ||
where construct |
where a > 0
b = 0
elsewhere
b = 1
end where |
b[a .> 0] .= 0
b[a .<= 0] .= 1 for i in eachindex(a)
a[i] > 0 ? b[i] = 0 : b[i] = 1
end |
Comprehension |
integer, parameter :: n = 20
integer, parameter :: m = n*(n+1)/2
integer :: i, j
complex, dimension(m) :: a
a = [ ( ( cmplx(i,j), i=j,n), j=1,n) ] |
a = [ complex(i,j) for j=1:n for i=j:n] |
forall construct |
real, dimension(10, 10) :: a = 0
int :: i, j
...
forall (i = 1:10, j = 1:10, i <= j)
a(i, j) = i + j
end forall |
a = zeros(Float32, 10, 10)
for i in 1:10, j in 1:10
if i <= j
a[i, j] = i + j
end
end |
CPU time |
call cpu_time() |
time = @elapsed begin
...
end |
command line arguments |
call command_argument_count()
call get_command()
call get_command_argument() |
For basic parsing, use ARGS |
Input/output | ||
print fmt, <output list> |
println() |
|
read from the command prompt |
read fmt, <input list> |
readline() |
open a file |
open(unit, file, ...) |
f = open(file, 'r') |
read from a file |
read(unit, fmt, ...) <input list> |
read(f)
readlines(f) |
write to a file |
write(unit, fmt, ...) <output list> |
write(f, ...) |
close a file |
close(unit, ...) |
close(f) |
file inquiry |
inquire(unit, ...) |
isfile("my_file.txt") |
backspace in a file |
backspace(unit, ...) |
skip(f, -1) |
end of file (EOF) |
endfile(unit, ...) |
seekend(f) |
return to the start of a file |
rewind(unit, ...) |
seekstart(f) |
Here an example of a Fortran to Julia translation. We use the Yee numerical scheme FDTD: Finite-Difference Time-Domain method and MPI topology. You can find a serial version and a parallel version using MPI library.
Test your MPI.jl installation with
$ mpirun -np 4 julia --project hello_mpi.jl
Hello world, I am 0 of 4
Hello world, I am 3 of 4
Hello world, I am 1 of 4
Hello world, I am 2 of 4
On small program like this in Julia is really fast.
julia -O3 --check-bounds=no maxwell_serial.jl
: 14 secondsmake && time ./maxwell_serial_fortran
: 31 seconds
make && time mpirun -np 9 ./maxwell_mpi_fortran
: 7 secondsmpirun -np 9 julia --project -O3 --check-bounds=no
: 5 seconds
Uncomment the plot_fields call in Julia programs or change idiag value in input_data for fortran.
gnuplot bz.gnu