FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
gaussian_topog.inc
1!***********************************************************************
2!* GNU Lesser General Public License
3!*
4!* This file is part of the GFDL Flexible Modeling System (FMS).
5!*
6!* FMS is free software: you can redistribute it and/or modify it under
7!* the terms of the GNU Lesser General Public License as published by
8!* the Free Software Foundation, either version 3 of the License, or (at
9!* your option) any later version.
10!*
11!* FMS is distributed in the hope that it will be useful, but WITHOUT
12!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14!* for more details.
15!*
16!* You should have received a copy of the GNU Lesser General Public
17!* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18!***********************************************************************
19!> @defgroup gaussian_topog_mod gaussian_topog_mod
20!> @ingroup topography
21!> @brief Routines for creating Gaussian-shaped land surface topography
22!! for latitude-longitude grids.
23!> @author Bruce Wyman
24!!
25!! Interfaces generate simple Gaussian-shaped mountains from
26!! parameters specified by either argument list or namelist input.
27!! The mountain shapes are controlled by the height, half-width,
28!! and ridge-width parameters.
29
30!> @addtogroup gaussian_topog_mod
31!> @{
32
33!#######################################################################
34!> @brief Returns a simple surface height field that consists of a single
35!! Gaussian-shaped mountain.
36!!
37!> Returns a surface height field that consists
38!! of the sum of one or more Gaussian-shaped mountains.
39!!
40subroutine gaussian_topog_init_ ( lon, lat, zsurf )
41
42real(kind=fms_top_kind_), intent(in) :: lon(:) !< The mean grid box longitude in radians
43real(kind=fms_top_kind_), intent(in) :: lat(:) !< The mean grid box latitude in radians
44real(kind=fms_top_kind_), intent(out) :: zsurf(:,:) !< The surface height (meters). Size must be size(lon) by size(lat)
45
46integer :: n
47integer, parameter :: lkind=fms_top_kind_ !local FMS_TOP_KIND_ kind
48
49 if (.not.module_is_initialized) then
50 call write_version_number("GAUSSIAN_TOPOG_MOD", version)
51 endif
52
53 if(any(shape(zsurf) /= (/size(lon(:)),size(lat(:))/))) then
54 call error_mesg ('get_gaussian_topog in topography_mod', &
55 'shape(zsurf) is not equal to (/size(lon),size(lat)/)', fatal)
56 endif
57
58 if (do_nml) call read_namelist
59
60! compute sum of all non-zero mountains
61 zsurf(:,:) = 0.0_lkind
62 do n = 1, maxmts
63 if ( height(n) == 0.0_r8_kind ) cycle
64 zsurf = zsurf + get_gaussian_topog( lon, lat, real(height(n),lkind), &
65 real(olon(n),lkind), real(olat(n),lkind), real(wlon(n),lkind), &
66 real(wlat(n),lkind), real(rlon(n),lkind), real(rlat(n),lkind))
67 enddo
68 module_is_initialized = .true.
69
70end subroutine gaussian_topog_init_
71!#######################################################################
72!> The height, position, width, and elongation of the mountain
73!! is controlled by optional arguments.
74!! @param real lon The mean grid box longitude in radians.
75!! @param real lat The mean grid box latitude in radians.
76!! @param real height Maximum surface height in meters.
77!! @param real olond, olatd Position/origin of mountain in degrees longitude and latitude.
78!! This is the location of the maximum height.
79!! @param real wlond, wlatd Gaussian half-width of mountain in degrees longitude and latitude.
80!! @param real rlond, rlatd Ridge half-width of mountain in degrees longitude and latitude.
81!! This is the elongation of the maximum height.
82!! @param real zsurf The surface height (in meters).
83!! The size of the returned field is size(lon) by size(lat).
84!! </OUT>
85!!
86!! @throws FATAL shape(zsurf) is not equal to (/size(lon),size(lat)/)
87!! Check the input grid size and output field size.
88!! The input grid is defined at the midpoint of grid boxes.
89!!
90!! @note
91!! Mountains do not wrap around the poles.
92!
93!! <br>Example usage:
94!! @code{.F90} zsurf = <B>get_gaussian_topog</B> ( lon, lat, height
95!! [, olond, olatd, wlond, wlatd, rlond, rlatd ] )@endcode
96!> Returns a land surface topography that consists of a "set" of
97!! simple Gaussian-shaped mountains. The height, position,
98!! width, and elongation of the mountains can be controlled
99!! by variables in the namelist.
100function get_gaussian_topog_(lon, lat, height, &
101 olond, olatd, wlond, wlatd, rlond, rlatd ) &
102 result(zsurf )
103
104real(kind=fms_top_kind_), intent(in) :: lon(:), lat(:)
105real(kind=fms_top_kind_), intent(in) :: height
106real(kind=fms_top_kind_), intent(in), optional :: olond, olatd, wlond, wlatd, rlond, rlatd
107real(kind=fms_top_kind_) :: zsurf(size(lon,1),size(lat,1))
108
109integer :: i, j
110real(kind=fms_top_kind_) :: olon, olat, wlon, wlat, rlon, rlat
111real(kind=fms_top_kind_) :: tpi, dtr, dx, dy, xx, yy
112integer, parameter :: lkind = fms_top_kind_
113
114 if (do_nml) call read_namelist
115
116! no need to compute mountain if height=0
117 if ( height == 0.0_lkind) then
118 zsurf(:,:) = 0.0_lkind
119 return
120 endif
121
122 tpi = 2.0_lkind*real(pi, fms_top_kind_)
123 dtr = tpi/360.0_lkind
124
125! defaults and convert degrees to radians (dtr)
126 olon = 90.0_r8_kind*real(dtr, r8_kind); if (present(olond)) olon=real(olond*dtr,r8_kind)
127 olat = 45.0_r8_kind*real(dtr, r8_kind); if (present(olatd)) olat=real(olatd*dtr,r8_kind)
128 wlon = 15.0_r8_kind*real(dtr, r8_kind); if (present(wlond)) wlon=real(wlond*dtr,r8_kind)
129 wlat = 15.0_r8_kind*real(dtr, r8_kind); if (present(wlatd)) wlat=real(wlatd*dtr,r8_kind)
130 rlon = 0.0_r8_kind ; if (present(rlond)) rlon=real(rlond*dtr,r8_kind)
131 rlat = 0.0_r8_kind ; if (present(rlatd)) rlat=real(rlatd*dtr,r8_kind)
132
133! compute gaussian-shaped mountain
134 do j=1,size(lat(:))
135 dy = abs(lat(j) - real(olat,lkind)) ! dist from y origin
136 yy = max(0.0_lkind, dy-real(rlat,lkind))/real(wlat,lkind)
137 do i=1,size(lon(:))
138 dx = abs(lon(i) - real(olon,lkind)) ! dist from x origin
139 dx = min(dx, abs(dx-tpi)) ! To ensure that: -pi <= dx <= pi
140 xx = max(0.0_lkind, dx-real(rlon,lkind))/real(wlon,lkind)
141 zsurf(i,j) = real(height,lkind)*exp(-xx**2 - yy**2)
142 enddo
143 enddo
144
145end function get_gaussian_topog_
146
147!> @}
148! close documentation grouping
real(kind=fms_top_kind_) function, dimension(size(lon, 1), size(lat, 1)) get_gaussian_topog_(lon, lat, height, olond, olatd, wlond, wlatd, rlond, rlatd)
The height, position, width, and elongation of the mountain is controlled by optional arguments.
subroutine gaussian_topog_init_(lon, lat, zsurf)
Returns a simple surface height field that consists of a single Gaussian-shaped mountain.