PartMC  2.2.1
netcdf.F90
Go to the documentation of this file.
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