├── .gitignore ├── LICENSE ├── README.md ├── src ├── input.up ├── install.sh ├── main.f90 ├── read_geogrid.c ├── updatelanduse └── write_geogrid.c └── utils ├── install.sh ├── nc2bin └── nc2bin.f90 /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> C 2 | # Object files 3 | *.dat 4 | *.o 5 | *.ko 6 | *.obj 7 | *.elf 8 | 9 | # Precompiled Headers 10 | *.gch 11 | *.pch 12 | 13 | # Libraries 14 | *.lib 15 | *.a 16 | *.la 17 | *.lo 18 | 19 | # Shared objects (inc. Windows DLLs) 20 | *.dll 21 | *.so 22 | *.so.* 23 | *.dylib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | *.i*86 30 | *.x86_64 31 | *.hex 32 | 33 | # Debug files 34 | *.dSYM/ 35 | 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 土地利用更新工具 2 | 3 | 部分更新WRF静态数据中的土地利用数据。 4 | 5 | ## 设计 6 | 在WRF的前处理模块(WPS)中,程序geogrid会根据定义的网格信息,计算每个网格的经纬度和投影比例因子,同时,将静态地理数据集(static geographical Data)插值到定义好的区域网格中。 7 | 8 | 静态数据的好坏直接影响陆-气交换过程,对模式预报效果存在较大的影响。但多数下垫面数据是根据历史观测数据统计得来,其更新周期较长,与当前真实的地表情况存在差异。理论上讲,更新下垫面数据,缩小其与真实情况的差异,可以提升局地的预报效果。 9 | 10 | 由于数据的获取难度,真正能够更新的数据,只有地形和土地利用数据子集。基于GMTED2010(Global Multi-resolution Terrain Elevation Data 2010),WPSv3.8对地形高程数据进行了一次更新,GMTED2010精度在200米以上,基本满足WRF模拟的需求,故没有自己修改的必要。 11 | 12 | 土地类型子集的统计时间相对较老,且土地利用类型本身相对易变(如城市的扩展等);从理论上可知,更新局地土地利用类型数据,对预报效果有一定的促进作用。鉴于此,本次WRF静态数据集更新工具的开发,主要针对土地利用数据进行。 13 | 14 | 更新WFS土地类型(这里的更新是指:更新部分土地利用类型,从头构建一个土地利用类型数据集太难),可以通过两种方式,首先,可以更新WPS生成的```geo_em.d0*.nc```中的LANDUSEF变量,由于针对nc格式进行操作,在读写方面比较方便,但由于每次模拟的区域和分辨率均不一样,可能反而增加了难度; 15 | 16 | 第二种方式是直接在默认基础数据集上进行更新,一套静态数据子集的网格点是固定,可以针对性的进行替换和处理。但WPS读取的静态数据(2-D或者3-D变量)采用二进制(binary raster format)的形式进行存储,且存储为特定的数据类型(有别于普通的整型、浮点)。因而采用该种方式进行更新的主要难点在于数据的读写。 17 | 18 | 更新工具设计的原则是一次只更新某一类土地利用类型(如城市用地);如果要更新多个类型,需要运行多次。 19 | 20 | 21 | 22 | ## 转化工具 23 | 24 | ### nc2bin 25 | 该工具可将NetCDF格式的土地利用数据转化为fortran的无格式二进制数据,便于土地利用更新工具读取。 26 | 27 | **安装** 28 | 该工具存放在HOME/utile目录中;安装时需要修改HOME/utile/install.sh中NetCDF库的位置。 29 | 30 | 修改完成后,执行 31 | ``` bash 32 | bash install.sh 33 | ``` 34 | 35 | **使用** 36 | 37 | 使用时,执行 38 | ``` bash 39 | nc2bin MCD12Q1.nc asia_landuse.dat 19200 12000 40 | ``` 41 | 其中, 42 | 43 | 1. MCD12Q1.nc为存放土里利用类型的NC格式数据; 44 | 2. asia_landuse.dat 为输出数据; 45 | 3. 19200 12000:为网格信息; 46 | 47 | MCD12Q1.nc的具体信息如下 48 | 49 | ``` 50 | dimensions: 51 | y = 12000 ; 52 | x = 19200 ; 53 | variables: 54 | float lats(y, x) ; 55 | lats:_FillValue = -999.f ; 56 | float lons(y, x) ; 57 | lons:_FillValue = -999.f ; 58 | float landuse(y, x) ; 59 | landuse:_FillValue = -999.f ; 60 | landuse:coordinates = "lons lats" ; 61 | ``` 62 | 63 | nc2bin的输出格式如下 64 | ``` fortran 65 | open(100,file=trim(fname), form='unformatted', iostat=ierror, iomsg=errormg) 66 | write(100) lats 67 | write(100) lons 68 | write(100) array 69 | ``` 70 | 71 | ## 更新工具 72 | 73 | 更新工具的名称为updatelanduse,存放在HOME/src目录中。设计的目的是基于WRF原有的静态数据,只更新其中一种土地利用类型。 74 | 75 | **安装** 76 | 77 | 安装时注意编译器的选择即可。 78 | 79 | ``` bash 80 | bash install.sh 81 | ``` 82 | 83 | **配置** 84 | 85 | ``` bash 86 | vim input.up 87 | ``` 88 | 89 | 配置文件中,原始数据(WRF自带的静态数据集)的配置信息均可在静态数据集中的index文件中获取。 90 | ``` 91 | &description 92 | xdim = 43200 ! x-dimension of raw array 93 | ydim = 21600 ! y-dimension of raw array 94 | zdim = 1 ! z-dimension of raw array 95 | xdelta = 1200 ! number of points in each tile 96 | ydelta = 1200 ! number of points in each tile 97 | known_lat = -89.99583 ! the lat of bottom-left point 98 | known_lon = -179.99583 ! the lon of bottom-left point 99 | dx = 0.00833333 ! the delta x in deg 100 | dy = 0.00833333 ! the delta y in deg 101 | signed = 0 ! 0=unsigned data, 1=signed data 102 | endian = 0 ! 0=big endian, 1=little endian 103 | urban = 13 ! the id of urban 104 | wordsize = 1 ! number of bytes to use for each array element 105 | scale = 1.0 ! value to multiply array elements by before truncation to integers 106 | newnx = 19200 ! x-dimension of new array 新土里利用类型的数据大小 107 | newny = 12000 ! y-dimension of new array 108 | oldindex = 13 ! index of landuse that will be change in raw data 待更新的土地利用类型指数 109 | newindex = 13 ! index of landuse that will be change in new data 110 | / 111 | 112 | &path 113 | oldpath = "PATH/geog/modis_landuse_20class_30s_with_lakes", !原始的静态数据路径 114 | newfile = "PATH/asia_landuse.dat", ! 新的土里利用数据 115 | outpath = "./out", ! 输出路径 116 | / 117 | ``` 118 | 119 | **使用** 120 | 121 | ``` bash 122 | updatelanduse input.up 123 | ``` 124 | 125 | 运行完成后,可将out文件替代modis_landuse_20class_30s_with_lakes文件,在运行WRF即可。 126 | 127 | **注意** 128 | 129 | 更新工具读入的文件格式必须是fortran的无格式文件,按照下面的接口函数转换。 130 | 131 | ``` fortran 132 | subroutine writenew(fname, nx, ny, lats, lons, array) 133 | implicit none 134 | ! calling 135 | character(len=*),intent(in) :: fname 136 | integer, intent(in) :: nx 137 | integer, intent(in) :: ny 138 | real, intent(in) ,dimension(nx, ny) :: lats 139 | real, intent(in) ,dimension(nx, ny) :: lons 140 | real, intent(in) ,dimension(nx, ny) :: array 141 | 142 | ! local 143 | character(200) :: errormg ! the message of fail opening 144 | integer :: ierror ! Flag for allocate 145 | 146 | open(100,file=trim(fname), form='unformatted', iostat=ierror, iomsg=errormg) 147 | write(100) lats 148 | write(100) lons 149 | write(100) array 150 | ! Check if writing data is successfule. 151 | if(ierror /= 0) then 152 | write(*,*) errormg 153 | stop 154 | end if 155 | close(100) 156 | end subroutine writenew 157 | ``` 158 | 159 | 具体操作可参见nc2bin。 -------------------------------------------------------------------------------- /src/input.up: -------------------------------------------------------------------------------- 1 | &description 2 | xdim = 43200 ! x-dimension of raw array 3 | ydim = 21600 ! y-dimension of raw array 4 | zdim = 1 ! z-dimension of raw array 5 | xdelta = 1200 ! number of points in each tile 6 | ydelta = 1200 ! number of points in each tile 7 | known_lat = -89.99583 ! the lat of bottom-left point 8 | known_lon = -179.99583 ! the lon of bottom-left point 9 | dx = 0.00833333 ! the delta x in deg 10 | dy = 0.00833333 ! the delta y in deg 11 | signed = 0 ! 0=unsigned data, 1=signed data 12 | endian = 0 ! 0=big endian, 1=little endian 13 | urban = 13 ! the id of urban 14 | wordsize = 1 ! number of bytes to use for each array element 15 | scale = 1.0 ! value to multiply array elements by before truncation to integers 16 | newnx = 19200 ! x-dimension of new array 17 | newny = 12000 ! y-dimension of new array 18 | oldindex = 13 ! index of landuse that will be change in raw data 19 | newindex = 13 ! index of landuse that will be change in new data 20 | / 21 | 22 | &path 23 | oldpath = "/public/home/xiaolh/Data/geog/modis_landuse_20class_30s_with_lakes", 24 | newfile = "/public/home/xiaolh/project/updatelanduse/utils/asia_landuse.dat", 25 | outpath = "./out", 26 | / 27 | 28 | -------------------------------------------------------------------------------- /src/install.sh: -------------------------------------------------------------------------------- 1 | 2 | CC=icc 3 | FC=ifort 4 | 5 | #ENDIAN=little_endian 6 | ENDIAN=big_endian 7 | 8 | # I/O routine 9 | $CC -D _UNDERSCORE=1 -w -c read_geogrid.c 10 | $CC -D _UNDERSCORE=1 -w -c write_geogrid.c 11 | 12 | #$FC -convert $ENDIAN -c main.f90 13 | $FC -mcmodel=medium -c main.f90 14 | 15 | # link 16 | $FC -o updatelanduse *.o 17 | -------------------------------------------------------------------------------- /src/main.f90: -------------------------------------------------------------------------------- 1 | program main 2 | implicit none 3 | 4 | ! raw data information 5 | integer :: xdim ! x-dimension of raw array 6 | integer :: ydim ! y-dimension of raw array 7 | integer :: zdim ! z-dimension of raw array 8 | integer :: xdelta ! number of points in each tile 9 | integer :: ydelta ! number of points in each tile 10 | real :: known_lat ! the lat of bottom-left point 11 | real :: known_lon ! the lon of bottom-left point 12 | real :: dx ! the delta x in deg 13 | real :: dy ! the delta y in deg 14 | 15 | integer :: signed ! 0=unsigned data, 1=signed data 16 | integer :: endian ! 0=big endian, 1=little endian 17 | integer :: urban ! the id of urban 18 | integer :: wordsize ! number of bytes to use for each array element 19 | real :: scale ! value to multiply array elements by before truncation to integers 20 | 21 | ! new data 22 | integer :: newnx ! x-dimension of raw array 23 | integer :: newny ! y-dimension of raw array 24 | 25 | ! raw data 26 | real,allocatable,dimension(:) :: lats ! lats of raw data 27 | real,allocatable,dimension(:) :: lons ! lons of raw data 28 | real,allocatable,dimension(:,:,:) :: modis ! raw data 29 | 30 | real,allocatable,dimension(:,:) :: newlats ! lats of raw data 31 | real,allocatable,dimension(:,:) :: newlons ! lons of raw data 32 | real,allocatable,dimension(:,:) :: newdata ! raw data 33 | 34 | ! landindex 35 | integer :: oldindex = 13 36 | integer :: newindex = 13 37 | 38 | ! file 39 | character(len=200) :: oldfile 40 | character(len=200) :: newfile 41 | character(len=200) :: outfile 42 | 43 | character(len=128) :: oldpath 44 | character(len=128) :: newpath 45 | character(len=128) :: outpath 46 | 47 | ! local 48 | integer :: i,j,k 49 | integer :: status, strlen 50 | real :: xleft, yleft 51 | real :: maxlat,maxlon,minlat,minlon 52 | integer :: xstart, xend, ystart, yend 53 | character(len=23) :: fname 54 | ! function 55 | character(len=5),external :: integerToCharacter 56 | integer, external :: system 57 | 58 | ! Declare the local variables 59 | integer :: fnamelen ! The len of the name of input file. 60 | integer :: ierror ! Flag for open file error 61 | integer :: inputunit=9 ! Open unit 62 | character(len=100) :: inputname ! The name of input file 63 | character(len=200) :: errmsg ! error message 64 | 65 | namelist /description/ xdim, ydim, zdim, xdelta, ydelta, known_lat, known_lon, & 66 | dx, dy, signed, endian, urban, wordsize, scale, newnx, newny, & 67 | oldindex, newindex 68 | 69 | namelist /path/ oldpath, newfile, outpath 70 | 71 | ! write(*,*) "==========================================================" 72 | ! write(*,*) " Copyright (C) 2018, Linhong Xiao" 73 | ! write(*,*) " updateLanduse version 2.0.1 2018.05.02 " 74 | ! write(*,*) "==========================================================" 75 | 76 | ! read the input file name 77 | if (command_argument_count() == 0) then 78 | write(*,*) '-------------------parameter file name--------------------' 79 | write(*,*) 'Notice: The input file used is input.up in local folder. ' 80 | write(*,*) '----------------------------------------------------------' 81 | write(*,*) ' ' 82 | inputname = 'input.up' 83 | elseif (command_argument_count() > 0) then 84 | call get_command_argument(1,inputname,fnamelen,ierror) 85 | ! write(*,*) fnamelen 86 | if (fnamelen < 100) then 87 | write(*,*) '-------------------parameter file name--------------------' 88 | write(*,*) 'Notice: The input file used is ' // trim(inputname) 89 | write(*,*) '----------------------------------------------------------' 90 | write(*,*) ' ' 91 | else 92 | write(*,*) '****************************************************' 93 | write(*,*) '*** Error: The name of input file is too LONG! ***' 94 | write(*,*) '*** The length of the input name is:',fnamelen, '***' 95 | write(*,*) '*** Please keep the LEN less than 100 ! ***' 96 | write(*,*) '****************************************************' 97 | stop 98 | end if 99 | end if 100 | 101 | ! open input file and deteminte if exists 102 | open(inputunit,file=inputname,form='formatted',iostat=ierror,status='old',iomsg=errmsg) 103 | if(ierror /= 0)then 104 | write(*,*) errmsg 105 | write(*,*) inputname 106 | stop 107 | end if 108 | 109 | read(inputunit,NML=description,iostat=ierror,iomsg=errmsg ) 110 | if(ierror/=0) write(*,*) errmsg 111 | if(ierror/=0) stop 112 | 113 | read(inputunit,NML=path,iostat=ierror,iomsg=errmsg ) 114 | if(ierror/=0) write(*,*) errmsg 115 | if(ierror/=0) stop 116 | close(inputunit) 117 | 118 | 119 | allocate( lats(ydelta),lons(xdelta),modis(xdelta, ydelta, zdim) ) 120 | allocate( newlats(newnx, newny),newlons(newnx, newny),newdata(newnx, newny) ) 121 | call readnew(newfile, newnx, newny, newlats, newlons, newdata) 122 | 123 | ! handle the core operations 124 | do i=1,xdim/xdelta 125 | xleft=known_lon+(i-1)*xdelta*dx 126 | call createlist(xleft, dx, xdelta, lons) 127 | 128 | do j=1,ydim/ydelta 129 | yleft=known_lat+(j-1)*ydelta*dy 130 | call createlist(yleft, dy, ydelta, lats) 131 | 132 | xstart = (i-1)*xdelta+1 133 | xend = i*xdelta 134 | ystart = (j-1)*ydelta+1 135 | yend = j*ydelta 136 | fname = integerToCharacter(xstart)//"-"//integerToCharacter(xend)// & 137 | "."//integerToCharacter(ystart)//"-"//integerToCharacter(yend) 138 | ! read the raw data 139 | write(*,*) fname 140 | oldfile = trim(oldpath)//"/"//trim(fname) 141 | call countLen(oldfile,strlen) 142 | call read_geogrid(oldfile, strlen, modis, xdelta, ydelta, zdim,& 143 | signed, endian, scale, wordsize, status) 144 | ! char * fname, /* The name of the file to read from */ 145 | ! int * len, /* The length of the filename */ 146 | ! float * rarray, /* The array to be filled */ 147 | ! int * nx, /* x-dimension of the array */ 148 | ! int * ny, /* y-dimension of the array */ 149 | ! int * nz, /* z-dimension of the array */ 150 | ! int * isigned, /* 0=unsigned data, 1=signed data */ 151 | ! int * endian, /* 0=big endian, 1=little endian */ 152 | ! float * scalefactor, /* value to multiply array elements by before truncation to integers */ 153 | ! int * wordsize, /* number of bytes to use for each array element */ 154 | ! int * status) 155 | !write(*,"(F10.2)") maxval(modis) 156 | !stop 157 | ! do some change 158 | call match(xdelta, ydelta, lons, lats, modis, newnx, newny, newlons, newlats, newdata, oldindex, newindex) 159 | 160 | ! output the new 161 | outfile = trim(outpath)//"/"//trim(fname) 162 | !write(*,*) outfile 163 | status = system( "mkdir -p "// outpath ) 164 | call countLen(outfile,strlen) 165 | call write_geogrid(modis, xdelta, ydelta, zdim, signed, endian, scale, wordsize, outfile, strlen) 166 | !stop 167 | end do 168 | end do 169 | status = system( "cp "//trim(oldpath)//"/index"//" "//outpath ) 170 | end program 171 | 172 | !=====================================================================================! 173 | 174 | character(len=*) function integerToCharacter(ii) 175 | ! usage: 176 | ! character(len=5),external :: integerToCharacter 177 | ! write(*,*) integerToCharacter(2) 178 | implicit none 179 | integer, intent(in) :: ii 180 | write(integerToCharacter,"(I5.5)") ii 181 | 182 | end function integerToCharacter 183 | 184 | subroutine countLen(string, strlen) 185 | 186 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 187 | ! Name: countLen 188 | ! 189 | ! Purpose: This routine receives a fortran string, and returns the number of 190 | ! characters in the string before the first "space" is encountered. It 191 | ! considers ascii characters 33 to 126 to be valid characters, and ascii 192 | ! 0 to 32, and 127 to be "space" characters. 193 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 194 | 195 | implicit none 196 | 197 | ! Arguments 198 | character (len=*), intent(in) :: string 199 | integer, intent(out) :: strlen 200 | 201 | ! Local variables 202 | integer :: i, len_str, aval 203 | logical :: space 204 | 205 | space = .false. 206 | i = 1 207 | len_str = len(string) 208 | strlen = len_str 209 | do while ((i .le. len_str) .and. (.not. space)) 210 | aval = ichar(string(i:i)) 211 | if ((aval .lt. 33) .or. (aval .gt. 126)) then 212 | strlen = i - 1 213 | space = .true. 214 | end if 215 | i = i + 1 216 | end do 217 | end subroutine countLen 218 | 219 | 220 | subroutine createlist(start, delta, num, array) 221 | implicit none 222 | ! parameter 223 | real, intent(in) :: start 224 | real, intent(in) :: delta 225 | integer, intent(in) :: num 226 | real, intent(out) ,dimension(num) :: array 227 | 228 | ! local 229 | integer :: i 230 | do i =1, num 231 | array(i) = start + (i-1)*delta 232 | end do 233 | 234 | end subroutine createlist 235 | 236 | 237 | subroutine readnew(fname, nx, ny, lats, lons, array) 238 | implicit none 239 | ! calling 240 | character(len=*),intent(in) :: fname 241 | integer, intent(in) :: nx 242 | integer, intent(in) :: ny 243 | real, intent(out) ,dimension(nx, ny) :: lats 244 | real, intent(out) ,dimension(nx, ny) :: lons 245 | real, intent(out) ,dimension(nx, ny) :: array 246 | 247 | ! local 248 | character(200) :: errormg ! the message of fail opening 249 | integer :: ierror ! Flag for allocate 250 | open(100,file=fname, form='unformatted', iostat=ierror, iomsg=errormg) 251 | read(100) lats 252 | read(100) lons 253 | read(100) array 254 | ! Check if writing data is successfule. 255 | if(ierror /= 0) then 256 | write(*,*) errormg 257 | stop 258 | end if 259 | close(100) 260 | end subroutine readnew 261 | 262 | subroutine match(nx, ny, lons, lats, modis, newnx, newny, newlons, newlats, newdata, oldindex, newindex) 263 | 264 | implicit none 265 | ! calling 266 | integer, intent(in) :: nx 267 | integer, intent(in) :: ny 268 | real, intent(in) ,dimension(nx) :: lons 269 | real, intent(in) ,dimension(ny) :: lats 270 | real, intent(inout) ,dimension(nx,ny) :: modis 271 | 272 | integer, intent(in) :: newnx 273 | integer, intent(in) :: newny 274 | real, intent(in) ,dimension(newnx, newny) :: newlons 275 | real, intent(in) ,dimension(newnx, newny) :: newlats 276 | real, intent(in) ,dimension(newnx, newny) :: newdata 277 | 278 | integer, intent(in) :: oldindex 279 | integer, intent(in) :: newindex 280 | 281 | ! local 282 | integer :: i,j 283 | integer :: ix 284 | integer :: iy 285 | 286 | do i=1,newnx 287 | do j=1,newny 288 | if ( newlons(i,j)>lons(1) .and. newlons(i,j)lats(1) .and. newlats(i,j) lon ) then 323 | ix=i 324 | exit 325 | end if 326 | end do 327 | 328 | do i=1,ny-1 329 | if ( lats(i)<= lat .and. lats(i+1)> lat ) then 330 | iy=i 331 | exit 332 | end if 333 | end do 334 | end subroutine ind 335 | -------------------------------------------------------------------------------- /src/read_geogrid.c: -------------------------------------------------------------------------------- 1 | /* File: read_geogrid.c 2 | 3 | Sample subroutine to read an array from the geogrid binary format. 4 | 5 | Notes: Depending on the compiler and compiler flags, the name of 6 | the read_geogrid() routine may need to be adjusted with respect 7 | to the number of trailing underscores when calling from Fortran. 8 | 9 | Michael G. Duda, NCAR/MMM 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _UNDERSCORE 17 | #define read_geogrid read_geogrid_ 18 | #endif 19 | #ifdef _DOUBLEUNDERSCORE 20 | #define read_geogrid read_geogrid__ 21 | #endif 22 | 23 | #define ENDIAN 0 24 | 25 | int read_geogrid( 26 | char * fname, /* The name of the file to read from */ 27 | int * len, /* The length of the filename */ 28 | float * rarray, /* The array to be filled */ 29 | int * nx, /* x-dimension of the array */ 30 | int * ny, /* y-dimension of the array */ 31 | int * nz, /* z-dimension of the array */ 32 | int * isigned, /* 0=unsigned data, 1=signed data */ 33 | int * endian, /* 0=big endian, 1=little endian */ 34 | float * scalefactor, /* value to multiply array elements by before truncation to integers */ 35 | int * wordsize, /* number of bytes to use for each array element */ 36 | int * status) 37 | { 38 | size_t i, cnt, narray; 39 | int ival; 40 | int A2, B2; 41 | int A3, B3, C3; 42 | int A4, B4, C4, D4; 43 | unsigned char * c; 44 | char local_fname[1024]; 45 | FILE * bfile; 46 | 47 | *status = 0; 48 | 49 | narray = (size_t)(*nx) * (size_t)(*ny) * (size_t)(*nz); 50 | 51 | /* Make a null-terminated local copy of the filename */ 52 | strncpy(local_fname,fname,*len); 53 | local_fname[*len]='\0'; 54 | 55 | /* Attempt to open file for reading */ 56 | if (!(bfile = fopen(local_fname,"rb"))) 57 | { 58 | *status = 1; 59 | return 1; 60 | } 61 | 62 | /* Allocate memory to hold bytes from file and read data */ 63 | c = (unsigned char *)malloc(sizeof(unsigned char)*(*wordsize) * narray); 64 | cnt = fread((void *)c, sizeof(unsigned char), narray*(size_t)(*wordsize), bfile); 65 | 66 | fclose(bfile); 67 | 68 | if (cnt == 0) 69 | { 70 | *status = 1; 71 | return 1; 72 | } 73 | 74 | /* 75 | Set up byte offsets for each wordsize depending on byte order. 76 | A, B, C, D give the offsets of the LSB through MSB (i.e., for 77 | word ABCD, A=MSB, D=LSB) in the array from the beginning of a word 78 | */ 79 | if (*endian == ENDIAN) { 80 | A2 = 0; B2 = 1; 81 | A3 = 0; B3 = 1; C3 = 2; 82 | A4 = 0; B4 = 1; C4 = 2; D4 = 3; 83 | } 84 | else { 85 | B2 = 0; A2 = 1; 86 | C3 = 0; B3 = 1; A3 = 2; 87 | D4 = 0; C4 = 1; B4 = 2; A4 = 3; 88 | } 89 | 90 | /* Convert words from native byte order */ 91 | switch(*wordsize) { 92 | case 1: 93 | for(i=0; i (1 << 7))) ival -= (1 << 8); 97 | rarray[i] = (float)ival; 98 | } 99 | break; 100 | 101 | case 2: 102 | for(i=0; i (1 << 15))) ival -= (1 << 16); 106 | rarray[i] = (float)ival; 107 | } 108 | break; 109 | 110 | case 3: 111 | for(i=0; i (1 << 23))) ival -= (1 << 24); 115 | rarray[i] = (float)ival; 116 | } 117 | break; 118 | 119 | case 4: 120 | for(i=0; i (1 << 31))) ival -= (1 << 32); 124 | rarray[i] = (float)ival; 125 | } 126 | break; 127 | } 128 | 129 | free(c); 130 | 131 | /* Scale real-valued array by scalefactor */ 132 | if (*scalefactor != 1.0) 133 | { 134 | for (i=0; i.00001- is 6 | created, where is the argument nx and is the argument ny, 7 | both in i5.5 format. 8 | 9 | Notes: Depending on the compiler and compiler flags, the name of 10 | the write_geogrid() routine may need to be adjusted with respect 11 | to the number of trailing underscores when calling from Fortran. 12 | 13 | Michael G. Duda, NCAR/MMM 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #ifdef _UNDERSCORE 21 | #define write_geogrid write_geogrid_ 22 | #endif 23 | #ifdef _DOUBLEUNDERSCORE 24 | #define write_geogrid write_geogrid__ 25 | #endif 26 | 27 | #define ENDIAN 0 28 | //#define LITTLE_ENDIAN 1 29 | 30 | int write_geogrid( 31 | float * rarray, /* The array to be written */ 32 | int * nx, /* x-dimension of the array */ 33 | int * ny, /* y-dimension of the array */ 34 | int * nz, /* z-dimension of the array */ 35 | int * isigned, /* 0=unsigned data, 1=signed data */ 36 | int * endian, /* 0=big endian, 1=little endian */ 37 | float * scalefactor, /* value to divide array elements by before truncation to integers */ 38 | int * wordsize, /* number of bytes to use for each array element */ 39 | char * fname, 40 | int * len) 41 | { 42 | int i, narray; 43 | int A2, B2; 44 | int A3, B3, C3; 45 | int A4, B4, C4, D4; 46 | unsigned int * iarray; 47 | unsigned char * barray; 48 | char local_fname[1024]; 49 | FILE * bfile; 50 | 51 | narray = (*nx) * (*ny) * (*nz); 52 | 53 | iarray = (unsigned int *)malloc(sizeof(int) * narray); 54 | barray = (unsigned char *)malloc(sizeof(unsigned char) * narray * (*wordsize)); 55 | 56 | /* Scale real-valued array by scalefactor and convert to integers */ 57 | for (i=0; i> 8) & 0xff); 89 | barray[(*wordsize)*i+B2] = (unsigned char)( iarray[i] & 0xff); 90 | } 91 | break; 92 | 93 | case 3: 94 | for(i=0; i> 16) & 0xff); 97 | barray[(*wordsize)*i+B3] = (unsigned char)((iarray[i] >> 8) & 0xff); 98 | barray[(*wordsize)*i+C3] = (unsigned char)( iarray[i] & 0xff); 99 | } 100 | break; 101 | 102 | case 4: 103 | for(i=0; i> 24) & 0xff); 106 | barray[(*wordsize)*i+B4] = (unsigned char)((iarray[i] >> 16) & 0xff); 107 | barray[(*wordsize)*i+C4] = (unsigned char)((iarray[i] >> 8) & 0xff); 108 | barray[(*wordsize)*i+D4] = (unsigned char)( iarray[i] & 0xff); 109 | } 110 | break; 111 | } 112 | 113 | //sprintf(fname,"%5.5i-%5.5i.%5.5i-%5.5i",1,*nx,1,*ny); 114 | 115 | /* Write array to file */ 116 | strncpy(local_fname,fname,*len); 117 | local_fname[*len]='\0'; 118 | 119 | bfile = fopen(local_fname,"wb"); 120 | fwrite(barray,sizeof(unsigned char),narray*(*wordsize),bfile); 121 | fclose(bfile); 122 | 123 | free(iarray); 124 | free(barray); 125 | 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /utils/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | NETCDF=/public/home/xiaolh/software/netcdf/all 3 | ifort convert.f90 -L$NETCDF/lib -lnetcdff -lnetcdf -I$NETCDF/include -o convert 4 | -------------------------------------------------------------------------------- /utils/nc2bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XiaoLinhong/uplandsue/524ce2cf0dd97d16e6372b2d9cde2d5890779289/utils/nc2bin -------------------------------------------------------------------------------- /utils/nc2bin.f90: -------------------------------------------------------------------------------- 1 | program main 2 | use netcdf 3 | implicit none 4 | 5 | ! new data 6 | character(len=200) :: iname, oname 7 | character(len=10) :: strnx, strny 8 | 9 | integer :: newnx ! x-dimension of raw array 10 | integer :: newny ! y-dimension of raw array 11 | 12 | integer :: nlen, ierror 13 | 14 | real,allocatable,dimension(:,:) :: newlats ! lats of raw data 15 | real,allocatable,dimension(:,:) :: newlons ! lons of raw data 16 | real,allocatable,dimension(:,:) :: newdata ! raw data 17 | 18 | integer :: ncid, varid 19 | ! newnx = 19200 20 | ! newny = 12000 21 | 22 | if (command_argument_count() /= 4) then 23 | write(*,*) ' Convert NetCDF to Binary' 24 | write(*,*) ' Usage: convert iname oname nx ny ' 25 | stop 26 | end if 27 | 28 | call get_command_argument(1, iname, nlen, ierror) 29 | call get_command_argument(2, oname, nlen, ierror) 30 | call get_command_argument(3, strnx, nlen, ierror) 31 | call get_command_argument(4, strny, nlen, ierror) 32 | 33 | read(strnx, '(I10)') newnx 34 | read(strny, '(I10)') newny 35 | 36 | allocate(newlats(newnx, newny), newlons(newnx, newny), newdata(newnx, newny)) 37 | 38 | ! Open the file. NF90_NOWRITE tells netCDF we want read-only access to 39 | ! the file. 40 | call check( nf90_open(trim(iname), NF90_NOWRITE, ncid) ) 41 | 42 | ! Get the varid of the data variable, based on its name. 43 | call check( nf90_inq_varid(ncid, "lats", varid) ) 44 | 45 | ! Read the data. 46 | call check( nf90_get_var(ncid, varid, newlats) ) 47 | 48 | ! Get the varid of the data variable, based on its name. 49 | call check( nf90_inq_varid(ncid, "lons", varid) ) 50 | 51 | ! Read the data. 52 | call check( nf90_get_var(ncid, varid, newlons) ) 53 | 54 | ! Get the varid of the data variable, based on its name. 55 | call check( nf90_inq_varid(ncid, "landuse", varid) ) 56 | ! Read the data. 57 | 58 | call check( nf90_get_var(ncid, varid, newdata) ) 59 | 60 | call check( nf90_close(ncid) ) 61 | 62 | call writenew(oname, newnx, newny, transpose(newlats), transpose(newlons), transpose(newdata)) 63 | 64 | end program main 65 | 66 | subroutine writenew(fname, nx, ny, lats, lons, array) 67 | implicit none 68 | ! calling 69 | character(len=*),intent(in) :: fname 70 | integer, intent(in) :: nx 71 | integer, intent(in) :: ny 72 | real, intent(in) ,dimension(nx, ny) :: lats 73 | real, intent(in) ,dimension(nx, ny) :: lons 74 | real, intent(in) ,dimension(nx, ny) :: array 75 | 76 | ! local 77 | character(200) :: errormg ! the message of fail opening 78 | integer :: ierror ! Flag for allocate 79 | 80 | open(100,file=trim(fname), form='unformatted', iostat=ierror, iomsg=errormg) 81 | write(100) lats 82 | write(100) lons 83 | write(100) array 84 | ! Check if writing data is successfule. 85 | if(ierror /= 0) then 86 | write(*,*) errormg 87 | stop 88 | end if 89 | close(100) 90 | end subroutine writenew 91 | 92 | subroutine check(status) 93 | use netcdf 94 | integer, intent ( in) :: status 95 | if(status /= nf90_noerr) then 96 | write(*,*), trim(nf90_strerror(status)) 97 | write(*,*) "error" 98 | stop 2 99 | end if 100 | end subroutine check 101 | --------------------------------------------------------------------------------