!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! 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 General Public License !! !! along with FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! module gaussian_topog_mod ! ! Bruce Wyman ! ! ! ! Routines for creating Gaussian-shaped land surface topography ! for latitude-longitude grids. ! ! ! 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. ! use fms_mod, only: file_exist, open_namelist_file, & check_nml_error, close_file, & stdlog, write_version_number, & mpp_pe, mpp_root_pe, & error_mesg, FATAL use constants_mod, only: pi 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 ! !----------------------------------------------------------------------- character(len=128) :: version = '$Id: gaussian_topog.F90,v 13.0 2006/03/28 21:43:27 fms Exp $' character(len=128) :: tagname = '$Name: mom4p1_pubrel_dec2009_nnz $' logical :: do_nml = .true. logical :: module_is_initialized = .FALSE. !----------------------------------------------------------------------- contains !####################################################################### ! ! ! 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 namelist &gaussian_topog_nml. ! ! ! ! The mean grid box longitude in radians. ! ! ! The mean grid box latitude in radians. ! ! ! The surface height (in meters). ! The size of this field must be size(lon) by size(lat). ! subroutine gaussian_topog_init ( lon, lat, zsurf ) real, intent(in) :: lon(:), lat(:) real, intent(out) :: zsurf(:,:) integer :: n if (.not.module_is_initialized) then call write_version_number( version, tagname ) 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 ! !####################################################################### ! ! ! Returns a simple surface height field that consists of a single ! Gaussian-shaped mountain. ! ! ! Returns a single Gaussian-shaped mountain. ! The height, position, width, and elongation of the mountain ! is controlled by optional arguments. ! ! ! ! The mean grid box longitude in radians. ! ! ! The mean grid box latitude in radians. ! ! ! Maximum surface height in meters. ! ! ! Position/origin of mountain in degrees longitude and latitude. ! This is the location of the maximum height. ! ! ! Gaussian half-width of mountain in degrees longitude and latitude. ! ! ! Ridge half-width of mountain in degrees longitude and latitude. ! This is the elongation of the maximum height. ! ! ! The surface height (in meters). ! The size of the returned field is size(lon) by size(lat). ! ! ! Check the input grid size and output field size. ! The input grid is defined at the midpoint of grid boxes. ! ! ! Mountains do not wrap around the poles. ! 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 real :: dtr ! read namelist if ( file_exist('input.nml')) then unit = open_namelist_file ( ) ierr=1; do while (ierr /= 0) read (unit, nml=gaussian_topog_nml, iostat=io, end=10) ierr = check_nml_error(io,'gaussian_topog_nml') enddo 10 call close_file (unit) endif ! write version and namelist to log file if (mpp_pe() == mpp_root_pe()) then unit = stdlog() write (unit, nml=gaussian_topog_nml) endif 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. !
!