!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! 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.
!
!
! call gaussian_topog_init ( lon, lat, zsurf )
!
!
! 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.
!
!
! zsurf = get_gaussian_topog ( lon, lat, height
! [, olond, olatd, wlond, wlatd, rlond, rlatd ] )
!
!
! 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 .
!
!