이번 포스팅은 정말 오랜만에 포트란입니다
WRF 결과물인 netCDF 파일을 읽고 격자들 전체의 평균 값을 구하는 코드를 해보겠습니다
전체 코드입니다
1 PROGRAM net1
2 use netcdf
3
4 IMPLICIT NONE
5
6 CHARACTER(len = 256) :: fi
7 REAL, ALLOCATABLE :: T2(:,:,:)
8
9 INTEGER :: dx, dy
10 INTEGER :: ncid, varid
11 INTEGER :: start(3), count(3)
12
13
14 fi = "wrfout_d01_2016-10-06_00.nc"
15 dx = 209
16 dy = 209
17
18 call check(nf90_open(fi, NF90_NOWRITE, ncid), "opening T2 file")
19 call check(nf90_inq_varid(ncid, "T2", varid), "getting T2 varid")
20
21 allocate(T2(209, 209, 1))
22 start = [1, 1, 1]
23 count = [209, 209, 1]
24
25 WRITE(*, *) "Reading Grid T2"
26 call check(nf90_get_var(ncid, varid, T2, start = start, count = count), "reading T2")
27 WRITE(*, *) "Mean T2 : ", sum(T2) / size(T2)
28
29 call check(nf90_close(ncid), "closing T2 file")
30 deallocate(T2)
31
32 contains
33 SUBROUTINE check(status, loc)
34 INTEGER, INTENT(in) :: status
35 CHARACTER(len = *), INTENT(in) :: loc
36
37 if(status /= NF90_NOERR) then
38 WRITE(*, *) "Error at ", loc
39 WRITE(*, *) NF90_STRERROR(status)
40 end if
41 END SUBROUTINE check
42 END PROGRAM
이번 작업을 하면서 코딩보다는 실행 부분에서 에러가 많이 발생했습니다
첫 번째로 발생한 에러는 두 번째 줄에 있는 use netcdf 부분이었습니다
코드를 다 짠 후에 gfortran으로 컴파일을 하면
Fatal Error: Can't open module file ‘netcdf.mod’ for reading at (1): No such file or directory compilation terminated.
에러가 발생했습니다
이것에 해결법은 netcdf fortran을 설치한 디렉토리와 링크를 해줘야합니다
nc-config --fflags
-I/home/lsh/WRF/Library/include -I/home/lsh/WRF/Library/include
nc-config --flibs
-L/home/lsh/WRF/Library/lib -lnetcdff -L/home/lsh/WRF/Library/lib -lnetcdf -ldl -lm -lnetcdf -lhdf5_hl -lhdf5 -lz
이렇게 하나씩 순서대로 실행해보면 긴 path가 나옵니다
위에 fflags는 2가지로 나오지만 하나만 복사해서 쓰시면 되고 lib 경로는 그대로 복사하면 됩니다
그 후에 gfortran으로 컴파일을 할 때 뒤에 경로 2개를 include lib 순서로 붙여넣기하면 됩니다
결과적으로 아래 코드처럼 실행하면 됩니다
gfortran net1.f90 -I/home/lsh/WRF/Library/include -L/home/lsh/WRF/Library/lib -lnetcdff -L/home/lsh/WRF/Library/lib -lnetcdf -ldl -lm -lnetcdf -lhdf5_hl -lhdf5 -lz
저는 이렇게 해결했지만 다른 방법이 있으신 분은 댓글 부탁드립니다 ㅠㅠ
(아직 리눅스에 적응을 다 못했어요ㅠㅠ)
이 글을 쓰면서 변수를 선언해서 쓰는법도 생각해봤는데 이것도 해보겠습니다!
두 번째로 발생한 에러는
undefined reference to nf_{}와 check였는데 nf90_{} 명령어들은 라이브러리 링크로 해결이 됐고
check는 단순히 제가 subroutine을 만들지 않아서 발생했던 에러였습니다
세 번째로 발생한 에러는
NetCDF: Start+count exceeds dimension bound
였습니다
이 에러는 격자 형태로 netCDF 파일을 읽는 과정에서 array를 사용하는데
start array와 count array의 크기가 맞지 않은 겁니다
이는 제가 포트란 array가 뒤에서부터 읽는 것을 몰랐어서 발생한 에러였습니다
제가 읽은 데이터는 T2로 2m 높이에서 관측한 기온으로 데이터 형태를 이렇습니다
float T2(Time, south_north, west_east) ;
T2:FieldType = 104 ;
T2:MemoryOrder = "XY " ;
T2:description = "TEMP at 2 M" ;
T2:units = "K" ;
T2:stagger = "" ;
T2:coordinates = "XLONG XLAT XTIME" ;
기존에는 count = [1, 209, 209]로 array를 만들었는데 포트란은 뒤에서부터 읽다보니까 발생한 에러였습니다
이렇게 모든 에러들을 해결하고 나온 결과입니다
(base) lsh@DESKTOP-8N2HJ5V:~$ ./a.out
Reading Grid T2
Mean T2 : 288.110718
'Fortran' 카테고리의 다른 글
Fortran으로 netCDF 파일 작성 (nf90_def_dim, def_var, put_att, put_var) (0) | 2023.08.31 |
---|---|
작업7 : Fortran으로 파장 별 방출에너지 구하기 (0) | 2022.10.26 |
작업6 : Fortran으로 합성 풍속 풍향 구하기2 (0) | 2022.10.26 |
작업5 : Fortran으로 합성 풍향 풍속 구하기1 (0) | 2022.10.26 |
작업4 : Fortran으로 시간방정식 계산하기 (0) | 2022.10.26 |