日期:2021/7/31
前言
我之前幾乎沒有寫過 Fortran,這次為了幫某人擺脫需要花錢購買的 Visual Fortran,我只好從零開始學 Fortran,並且試試看是否能用 GFortran 編譯他們實驗室需要的程式碼,由 csv 檔讀取資料經過一些運算後再儲存成另一個 csv 檔,以下是我測試的筆記。
於 Ubuntu 安裝 GFortran
我使用的作業系統是 Ubuntu 20.04.2 LTS,只要在文字界面中執行以下指令即可安裝 GFortran。
sudo apt install gfortran-10
安裝完畢之後可以用以下指令查詢安裝的版本,我安裝的版本是 10.3.0。
gfortran-10 --version
建立一個測試用的資料夾,於資料夾中用文字編輯器將以下內容儲存成 hello.f95。
program hello
write(*, *) 'Hello World!'
write(*, *) '哈囉世界!'
stop
end program hello
用以下指令將 hello.f95 編譯成執行檔再執行檔案。
gfortran-10 -o hello hello.f95
./hello
如果螢幕輸出以下文字就成功了。
Hello World!
哈囉世界!
於 Windows 10 安裝 GFortran
我使用的作業系統是 Windows 10 家用版。安裝步驟主要是參考這篇文章 Installation of GFortran in Windows 10。先安裝 mingw-w64,目前最新的版本是 msys2-x86_64-20210725.exe,下載連結在此。安裝完成之後開啟 MSYS2 MinGW 64-bit。
MSYS2
輸入以下指令更新軟體列表、安裝 GFortran。
pacman -Syu
pacman -Su gcc-fortran
輸入以下指令查詢安裝好的 GFortran 版本。
gfortran.exe --version
我安裝的是 10.2.0 版。用 pwd 查詢路徑,看起來是在 /home/[UserName] 底下,實際上的路徑是
C:\msys64\home\[UserName]
接著用 Hello World! 測試一下。
於 Windows 10 測試 GFortran
使用 Fortran 程式讀取、寫入 csv 檔
這次的目標是要在執行程式時於後方加上輸入、輸出檔名,由輸入的 csv 檔讀取資料,再將資料寫到輸出的 csv 檔,主要是參考這兩個網頁的內容:Passing command line arguments、TEK-TIPS.COM: Help with .csv。假設輸入檔名為 input.csv,內容如下,第一行開頭的 ! 是為了在讀取資料時忽略此行而加上的記號。
!h(m),t(s),errt(s)
2,0.65,0.01
4,0.89,0.01
6,1.11,0.01
8,1.27,0.01
10,1.42,0.01
12,1.57,0.01
14,1.71,0.01
16,1.79,0.01
18,1.92,0.01
20,2.03,0.01
以下是我測試成功的程式碼。
program fileIO
implicit none ! 不使用預設變數名稱及種類對應關係
character(20) :: inputfile ! 輸入檔名用的變數
character(20) :: outputfile ! 輸出檔名用的變數
integer :: flag1, flag2, line_num ! 檔案狀態1、2, 行號
character(80) :: line ! 讀取的整行資料
real :: h, t, t2, errt ! 儲存資料的變數
! 檢查輸入的參數是否為2個
if(command_argument_count().NE.2) then
write(*,*) 'Error! Please enter the input and output file names.'
stop
end if
! 由輸入的參數取得輸入、輸出檔名
call get_command_argument(1, inputfile)
call get_command_argument(2, outputfile)
write(*,*) 'The input file name is: ', inputfile
write(*,*) 'The output file name is: ', outputfile
! 由 inputfile 讀取資料, 準備寫入資料至 outputfile
open(3, file=inputfile, status='old', action='read', iostat=flag1)
open(4, file=outputfile, action='write', iostat=flag2)
! 檢查是否能開啟檔案
if(flag1 .NE. 0) then
write(*, *) 'Cannot open input file!'
go to 99
end if
if(flag2 .NE. 0) then
write(*, *) 'Cannot open output file!'
go to 99
end if
! 於 outputfile 寫入欄位標題
write(4, *) '!h(m),t(s),t2(s2),errt(s)'
line_num = 0
do
! 讀取整行資料並存入 line
read(3, '(A)', end=99, iostat=flag1) line
! 若 flag1 不等於 0 則跳到 99 continue
if(flag1 .NE. 0) then
write(*, *) 'Cannot read data!'
go to 99
end if
! 若 line 的開頭為 '!' 則不做任何事
if(adjustl(trim(line(1:1))) .EQ. '!') then
cycle
end if
! 將 line 的資料分別存入 h, t, errt, 計算 t^2, 存入 outputfile
read(line, *) h, t, errt
t2 = t**2
write(*, *) 'line ', line_num, ': ', h, t, t2, errt
line_num = line_num + 1
write(4, *) h, ',', t, ',', t2, ',', errt
end do
99 continue
close(3)
close(4)
stop
end program fileIO
假設檔名是 fileIO.f95,在 Ubuntu 可以使用以下指令編譯程式。
gfortran-10 -o fileIO fileIO.f95
在 Windows 10 可以使用以下指令編譯程式。
gfortran.exe -o fileIO fileIO.f95
使用以下指令執行程式。
./fileIO input.csv output.csv
於文字界面輸出以下的內容。
The input file name is: input.csv
The output file name is: output.csv
line 0 : 2.00000000 0.649999976 0.422499955 9.99999978E-03
line 1 : 4.00000000 0.889999986 0.792099953 9.99999978E-03
line 2 : 6.00000000 1.11000001 1.23210001 9.99999978E-03
line 3 : 8.00000000 1.26999998 1.61289990 9.99999978E-03
line 4 : 10.0000000 1.41999996 2.01639986 9.99999978E-03
line 5 : 12.0000000 1.57000005 2.46490026 9.99999978E-03
line 6 : 14.0000000 1.71000004 2.92410016 9.99999978E-03
line 7 : 16.0000000 1.78999996 3.20409989 9.99999978E-03
line 8 : 18.0000000 1.91999996 3.68639994 9.99999978E-03
line 9 : 20.0000000 2.02999997 4.12089968 9.99999978E-03
於 Windows 10 測試 fileIO 程式碼
輸出的 csv 檔如下,看來應該有達到我要的效果。
!h(m),t(s),t2(s2),errt(s)
2.00000000 , 0.649999976 , 0.422499955 , 9.99999978E-03
4.00000000 , 0.889999986 , 0.792099953 , 9.99999978E-03
6.00000000 , 1.11000001 , 1.23210001 , 9.99999978E-03
8.00000000 , 1.26999998 , 1.61289990 , 9.99999978E-03
10.0000000 , 1.41999996 , 2.01639986 , 9.99999978E-03
12.0000000 , 1.57000005 , 2.46490026 , 9.99999978E-03
14.0000000 , 1.71000004 , 2.92410016 , 9.99999978E-03
16.0000000 , 1.78999996 , 3.20409989 , 9.99999978E-03
18.0000000 , 1.91999996 , 3.68639994 , 9.99999978E-03
20.0000000 , 2.02999997 , 4.12089968 , 9.99999978E-03
結語
由於 Fortran 的語法與 Python、C、C++ 差異很大,寫起來感覺相當奇怪。接下來還要再修改他們實驗室以前的程式碼,其中一部分還是採用 Fortran 77 的語法撰寫,要修改成新版 GFotrtan 可以接受的語法才行,好像還有不少的麻煩要解決。
參考資料
- gfortran — the GNU Fortran compiler, part of GCC
- Installation of GFortran in Windows 10
- mingw-w64
- Passing command line arguments
- TEK-TIPS.COM: Help with .csv
HackMD 版本連結:https://hackmd.io/@yizhewang/Sk5vTFMyK
沒有留言:
張貼留言