PartMC
2.2.0
|
00001 ! Copyright (C) 2007-2010 Matthew West 00002 ! Licensed under the GNU General Public License version 2 or (at your 00003 ! option) any later version. See the file COPYING for details. 00004 00005 !> \file 00006 !> The pmc_netcdf module. 00007 00008 !> Wrapper functions for NetCDF. 00009 module pmc_netcdf 00010 00011 use netcdf 00012 use pmc_util 00013 00014 contains 00015 00016 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00017 00018 !> Check the status of a NetCDF function call. 00019 subroutine pmc_nc_check(status) 00020 00021 !> Status return value. 00022 integer, intent(in) :: status 00023 00024 if (status /= NF90_NOERR) then 00025 call die_msg(291021908, nf90_strerror(status)) 00026 end if 00027 00028 end subroutine pmc_nc_check 00029 00030 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00031 00032 !> Check the status of a NetCDF function call and prints the given 00033 !> error message on failure. 00034 subroutine pmc_nc_check_msg(status, error_msg) 00035 00036 !> Status return value. 00037 integer, intent(in) :: status 00038 !> Error message in case of failure. 00039 character(len=*), intent(in) :: error_msg 00040 00041 if (status /= NF90_NOERR) then 00042 call die_msg(701841139, trim(error_msg) & 00043 // " : " // trim(nf90_strerror(status))) 00044 end if 00045 00046 end subroutine pmc_nc_check_msg 00047 00048 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00049 00050 !> Open a NetCDF file for reading. 00051 subroutine pmc_nc_open_read(filename, ncid) 00052 00053 !> Filename of NetCDF file to open. 00054 character(len=*), intent(in) :: filename 00055 !> NetCDF file ID, in data mode. 00056 integer, intent(out) :: ncid 00057 00058 call pmc_nc_check_msg(nf90_open(filename, NF90_NOWRITE, ncid), & 00059 "opening " // trim(filename)) 00060 00061 end subroutine pmc_nc_open_read 00062 00063 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00064 00065 !> Close a NetCDF file. 00066 subroutine pmc_nc_close(ncid) 00067 00068 !> NetCDF file ID, in data mode. 00069 integer, intent(in) :: ncid 00070 00071 call pmc_nc_check(nf90_close(ncid)) 00072 00073 end subroutine pmc_nc_close 00074 00075 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00076 00077 !> Read a single real from a NetCDF file. 00078 subroutine pmc_nc_read_real(ncid, var, name, must_be_present) 00079 00080 !> NetCDF file ID, in data mode. 00081 integer, intent(in) :: ncid 00082 !> Data to write. 00083 real(kind=dp), intent(out) :: var 00084 !> Variable name in NetCDF file. 00085 character(len=*), intent(in) :: name 00086 !> Whether the variable must be present in the NetCDF file 00087 !> (default .true.). 00088 logical, optional, intent(in) :: must_be_present 00089 00090 integer :: varid, status 00091 logical :: use_must_be_present 00092 00093 if (present(must_be_present)) then 00094 use_must_be_present = must_be_present 00095 else 00096 use_must_be_present = .true. 00097 end if 00098 status = nf90_inq_varid(ncid, name, varid) 00099 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00100 ! variable was not present, but that's ok 00101 var = 0d0 00102 return 00103 end if 00104 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00105 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00106 "getting variable " // trim(name)) 00107 00108 end subroutine pmc_nc_read_real 00109 00110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00111 00112 !> Read a single integer from a NetCDF file. 00113 subroutine pmc_nc_read_integer(ncid, var, name, must_be_present) 00114 00115 !> NetCDF file ID, in data mode. 00116 integer, intent(in) :: ncid 00117 !> Data to write. 00118 integer, intent(out) :: var 00119 !> Variable name in NetCDF file. 00120 character(len=*), intent(in) :: name 00121 !> Whether the variable must be present in the NetCDF file 00122 !> (default .true.). 00123 logical, optional, intent(in) :: must_be_present 00124 00125 integer :: varid, status 00126 logical :: use_must_be_present 00127 00128 if (present(must_be_present)) then 00129 use_must_be_present = must_be_present 00130 else 00131 use_must_be_present = .true. 00132 end if 00133 status = nf90_inq_varid(ncid, name, varid) 00134 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00135 ! variable was not present, but that's ok 00136 var = 0 00137 return 00138 end if 00139 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00140 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00141 "getting variable " // trim(name)) 00142 00143 end subroutine pmc_nc_read_integer 00144 00145 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00146 00147 !> Read a simple real array from a NetCDF file. 00148 subroutine pmc_nc_read_real_1d(ncid, var, name, must_be_present) 00149 00150 !> NetCDF file ID, in data mode. 00151 integer, intent(in) :: ncid 00152 !> Data to read, must be correctly sized. 00153 real(kind=dp), intent(out) :: var(:) 00154 !> Variable name in NetCDF file. 00155 character(len=*), intent(in) :: name 00156 !> Whether the variable must be present in the NetCDF file 00157 !> (default .true.). 00158 logical, optional, intent(in) :: must_be_present 00159 00160 integer :: varid, status 00161 logical :: use_must_be_present 00162 00163 if (present(must_be_present)) then 00164 use_must_be_present = must_be_present 00165 else 00166 use_must_be_present = .true. 00167 end if 00168 status = nf90_inq_varid(ncid, name, varid) 00169 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00170 ! variable was not present, but that's ok 00171 var = 0d0 00172 return 00173 end if 00174 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00175 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00176 "getting variable " // trim(name)) 00177 00178 end subroutine pmc_nc_read_real_1d 00179 00180 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00181 00182 !> Read a simple integer array from a NetCDF file. 00183 subroutine pmc_nc_read_integer_1d(ncid, var, name, must_be_present) 00184 00185 !> NetCDF file ID, in data mode. 00186 integer, intent(in) :: ncid 00187 !> Data to read, must be correctly sized. 00188 integer, intent(out) :: var(:) 00189 !> Variable name in NetCDF file. 00190 character(len=*), intent(in) :: name 00191 !> Whether the variable must be present in the NetCDF file 00192 !> (default .true.). 00193 logical, optional, intent(in) :: must_be_present 00194 00195 integer :: varid, status 00196 logical :: use_must_be_present 00197 00198 if (present(must_be_present)) then 00199 use_must_be_present = must_be_present 00200 else 00201 use_must_be_present = .true. 00202 end if 00203 status = nf90_inq_varid(ncid, name, varid) 00204 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00205 ! variable was not present, but that's ok 00206 var = 0 00207 return 00208 end if 00209 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00210 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00211 "getting variable " // trim(name)) 00212 00213 end subroutine pmc_nc_read_integer_1d 00214 00215 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00216 00217 !> Read a simple real 2D array from a NetCDF file. 00218 subroutine pmc_nc_read_real_2d(ncid, var, name, must_be_present) 00219 00220 !> NetCDF file ID, in data mode. 00221 integer, intent(in) :: ncid 00222 !> Data to read, must be correctly sized. 00223 real(kind=dp), intent(out) :: var(:,:) 00224 !> Variable name in NetCDF file. 00225 character(len=*), intent(in) :: name 00226 !> Whether the variable must be present in the NetCDF file 00227 !> (default .true.). 00228 logical, optional, intent(in) :: must_be_present 00229 00230 integer :: varid, status 00231 logical :: use_must_be_present 00232 00233 if (present(must_be_present)) then 00234 use_must_be_present = must_be_present 00235 else 00236 use_must_be_present = .true. 00237 end if 00238 status = nf90_inq_varid(ncid, name, varid) 00239 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00240 ! variable was not present, but that's ok 00241 var = 0d0 00242 return 00243 end if 00244 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00245 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00246 "getting variable " // trim(name)) 00247 00248 end subroutine pmc_nc_read_real_2d 00249 00250 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00251 00252 !> Read a simple integer 2D array from a NetCDF file. 00253 subroutine pmc_nc_read_integer_2d(ncid, var, name, must_be_present) 00254 00255 !> NetCDF file ID, in data mode. 00256 integer, intent(in) :: ncid 00257 !> Data to read, must be correctly sized. 00258 integer, intent(out) :: var(:,:) 00259 !> Variable name in NetCDF file. 00260 character(len=*), intent(in) :: name 00261 !> Whether the variable must be present in the NetCDF file 00262 !> (default .true.). 00263 logical, optional, intent(in) :: must_be_present 00264 00265 integer :: varid, status 00266 logical :: use_must_be_present 00267 00268 if (present(must_be_present)) then 00269 use_must_be_present = must_be_present 00270 else 00271 use_must_be_present = .true. 00272 end if 00273 status = nf90_inq_varid(ncid, name, varid) 00274 if ((.not. use_must_be_present) .and. (status == NF90_ENOTVAR)) then 00275 ! variable was not present, but that's ok 00276 var = 0 00277 return 00278 end if 00279 call pmc_nc_check_msg(status, "inquiring variable " // trim(name)) 00280 call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), & 00281 "getting variable " // trim(name)) 00282 00283 end subroutine pmc_nc_read_integer_2d 00284 00285 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00286 00287 !> Write attributes for a variable to a NetCDF file. 00288 subroutine pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00289 description) 00290 00291 !> NetCDF file ID, in define mode. 00292 integer, intent(in) :: ncid 00293 !> Variable ID to write attributes for. 00294 integer, intent(in) :: varid 00295 !> Unit of variable. 00296 character(len=*), optional, intent(in) :: unit 00297 !> Long name of variable. 00298 character(len=*), optional, intent(in) :: long_name 00299 !> Standard name of variable. 00300 character(len=*), optional, intent(in) :: standard_name 00301 !> Description of variable. 00302 character(len=*), optional, intent(in) :: description 00303 00304 if (present(unit)) then 00305 call pmc_nc_check(nf90_put_att(ncid, varid, "unit", unit)) 00306 end if 00307 if (present(long_name)) then 00308 call pmc_nc_check(nf90_put_att(ncid, varid, "long_name", long_name)) 00309 end if 00310 if (present(standard_name)) then 00311 call pmc_nc_check(nf90_put_att(ncid, varid, "standard_name", & 00312 standard_name)) 00313 end if 00314 if (present(description)) then 00315 call pmc_nc_check(nf90_put_att(ncid, varid, "description", & 00316 description)) 00317 end if 00318 00319 end subroutine pmc_nc_write_atts 00320 00321 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00322 00323 !> Write a single real to a NetCDF file. 00324 subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, & 00325 standard_name, description) 00326 00327 !> NetCDF file ID, in data mode. 00328 integer, intent(in) :: ncid 00329 !> Data to write. 00330 real(kind=dp), intent(in) :: var 00331 !> Variable name in NetCDF file. 00332 character(len=*), intent(in) :: name 00333 !> Unit of variable. 00334 character(len=*), optional, intent(in) :: unit 00335 !> Long name of variable. 00336 character(len=*), optional, intent(in) :: long_name 00337 !> Standard name of variable. 00338 character(len=*), optional, intent(in) :: standard_name 00339 !> Description of variable. 00340 character(len=*), optional, intent(in) :: description 00341 00342 integer :: varid, dimids(0) 00343 00344 call pmc_nc_check(nf90_redef(ncid)) 00345 call pmc_nc_check(nf90_def_var(ncid, name, NF90_DOUBLE, dimids, varid)) 00346 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00347 description) 00348 call pmc_nc_check(nf90_enddef(ncid)) 00349 00350 call pmc_nc_check(nf90_put_var(ncid, varid, var)) 00351 00352 end subroutine pmc_nc_write_real 00353 00354 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00355 00356 !> Write a single integer to a NetCDF file. 00357 subroutine pmc_nc_write_integer(ncid, var, name, unit, long_name, & 00358 standard_name, description) 00359 00360 !> NetCDF file ID, in data mode. 00361 integer, intent(in) :: ncid 00362 !> Data to write. 00363 integer, intent(in) :: var 00364 !> Variable name in NetCDF file. 00365 character(len=*), intent(in) :: name 00366 !> Unit of variable. 00367 character(len=*), optional, intent(in) :: unit 00368 !> Long name of variable. 00369 character(len=*), optional, intent(in) :: long_name 00370 !> Standard name of variable. 00371 character(len=*), optional, intent(in) :: standard_name 00372 !> Description of variable. 00373 character(len=*), optional, intent(in) :: description 00374 00375 integer :: varid, dimids(0) 00376 00377 call pmc_nc_check(nf90_redef(ncid)) 00378 call pmc_nc_check(nf90_def_var(ncid, name, NF90_INT, dimids, varid)) 00379 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00380 description) 00381 call pmc_nc_check(nf90_enddef(ncid)) 00382 00383 call pmc_nc_check(nf90_put_var(ncid, varid, var)) 00384 00385 end subroutine pmc_nc_write_integer 00386 00387 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00388 00389 !> Write a simple real array to a NetCDF file. 00390 subroutine pmc_nc_write_real_1d(ncid, var, name, dimids, unit, long_name, & 00391 standard_name, description) 00392 00393 !> NetCDF file ID, in data mode. 00394 integer, intent(in) :: ncid 00395 !> Data to write. 00396 real(kind=dp), intent(in) :: var(:) 00397 !> Variable name in NetCDF file. 00398 character(len=*), intent(in) :: name 00399 !> NetCDF dimension IDs of the variable 00400 integer, intent(in) :: dimids(1) 00401 !> Unit of variable. 00402 character(len=*), optional, intent(in) :: unit 00403 !> Long name of variable. 00404 character(len=*), optional, intent(in) :: long_name 00405 !> Standard name of variable. 00406 character(len=*), optional, intent(in) :: standard_name 00407 !> Description of variable. 00408 character(len=*), optional, intent(in) :: description 00409 00410 integer :: varid, start(1), count(1) 00411 00412 call pmc_nc_check(nf90_redef(ncid)) 00413 call pmc_nc_check(nf90_def_var(ncid, name, NF90_DOUBLE, dimids, varid)) 00414 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00415 description) 00416 call pmc_nc_check(nf90_enddef(ncid)) 00417 00418 start = (/ 1 /) 00419 count = (/ size(var, 1) /) 00420 call pmc_nc_check(nf90_put_var(ncid, varid, var, & 00421 start = start, count = count)) 00422 00423 end subroutine pmc_nc_write_real_1d 00424 00425 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00426 00427 !> Write a simple integer array to a NetCDF file. 00428 subroutine pmc_nc_write_integer_1d(ncid, var, name, dimids, unit, & 00429 long_name, standard_name, description) 00430 00431 !> NetCDF file ID, in data mode. 00432 integer, intent(in) :: ncid 00433 !> Data to write. 00434 integer, intent(in) :: var(:) 00435 !> Variable name in NetCDF file. 00436 character(len=*), intent(in) :: name 00437 !> NetCDF dimension IDs of the variable 00438 integer, intent(in) :: dimids(1) 00439 !> Unit of variable. 00440 character(len=*), optional, intent(in) :: unit 00441 !> Long name of variable. 00442 character(len=*), optional, intent(in) :: long_name 00443 !> Standard name of variable. 00444 character(len=*), optional, intent(in) :: standard_name 00445 !> Description of variable. 00446 character(len=*), optional, intent(in) :: description 00447 00448 integer :: varid, start(1), count(1) 00449 00450 call pmc_nc_check(nf90_redef(ncid)) 00451 call pmc_nc_check(nf90_def_var(ncid, name, NF90_INT, dimids, varid)) 00452 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00453 description) 00454 call pmc_nc_check(nf90_enddef(ncid)) 00455 00456 start = (/ 1 /) 00457 count = (/ size(var, 1) /) 00458 call pmc_nc_check(nf90_put_var(ncid, varid, var, & 00459 start = start, count = count)) 00460 00461 end subroutine pmc_nc_write_integer_1d 00462 00463 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00464 00465 !> Write a simple real 2D array to a NetCDF file. 00466 subroutine pmc_nc_write_real_2d(ncid, var, name, dimids, unit, long_name, & 00467 standard_name, description) 00468 00469 !> NetCDF file ID, in data mode. 00470 integer, intent(in) :: ncid 00471 !> Data to write. 00472 real(kind=dp), intent(in) :: var(:,:) 00473 !> Variable name in NetCDF file. 00474 character(len=*), intent(in) :: name 00475 !> NetCDF dimension IDs of the variable 00476 integer, intent(in) :: dimids(2) 00477 !> Unit of variable. 00478 character(len=*), optional, intent(in) :: unit 00479 !> Long name of variable. 00480 character(len=*), optional, intent(in) :: long_name 00481 !> Standard name of variable. 00482 character(len=*), optional, intent(in) :: standard_name 00483 !> Description of variable. 00484 character(len=*), optional, intent(in) :: description 00485 00486 integer :: varid, start(2), count(2) 00487 00488 call pmc_nc_check(nf90_redef(ncid)) 00489 call pmc_nc_check(nf90_def_var(ncid, name, NF90_DOUBLE, dimids, varid)) 00490 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00491 description) 00492 call pmc_nc_check(nf90_enddef(ncid)) 00493 00494 start = (/ 1, 1 /) 00495 count = (/ size(var, 1), size(var, 2) /) 00496 call pmc_nc_check(nf90_put_var(ncid, varid, var, & 00497 start = start, count = count)) 00498 00499 end subroutine pmc_nc_write_real_2d 00500 00501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00502 00503 !> Write a simple integer 2D array to a NetCDF file. 00504 subroutine pmc_nc_write_integer_2d(ncid, var, name, dimids, unit, & 00505 long_name, standard_name, description) 00506 00507 !> NetCDF file ID, in data mode. 00508 integer, intent(in) :: ncid 00509 !> Data to write. 00510 integer, intent(in) :: var(:,:) 00511 !> Variable name in NetCDF file. 00512 character(len=*), intent(in) :: name 00513 !> NetCDF dimension IDs of the variable 00514 integer, intent(in) :: dimids(2) 00515 !> Unit of variable. 00516 character(len=*), optional, intent(in) :: unit 00517 !> Long name of variable. 00518 character(len=*), optional, intent(in) :: long_name 00519 !> Standard name of variable. 00520 character(len=*), optional, intent(in) :: standard_name 00521 !> Description of variable. 00522 character(len=*), optional, intent(in) :: description 00523 00524 integer :: varid, start(2), count(2) 00525 00526 call pmc_nc_check(nf90_redef(ncid)) 00527 call pmc_nc_check(nf90_def_var(ncid, name, NF90_INT, dimids, varid)) 00528 call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, & 00529 description) 00530 call pmc_nc_check(nf90_enddef(ncid)) 00531 00532 start = (/ 1, 1 /) 00533 count = (/ size(var, 1), size(var, 2) /) 00534 call pmc_nc_check(nf90_put_var(ncid, varid, var, & 00535 start = start, count = count)) 00536 00537 end subroutine pmc_nc_write_integer_2d 00538 00539 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00540 00541 end module pmc_netcdf