作为一只CFD小白,Fortran是无论如何都绕不开的语言,无数已有的程序甚至小规模的商用软件都是Fortran写的。但是这些古老的代码存在goto过多,format使用过多,大量的矩阵操作都是用do循环堆砌,以及变量命名过度简化,fixed格式导致排版乱七八糟等等问题。总之就是可读性差,复用困难。正好疫情期间躲在家,在改写已有的组内代码的同时,也将原来的.f程序升级成为.f90程序。为此学习fortran语言的书《Fortran 95 程序设计》 彭国伦著。

因为已经使用过一年左右的Fortran语言,主要关注点是之前不怎么使用的语法和功能,尤其是从F77升级到F90和F95之后的新增功能。对于已经比较熟悉的部分就会略过,只挑觉得重要,或写高性能计算程序时有用的部分说。作为这段时间改写程序的一个记录。

OK!那我们开始吧!

第一章 计算机概论

略,高性能计算和CPU运算的一些细节确实相关,不过最好参考更加专门的书籍,比如说《计算机体系结构》胡伟武

第二章 编译器的使用

win下的编译器比较常用的是Visual Fortran和VS之下的Fortran组件。笔者主要使用的是linux的编译器。Linux下的GNU会包含F77的编译器G77,编译方式如下

g77 hello.f
./a.out

F90则使用另外一个编译命令:

f90 hello.f90

而F95则使用:

F hello.f95

呃,不过现在我在用的是gfortran,书中并未介绍。正常编译.f90是可以通过的,等到遇到问题再回到这里补充吧。

第三章 Fortran程序设计基础

Fixed 和 Free 格式

在Fortran77的时候,使用的是Fixed Format固定格式。而在Fortran90以及95,则使用Free Format自由格式。两者的主要规则罗列如下:
Fixed Format:

  1. 每行第7到72个字符有效,会被编译。前六个字符一般为空格
  2. 每行第5个字符如果是空格或者0之外的字符,就是续航符
  3. 每行前几个字符可以用来给定行标,方便format,goto等等命令使用
  4. 使用小写字母c注释
    Free Format:
  5. 行首的六个空格被取消,可编写字符扩展到132个
  6. 续航符为每行尾或者行首的&符号
  7. 行标写在每行最前面即可
  8. 注释用!而不是c

Fortran的数据类型和数学表达式

相对F77没有新知识

第四章 输入输出声明

输出

输出使用如下两种:

write(*,*) "String"
print  *,"Hello"

其中F90使用双引号,F77使用单引号。输出特殊字符的细节此处不说明,write的左右*星号分别代表输出到那个端口,以及输出格式。而print只能控制输出格式,输出一定是输出到终端的。

变量的声明与kind

基础的变量声明没什么好说的,有一个新知识是声明使用的变量的bytes数

integer*4 a             !F77
integer(kind=4) a       !F90
real*8 b                !F77
real(kind=8) b          !F90

其中kind的值代表存储变量使用的bytes数量,上述分别代表长整型和双精度。而F90的声明可以向下兼容。其中变量某个值所需的kind值,可以通过fortran命令给出,具体需要查阅书中Page67

变量的赋值精度

为什么专门强调这个问题,在科学计算里面,有一些基础参数的设定一定要尽可能的精确。比如说测试数值格式精度,误差会下降到1e-10的情况下,如果计算区域长度的设置本来是real*8 :: a=1.0实际赋值之后的变量为a=1.000008,即单浮点数的精度之后,出现了误差,那么整体精度就不可能达到1e-10。

书中给出,给单精度浮点数赋值时,使用的是a=1.23E3。而给双精度浮点数赋值时,使用的是a=1.23D3。部分编译器即使是给双精度的变量赋值,也一定要带D才能有足够精度的赋值。

输入

就是read命令,这里介绍的都很基础,略。

format格式

基础用法如下:

write(*,100) a
100 format(I4)

要用到行号,书中给出了格式详细的参数说明,不过经常使用的是I,F,E,A,X这几个。详细的说明可以直接翻书或者百度,这里只简单说明罗列:

!整数I
write(*,"(I5)") 100  !5个字符宽的输出
write(*,"(I5.3)") 10 !5个字符宽的输出,最少输出3个数字
!浮点数E和D分别为单双精度
write(*,"(E15.7)") 123.45 !占15个字符,小数占7位
write(*,"(E9.2E3)") 12.34 !占9个字符,小数占2位,指数部分输出三个数字
!字符串A
write(*,"(A10)") "Hello" !10个字符宽
!移位X
write(*,"(5X,I3)") 100 !输出3个字符宽,同时先填5个空格

implicit命令

常用的就两个

implicit real*8 (a-h,o-z)
implicit none

不写的话,fortran也会默认第一行的情形,不过是单精度。不过比较推荐第二种,不然师兄的程序传给师弟的时候,师弟看得头发都快掉没了。

parameter参数

使用方法如下:

real,parameter :: a=1.0d0real a
parameter (a=1.0d0)

赋初值与双冒号

声明的同时赋初值的话,需要使用双冒号::,即

real :: a=1.0d0

也可以用Data进行赋初值,不过这里并不方便,不说明

等价声明

新知识,类似C语言里面的&a=b,这里对应

integer a,b
equivalence(a,b)

声明后,a和b使用同一个内存空间。主要作用是调用一些高维数组中的单个元素,因为数组下标索引时会带来额外的运算量。

equivalence (a(1,1,5),b)

声明在程序中的作用

这部分对于高性能计算还是比较重要的。首先对于编程来说,声明本身一定要出现在数值计算之后。对于数值计算来说,声明的部分在代码编译之后,编译器会预留空间给程序使用

Fortran中的结构体type功能

给一个实例:

!结构体定义
type: personinteger :: ageinteger :: lengthinteger :: weight
end type person!结构体声明和赋初值
type(person) :: a=person(20,170,60)!结构体的使用
a%age = 12

第五章 流程控制与逻辑运算

就是ifselect case命令。其中判断语句如果对字符串使用,字符串会转换成数字进行比较,例如"abc"<"abcd"。然后给出一个select case的例子

select case(score)
case(60)a=1
case(:59)a=0
case(61:100)a=2
case(101:)a=3
case defaulta=4
end select

pause,continue,stop

pause代表暂停,直到用户按下Enter键。continue功能就是继续向下执行程序,只是方便阅读。stop是终止程序运行。

第六章 循环

do循环的循环体有多种写法:

do i = 1,10a=a+i
end dodo 100 i=1,10
100    a=a+ido 100 i=1,10a = a+i
100 continue

cycle和exit

前者为直接进行下一次循环,后者为跳出当前循环

循环的署名

新知识,例子如下:

outter: do i = 1,10inner: do j = 1,10....end do inner
end do outter

第七章 数组

基本知识不提了,这里Fortran有一个其他语言中数组没有的功能,尤其是CFD中需要使用ghost point时非常方便的。

real a(-3:8)

即,下标起始位置可以人为规定,当然默认是1。

数组赋初值有以下几种技巧,其中隐含式循环为之前没用过的新知识:

integer A(5)
DATA A /1,2,3,4,5/integer b(5)
DATA (B(I),I=2,4) /2,3,4/integer c(5) = (/1,(2,I=2,4),5/)

对整个数组的操作

假设有三个维数相同的数组a,b,c,那么数组的操作和Matlab中的数组操作会非常类似。这是F90之后的新功能,也是Fortran适合科学计算的一个原因。

a = 5   !全部赋值为5
a=/(1,2,3)/   !数组前三个元素分别赋值1,2,3
a=b   !b的元素分别赋值给a
a=b+c
a=b-c
a=b*c
a=b/c
a=sin(b)   !对数组的元素分别进行四则运算或者函数运算

甚至还可以像matlab一样非常灵活的只对数组中其中一部分元素进行操作。

a(3:5)=5
a(3:)=5
a(3:5)=(/3,4,5/)
a(1:3) = b(4:6)
a(1:5:2) = 3
a(1:10) = a(10:1:-1)a(:) = b(:,2)
a(:,:) = b(:,:,1)

除此之外,F95还提供了WHERE功能和FORALL功能,能够自动检索并进行多元素操作。和matlab中功能也类似

where (a<3)b = a
end whereforall (i=1:size,j=1:size,i>j) a(i,j) = 1
forall (i=1:size,j=1:size,i==j) a(i,j) = 2
forall (i=1:size,j=1:size,i<j) a(i,j) = 3

数组的保存规则

Fortran中数组的保存规则和C语言恰好是相反的比如

integer a(2,3,4,5)

Fortran为下标从左向右,先跑最左侧下标。而C语言为从右向左。另外,当fortran运行时,索引数组中的一个元素,是从首地址开始,根据下标计算元素所在地址。所以维数很高的数组的元素调用会有较大的额外运算量。

另外,CPU在运行时,在地址相邻的位置调用元素可以大大提高cache的命中率,从而提高CPU运行速度。这就要求我们能够对数组下标的顺序进行调整。例如

do i = 1,5sum = sum + a(1,1,1,1,i)
end dodo i = 1,n
do j = 1,ma(i,j) = ...
end do
end do

就不如

do i = 1,5sum = sum + a(i,1,1,1,1)
end dodo i = 1,n
do j = 1,ma(j,i) = ...
end do
end do

可变大小数组

先给出用法

integer,allocatable :: a(:,:)if (.not. allocated(a)) then
allocate(a(-1:5,5),stat=error)
end ifa(1,1) = 1deallocate(a)

这里说明分配内存是动态的,会损失一部分运行速度,但是并不会损失特别多,是比较推荐的一种写法。而stat=error是用来反馈是否分配内存成功,可以不写。此时动态分配的内存和C类似,是必须释放的。而if条件可以判断a是否已经被分配内存。

彭国伦Fortran95学习笔记(一)第一至七章相关推荐

  1. 课本学习笔记5:第七章 20135115臧文君

    第七章 链接 注:作者:臧文君,原创作品转载请注明出处. 一.概述 1.链接(linking):是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载或被拷贝到存储器并执行. 2 ...

  2. 软考网络管理员学习笔记7之第七章网络管理技术

    第七章网络管理技术 考点1.Windows的基本管理 [考法分析] 本考点的基本考法是能够识别Windows系统下,常见命令的含义与作用 [要点分析] 1.需要熟悉掌握常见命令,如ipconfig.pi ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引...

    Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引 原文:Introduction to 3 ...

  4. 学习笔记-应用光学 第一章 几何光学的基本定律

    学习笔记-应用光学 第一章 几何光学的基本定律 1-1 发光点.波面.光线和光束 发光点:本身发光或被照明后发光的几何点 波面:发光点在某一时刻发出的光形成波面 (在各向同性均匀介质中波面是球形) 光 ...

  5. PMBOK(第六版) 学习笔记 ——《第一章 引论》

    系列文章目录 PMBOK(第六版) 学习笔记 --<第一章 引论> PMBOK(第六版) 学习笔记 --<第二章 项目运行环境> PMBOK(第六版) 学习笔记 --<第 ...

  6. 【Python学习笔记】第一章基础知识:格式化输出,转义字符,变量类型转换,算术运算符,运算符优先级和赋值运算符,逻辑运算符,世界杯案例题目,条件判断if语句,猜拳游戏与三目运算符

    Python学习笔记之[第一章]基础知识 前言: 一.格式化输出 1.基本格式: 2.练习代码: 二.转义字符 1.基本格式: 2.练习代码: 3.输出结果: 三.输入 1.基本格式: 2.练习代码: ...

  7. Java 学习笔记:第一章 Java入门

    Java 学习笔记:第一章 Java入门 1.1 计算机语言发展史以及未来方向 1.2 常见编程语言介绍 C语言 C++ 语言 Java语言 PHP 语言 Object-C和Swift 语言 Java ...

  8. c语言第七章函数笔记,我的C语学习笔记-C语言教程(七).doc

    我的C语学习笔记- C语言教程(七) C语言教程---第一章: C语言概论 C语言教程---第二章: 数据类型.运算符.表达式 C语言教程---第三章: C语言程序设计初步 C语言教程---第四章: ...

  9. MYSQL学习笔记(自用)第九章

    MYSQL学习笔记(自用)第九章 第一节. 触发器 | Triggers DELIMITER $$CREATE TRIGGER payments_after_insertAFTER INSERT ON ...

  10. C语言学习-翁凯(第七章笔记)

    C语言学习-翁凯(第七章笔记) 第七章 7.1.1初见函数 素数求和 int m,n;int i;int cnt=0;int sum=0;scanf("%d %d",&m, ...

最新文章

  1. Python日期操作
  2. python五十:反射
  3. 使用Varnish加速Web
  4. C语言家谱管理程序,课内资源 - 基于C语言实现的家谱管理系统
  5. 运用Appium 实现添加微信好友自动化
  6. Gartner 容器报告:阿里云与 AWS 并列第一,领先微软、谷歌
  7. 6-5-3:STL之stack和queue——优先级队列-priority_queue(堆)的基本使用和模拟实现以及仿函数
  8. ZooKeeper未授权访问漏洞记录(影响范围:全版本,端口:2181)
  9. 【图像处理】直方图均衡化(附带Matlab及OpenCV3自编程实现代码)
  10. 建模大师怎么安装到revit中_工程师最爱的REVIT插件,让BIM建模溜到飞起!
  11. Nexon由Xsolla全球支付服务
  12. 学习英文之社区,博客及源码 转载
  13. 3点画矩形的lisp_在CAD中,如何在这个矩形里面再画三个这样的矩形
  14. 【python + FFmpeg】对视频进行分辨率改变,(带音频)
  15. 直播问答的后博弈时代:社交化或许才是未来
  16. php坏处,cpu超频有什么坏处
  17. 计算机博弈围棋,计算机博弈:“不围棋”入门教程
  18. Android CoordinatorLayout Behavior
  19. 钉钉发起审批流程分析
  20. srs源码分析2-浅析state_threads

热门文章

  1. 使用SQL语句创建数据库
  2. 图书馆占座系统(五)
  3. SPSS参数检验、非参数检验、方差分析
  4. 关于E-Prime 2.0 无法呈现音频的一种解决方案
  5. Linux搭建流服务器笔记
  6. Qt 学习之路 2(3):Hello, world!
  7. Python3-环境篇-01-Python3安装
  8. java 中高级面试题_Java中高级面试题
  9. 清华学计算机的住在哪个公寓,清华大学考研之住宿篇
  10. matlab如何公式编辑器,公式编辑器怎么用 【搞定要领】