diff --git a/CMakeLists.txt b/CMakeLists.txt index 86826add70..687f519a75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,6 +312,7 @@ foreach(kind ${kinds}) random_numbers/include diag_manager/include constants4 + topography/include axis_utils/include constants astronomy/include @@ -362,9 +363,10 @@ foreach(kind ${kinds}) $ $ $ + $ + $ $ $ - $ $ $) diff --git a/topography/Makefile.am b/topography/Makefile.am index cf5ea84cf0..14a2249b8c 100644 --- a/topography/Makefile.am +++ b/topography/Makefile.am @@ -23,7 +23,8 @@ # Ed Hartnett 2/22/19 # Include .h and .mod files. -AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/topography/include + AM_FCFLAGS = $(FC_MODINC). $(FC_MODOUT)$(MODDIR) # Build these uninstalled convenience libraries. @@ -31,10 +32,25 @@ noinst_LTLIBRARIES = libtopography.la # Each convenience library depends on its source. libtopography_la_SOURCES = \ - topography.F90 \ - gaussian_topog.F90 - -topography_mod.$(FC_MODEXT): gaussian_topog_mod.$(FC_MODEXT) + topography.F90 \ + include/topography_r4.fh \ + include/topography_r8.fh \ + include/topography.inc \ + gaussian_topog.F90 \ + include/gaussian_topog_r4.fh \ + include/gaussian_topog_r8.fh \ + include/gaussian_topog.inc + +gaussian_topog_mod.$(FC_MODEXT): \ + include/gaussian_topog_r4.fh \ + include/gaussian_topog_r8.fh \ + include/gaussian_topog.inc + +topography_mod.$(FC_MODEXT): \ + gaussian_topog_mod.$(FC_MODEXT) \ + include/topography_r4.fh \ + include/topography_r8.fh \ + include/topography.inc # Mod files are built and then installed as headers. MODFILES = \ diff --git a/topography/gaussian_topog.F90 b/topography/gaussian_topog.F90 index 65d9c66dba..be1d94917c 100644 --- a/topography/gaussian_topog.F90 +++ b/topography/gaussian_topog.F90 @@ -39,12 +39,22 @@ module gaussian_topog_mod use constants_mod, only: pi use mpp_mod, only: input_nml_file +use platform_mod, only: r4_kind, r8_kind implicit none private public :: gaussian_topog_init, get_gaussian_topog +interface gaussian_topog_init + module procedure gaussian_topog_init_r4 + module procedure gaussian_topog_init_r8 +end interface gaussian_topog_init + +interface get_gaussian_topog + module procedure get_gaussian_topog_r4, get_gaussian_topog_r8 +end interface get_gaussian_topog + !----------------------------------------------------------------------- ! ! @@ -71,13 +81,13 @@ module gaussian_topog_mod integer, parameter :: maxmts = 10 - real, dimension(maxmts) :: height = 0. - real, dimension(maxmts) :: olon = 0. - real, dimension(maxmts) :: olat = 0. - real, dimension(maxmts) :: wlon = 0. - real, dimension(maxmts) :: wlat = 0. - real, dimension(maxmts) :: rlon = 0. - real, dimension(maxmts) :: rlat = 0. + real(kind=r8_kind), dimension(maxmts) :: height = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: olon = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: olat = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: wlon = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: wlat = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: rlon = 0.0_r8_kind + real(kind=r8_kind), dimension(maxmts) :: rlat = 0.0_r8_kind namelist /gaussian_topog_nml/ height, olon, olat, wlon, wlat, rlon, rlat ! @@ -96,120 +106,6 @@ module gaussian_topog_mod !####################################################################### -!> Returns a surface height field that consists -!! of the sum of one or more Gaussian-shaped mountains. -!! -!> Returns a land surface topography that consists of a "set" of -!! simple Gaussian-shaped mountains. The height, position, -!! width, and elongation of the mountains can be controlled -!! by variables in the namelist. -subroutine gaussian_topog_init ( lon, lat, zsurf ) - -real, intent(in) :: lon(:) !< The mean grid box longitude in radians -real, intent(in) :: lat(:) !< The mean grid box latitude in radians -real, intent(out) :: zsurf(:,:) !< The surface height (meters). Size must be size(lon) by size(lat) - -integer :: n - - if (.not.module_is_initialized) then - call write_version_number("GAUSSIAN_TOPOG_MOD", version) - endif - - if(any(shape(zsurf) /= (/size(lon(:)),size(lat(:))/))) then - call error_mesg ('get_gaussian_topog in topography_mod', & - 'shape(zsurf) is not equal to (/size(lon),size(lat)/)', FATAL) - endif - - if (do_nml) call read_namelist - -! compute sum of all non-zero mountains - zsurf(:,:) = 0. - do n = 1, maxmts - if ( height(n) == 0. ) cycle - zsurf = zsurf + get_gaussian_topog ( lon, lat, height(n), & - olon(n), olat(n), wlon(n), wlat(n), rlon(n), rlat(n)) - enddo - module_is_initialized = .TRUE. - -end subroutine gaussian_topog_init - -!####################################################################### - -!> @brief Returns a simple surface height field that consists of a single -!! Gaussian-shaped mountain. -!! -!> The height, position, width, and elongation of the mountain -!! is controlled by optional arguments. -!! @param real lon The mean grid box longitude in radians. -!! @param real lat The mean grid box latitude in radians. -!! @param real height Maximum surface height in meters. -!! @param real olond, olatd Position/origin of mountain in degrees longitude and latitude. -!! This is the location of the maximum height. -!! @param real wlond, wlatd Gaussian half-width of mountain in degrees longitude and latitude. -!! @param real rlond, rlatd Ridge half-width of mountain in degrees longitude and latitude. -!! This is the elongation of the maximum height. -!! @param real zsurf The surface height (in meters). -!! The size of the returned field is size(lon) by size(lat). -!! -!! -!! @throws FATAL shape(zsurf) is not equal to (/size(lon),size(lat)/) -!! Check the input grid size and output field size. -!! The input grid is defined at the midpoint of grid boxes. -!! -!! @note -!! Mountains do not wrap around the poles. -! -!!
Example usage: -!! @code{.F90} zsurf = get_gaussian_topog ( lon, lat, height -!! [, olond, olatd, wlond, wlatd, rlond, rlatd ] )@endcode -function get_gaussian_topog ( lon, lat, height, & - olond, olatd, wlond, wlatd, rlond, rlatd ) & - result ( zsurf ) - -real, intent(in) :: lon(:), lat(:) -real, intent(in) :: height -real, intent(in), optional :: olond, olatd, wlond, wlatd, rlond, rlatd -real :: zsurf(size(lon,1),size(lat,1)) - -integer :: i, j -real :: olon, olat, wlon, wlat, rlon, rlat -real :: tpi, dtr, dx, dy, xx, yy - - if (do_nml) call read_namelist - -! no need to compute mountain if height=0 - if ( height == 0. ) then - zsurf(:,:) = 0. - return - endif - - tpi = 2.0*pi - dtr = tpi/360. - -! defaults and convert degrees to radians (dtr) - olon = 90.*dtr; if (present(olond)) olon=olond*dtr - olat = 45.*dtr; if (present(olatd)) olat=olatd*dtr - wlon = 15.*dtr; if (present(wlond)) wlon=wlond*dtr - wlat = 15.*dtr; if (present(wlatd)) wlat=wlatd*dtr - rlon = 0. ; if (present(rlond)) rlon=rlond*dtr - rlat = 0. ; if (present(rlatd)) rlat=rlatd*dtr - -! compute gaussian-shaped mountain - do j=1,size(lat(:)) - dy = abs(lat(j) - olat) ! dist from y origin - yy = max(0., dy-rlat)/wlat - do i=1,size(lon(:)) - dx = abs(lon(i) - olon) ! dist from x origin - dx = min(dx, abs(dx-tpi)) ! To ensure that: -pi <= dx <= pi - xx = max(0., dx-rlon)/wlon - zsurf(i,j) = height*exp(-xx**2 - yy**2) - enddo - enddo - -end function get_gaussian_topog - -!####################################################################### - subroutine read_namelist integer :: unit, ierr, io @@ -232,6 +128,9 @@ end subroutine read_namelist !####################################################################### +#include "gaussian_topog_r4.fh" +#include "gaussian_topog_r8.fh" + end module gaussian_topog_mod ! diff --git a/topography/include/gaussian_topog.inc b/topography/include/gaussian_topog.inc index 65d9c66dba..1a39983ca8 100644 --- a/topography/include/gaussian_topog.inc +++ b/topography/include/gaussian_topog.inc @@ -29,87 +29,22 @@ !> @addtogroup gaussian_topog_mod !> @{ -module gaussian_topog_mod - -use fms_mod, only: check_nml_error, & - stdlog, write_version_number, & - mpp_pe, mpp_root_pe, & - error_mesg, FATAL - -use constants_mod, only: pi - -use mpp_mod, only: input_nml_file - -implicit none -private - -public :: gaussian_topog_init, get_gaussian_topog - -!----------------------------------------------------------------------- -! -! -! Height in meters of the Gaussian mountains. -! -! -! The longitude and latitude of mountain origins (in degrees). -! -! -! The longitude and latitude half-width of mountain tails (in degrees). -! -! -! The longitude and latitude half-width of mountain ridges (in degrees). For a -! "standard" Gaussian mountain set rlon=rlat=0. -! -! -! -! The variables in this namelist are only used when routine -! gaussian_topog_init is called. The namelist variables -! are dimensioned (by 10), so that multiple mountains can be generated. -! -! Internal parameter mxmtns = 10. By default no mountains are generated. -! - - integer, parameter :: maxmts = 10 - - real, dimension(maxmts) :: height = 0. - real, dimension(maxmts) :: olon = 0. - real, dimension(maxmts) :: olat = 0. - real, dimension(maxmts) :: wlon = 0. - real, dimension(maxmts) :: wlat = 0. - real, dimension(maxmts) :: rlon = 0. - real, dimension(maxmts) :: rlat = 0. - - namelist /gaussian_topog_nml/ height, olon, olat, wlon, wlat, rlon, rlat -! - -!----------------------------------------------------------------------- - -! Include variable "version" to be written to log file. -#include - -logical :: do_nml = .true. -logical :: module_is_initialized = .FALSE. - -!----------------------------------------------------------------------- - -contains !####################################################################### - +!> @brief Returns a simple surface height field that consists of a single +!! Gaussian-shaped mountain. +!! !> Returns a surface height field that consists !! of the sum of one or more Gaussian-shaped mountains. !! -!> Returns a land surface topography that consists of a "set" of -!! simple Gaussian-shaped mountains. The height, position, -!! width, and elongation of the mountains can be controlled -!! by variables in the namelist. -subroutine gaussian_topog_init ( lon, lat, zsurf ) +subroutine GAUSSIAN_TOPOG_INIT_ ( lon, lat, zsurf ) -real, intent(in) :: lon(:) !< The mean grid box longitude in radians -real, intent(in) :: lat(:) !< The mean grid box latitude in radians -real, intent(out) :: zsurf(:,:) !< The surface height (meters). Size must be size(lon) by size(lat) +real(kind=FMS_TOP_KIND_), intent(in) :: lon(:) !< The mean grid box longitude in radians +real(kind=FMS_TOP_KIND_), intent(in) :: lat(:) !< The mean grid box latitude in radians +real(kind=FMS_TOP_KIND_), intent(out) :: zsurf(:,:) !< The surface height (meters). Size must be size(lon) by size(lat) integer :: n +integer, parameter :: lkind=FMS_TOP_KIND_ !local FMS_TOP_KIND_ kind if (.not.module_is_initialized) then call write_version_number("GAUSSIAN_TOPOG_MOD", version) @@ -123,21 +58,17 @@ integer :: n if (do_nml) call read_namelist ! compute sum of all non-zero mountains - zsurf(:,:) = 0. + zsurf(:,:) = 0.0_lkind do n = 1, maxmts - if ( height(n) == 0. ) cycle - zsurf = zsurf + get_gaussian_topog ( lon, lat, height(n), & - olon(n), olat(n), wlon(n), wlat(n), rlon(n), rlat(n)) + if ( height(n) == 0.0_r8_kind ) cycle + zsurf = zsurf + get_gaussian_topog ( lon, lat, real(height(n),lkind), & + real(olon(n),lkind), real(olat(n),lkind), real(wlon(n),lkind), & + real(wlat(n),lkind), real(rlon(n),lkind), real(rlat(n),lkind)) enddo module_is_initialized = .TRUE. -end subroutine gaussian_topog_init - +end subroutine GAUSSIAN_TOPOG_INIT_ !####################################################################### - -!> @brief Returns a simple surface height field that consists of a single -!! Gaussian-shaped mountain. -!! !> The height, position, width, and elongation of the mountain !! is controlled by optional arguments. !! @param real lon The mean grid box longitude in radians. @@ -162,112 +93,56 @@ end subroutine gaussian_topog_init !!
Example usage: !! @code{.F90} zsurf = get_gaussian_topog ( lon, lat, height !! [, olond, olatd, wlond, wlatd, rlond, rlatd ] )@endcode -function get_gaussian_topog ( lon, lat, height, & - olond, olatd, wlond, wlatd, rlond, rlatd ) & - result ( zsurf ) +!> Returns a land surface topography that consists of a "set" of +!! simple Gaussian-shaped mountains. The height, position, +!! width, and elongation of the mountains can be controlled +!! by variables in the namelist. +function GET_GAUSSIAN_TOPOG_(lon, lat, height, & + olond, olatd, wlond, wlatd, rlond, rlatd ) & + result (zsurf ) -real, intent(in) :: lon(:), lat(:) -real, intent(in) :: height -real, intent(in), optional :: olond, olatd, wlond, wlatd, rlond, rlatd -real :: zsurf(size(lon,1),size(lat,1)) +real(kind=FMS_TOP_KIND_), intent(in) :: lon(:), lat(:) +real(kind=FMS_TOP_KIND_), intent(in) :: height +real(kind=FMS_TOP_KIND_), intent(in), optional :: olond, olatd, wlond, wlatd, rlond, rlatd +real(kind=FMS_TOP_KIND_) :: zsurf(size(lon,1),size(lat,1)) integer :: i, j -real :: olon, olat, wlon, wlat, rlon, rlat -real :: tpi, dtr, dx, dy, xx, yy +real(kind=FMS_TOP_KIND_) :: olon, olat, wlon, wlat, rlon, rlat +real(kind=FMS_TOP_KIND_) :: tpi, dtr, dx, dy, xx, yy +integer, parameter :: lkind = FMS_TOP_KIND_ if (do_nml) call read_namelist ! no need to compute mountain if height=0 - if ( height == 0. ) then - zsurf(:,:) = 0. + if ( height == 0.0_lkind) then + zsurf(:,:) = 0.0_lkind return endif - tpi = 2.0*pi - dtr = tpi/360. + tpi = 2.0_lkind*real(pi, FMS_TOP_KIND_) + dtr = tpi/360.0_lkind ! defaults and convert degrees to radians (dtr) - olon = 90.*dtr; if (present(olond)) olon=olond*dtr - olat = 45.*dtr; if (present(olatd)) olat=olatd*dtr - wlon = 15.*dtr; if (present(wlond)) wlon=wlond*dtr - wlat = 15.*dtr; if (present(wlatd)) wlat=wlatd*dtr - rlon = 0. ; if (present(rlond)) rlon=rlond*dtr - rlat = 0. ; if (present(rlatd)) rlat=rlatd*dtr + olon = 90.0_r8_kind*real(dtr, r8_kind); if (present(olond)) olon=real(olond*dtr,r8_kind) + olat = 45.0_r8_kind*real(dtr, r8_kind); if (present(olatd)) olat=real(olatd*dtr,r8_kind) + wlon = 15.0_r8_kind*real(dtr, r8_kind); if (present(wlond)) wlon=real(wlond*dtr,r8_kind) + wlat = 15.0_r8_kind*real(dtr, r8_kind); if (present(wlatd)) wlat=real(wlatd*dtr,r8_kind) + rlon = 0.0_r8_kind ; if (present(rlond)) rlon=real(rlond*dtr,r8_kind) + rlat = 0.0_r8_kind ; if (present(rlatd)) rlat=real(rlatd*dtr,r8_kind) ! compute gaussian-shaped mountain do j=1,size(lat(:)) - dy = abs(lat(j) - olat) ! dist from y origin - yy = max(0., dy-rlat)/wlat + dy = abs(lat(j) - real(olat,lkind)) ! dist from y origin + yy = max(0.0_lkind, dy-real(rlat,lkind))/real(wlat,lkind) do i=1,size(lon(:)) - dx = abs(lon(i) - olon) ! dist from x origin + dx = abs(lon(i) - real(olon,lkind)) ! dist from x origin dx = min(dx, abs(dx-tpi)) ! To ensure that: -pi <= dx <= pi - xx = max(0., dx-rlon)/wlon - zsurf(i,j) = height*exp(-xx**2 - yy**2) + xx = max(0.0_lkind, dx-real(rlon,lkind))/real(wlon,lkind) + zsurf(i,j) = real(height,lkind)*exp(-xx**2 - yy**2) enddo enddo -end function get_gaussian_topog - -!####################################################################### - -subroutine read_namelist - - integer :: unit, ierr, io - -!> read namelist - - read (input_nml_file, gaussian_topog_nml, iostat=io) - ierr = check_nml_error(io,'gaussian_topog_nml') - -!> write version and namelist to log file - - if (mpp_pe() == mpp_root_pe()) then - unit = stdlog() - write (unit, nml=gaussian_topog_nml) - endif +end function GET_GAUSSIAN_TOPOG_ - do_nml = .false. - -end subroutine read_namelist - -!####################################################################### - -end module gaussian_topog_mod - -! -! -! NAMELIST FOR GENERATING GAUSSIAN MOUNTAINS -! -! * multiple mountains can be generated -! * the final mountains are the sum of all -! -! height = height in meters -! olon, olat = longitude,latitude origin (degrees) -! rlon, rlat = longitude,latitude half-width of ridge (degrees) -! wlon, wlat = longitude,latitude half-width of tail (degrees) -! -! Note: For the standard gaussian mountain -! set rlon = rlat = 0 . -! -!
-!
-!       height -->   ___________________________
-!                   /                           \
-!                  /              |              \
-!    gaussian     /               |               \
-!      sides --> /                |                \
-!               /               olon                \
-!         _____/                olat                 \______
-!
-!              |    |             |
-!              |<-->|<----------->|
-!              |wlon|    rlon     |
-!               wlat     rlat
-!
-! 
-! -!See the topography module documentation for a test program. -!
-!
!> @} ! close documentation grouping diff --git a/topography/include/gaussian_topog_r4.fh b/topography/include/gaussian_topog_r4.fh new file mode 100644 index 0000000000..54b38b093b --- /dev/null +++ b/topography/include/gaussian_topog_r4.fh @@ -0,0 +1,44 @@ +!*********************************************************************** +!* GNU Lesser General Public License +!* +!* This file is part of the GFDL Flexible Modeling System (FMS). +!* +!* FMS is free software: you can redistribute it and/or modify it under +!* the terms of the GNU Lesser General Public License as published by +!* the Free Software Foundation, either version 3 of the License, or (at +!* your option) any later version. +!* +!* FMS is distributed in the hope that it will be useful, but WITHOUT +!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +!* for more details. +!* +!* You should have received a copy of the GNU Lesser General Public +!* License along with FMS. If not, see . +!*********************************************************************** +!> @defgroup gaussian_topog_mod gaussian_topog_mod +!> @ingroup topography +!> @brief Routines for creating Gaussian-shaped land surface topography +!! for latitude-longitude grids. +!> @author Bruce Wyman +!! +!! Interfaces generate simple Gaussian-shaped mountains from +!! parameters specified by either argument list or namelist input. +!! The mountain shapes are controlled by the height, half-width, +!! and ridge-width parameters. + +!> @addtogroup gaussian_topog_mod +!> @{ + +#undef FMS_TOP_KIND_ +#define FMS_TOP_KIND_ r4_kind + +#undef GAUSSIAN_TOPOG_INIT_ +#define GAUSSIAN_TOPOG_INIT_ gaussian_topog_init_r4 + +#undef GET_GAUSSIAN_TOPOG_ +#define GET_GAUSSIAN_TOPOG_ get_gaussian_topog_r4 + +#include "gaussian_topog.inc" +!> @} +! close documentation grouping diff --git a/topography/include/gaussian_topog_r8.fh b/topography/include/gaussian_topog_r8.fh new file mode 100644 index 0000000000..5e4d423bd0 --- /dev/null +++ b/topography/include/gaussian_topog_r8.fh @@ -0,0 +1,43 @@ +!*********************************************************************** +!* GNU Lesser General Public License +!* +!* This file is part of the GFDL Flexible Modeling System (FMS). +!* +!* FMS is free software: you can redistribute it and/or modify it under +!* the terms of the GNU Lesser General Public License as published by +!* the Free Software Foundation, either version 3 of the License, or (at +!* your option) any later version. +!* +!* FMS is distributed in the hope that it will be useful, but WITHOUT +!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +!* for more details. +!* +!* You should have received a copy of the GNU Lesser General Public +!* License along with FMS. If not, see . +!*********************************************************************** +!> @defgroup gaussian_topog_mod gaussian_topog_mod +!> @ingroup topography +!> @brief Routines for creating Gaussian-shaped land surface topography +!! for latitude-longitude grids. +!> @author Bruce Wyman +!! +!! Interfaces generate simple Gaussian-shaped mountains from +!! parameters specified by either argument list or namelist input. +!! The mountain shapes are controlled by the height, half-width, +!! and ridge-width parameters. + +!> @addtogroup gaussian_topog_mod +!> @{ +#undef FMS_TOP_KIND_ +#define FMS_TOP_KIND_ r8_kind + +#undef GAUSSIAN_TOPOG_INIT_ +#define GAUSSIAN_TOPOG_INIT_ gaussian_topog_init_r8 + +#undef GET_GAUSSIAN_TOPOG_ +#define GET_GAUSSIAN_TOPOG_ get_gaussian_topog_r8 + +#include "gaussian_topog.inc" +!> @} +! close documentation grouping diff --git a/topography/include/topography.inc b/topography/include/topography.inc index 1cfe0ec7fb..0f2cffbdc2 100644 --- a/topography/include/topography.inc +++ b/topography/include/topography.inc @@ -35,223 +35,6 @@ !! The interfaces get_gaussian_topog and gaussian_topog_init are documented !! in @ref gaussian_topog_mod -module topography_mod - -use gaussian_topog_mod, only: gaussian_topog_init, get_gaussian_topog -use horiz_interp_mod, only: horiz_interp_type, horiz_interp_new, & - horiz_interp, horiz_interp_del - -use fms_mod, only: check_nml_error, stdlog, & - mpp_pe, mpp_root_pe, write_version_number, & - error_mesg, FATAL, NOTE, & - mpp_error -! required for fms2_io -use fms2_io_mod, only: read_data, FmsNetcdfFile_t, file_exists, open_file -!----------------------------------------------------------------------- - -use constants_mod, only: PI -use mpp_mod, only: input_nml_file - -implicit none -private - -public :: topography_init, & - get_topog_mean, get_topog_stdev, & - get_ocean_frac, get_ocean_mask, & - get_water_frac, get_water_mask, & - gaussian_topog_init, get_gaussian_topog - -!> @brief Returns a "realistic" mean surface height field. -!! -!> Returns realistic mountains on a latitude-longtude grid. -!! The returned field is the mean topography for the given grid boxes. -!! Computed using a conserving area-weighted interpolation. -!! The current input data set is the 1/6 degree Navy mean topography. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param zmean The mean surface height (meters). The size of this -!! field must be size(blon)-1 by size(blat)-1. -!! @return A logical value of TRUE is returned if the surface height field -!! was successfully created. A value of FALSE may be returned if the -!! input topography data set was not readable. -!! -!!
Example usage: -!! @code{.F90} flag = get_topog_mean ( blon, blat, zmean )@endcode -!> @ingroup topography_mod -interface get_topog_mean - module procedure get_topog_mean_1d, get_topog_mean_2d -end interface - -!> Returns a standard deviation of higher resolution topography with -!! the given model grid boxes. -!! -!> Returns the standard deviation of the "finer" input topography data set, -!! currently the Navy 1/6 degree mean topography data, within the -!! boundaries of the given input grid. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param [out] stdev The standard deviation of surface height (in meters) within -!! given input model grid boxes. -!! The size of this field must be size(blon)-1 by size(blat)-1. -!! -!! @return A logical value of TRUE is returned if the output field was -!! successfully created. A value of FALSE may be returned if the -!! input topography data set was not readable. -!! -!! Example usage: -!! @code{.F90} flag = get_topog_stdev( blon, blat, stdev ) @code -!> @ingroup topography_mod -interface get_topog_stdev - module procedure get_topog_stdev_1d, get_topog_stdev_2d -end interface - -!> @brief Returns fractional area covered by ocean in a grid box. -!! Returns fractional area covered by ocean in the given model grid boxes. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param ocean_frac The fractional amount (0 to 1) of ocean in a grid box. -!! The size of this field must be size(blon)-1 by size(blat)-1. -!! -!! @return A logical value of TRUE is returned if the output field -!! was successfully created. A value of FALSE may be returned -!! if the Navy 1/6 degree percent water data set was not readable. -!! -!! Example usage: -!! @code{.F90} flag = get_ocean_frac ( blon, blat, ocean_frac ) @endcode -!> @ingroup topography_mod -interface get_ocean_frac - module procedure get_ocean_frac_1d, get_ocean_frac_2d -end interface - -!> @brief Returns a land-ocean mask in a grid box. -!! -!> Returns a land-ocean mask in the given model grid boxes. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param ocean_frac The fractional amount (0 to 1) of ocean in a grid box. -!! The size of this field must be size(blon)-1 by size(blat)-1. -!! -!! @return A logical value of TRUE is returned if the output field -!! was successfully created. A value of FALSE may be returned -!! if the Navy 1/6 degree percent water data set was not readable. -!! -!! Example code: -!! @code{.F90} flag = get_ocean_mask( blon, blat, ocean_mask ) @endcode -!> @ingroup topography_mod -interface get_ocean_mask - module procedure get_ocean_mask_1d, get_ocean_mask_2d -end interface - -!> @brief Returns fractional area covered by water. -!! -!> Returns the percent of water in a grid box. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param [out] water_frac The fractional amount (0 to 1) of water in a grid box. -!! The size of this field must be size(blon)-1 by size(blat)-1. -!! -!! @return A logical value of TRUE is returned if the output field -!! was successfully created. A value of FALSE may be returned -!! if the Navy 1/6 degree percent water data set was not readable. -!! -!!
Example usage:
@code{.F90} flag = get_water_frac ( blon, blat, water_frac ) @endcode -!> @ingroup topography_mod -interface get_water_frac - module procedure get_water_frac_1d, get_water_frac_2d -end interface - -!> @brief Returns a land-water mask in a grid box. -!! -!> Returns a land-water mask in the given model grid boxes. -!! -!! @param blon The longitude (in radians) at grid box boundaries. -!! @param blat The latitude (in radians) at grid box boundaries. -!! @param water_mask A binary mask for water (true) or land (false). -!! The size of this field must be size(blon)-1 by size(blat)-1. -!! -!! @return A logical value of TRUE is returned if the output field -!! was successfully created. A value of FALSE may be returned -!! if the Navy 1/6 degree percent water data set was not readable. -!! -!! Example usage: @code{.F90}flag = get_water_mask( blon, blat, water_mask ) @endcode -!> @ingroup topography_mod -interface get_water_mask - module procedure get_water_mask_1d, get_water_mask_2d -end interface - -!> @addtogroup topography_mod -!> @{ - - logical :: use_mpp_io=.false.!>@var deprecated namelist variable for using mpp_io in this module - character(len=128) :: topog_file = 'DATA/navy_topography.data', & - water_file = 'DATA/navy_pctwater.data' - namelist /topography_nml/ topog_file, water_file, use_mpp_io - - integer, parameter :: TOPOG_INDEX = 1 - integer, parameter :: WATER_INDEX = 2 - logical :: file_is_opened(2) = .false. - type(FmsNetcdfFile_t) :: fileobj(2) !< needed for fms2_io - -!----------------------------------------------------------------------- -! --- resolution of the topography data set --- -! -! This module uses the 1/6 degree U.S. Navy mean topography -! and percent water data sets. -! -! These data sets have been re-formatted to separate 32-bit IEEE files. -! The names of these files is specified by the namelist input. -! -!The format for both files is as follows: -!
-!     record = 1    nlon, nlat
-!     record = 2    blon, blat
-!     record = 3    data
-! 
-!where: -!
-!     nlon, nlat = The number of longitude and latitude points
-!                  in the horizontal grid.  For the 1/6 degree
-!                  data sets this is 2160 x 1080. [integer]
-!     blon, blat = The longitude and latitude grid box boundaries in degrees.
-!                     [real :: blon(nlon+1), blat(nlat+1)]
-!
-!     data       = The topography or percent water data.
-!                    [real :: data(nlon,nlat)]
-! 
-!
- integer :: ipts, jpts - integer, parameter :: COMPUTE_STDEV = 123 ! use this flag to - ! compute st dev - -!----------------------------------------------------------------------- - -! Include variable "version" to be written to log file. -#include - - logical :: module_is_initialized = .FALSE. - -!----------------------------------------------------------------------- - - contains - -!####################################################################### - - subroutine topography_init () - if ( module_is_initialized ) return - call write_version_number("TOPOGRAPHY_MOD", version) - call read_namelist - module_is_initialized = .TRUE. - if (use_mpp_io) then - call mpp_error('topography_mod', & - 'MPP_IO is no longer supported. Please remove use_mpp_io from topography_nml', FATAL) - endif - end subroutine topography_init - !####################################################################### !> @brief Returns a "realistic" mean surface height field. @@ -266,13 +49,15 @@ end interface !! !! @throws FATAL, shape(zmean) is not equal to (/size(blon)-1,size(blat)-1/) !! Check the input grid size and output field size. - function get_topog_mean_1d(blon, blat, zmean) - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: zmean !< Mean surface height(meters). Size must be + function GET_TOPOG_MEAN_1D_(blon, blat, zmean) + + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: zmean !< Mean surface height(meters). Size must be !! size(blon)-1 by size(blat)-1 - logical :: get_topog_mean_1d + logical :: GET_TOPOG_MEAN_1D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -281,21 +66,22 @@ end interface call error_mesg('get_topog_mean_1d','shape(zmean) is not& & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - get_topog_mean_1d = open_topog_file() + GET_TOPOG_MEAN_1D_ = open_topog_file() - if ( get_topog_mean_1d ) call interp_topog_1d ( blon, blat, zmean) + if (GET_TOPOG_MEAN_1D_) call interp_topog(blon, blat, zmean) !----------------------------------------------------------------------- - end function get_topog_mean_1d + end function GET_TOPOG_MEAN_1D_ !############################################################ - function get_topog_mean_2d (blon, blat, zmean) + function GET_TOPOG_MEAN_2D_(blon, blat, zmean) - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: zmean - logical :: get_topog_mean_2d + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon, blat + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: zmean + logical :: GET_TOPOG_MEAN_2D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -304,12 +90,12 @@ end interface call error_mesg('get_topog_mean_2d','shape(zmean) is not& & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - get_topog_mean_2d = open_topog_file() + GET_TOPOG_MEAN_2D_ = open_topog_file() - if ( get_topog_mean_2d ) call interp_topog_2d ( blon, blat, zmean) + if (GET_TOPOG_MEAN_2D_) call interp_topog(blon, blat, zmean) !----------------------------------------------------------------------- - end function get_topog_mean_2d + end function GET_TOPOG_MEAN_2D_ !####################################################################### @@ -322,14 +108,15 @@ end interface !! !! @returns A logical value of true if the output field was successfully created and false !! if the input topography data set was not readable. - function get_topog_stdev_1d (blon, blat, stdev) + function GET_TOPOG_STDEV_1D_(blon, blat, stdev) - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: stdev !< The standard deviation of surface height (in + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: stdev !< The standard deviation of surface height (in !! meters) within given input model grid boxes. Size must be !! size(blon)-1 by size(blat)-1 - logical :: get_topog_stdev_1d + logical :: GET_TOPOG_STDEV_1D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -337,22 +124,23 @@ end interface call error_mesg('get_topog_stdev','shape(stdev) is not& & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - get_topog_stdev_1d = open_topog_file() + GET_TOPOG_STDEV_1D_ = open_topog_file() - if ( get_topog_stdev_1d ) call interp_topog_1d ( blon, blat, & + if (GET_TOPOG_STDEV_1D_) call interp_topog(blon, blat, & stdev, flag=COMPUTE_STDEV) !----------------------------------------------------------------------- - end function get_topog_stdev_1d + end function GET_TOPOG_STDEV_1D_ !####################################################################### - function get_topog_stdev_2d (blon, blat, stdev) + function GET_TOPOG_STDEV_2D_(blon, blat, stdev) - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: stdev - logical :: get_topog_stdev_2d + real(FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon, blat + real(FMS_TOP_KIND_), intent(out), dimension(:,:) :: stdev + logical :: GET_TOPOG_STDEV_2D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -361,26 +149,27 @@ end interface call error_mesg('get_topog_stdev_2d','shape(stdev) is not& & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - get_topog_stdev_2d = open_topog_file() + GET_TOPOG_STDEV_2D_ = open_topog_file() - if ( get_topog_stdev_2d ) call interp_topog_2d ( blon, blat, & + if (GET_TOPOG_STDEV_2D_) call interp_topog(blon, blat, & stdev, flag=COMPUTE_STDEV) !----------------------------------------------------------------------- - end function get_topog_stdev_2d + end function GET_TOPOG_STDEV_2D_ !####################################################################### !> @brief Returns fractional area covered by ocean in a grid box. !> @returns A logical value of true if the output field was successfully created. A value of false !! may be returned if the Navy 1/6 degree percent water data set was not readable. - function get_ocean_frac_1d (blon, blat, ocean_frac) + function GET_OCEAN_FRAC_1D_(blon, blat, ocean_frac) - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: ocean_frac !< The fractional amount (0-1) of ocean in a grid + real(FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries + real(FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries + real(FMS_TOP_KIND_), intent(out), dimension(:,:) :: ocean_frac !< The fractional amount (0-1) of ocean in a grid !! box. The size must be size(blon)-1 by size(blat)-1 - logical :: get_ocean_frac_1d + logical :: GET_OCEAN_FRAC_1D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -388,21 +177,22 @@ end interface call error_mesg('get_ocean_frac','shape(ocean_frac) is not& & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - get_ocean_frac_1d = open_water_file() - if( get_ocean_frac_1d ) call interp_water_1d ( blon, blat, & + GET_OCEAN_FRAC_1D_ = open_water_file() + if(GET_OCEAN_FRAC_1D_) call interp_water( blon, blat, & ocean_frac, do_ocean=.true. ) !----------------------------------------------------------------------- - end function get_ocean_frac_1d + end function GET_OCEAN_FRAC_1D_ !####################################################################### - function get_ocean_frac_2d (blon, blat, ocean_frac) + function GET_OCEAN_FRAC_2D_(blon, blat, ocean_frac) - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: ocean_frac - logical :: get_ocean_frac_2d + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon, blat + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: ocean_frac + logical :: GET_OCEAN_FRAC_2D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -411,69 +201,71 @@ end interface call error_mesg('get_ocean_frac_2d','shape(ocean_frac) is not& & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - get_ocean_frac_2d = open_water_file() - if( get_ocean_frac_2d ) call interp_water_2d ( blon, blat, & + GET_OCEAN_FRAC_2D_ = open_water_file() + if(GET_OCEAN_FRAC_2D_) call interp_water( blon, blat, & ocean_frac, do_ocean=.true. ) !----------------------------------------------------------------------- - end function get_ocean_frac_2d + end function GET_OCEAN_FRAC_2D_ !####################################################################### !> @brief Returns a land-ocean mask in a grid box. !> @returns A logical value of true if the output field was successfully created. A value of false !! may be returned if the Navy 1/6 degree percent water data set was not readable. - function get_ocean_mask_1d (blon, blat, ocean_mask) + function GET_OCEAN_MASK_1D_(blon, blat, ocean_mask) - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries logical, intent(out), dimension(:,:) :: ocean_mask !< Mask for ocean in a grid box. !! The size must be size(blon)-1 by size(blat)-1 - logical :: get_ocean_mask_1d - real, dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac + logical :: GET_OCEAN_MASK_1D_ + real(kind=FMS_TOP_KIND_), dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() - if ( get_ocean_frac_1d(blon, blat, ocean_frac) ) then - where (ocean_frac > 0.50) + if (get_ocean_frac(blon, blat, ocean_frac) ) then + where (ocean_frac > 0.50_lkind) ocean_mask = .true. elsewhere ocean_mask = .false. end where - get_ocean_mask_1d = .true. + GET_OCEAN_MASK_1D_ = .true. else - get_ocean_mask_1d = .false. + GET_OCEAN_MASK_1D_ = .false. endif !----------------------------------------------------------------------- - end function get_ocean_mask_1d + end function GET_OCEAN_MASK_1D_ !####################################################################### - function get_ocean_mask_2d (blon, blat, ocean_mask) + function GET_OCEAN_MASK_2D_(blon, blat, ocean_mask) - real , intent(in), dimension(:,:) :: blon, blat + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon, blat logical, intent(out), dimension(:,:) :: ocean_mask - logical :: get_ocean_mask_2d - real, dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac + logical :: GET_OCEAN_MASK_2D_ + real(kind=FMS_TOP_KIND_), dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() - if ( get_ocean_frac_2d(blon, blat, ocean_frac) ) then - where (ocean_frac > 0.50) + if (get_ocean_frac(blon, blat, ocean_frac) ) then + where (ocean_frac > 0.50_lkind) ocean_mask = .true. elsewhere ocean_mask = .false. end where - get_ocean_mask_2d = .true. + GET_OCEAN_MASK_2D_ = .true. else - get_ocean_mask_2d = .false. + GET_OCEAN_MASK_2D_ = .false. endif !----------------------------------------------------------------------- - end function get_ocean_mask_2d + end function GET_OCEAN_MASK_2D_ !> @brief Returns the percent of water in a grid box. !> @returns A logical value of true if the output field was successfully created. A value of false @@ -481,12 +273,13 @@ end interface !! !! @throws FATAL, shape(water_frac) is not equal to (/size(blon)-1,size(blat)-1/) !! Check the input grid size and output field size. - function get_water_frac_1d (blon, blat, water_frac) - real, intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. - real, intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a + function GET_WATER_FRAC_1D_(blon, blat, water_frac) + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a !! grid box. The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_frac_1d + logical :: GET_WATER_FRAC_1D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -495,22 +288,23 @@ end interface call error_mesg('get_water_frac_1d','shape(water_frac) is not& & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - get_water_frac_1d = open_water_file() - if(get_water_frac_1d) call interp_water_1d ( blon, blat, water_frac ) + GET_WATER_FRAC_1D_ = open_water_file() + if(GET_WATER_FRAC_1D_) call interp_water( blon, blat, water_frac ) !----------------------------------------------------------------------- - end function get_water_frac_1d + end function GET_WATER_FRAC_1D_ !####################################################################### - function get_water_frac_2d (blon, blat, water_frac) + function GET_WATER_FRAC_2D_(blon, blat, water_frac) - real, intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. - real, intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a !! grid box. The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_frac_2d + logical :: GET_WATER_FRAC_2D_ + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() @@ -520,12 +314,12 @@ end interface call error_mesg('get_water_frac_2d','shape(water_frac) is not& & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - get_water_frac_2d = open_water_file() - if(get_water_frac_2d) call interp_water_2d ( blon, blat, water_frac ) + GET_WATER_FRAC_2D_ = open_water_file() + if(GET_WATER_FRAC_2D_) call interp_water( blon, blat, water_frac ) !----------------------------------------------------------------------- - end function get_water_frac_2d + end function GET_WATER_FRAC_2D_ !####################################################################### @@ -533,166 +327,111 @@ end interface !> @return A logical value of TRUE is returned if the output field !! was successfully created. A value of FALSE may be returned !! if the Navy 1/6 degree percent water data set was not readable. - function get_water_mask_1d (blon, blat, water_mask) + function GET_WATER_MASK_1D_(blon, blat, water_mask) - real, intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. logical, intent(out), dimension(:,:) :: water_mask !< A binary mask for water (true) or land (false). !! The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_mask_1d + logical :: GET_WATER_MASK_1D_ - real, dimension(size(water_mask,1),size(water_mask,2)) :: water_frac + real(kind=FMS_TOP_KIND_), dimension(size(water_mask,1),size(water_mask,2)) :: water_frac + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() - if ( get_water_frac_1d(blon, blat, water_frac) ) then - where (water_frac > 0.50) + if (get_water_frac(blon, blat, water_frac) ) then + where (water_frac > 0.50_lkind) water_mask = .true. elsewhere water_mask = .false. end where - get_water_mask_1d = .true. + GET_WATER_MASK_1D_ = .true. else - get_water_mask_1d = .false. + GET_WATER_MASK_1D_ = .false. endif !----------------------------------------------------------------------- - end function get_water_mask_1d + end function GET_WATER_MASK_1D_ !####################################################################### - function get_water_mask_2d (blon, blat, water_mask) + function GET_WATER_MASK_2D_(blon, blat, water_mask) - real, intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. + real(kind=FMS_TOP_KIND_), intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. logical, intent(out), dimension(:,:) :: water_mask !< A binary mask for water (true) or land (false). !! The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_mask_2d - real, dimension(size(water_mask,1),size(water_mask,2)) :: water_frac + logical :: GET_WATER_MASK_2D_ + real(kind=FMS_TOP_KIND_), dimension(size(water_mask,1),size(water_mask,2)) :: water_frac + integer, parameter :: lkind = FMS_TOP_KIND_ !----------------------------------------------------------------------- if (.not. module_is_initialized) call topography_init() - if ( get_water_frac_2d(blon, blat, water_frac) ) then - where (water_frac > 0.50) + if (get_water_frac(blon, blat, water_frac) ) then + where (water_frac > 0.50_lkind) water_mask = .true. elsewhere water_mask = .false. end where - get_water_mask_2d = .true. + GET_WATER_MASK_2D_ = .true. else - get_water_mask_2d = .false. + GET_WATER_MASK_2D_ = .false. endif !----------------------------------------------------------------------- - end function get_water_mask_2d - -!####################################################################### -!################## private interfaces below here ################## -!####################################################################### - - function open_topog_file ( ) - logical :: open_topog_file - real :: r_ipts, r_jpts - integer :: namelen - - namelen = len(trim(topog_file)) - if ( file_exists(topog_file) .AND. topog_file(namelen-2:namelen) == '.nc') then - if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & - 'Reading NetCDF formatted input data file: '//trim(topog_file), NOTE) - if(.not. file_is_opened(TOPOG_INDEX) ) then - if(.not. open_file(fileobj(TOPOG_INDEX), topog_file, 'read' )) then - call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(topog_file)) - endif - endif - - call read_data(fileobj(TOPOG_INDEX), 'ipts', r_ipts) - call read_data(fileobj(TOPOG_INDEX), 'jpts', r_jpts) - ipts = nint(r_ipts) - jpts = nint(r_jpts) - open_topog_file = .true. - file_is_opened(TOPOG_INDEX) = .true. - else - open_topog_file = .false. - endif - - end function open_topog_file - - function open_water_file ( ) - logical :: open_water_file - real :: r_ipts, r_jpts - integer :: namelen - - namelen = len(trim(water_file)) - if ( file_exists(water_file) .AND. water_file(namelen-2:namelen) == '.nc') then - if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & - 'Reading NetCDF formatted input data file: '//trim(water_file), NOTE) - if(.not. file_is_opened(WATER_INDEX) ) then - if(.not. open_file(fileobj(WATER_INDEX), water_file, 'read' )) then - call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(water_file)) - endif - endif - - call read_data(fileobj(WATER_INDEX), 'ipts', r_ipts) - call read_data(fileobj(WATER_INDEX), 'jpts', r_jpts) - ipts = nint(r_ipts) - jpts = nint(r_jpts) - open_water_file = .true. - file_is_opened(WATER_INDEX) = .true. - else - open_water_file = .false. - endif - - end function open_water_file - + end function GET_WATER_MASK_2D_ !####################################################################### - subroutine interp_topog_1d ( blon, blat, zout, flag) - real , intent(in) :: blon(:), blat(:) - real , intent(out) :: zout(:,:) - integer, intent(in), optional :: flag +subroutine INTERP_TOPOG_1D_( blon, blat, zout, flag) +real(kind=FMS_TOP_KIND_), intent(in) :: blon(:), blat(:) +real(kind=FMS_TOP_KIND_), intent(out) :: zout(:,:) +integer, intent(in), optional :: flag - real :: xdat(ipts+1), ydat(jpts+1) - real :: zdat(ipts,jpts) - real :: zout2(size(zout,1),size(zout,2)) +real(kind=FMS_TOP_KIND_) :: xdat(ipts+1), ydat(jpts+1) +real(kind=FMS_TOP_KIND_) :: zdat(ipts,jpts) +real(kind=FMS_TOP_KIND_) :: zout2(size(zout,1),size(zout,2)) +integer, parameter :: lkind = FMS_TOP_KIND_ - call input_data( TOPOG_INDEX, xdat, ydat, zdat) + call input_data(TOPOG_INDEX, xdat, ydat, zdat) - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) + call horiz_interp( zdat, xdat, ydat, blon, blat, zout ) -! compute standard deviation if necessary - if (present(flag)) then - if (flag == COMPUTE_STDEV) then - zdat = zdat*zdat - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout2 ) - zout = zout2 - zout*zout - where (zout > 0.0) +! compute standard deviation if necessary. + if (present(flag)) then + if (flag == COMPUTE_STDEV) then + zdat = zdat*zdat + call horiz_interp ( zdat, xdat, ydat, blon, blat, zout2 ) + zout = zout2 - zout*zout + where (zout > 0.0_lkind) zout = sqrt ( zout ) elsewhere - zout = 0.0 + zout = 0.0_lkind endwhere endif endif - end subroutine interp_topog_1d +end subroutine INTERP_TOPOG_1D_ !####################################################################### - subroutine interp_topog_2d ( blon, blat, zout, flag ) - real , intent(in) :: blon(:,:), blat(:,:) - real , intent(out) :: zout(:,:) - integer, intent(in), optional :: flag +subroutine INTERP_TOPOG_2D_( blon, blat, zout, flag ) +real(kind=FMS_TOP_KIND_), intent(in) :: blon(:,:), blat(:,:) +real(kind=FMS_TOP_KIND_), intent(out) :: zout(:,:) +integer, intent(in), optional :: flag - real :: xdat(ipts+1), ydat(jpts+1) - real :: zdat(ipts,jpts) - real :: zout2(size(zout,1),size(zout,2)) - integer :: js, je - type (horiz_interp_type) :: Interp +real(kind=FMS_TOP_KIND_) :: xdat(ipts+1), ydat(jpts+1) +real(kind=FMS_TOP_KIND_) :: zdat(ipts,jpts) +real(kind=FMS_TOP_KIND_) :: zout2(size(zout,1),size(zout,2)) +integer, parameter :: lkind = FMS_TOP_KIND_ +integer :: js, je +type (horiz_interp_type) :: Interp - call input_data( TOPOG_INDEX, xdat, ydat, zdat) + call input_data(TOPOG_INDEX, xdat, ydat, zdat) - call find_indices ( minval(blat), maxval(blat), ydat, js, je ) + call find_indices( minval(blat), maxval(blat), ydat, js, je ) call horiz_interp_new ( Interp, xdat, ydat(js:je+1), blon, blat ) call horiz_interp ( Interp, zdat(:,js:je), zout ) @@ -703,24 +442,25 @@ end interface zdat = zdat*zdat call horiz_interp ( Interp, zdat(:,js:je), zout2 ) zout = zout2 - zout*zout - where (zout > 0.0) + where (zout > 0.0_lkind) zout = sqrt ( zout ) elsewhere - zout = 0.0 + zout = 0.0_lkind endwhere endif endif - call horiz_interp_del ( Interp ) + call horiz_interp_del( Interp ) - end subroutine interp_topog_2d +end subroutine INTERP_TOPOG_2D_ !####################################################################### - subroutine find_indices ( ybeg, yend, ydat, js, je ) - real, intent(in) :: ybeg, yend, ydat(:) - integer, intent(out) :: js, je - integer :: j +subroutine FIND_INDICES_( ybeg, yend, ydat, js, je ) +real(kind=FMS_TOP_KIND_), intent(in) :: ybeg, yend, ydat(:) +integer, intent(out) :: js, je +integer :: j +integer, parameter :: lkind = FMS_TOP_KIND_ js = 1 do j = 1, size(ydat(:))-1 @@ -738,237 +478,116 @@ end interface endif enddo - !print '(a,i2,2(a,f10.5),2(a,i4))', "PE=",mpp_pe()," phs=",ybeg," phn=",yend," js=",js," je=",je +!print '(a,i2,2(a,f10.5),2(a,i4))', "PE=",mpp_pe()," phs=",ybeg," phn=",yend," js=",js," je=",je - end subroutine find_indices +end subroutine FIND_INDICES_ !####################################################################### - subroutine input_data ( indx, xdat, ydat, zdat ) - integer, intent(in) :: indx - real, intent(out) :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) +subroutine INPUT_DATA_( indx, xdat, ydat, zdat ) +integer, intent(in) :: indx +real(kind=FMS_TOP_KIND_), intent(out) :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) - if( file_is_opened(indx) ) then - call read_data(fileobj(indx), 'xdat', xdat) - call read_data(fileobj(indx), 'ydat', ydat) - call read_data(fileobj(indx), 'zdat', zdat) - endif +if( file_is_opened(indx) ) then + call read_data(fileobj(indx), 'xdat', xdat) + call read_data(fileobj(indx), 'ydat', ydat) + call read_data(fileobj(indx), 'zdat', zdat) +endif - end subroutine input_data +end subroutine INPUT_DATA_ !####################################################################### - subroutine interp_water_1d ( blon, blat, zout, do_ocean ) - real , intent(in) :: blon(:), blat(:) - real , intent(out) :: zout(:,:) - logical, intent(in), optional :: do_ocean - real :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) +subroutine INTERP_WATER_1D_( blon, blat, zout, do_ocean ) +real(kind=FMS_TOP_KIND_), intent(in) :: blon(:), blat(:) +real(kind=FMS_TOP_KIND_), intent(out) :: zout(:,:) +logical, intent(in), optional :: do_ocean +real(kind=FMS_TOP_KIND_) :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) call input_data ( WATER_INDEX, xdat, ydat, zdat ) ! only use designated ocean points - if (present(do_ocean)) then - if (do_ocean) call determine_ocean_points (zdat) - endif +if (present(do_ocean)) then + if (do_ocean) call determine_ocean_points (zdat) +endif ! interpolate onto output grid - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) +call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) - end subroutine interp_water_1d +end subroutine INTERP_WATER_1D_ !####################################################################### - subroutine interp_water_2d ( blon, blat, zout, do_ocean ) - real , intent(in) :: blon(:,:), blat(:,:) - real , intent(out) :: zout(:,:) - logical, intent(in), optional :: do_ocean - real :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) +subroutine INTERP_WATER_2D_( blon, blat, zout, do_ocean ) +real(kind=FMS_TOP_KIND_), intent(in) :: blon(:,:), blat(:,:) +real(kind=FMS_TOP_KIND_), intent(out) :: zout(:,:) +logical, intent(in), optional :: do_ocean +real(kind=FMS_TOP_KIND_) :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) - call input_data ( WATER_INDEX, xdat, ydat, zdat ) +call input_data ( WATER_INDEX, xdat, ydat, zdat ) ! only use designated ocean points - if (present(do_ocean)) then - if (do_ocean) call determine_ocean_points (zdat) - endif +if (present(do_ocean)) then + if (do_ocean) call determine_ocean_points (zdat) +endif ! interpolate onto output grid - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) +call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) - end subroutine interp_water_2d +end subroutine INTERP_WATER_2D_ !####################################################################### - subroutine determine_ocean_points ( pctwater ) - real, intent(inout) :: pctwater(:,:) - logical :: ocean(size(pctwater,1),size(pctwater,2)) - integer :: i, j, m, n, im, ip, jm, jp, new +subroutine DETERMINE_OCEAN_POINTS_(pctwater) +real(kind=FMS_TOP_KIND_), intent(inout) :: pctwater(:,:) +logical :: ocean(size(pctwater,1),size(pctwater,2)) +integer :: i, j, m, n, im, ip, jm, jp, new +integer, parameter :: lkind = FMS_TOP_KIND_ +real(kind=FMS_TOP_KIND_) :: ocean_pct_crit = 0.500_lkind - real :: ocean_pct_crit = .500 - ! resolution of the grid - m = size(pctwater,1) - n = size(pctwater,2) +! resolution of the grid +m = size(pctwater,1) +n = size(pctwater,2) - ! the 1/6 degree navy percent water data set - ! designates ocean grid boxes as 100 percent water - ! all other grid boxes have <= 99 percent water +! the 1/6 degree navy percent water data set +! designates ocean grid boxes as 100 percent water +! all other grid boxes have <= 99 percent water - ! set a mask for ocean grid boxes - ocean = (pctwater > .999) - new = count(ocean) +! set a mask for ocean grid boxes +ocean = (pctwater > 0.999_lkind) +new = count(ocean) - ! set land grid boxes that have sufficient amount of water - ! to ocean grid boxes when they are adjacent to ocean points - ! iterate until there are no new ocean points - do +! set land grid boxes that have sufficient amount of water +! to ocean grid boxes when they are adjacent to ocean points +! iterate until there are no new ocean points +do if (new == 0) exit - new = 0 + new = 0 do j = 1, n - do i = 1, m - if (.not.ocean(i,j) .and. pctwater(i,j) > ocean_pct_crit) then - im = i-1; ip = i+1; jm = j-1; jp = j+1 - if (im == 0) im = m - if (ip == m+1) ip = 1 - if (jm == 0) jm = 1 - if (jp == n+1) jp = n - ! check the 8 grid boxes that surround this grid box - if (ocean(im,j ) .or. ocean(ip,j ) .or. ocean(i ,jm) .or. ocean(i ,jp) .or. & - ocean(im,jm) .or. ocean(ip,jm) .or. ocean(ip,jp) .or. ocean(im,jp)) then - ocean(i,j) = .true. - new = new + 1 - endif - endif - enddo - enddo + do i = 1, m + if (.not.ocean(i,j) .and. pctwater(i,j) > ocean_pct_crit) then + im = i-1; ip = i+1; jm = j-1; jp = j+1 + if (im == 0) im = m + if (ip == m+1) ip = 1 + if (jm == 0) jm = 1 + if (jp == n+1) jp = n + ! check the 8 grid boxes that surround this grid box + if (ocean(im,j ) .or. ocean(ip,j ) .or. ocean(i ,jm) .or. ocean(i ,jp) .or. & + ocean(im,jm) .or. ocean(ip,jm) .or. ocean(ip,jp) .or. ocean(im,jp)) then + ocean(i,j) = .true. + new = new + 1 + endif + endif + enddo + enddo !print *, 'new=',new - enddo +enddo - ! final step is to elimate water percentage if land - where (.not.ocean) pctwater = 0. +! final step is to elimate water percentage if land +where (.not.ocean) pctwater = 0.0_lkind - end subroutine determine_ocean_points - -!####################################################################### -!> @brief Reads the namelist file, write namelist to log file, -!! and initializes constants -subroutine read_namelist - - integer :: unit, ierr, io - -! read namelist - - read (input_nml_file, topography_nml, iostat=io) - ierr = check_nml_error(io,'topography_nml') - -! write version and namelist to log file - - if (mpp_pe() == mpp_root_pe()) then - unit = stdlog() - write (unit, nml=topography_nml) - endif +end subroutine DETERMINE_OCEAN_POINTS_ -end subroutine read_namelist - -end module topography_mod - -! - -! -! -! To run this program you will need the topography and percent water -! data sets and use the following namelist (in the input nml file). -! -! &gaussian_topog_nml -! height = 5000., 3000., 3000., 3000., -! olon = 90., 255., 285., 0., -! olat = 45., 45., -15., -90., -! wlon = 15., 10., 5., 180., -! wlat = 15., 25., 25., 20., / -! -! program test -! -! ! test program for topography and gaussian_topog modules -!
-!  use topography_mod
-!  implicit none
-!
-!  integer, parameter :: nlon=24, nlat=18
-!  real :: x(nlon), y(nlat), xb(nlon+1), yb(nlat+1), z(nlon,nlat)
-!  real :: hpi, rtd
-!  integer :: i,j
-!  logical :: a
-!
-!  ! gaussian mountain parameters
-!  real, parameter :: ht=4000.
-!  real, parameter :: x0=90., y0=45. ! origin in degrees
-!  real, parameter :: xw=15., yw=15. ! half-width in degees
-!  real, parameter :: xr=30., yr= 0. ! ridge-width in degrees
-!
-!  ! create lat/lon grid in radians
-!    hpi = acos(0.0)
-!    rtd = 90./hpi ! rad to deg
-!    do i=1,nlon
-!      xb(i) = 4.*hpi*real(i-1)/real(nlon)
-!    enddo
-!      xb(nlon+1) = xb(1)+4.*hpi
-!      yb(1) = -hpi
-!    do j=2,nlat
-!      yb(j) = yb(j-1) + 2.*hpi/real(nlat)
-!    enddo
-!      yb(nlat+1) = hpi
-!  ! mid-point of grid boxes
-!    x(1:nlon) = 0.5*(xb(1:nlon)+xb(2:nlon+1))
-!    y(1:nlat) = 0.5*(yb(1:nlat)+yb(2:nlat+1))
-!  ! test topography_mod routines
-!    a = get_topog_mean(xb,yb,z)
-!    call printz ('get_topog_mean')
-!
-!    a = get_water_frac(xb,yb,z)
-!    z = z*100. ! in percent
-!    call printz ('get_water_frac')
-!
-!    a = get_ocean_frac(xb,yb,z)
-!    z = z*100. ! in percent
-!    call printz ('get_ocean_frac')
-!
-!  ! test gaussian_topog_mod routines
-!    a = .true.
-!    z = get_gaussian_topog(x,y,ht,x0,y0,xw,yw,xr,yr)
-!    call printz ('get_gaussian_topog')
-!
-!    call gaussian_topog_init (x,y,z)
-!    call printz ('gaussian_topog_init')
-!
-!  contains
-!
-!  ! simple printout of topog/water array
-!    subroutine printz (lab)
-!    character(len=*), intent(in) :: lab
-!     if (a) then
-!        print '(/a)', trim(lab)
-!     else
-!        print '(/a)', 'no data available: '//trim(lab)
-!        return
-!     endif
-!      ! print full grid
-!        print '(3x,25i5)', (nint(x(i)*rtd),i=1,nlon)
-!      do j=nlat,1,-1
-!        print '(i3,25i5)', nint(y(j)*rtd), (nint(z(i,j)),i=1,nlon)
-!      enddo
-!    end subroutine printz
-!
-!  end program test
-!   
-!
- -! -! Water mask produces some possible erroneous water points along -! the coast of Antarctic (at about 90W). -! - -! Use of netcdf data sets. -! Incorporate other topography and ocean data sets. -! -!
!> @} ! close documentation grouping diff --git a/topography/include/topography_r4.fh b/topography/include/topography_r4.fh new file mode 100644 index 0000000000..d832f613a5 --- /dev/null +++ b/topography/include/topography_r4.fh @@ -0,0 +1,95 @@ +!*********************************************************************** +!* GNU Lesser General Public License +!* +!* This file is part of the GFDL Flexible Modeling System (FMS). +!* +!* FMS is free software: you can redistribute it and/or modify it under +!* the terms of the GNU Lesser General Public License as published by +!* the Free Software Foundation, either version 3 of the License, or (at +!* your option) any later version. +!* +!* FMS is distributed in the hope that it will be useful, but WITHOUT +!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +!* for more details. +!* +!* You should have received a copy of the GNU Lesser General Public +!* License along with FMS. If not, see . +!*********************************************************************** +!> @defgroup gaussian_topog_mod gaussian_topog_mod +!> @ingroup topography +!> @brief Routines for creating Gaussian-shaped land surface topography +!! for latitude-longitude grids. +!> @author Bruce Wyman +!! +!! Interfaces generate simple Gaussian-shaped mountains from +!! parameters specified by either argument list or namelist input. +!! The mountain shapes are controlled by the height, half-width, +!! and ridge-width parameters. + +!> @addtogroup gaussian_topog_mod +!> @{ + +#undef FMS_TOP_KIND_ +#define FMS_TOP_KIND_ r4_kind + +#undef GET_TOPOG_MEAN_1D_ +#define GET_TOPOG_MEAN_1D_ get_topog_mean_1d_r4 + +#undef GET_TOPOG_MEAN_2D_ +#define GET_TOPOG_MEAN_2D_ get_topog_mean_2d_r4 + +#undef GET_TOPOG_STDEV_1D_ +#define GET_TOPOG_STDEV_1D_ get_topog_stdev_1d_r4 + +#undef GET_TOPOG_STDEV_2D_ +#define GET_TOPOG_STDEV_2D_ get_topog_stdev_2d_r4 + +#undef GET_OCEAN_FRAC_1D_ +#define GET_OCEAN_FRAC_1D_ get_ocean_frac_1d_r4 + +#undef GET_OCEAN_FRAC_2D_ +#define GET_OCEAN_FRAC_2D_ get_ocean_frac_2d_r4 + +#undef GET_OCEAN_MASK_1D_ +#define GET_OCEAN_MASK_1D_ get_ocean_mask_1d_r4 + +#undef GET_OCEAN_MASK_2D_ +#define GET_OCEAN_MASK_2D_ get_ocean_mask_2d_r4 + +#undef GET_WATER_FRAC_1D_ +#define GET_WATER_FRAC_1D_ get_water_frac_1d_r4 + +#undef GET_WATER_FRAC_2D_ +#define GET_WATER_FRAC_2D_ get_water_frac_2d_r4 + +#undef GET_WATER_MASK_1D_ +#define GET_WATER_MASK_1D_ get_water_mask_1d_r4 + +#undef GET_WATER_MASK_2D_ +#define GET_WATER_MASK_2D_ get_water_mask_2d_r4 + +#undef INTERP_TOPOG_1D_ +#define INTERP_TOPOG_1D_ interp_topog_1d_r4 + +#undef INTERP_TOPOG_2D_ +#define INTERP_TOPOG_2D_ interp_topog_2d_r4 + +#undef FIND_INDICES_ +#define FIND_INDICES_ find_indices_r4 + +#undef INPUT_DATA_ +#define INPUT_DATA_ input_data_r4 + +#undef INTERP_WATER_1D_ +#define INTERP_WATER_1D_ interp_water_1d_r4 + +#undef INTERP_WATER_2D_ +#define INTERP_WATER_2D_ interp_water_2d_r4 + +#undef DETERMINE_OCEAN_POINTS_ +#define DETERMINE_OCEAN_POINTS_ determine_ocean_points_r4 + +#include "topography.inc" +!> @} +! close documentation grouping \ No newline at end of file diff --git a/topography/include/topography_r8.fh b/topography/include/topography_r8.fh new file mode 100644 index 0000000000..b36209f4b1 --- /dev/null +++ b/topography/include/topography_r8.fh @@ -0,0 +1,95 @@ +!*********************************************************************** +!* GNU Lesser General Public License +!* +!* This file is part of the GFDL Flexible Modeling System (FMS). +!* +!* FMS is free software: you can redistribute it and/or modify it under +!* the terms of the GNU Lesser General Public License as published by +!* the Free Software Foundation, either version 3 of the License, or (at +!* your option) any later version. +!* +!* FMS is distributed in the hope that it will be useful, but WITHOUT +!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +!* for more details. +!* +!* You should have received a copy of the GNU Lesser General Public +!* License along with FMS. If not, see . +!*********************************************************************** +!> @defgroup gaussian_topog_mod gaussian_topog_mod +!> @ingroup topography +!> @brief Routines for creating Gaussian-shaped land surface topography +!! for latitude-longitude grids. +!> @author Bruce Wyman +!! +!! Interfaces generate simple Gaussian-shaped mountains from +!! parameters specified by either argument list or namelist input. +!! The mountain shapes are controlled by the height, half-width, +!! and ridge-width parameters. + +!> @addtogroup gaussian_topog_mod +!> @{ + +#undef FMS_TOP_KIND_ +#define FMS_TOP_KIND_ r8_kind + +#undef GET_TOPOG_MEAN_1D_ +#define GET_TOPOG_MEAN_1D_ get_topog_mean_1d_r8 + +#undef GET_TOPOG_MEAN_2D_ +#define GET_TOPOG_MEAN_2D_ get_topog_mean_2d_r8 + +#undef GET_TOPOG_STDEV_1D_ +#define GET_TOPOG_STDEV_1D_ get_topog_stdev_1d_r8 + +#undef GET_TOPOG_STDEV_2D_ +#define GET_TOPOG_STDEV_2D_ get_topog_stdev_2d_r8 + +#undef GET_OCEAN_FRAC_1D_ +#define GET_OCEAN_FRAC_1D_ get_ocean_frac_1d_r8 + +#undef GET_OCEAN_FRAC_2D_ +#define GET_OCEAN_FRAC_2D_ get_ocean_frac_2d_r8 + +#undef GET_OCEAN_MASK_1D_ +#define GET_OCEAN_MASK_1D_ get_ocean_mask_1d_r8 + +#undef GET_OCEAN_MASK_2D_ +#define GET_OCEAN_MASK_2D_ get_ocean_mask_2d_r8 + +#undef GET_WATER_FRAC_1D_ +#define GET_WATER_FRAC_1D_ get_water_frac_1d_r8 + +#undef GET_WATER_FRAC_2D_ +#define GET_WATER_FRAC_2D_ get_water_frac_2d_r8 + +#undef GET_WATER_MASK_1D_ +#define GET_WATER_MASK_1D_ get_water_mask_1d_r8 + +#undef GET_WATER_MASK_2D_ +#define GET_WATER_MASK_2D_ get_water_mask_2d_r8 + +#undef INTERP_TOPOG_1D_ +#define INTERP_TOPOG_1D_ interp_topog_1d_r8 + +#undef INTERP_TOPOG_2D_ +#define INTERP_TOPOG_2D_ interp_topog_2d_r8 + +#undef FIND_INDICES_ +#define FIND_INDICES_ find_indices_r8 + +#undef INPUT_DATA_ +#define INPUT_DATA_ input_data_r8 + +#undef INTERP_WATER_1D_ +#define INTERP_WATER_1D_ interp_water_1d_r8 + +#undef INTERP_WATER_2D_ +#define INTERP_WATER_2D_ interp_water_2d_r8 + +#undef DETERMINE_OCEAN_POINTS_ +#define DETERMINE_OCEAN_POINTS_ determine_ocean_points_r8 + +#include "topography.inc" +!> @} +! close documentation grouping \ No newline at end of file diff --git a/topography/topography.F90 b/topography/topography.F90 index 1cfe0ec7fb..1c4312d7fd 100644 --- a/topography/topography.F90 +++ b/topography/topography.F90 @@ -51,6 +51,7 @@ module topography_mod use constants_mod, only: PI use mpp_mod, only: input_nml_file +use platform_mod, only: r4_kind, r8_kind implicit none private @@ -79,9 +80,11 @@ module topography_mod !!
Example usage: !! @code{.F90} flag = get_topog_mean ( blon, blat, zmean )@endcode !> @ingroup topography_mod + interface get_topog_mean - module procedure get_topog_mean_1d, get_topog_mean_2d -end interface + module procedure get_topog_mean_1d_r4, get_topog_mean_1d_r8 + module procedure get_topog_mean_2d_r4, get_topog_mean_2d_r8 +end interface get_topog_mean !> Returns a standard deviation of higher resolution topography with !! the given model grid boxes. @@ -104,8 +107,9 @@ module topography_mod !! @code{.F90} flag = get_topog_stdev( blon, blat, stdev ) @code !> @ingroup topography_mod interface get_topog_stdev - module procedure get_topog_stdev_1d, get_topog_stdev_2d -end interface + module procedure get_topog_stdev_1d_r4, get_topog_stdev_1d_r8 + module procedure get_topog_stdev_2d_r4, get_topog_stdev_2d_r8 +end interface get_topog_stdev !> @brief Returns fractional area covered by ocean in a grid box. !! Returns fractional area covered by ocean in the given model grid boxes. @@ -123,8 +127,9 @@ module topography_mod !! @code{.F90} flag = get_ocean_frac ( blon, blat, ocean_frac ) @endcode !> @ingroup topography_mod interface get_ocean_frac - module procedure get_ocean_frac_1d, get_ocean_frac_2d -end interface + module procedure get_ocean_frac_1d_r4, get_ocean_frac_1d_r8 + module procedure get_ocean_frac_2d_r4, get_ocean_frac_2d_r8 +end interface get_ocean_frac !> @brief Returns a land-ocean mask in a grid box. !! @@ -143,8 +148,9 @@ module topography_mod !! @code{.F90} flag = get_ocean_mask( blon, blat, ocean_mask ) @endcode !> @ingroup topography_mod interface get_ocean_mask - module procedure get_ocean_mask_1d, get_ocean_mask_2d -end interface + module procedure get_ocean_mask_1d_r4, get_ocean_mask_1d_r8 + module procedure get_ocean_mask_2d_r4, get_ocean_mask_2d_r8 +end interface get_ocean_mask !> @brief Returns fractional area covered by water. !! @@ -162,8 +168,9 @@ module topography_mod !!
Example usage:
@code{.F90} flag = get_water_frac ( blon, blat, water_frac ) @endcode !> @ingroup topography_mod interface get_water_frac - module procedure get_water_frac_1d, get_water_frac_2d -end interface + module procedure get_water_frac_1d_r4, get_water_frac_1d_r8 + module procedure get_water_frac_2d_r4, get_water_frac_2d_r8 +end interface get_water_frac !> @brief Returns a land-water mask in a grid box. !! @@ -181,21 +188,43 @@ module topography_mod !! Example usage: @code{.F90}flag = get_water_mask( blon, blat, water_mask ) @endcode !> @ingroup topography_mod interface get_water_mask - module procedure get_water_mask_1d, get_water_mask_2d -end interface + module procedure get_water_mask_1d_r4, get_water_mask_1d_r8 + module procedure get_water_mask_2d_r4, get_water_mask_2d_r8 +end interface get_water_mask + +interface interp_topog + module procedure interp_topog_1d_r4, interp_topog_1d_r8 + module procedure interp_topog_2d_r4, interp_topog_2d_r8 +end interface interp_topog + +interface find_indices + module procedure find_indices_r4, find_indices_r8 +end interface find_indices + +interface input_data + module procedure input_data_r4, input_data_r8 +end interface input_data + +interface interp_water + module procedure interp_water_1d_r4, interp_water_1d_r8 + module procedure interp_water_2d_r4, interp_water_2d_r8 +end interface interp_water + +interface determine_ocean_points + module procedure determine_ocean_points_r4, determine_ocean_points_r8 +end interface determine_ocean_points !> @addtogroup topography_mod !> @{ - logical :: use_mpp_io=.false.!>@var deprecated namelist variable for using mpp_io in this module - character(len=128) :: topog_file = 'DATA/navy_topography.data', & - water_file = 'DATA/navy_pctwater.data' - namelist /topography_nml/ topog_file, water_file, use_mpp_io +character(len=128) :: topog_file = 'DATA/navy_topography.data', & + water_file = 'DATA/navy_pctwater.data' +namelist /topography_nml/ topog_file, water_file - integer, parameter :: TOPOG_INDEX = 1 - integer, parameter :: WATER_INDEX = 2 - logical :: file_is_opened(2) = .false. - type(FmsNetcdfFile_t) :: fileobj(2) !< needed for fms2_io +integer, parameter :: TOPOG_INDEX = 1 +integer, parameter :: WATER_INDEX = 2 +logical :: file_is_opened(2) = .false. +type(FmsNetcdfFile_t) :: fileobj(2) !< needed for fms2_io !----------------------------------------------------------------------- ! --- resolution of the topography data set --- @@ -224,8 +253,8 @@ module topography_mod ! [real :: data(nlon,nlat)] ! ! - integer :: ipts, jpts - integer, parameter :: COMPUTE_STDEV = 123 ! use this flag to +integer :: ipts, jpts +integer, parameter :: COMPUTE_STDEV = 123 ! use this flag to ! compute st dev !----------------------------------------------------------------------- @@ -233,642 +262,106 @@ module topography_mod ! Include variable "version" to be written to log file. #include - logical :: module_is_initialized = .FALSE. - -!----------------------------------------------------------------------- - - contains - -!####################################################################### - - subroutine topography_init () - if ( module_is_initialized ) return - call write_version_number("TOPOGRAPHY_MOD", version) - call read_namelist - module_is_initialized = .TRUE. - if (use_mpp_io) then - call mpp_error('topography_mod', & - 'MPP_IO is no longer supported. Please remove use_mpp_io from topography_nml', FATAL) - endif - end subroutine topography_init - -!####################################################################### - - !> @brief Returns a "realistic" mean surface height field. - !! - !> Returns realistic mountains on a latitude-longtude grid. - !! The returned field is the mean topography for the given grid boxes. - !! Computed using a conserving area-weighted interpolation. - !! The current input data set is the 1/6 degree Navy mean topography. - !! - !! @returns A logical value of true is returned if the surface height field was successfully - !! created. A value of false may be returned if the input topography data set was not readable. - !! - !! @throws FATAL, shape(zmean) is not equal to (/size(blon)-1,size(blat)-1/) - !! Check the input grid size and output field size. - function get_topog_mean_1d(blon, blat, zmean) - - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: zmean !< Mean surface height(meters). Size must be - !! size(blon)-1 by size(blat)-1 - logical :: get_topog_mean_1d - -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(zmean(:,:)) /= (/size(blon(:))-1,size(blat(:))-1/)) ) & - call error_mesg('get_topog_mean_1d','shape(zmean) is not& - & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - - get_topog_mean_1d = open_topog_file() - - if ( get_topog_mean_1d ) call interp_topog_1d ( blon, blat, zmean) - -!----------------------------------------------------------------------- - - end function get_topog_mean_1d - -!############################################################ - - function get_topog_mean_2d (blon, blat, zmean) - - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: zmean - logical :: get_topog_mean_2d -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(zmean(:,:)) /= (/size(blon,1)-1,size(blon,2)-1/)) .or. & - any(shape(zmean(:,:)) /= (/size(blat,1)-1,size(blat,2)-1/)) ) & - call error_mesg('get_topog_mean_2d','shape(zmean) is not& - & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - - get_topog_mean_2d = open_topog_file() - - if ( get_topog_mean_2d ) call interp_topog_2d ( blon, blat, zmean) -!----------------------------------------------------------------------- - - end function get_topog_mean_2d - -!####################################################################### - - !> @brief Returns a standard deviation of higher resolution topography with - !! the given model grid boxes. - !! - !> Returns the standard deviation of the "finer" input topography data set, - !! currently the Navy 1/6 degree mean topography data, within the - !! boundaries of the given input grid. - !! - !! @returns A logical value of true if the output field was successfully created and false - !! if the input topography data set was not readable. - function get_topog_stdev_1d (blon, blat, stdev) - - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: stdev !< The standard deviation of surface height (in - !! meters) within given input model grid boxes. Size must be - !! size(blon)-1 by size(blat)-1 - logical :: get_topog_stdev_1d -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(stdev(:,:)) /= (/size(blon(:))-1,size(blat(:))-1/)) ) & - call error_mesg('get_topog_stdev','shape(stdev) is not& - & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - - get_topog_stdev_1d = open_topog_file() - - if ( get_topog_stdev_1d ) call interp_topog_1d ( blon, blat, & - stdev, flag=COMPUTE_STDEV) - -!----------------------------------------------------------------------- - - end function get_topog_stdev_1d - -!####################################################################### - - function get_topog_stdev_2d (blon, blat, stdev) - - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: stdev - logical :: get_topog_stdev_2d -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(stdev(:,:)) /= (/size(blon,1)-1,size(blon,2)-1/)) .or. & - any(shape(stdev(:,:)) /= (/size(blat,1)-1,size(blat,2)-1/)) ) & - call error_mesg('get_topog_stdev_2d','shape(stdev) is not& - & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - - get_topog_stdev_2d = open_topog_file() - - if ( get_topog_stdev_2d ) call interp_topog_2d ( blon, blat, & - stdev, flag=COMPUTE_STDEV) -!----------------------------------------------------------------------- - - end function get_topog_stdev_2d - -!####################################################################### - - !> @brief Returns fractional area covered by ocean in a grid box. - !> @returns A logical value of true if the output field was successfully created. A value of false - !! may be returned if the Navy 1/6 degree percent water data set was not readable. - function get_ocean_frac_1d (blon, blat, ocean_frac) - - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - real, intent(out), dimension(:,:) :: ocean_frac !< The fractional amount (0-1) of ocean in a grid - !! box. The size must be size(blon)-1 by size(blat)-1 - logical :: get_ocean_frac_1d -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(ocean_frac(:,:)) /= (/size(blon(:))-1,size(blat(:))-1/)) ) & - call error_mesg('get_ocean_frac','shape(ocean_frac) is not& - & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - - get_ocean_frac_1d = open_water_file() - if( get_ocean_frac_1d ) call interp_water_1d ( blon, blat, & - ocean_frac, do_ocean=.true. ) - -!----------------------------------------------------------------------- - - end function get_ocean_frac_1d - -!####################################################################### - - function get_ocean_frac_2d (blon, blat, ocean_frac) - - real, intent(in), dimension(:,:) :: blon, blat - real, intent(out), dimension(:,:) :: ocean_frac - logical :: get_ocean_frac_2d -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(ocean_frac(:,:)) /= (/size(blon,1)-1,size(blon,2)-1/)) .or. & - any(shape(ocean_frac(:,:)) /= (/size(blat,1)-1,size(blat,2)-1/)) ) & - call error_mesg('get_ocean_frac_2d','shape(ocean_frac) is not& - & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - - get_ocean_frac_2d = open_water_file() - if( get_ocean_frac_2d ) call interp_water_2d ( blon, blat, & - ocean_frac, do_ocean=.true. ) - -!----------------------------------------------------------------------- - - end function get_ocean_frac_2d - -!####################################################################### - - !> @brief Returns a land-ocean mask in a grid box. - !> @returns A logical value of true if the output field was successfully created. A value of false - !! may be returned if the Navy 1/6 degree percent water data set was not readable. - function get_ocean_mask_1d (blon, blat, ocean_mask) - - real, intent(in), dimension(:) :: blon !< Longitude (radians) at grid box boundaries - real, intent(in), dimension(:) :: blat !< Latitude (radians) at grid box boundaries - logical, intent(out), dimension(:,:) :: ocean_mask !< Mask for ocean in a grid box. - !! The size must be size(blon)-1 by size(blat)-1 - logical :: get_ocean_mask_1d - real, dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( get_ocean_frac_1d(blon, blat, ocean_frac) ) then - where (ocean_frac > 0.50) - ocean_mask = .true. - elsewhere - ocean_mask = .false. - end where - get_ocean_mask_1d = .true. - else - get_ocean_mask_1d = .false. - endif -!----------------------------------------------------------------------- - - end function get_ocean_mask_1d - -!####################################################################### - - function get_ocean_mask_2d (blon, blat, ocean_mask) - - real , intent(in), dimension(:,:) :: blon, blat - logical, intent(out), dimension(:,:) :: ocean_mask - logical :: get_ocean_mask_2d - real, dimension(size(ocean_mask,1),size(ocean_mask,2)) :: ocean_frac -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( get_ocean_frac_2d(blon, blat, ocean_frac) ) then - where (ocean_frac > 0.50) - ocean_mask = .true. - elsewhere - ocean_mask = .false. - end where - get_ocean_mask_2d = .true. - else - get_ocean_mask_2d = .false. - endif - -!----------------------------------------------------------------------- - - end function get_ocean_mask_2d - - !> @brief Returns the percent of water in a grid box. - !> @returns A logical value of true if the output field was successfully created. A value of false - !! may be returned if the Navy 1/6 degree percent water data set was not readable. - !! - !! @throws FATAL, shape(water_frac) is not equal to (/size(blon)-1,size(blat)-1/) - !! Check the input grid size and output field size. - function get_water_frac_1d (blon, blat, water_frac) - real, intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. - real, intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a - !! grid box. The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_frac_1d - -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(water_frac(:,:)) /= (/size(blon(:))-1,size(blat(:))-1/)) ) & - call error_mesg('get_water_frac_1d','shape(water_frac) is not& - & equal to (/size(blon)-1,size(blat)-1/))', FATAL) - - get_water_frac_1d = open_water_file() - if(get_water_frac_1d) call interp_water_1d ( blon, blat, water_frac ) - -!----------------------------------------------------------------------- - - end function get_water_frac_1d - -!####################################################################### - - function get_water_frac_2d (blon, blat, water_frac) - - real, intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. - real, intent(out), dimension(:,:) :: water_frac !< The fractional amount (0 to 1) of water in a - !! grid box. The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_frac_2d - -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( any(shape(water_frac(:,:)) /= (/size(blon,1)-1,size(blon,2)-1/)) .or. & - any(shape(water_frac(:,:)) /= (/size(blat,1)-1,size(blat,2)-1/)) ) & - call error_mesg('get_water_frac_2d','shape(water_frac) is not& - & equal to (/size(blon,1)-1,size(blon,2)-1/))', FATAL) - - get_water_frac_2d = open_water_file() - if(get_water_frac_2d) call interp_water_2d ( blon, blat, water_frac ) +logical :: module_is_initialized = .FALSE. !----------------------------------------------------------------------- - end function get_water_frac_2d +contains !####################################################################### - !> @brief Returns a land-water mask in the given model grid boxes. - !> @return A logical value of TRUE is returned if the output field - !! was successfully created. A value of FALSE may be returned - !! if the Navy 1/6 degree percent water data set was not readable. - function get_water_mask_1d (blon, blat, water_mask) - - real, intent(in), dimension(:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:) :: blat !< The latitude (in radians) at grid box boundaries. - logical, intent(out), dimension(:,:) :: water_mask !< A binary mask for water (true) or land (false). - !! The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_mask_1d - - real, dimension(size(water_mask,1),size(water_mask,2)) :: water_frac -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( get_water_frac_1d(blon, blat, water_frac) ) then - where (water_frac > 0.50) - water_mask = .true. - elsewhere - water_mask = .false. - end where - get_water_mask_1d = .true. - else - get_water_mask_1d = .false. - endif -!----------------------------------------------------------------------- - - end function get_water_mask_1d +subroutine topography_init () + if ( module_is_initialized ) return + call write_version_number("TOPOGRAPHY_MOD", version) + call read_namelist + module_is_initialized = .TRUE. +end subroutine topography_init !####################################################################### - - function get_water_mask_2d (blon, blat, water_mask) - - real, intent(in), dimension(:,:) :: blon !< The longitude (in radians) at grid box boundaries. - real, intent(in), dimension(:,:) :: blat !< The latitude (in radians) at grid box boundaries. - logical, intent(out), dimension(:,:) :: water_mask !< A binary mask for water (true) or land (false). - !! The size of this field must be size(blon)-1 by size(blat)-1. - logical :: get_water_mask_2d - real, dimension(size(water_mask,1),size(water_mask,2)) :: water_frac -!----------------------------------------------------------------------- - if (.not. module_is_initialized) call topography_init() - - if ( get_water_frac_2d(blon, blat, water_frac) ) then - where (water_frac > 0.50) - water_mask = .true. - elsewhere - water_mask = .false. - end where - get_water_mask_2d = .true. - else - get_water_mask_2d = .false. - endif - -!----------------------------------------------------------------------- - - end function get_water_mask_2d - !####################################################################### !################## private interfaces below here ################## !####################################################################### - function open_topog_file ( ) - logical :: open_topog_file - real :: r_ipts, r_jpts - integer :: namelen +function open_topog_file ( ) +logical :: open_topog_file +real(kind=r4_kind) :: r_ipts, r_jpts +integer :: namelen - namelen = len(trim(topog_file)) - if ( file_exists(topog_file) .AND. topog_file(namelen-2:namelen) == '.nc') then - if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & +namelen = len(trim(topog_file)) + if ( file_exists(topog_file) .AND. topog_file(namelen-2:namelen) == '.nc') then + if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & 'Reading NetCDF formatted input data file: '//trim(topog_file), NOTE) - if(.not. file_is_opened(TOPOG_INDEX) ) then - if(.not. open_file(fileobj(TOPOG_INDEX), topog_file, 'read' )) then - call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(topog_file)) - endif - endif - - call read_data(fileobj(TOPOG_INDEX), 'ipts', r_ipts) - call read_data(fileobj(TOPOG_INDEX), 'jpts', r_jpts) - ipts = nint(r_ipts) - jpts = nint(r_jpts) - open_topog_file = .true. - file_is_opened(TOPOG_INDEX) = .true. - else - open_topog_file = .false. - endif - - end function open_topog_file - - function open_water_file ( ) - logical :: open_water_file - real :: r_ipts, r_jpts - integer :: namelen - - namelen = len(trim(water_file)) - if ( file_exists(water_file) .AND. water_file(namelen-2:namelen) == '.nc') then - if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & - 'Reading NetCDF formatted input data file: '//trim(water_file), NOTE) - if(.not. file_is_opened(WATER_INDEX) ) then - if(.not. open_file(fileobj(WATER_INDEX), water_file, 'read' )) then - call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(water_file)) - endif - endif - - call read_data(fileobj(WATER_INDEX), 'ipts', r_ipts) - call read_data(fileobj(WATER_INDEX), 'jpts', r_jpts) - ipts = nint(r_ipts) - jpts = nint(r_jpts) - open_water_file = .true. - file_is_opened(WATER_INDEX) = .true. - else - open_water_file = .false. - endif - - end function open_water_file - - -!####################################################################### - - subroutine interp_topog_1d ( blon, blat, zout, flag) - real , intent(in) :: blon(:), blat(:) - real , intent(out) :: zout(:,:) - integer, intent(in), optional :: flag - - real :: xdat(ipts+1), ydat(jpts+1) - real :: zdat(ipts,jpts) - real :: zout2(size(zout,1),size(zout,2)) - - call input_data( TOPOG_INDEX, xdat, ydat, zdat) - - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) - -! compute standard deviation if necessary - if (present(flag)) then - if (flag == COMPUTE_STDEV) then - zdat = zdat*zdat - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout2 ) - zout = zout2 - zout*zout - where (zout > 0.0) - zout = sqrt ( zout ) - elsewhere - zout = 0.0 - endwhere - endif - endif - - end subroutine interp_topog_1d - -!####################################################################### - - subroutine interp_topog_2d ( blon, blat, zout, flag ) - real , intent(in) :: blon(:,:), blat(:,:) - real , intent(out) :: zout(:,:) - integer, intent(in), optional :: flag - - real :: xdat(ipts+1), ydat(jpts+1) - real :: zdat(ipts,jpts) - real :: zout2(size(zout,1),size(zout,2)) - integer :: js, je - type (horiz_interp_type) :: Interp - - call input_data( TOPOG_INDEX, xdat, ydat, zdat) - - call find_indices ( minval(blat), maxval(blat), ydat, js, je ) - - call horiz_interp_new ( Interp, xdat, ydat(js:je+1), blon, blat ) - call horiz_interp ( Interp, zdat(:,js:je), zout ) - -! compute standard deviation if necessary - if (present(flag)) then - if (flag == COMPUTE_STDEV) then - zdat = zdat*zdat - call horiz_interp ( Interp, zdat(:,js:je), zout2 ) - zout = zout2 - zout*zout - where (zout > 0.0) - zout = sqrt ( zout ) - elsewhere - zout = 0.0 - endwhere - endif - endif - - call horiz_interp_del ( Interp ) - - end subroutine interp_topog_2d - -!####################################################################### - - subroutine find_indices ( ybeg, yend, ydat, js, je ) - real, intent(in) :: ybeg, yend, ydat(:) - integer, intent(out) :: js, je - integer :: j - - js = 1 - do j = 1, size(ydat(:))-1 - if (ybeg >= ydat(j) .and. ybeg <= ydat(j+1)) then - js = j - exit + if(.not. file_is_opened(TOPOG_INDEX) ) then + if(.not. open_file(fileobj(TOPOG_INDEX), topog_file, 'read' )) then + call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(topog_file)) + endif + endif + + call read_data(fileobj(TOPOG_INDEX), 'ipts', r_ipts) + call read_data(fileobj(TOPOG_INDEX), 'jpts', r_jpts) + ipts = nint(r_ipts) + jpts = nint(r_jpts) + open_topog_file = .true. + file_is_opened(TOPOG_INDEX) = .true. + else + open_topog_file = .false. endif - enddo - je = size(ydat(:))-1 - do j = js, size(ydat(:))-1 - if (yend >= ydat(j) .and. yend <= ydat(j+1)) then - je = j - exit +end function open_topog_file + +function open_water_file ( ) +logical :: open_water_file +real(kind=r4_kind) :: r_ipts, r_jpts +integer :: namelen + +namelen = len(trim(water_file)) +if ( file_exists(water_file) .AND. water_file(namelen-2:namelen) == '.nc') then + if (mpp_pe() == mpp_root_pe()) call mpp_error ('topography_mod', & + 'Reading NetCDF formatted input data file: '//trim(water_file), NOTE) + if(.not. file_is_opened(WATER_INDEX) ) then + if(.not. open_file(fileobj(WATER_INDEX), water_file, 'read' )) then + call mpp_error(FATAL, 'topography_mod: Error in opening file '//trim(water_file)) + endif endif - enddo - - !print '(a,i2,2(a,f10.5),2(a,i4))', "PE=",mpp_pe()," phs=",ybeg," phn=",yend," js=",js," je=",je - - end subroutine find_indices -!####################################################################### - subroutine input_data ( indx, xdat, ydat, zdat ) - integer, intent(in) :: indx - real, intent(out) :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) - - if( file_is_opened(indx) ) then - call read_data(fileobj(indx), 'xdat', xdat) - call read_data(fileobj(indx), 'ydat', ydat) - call read_data(fileobj(indx), 'zdat', zdat) - endif - - end subroutine input_data - -!####################################################################### - - subroutine interp_water_1d ( blon, blat, zout, do_ocean ) - real , intent(in) :: blon(:), blat(:) - real , intent(out) :: zout(:,:) - logical, intent(in), optional :: do_ocean - real :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) - call input_data ( WATER_INDEX, xdat, ydat, zdat ) - -! only use designated ocean points - if (present(do_ocean)) then - if (do_ocean) call determine_ocean_points (zdat) - endif - -! interpolate onto output grid - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) - - end subroutine interp_water_1d - -!####################################################################### - - subroutine interp_water_2d ( blon, blat, zout, do_ocean ) - real , intent(in) :: blon(:,:), blat(:,:) - real , intent(out) :: zout(:,:) - logical, intent(in), optional :: do_ocean - real :: xdat(ipts+1), ydat(jpts+1), zdat(ipts,jpts) - - call input_data ( WATER_INDEX, xdat, ydat, zdat ) - -! only use designated ocean points - if (present(do_ocean)) then - if (do_ocean) call determine_ocean_points (zdat) - endif + call read_data(fileobj(WATER_INDEX), 'ipts', r_ipts) + call read_data(fileobj(WATER_INDEX), 'jpts', r_jpts) + ipts = nint(r_ipts) + jpts = nint(r_jpts) + open_water_file = .true. + file_is_opened(WATER_INDEX) = .true. + else + open_water_file = .false. + endif -! interpolate onto output grid - call horiz_interp ( zdat, xdat, ydat, blon, blat, zout ) +end function open_water_file - end subroutine interp_water_2d !####################################################################### - subroutine determine_ocean_points ( pctwater ) - real, intent(inout) :: pctwater(:,:) - logical :: ocean(size(pctwater,1),size(pctwater,2)) - integer :: i, j, m, n, im, ip, jm, jp, new - - real :: ocean_pct_crit = .500 - - ! resolution of the grid - m = size(pctwater,1) - n = size(pctwater,2) - - ! the 1/6 degree navy percent water data set - ! designates ocean grid boxes as 100 percent water - ! all other grid boxes have <= 99 percent water - - ! set a mask for ocean grid boxes - ocean = (pctwater > .999) - new = count(ocean) - - ! set land grid boxes that have sufficient amount of water - ! to ocean grid boxes when they are adjacent to ocean points - ! iterate until there are no new ocean points - do - if (new == 0) exit - new = 0 - - do j = 1, n - do i = 1, m - if (.not.ocean(i,j) .and. pctwater(i,j) > ocean_pct_crit) then - im = i-1; ip = i+1; jm = j-1; jp = j+1 - if (im == 0) im = m - if (ip == m+1) ip = 1 - if (jm == 0) jm = 1 - if (jp == n+1) jp = n - ! check the 8 grid boxes that surround this grid box - if (ocean(im,j ) .or. ocean(ip,j ) .or. ocean(i ,jm) .or. ocean(i ,jp) .or. & - ocean(im,jm) .or. ocean(ip,jm) .or. ocean(ip,jp) .or. ocean(im,jp)) then - ocean(i,j) = .true. - new = new + 1 - endif - endif - enddo - enddo - !print *, 'new=',new - - enddo - - ! final step is to elimate water percentage if land - where (.not.ocean) pctwater = 0. - - end subroutine determine_ocean_points - -!####################################################################### !> @brief Reads the namelist file, write namelist to log file, !! and initializes constants subroutine read_namelist - integer :: unit, ierr, io +integer :: unit, ierr, io ! read namelist - read (input_nml_file, topography_nml, iostat=io) - ierr = check_nml_error(io,'topography_nml') +read (input_nml_file, topography_nml, iostat=io) +ierr = check_nml_error(io,'topography_nml') ! write version and namelist to log file - if (mpp_pe() == mpp_root_pe()) then - unit = stdlog() - write (unit, nml=topography_nml) - endif +if (mpp_pe() == mpp_root_pe()) then + unit = stdlog() + write (unit, nml=topography_nml) +endif end subroutine read_namelist +#include "topography_r4.fh" +#include "topography_r8.fh" + end module topography_mod !