# Fortran

# 基本结构

program findv
    !calculate the velocity from the acceleration and time
    implicit none
    real::v,a=128.0,t=8.0
    v=a*t
    write (*,*) "V=", v
end program findv

一行一句,用&换行

# 编译

gfortran -o hello.exe hello.f90

# 类型

integer::a,b
real::c=1.1
real,parameter::pi=3.14	!常量
integer*8::bignum	!8字节(默认4字节)
integer(kind=8)::bignum!同上
complex::d=(2.1e-1,-3)
character(9)::s="Hello"	!不够长则右侧补空格
character(len=9)::s
character(*),parameter::s="Hello"!常量可以不写长度
logical::t=.true.

# 派生类(结构体)

type student
    integer::id
    real::score
end type student
type(student)::a,b
a%id=123
a%score=99.9
b=a

# 表达式

r=-b+sqrt(b**2-4*a*c)
a/=b .and. a==1
"a""b"	!a"b,连用引号会转义
'Hello'//'World'!连接,'HelloWOrld'
'abcde'(2,4)	!子串,'bcd'
'abc'(2:2)		!取单个字符
"A"<"D"	!按ascii码,字典序比较

字符串用单双引号都行,'"'就是双引号字符

负号优先级最高

# 内置函数

函数 备注 函数 备注
sin 弧度 achar 整数转字符(Ascii)
sind 角度 iachar 字符转整数
asin 反三角 len 字符串长度
int 向下取整 len_trim 字符串长度(忽略末尾空格)
nint 四舍五入 trim 去除末尾空格的子串
real 类型转换 adjustl 左侧空格挪到右侧(左对齐)
mod(a,b) a模b adjustr 右侧空格挪到左侧(右对齐)

# I/O

print *,"a=",a	!只能输出到终端
read (*,*) a,b
write (*,*) "a=",a,"b=",b

# 参数

# 格式化

Description Specifier Description Specifier
integer rIw or rIw.m 宽度 w
real rFw.d 最小宽度 m
logical(输出T/F) rLw 小数点后位数 d
character rA or rAw 数量 n
连续n个空格 nX 列数 c
补空格到第c列 Tc 重复 r
空行 n/
write (*,'(i2,i4,f6.4,2x,a)') 42,123,42,'haha'
!42 123  0042  haha
!逗号可忽略

# advance

默认‘yes’换行

write (*,'(a)',advance="no") "Enter n: "
read (*,*) n

# iostat

标志变量,若成功则置0,失败则>0

# 文件

open(unit=10, file='out.txt', status="replace", &
    action="write", position="rewind", iostat=t)
if(t>0) stop "Cannot open file."
write(10, '(a/,i5/,f6.3)',iostat=s2) msg, a, pi
close(10)
参数 解释
unit 序号,[10,99]范围内
file 文件名
status “old”:已有, “new”:新建, “replace”:新建,若已有则替换
action “read”, “write”, “readwrite”
position “rewind”:beginning, “append”:end
iostat 标志变量,若成功则置0,失败则>0
rewind(<unit>)	!回到文件开头
backspace(<unit>)!回上一行

# Internal read/write

Read and write directly from and to variables.

用于字符串与数字相互转换

字符串转数字:

read(str,'(i5)') i

数字转字符串:

write(str,'(i5)') i

# 分支循环

# if

if(l==0)write (*,*) "Game Over."
if(l==0)then
	print*,"Game Over"
else if(l==1)then
	print*,"a"
else
	print*,l
end if

# select case

select case(h)
    case (0)
        print*."midnight"
    case (1:11)	!闭区间
        print*."am"
    case default
    	print*,"pm"
end select

# do

do i=1,10,2	!闭区间
    print*,i
end do
i=1.5
do while(i<=4.5)
    print*,"i=",i
    i=i+0.25
end do
do
	print*,"haha"
end do
Fortran C
cycle continue
exit break

# 数组

integer,dimension(8)::a		![1,8],8个
integer,dimension(-4:4)::b	![-4,4],9个
integer,dimension(3)::c=1
integer,dimension(3)::c=(/2,1,3/)
integer,dimension(3)::c=(/(i,i=1,3)/)
a=1		!将所有值设为1
a(2)=2

编译时启用-fcheck=bound,溢出时会产生RE。不然可能导致内存泄漏。

maxval(a)	!最大值
sum(a)		!求和

# 动态数组

可以先声明,运行时再申请空间。申请后长度就是确定的了

integer,dimension(:),allocatable::d
integer::i
!input i
allocate(d(i),stat=t

# Implied Do-Loop

可以嵌套

print*,(a(i),b(i),i=1,3,2)
!同a(1),b(1),a(3),b(3)

# 多维数组

integer,dimension(9,9)::a
integer,dimension(0:5,6)::b
integer,dimension(:,:),allocatable::a
allocate(d(9,9),stat=t

# 其他语句、内置函数

# 报错

stop 'Cannot open file'

# 随机数

[0,1)均匀分布

real::x
call random_seed()
call random_number(x)

# 获取时间

至少包含一个参数

参数 类型 解释
date character(8) YYYYMMDD
time character(8) HHMMSS.SSS
zone character(8) ±HHMM,本地时间与UTC差距
values integer,dimension(8) 见下表
index 解释
1
2
3
4 本地时间与UTC差距(分钟)
5
6
7
8 毫秒
call date_and_time(date=today)

# 命令行参数

argc=command_argument_count()
call get_command_argument(number=1,value=str)

get_command_argument的参数:

参数 解释 intent
number 第几个命令行参数 in
value 字符串,长度大于实际参数长度即可 out
length 实际长度 out
status 0:成功, -1:失败 out

# 子程序

program name
    !声明
    !程序
contains
    !内部函数
end program name
    !外部函数

fortran传参时直接传地址,所以为防止修改主程序段的参数,要给出intent

intent 解释
in 只读
out 必须赋新值
inout 随意(默认)

默认不能调用自己,递归函数/子程序需要在声明前加recursive

# 函数

形式

<type> function <name>(<arguments>)<declarations>
!可换行声明参数
    <body of function>
    <name> = expression
    return
end function <name>

例如

real function f2c(f)
real,intent(in)::f
    f2c=(f-32.0)/1.8
    return
end function f2c

递归

<type> recursive function <name>(<arguments>)result(<variable>)
<declarations>
    <body of function>
    <variable> = expression
    return
end function <name>

# Subroutine

subroutine sumAve(a,b,s)
real,intent(in)::a,b
real,intent(out)::s
	s=a+b
    return
end subroutine sumAve

递归

recursive subroutine <name>(<arguments>)
<declarations>
    <body of subroutine>
    return
end subroutine <name>

# 模块

模块实现:

module <module name>
    <global variable declarations>
contains
    <function definitions>
end module <module name>

主程序:

program <name>
use <module name>
implicit none
!...
end program <name>

编译模块

gfortran -c module.f90

产生源文件名.o模块名.mod

gfortran -o out.exe main.f90 module.o

只需列出.o文件,gfortran会自动寻找.mod文件