MOM6
benchmark_initialization.F90
1 !> Initialization for the "bench mark" configuration
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_sponge, only : sponge_cs, set_up_sponge_field, initialize_sponge
8 use mom_error_handler, only : mom_mesg, mom_error, fatal, is_root_pe
10 use mom_get_input, only : directories
11 use mom_grid, only : ocean_grid_type
17 
18 implicit none ; private
19 
20 #include <MOM_memory.h>
21 
22 public benchmark_initialize_topography
23 public benchmark_initialize_thickness
24 public benchmark_init_temperature_salinity
25 
26 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
27 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
28 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
29 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
30 
31 contains
32 
33 !> This subroutine sets up the benchmark test case topography.
34 subroutine benchmark_initialize_topography(D, G, param_file, max_depth, US)
35  type(dyn_horgrid_type), intent(in) :: g !< The dynamic horizontal grid type
36  real, dimension(G%isd:G%ied,G%jsd:G%jed), &
37  intent(out) :: d !< Ocean bottom depth in m or [Z ~> m] if US is present
38  type(param_file_type), intent(in) :: param_file !< Parameter file structure
39  real, intent(in) :: max_depth !< Maximum model depth in the units of D
40  type(unit_scale_type), optional, intent(in) :: us !< A dimensional unit scaling type
41 
42  ! Local variables
43  real :: min_depth ! The minimum and maximum depths [Z ~> m].
44  real :: pi ! 3.1415926... calculated as 4*atan(1)
45  real :: d0 ! A constant to make the maximum !
46  ! basin depth MAXIMUM_DEPTH. !
47  real :: m_to_z ! A dimensional rescaling factor.
48  real :: x, y
49  ! This include declares and sets the variable "version".
50 # include "version_variable.h"
51  character(len=40) :: mdl = "benchmark_initialize_topography" ! This subroutine's name.
52  integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
53  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
54  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
55 
56  call mom_mesg(" benchmark_initialization.F90, benchmark_initialize_topography: setting topography", 5)
57 
58  m_to_z = 1.0 ; if (present(us)) m_to_z = us%m_to_Z
59 
60  call log_version(param_file, mdl, version, "")
61  call get_param(param_file, mdl, "MINIMUM_DEPTH", min_depth, &
62  "The minimum depth of the ocean.", units="m", default=0.0, scale=m_to_z)
63 
64  pi = 4.0*atan(1.0)
65  d0 = max_depth / 0.5
66 
67 ! Calculate the depth of the bottom.
68  do j=js,je ; do i=is,ie
69  x = (g%geoLonT(i,j)-g%west_lon) / g%len_lon
70  y = (g%geoLatT(i,j)-g%south_lat) / g%len_lat
71 ! This sets topography that has a reentrant channel to the south.
72  d(i,j) = -d0 * ( y*(1.0 + 0.6*cos(4.0*pi*x)) &
73  + 0.75*exp(-6.0*y) &
74  + 0.05*cos(10.0*pi*x) - 0.7 )
75  if (d(i,j) > max_depth) d(i,j) = max_depth
76  if (d(i,j) < min_depth) d(i,j) = 0.
77  enddo ; enddo
78 
79 end subroutine benchmark_initialize_topography
80 
81 !> Initializes layer thicknesses for the benchmark test case,
82 !! by finding the depths of interfaces in a specified latitude-dependent
83 !! temperature profile with an exponentially decaying thermocline on top of a
84 !! linear stratification.
85 subroutine benchmark_initialize_thickness(h, G, GV, US, param_file, eqn_of_state, &
86  P_Ref, just_read_params)
87  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
88  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
89  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
90  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
91  intent(out) :: h !< The thickness that is being initialized [H ~> m or kg m-2].
92  type(param_file_type), intent(in) :: param_file !< A structure indicating the open file
93  !! to parse for model parameter values.
94  type(eos_type), pointer :: eqn_of_state !< Equation of state structure
95  real, intent(in) :: p_ref !< The coordinate-density
96  !! reference pressure [R L2 T-2 ~> Pa].
97  logical, optional, intent(in) :: just_read_params !< If present and true, this call will
98  !! only read parameters without changing h.
99  ! Local variables
100  real :: e0(szk_(gv)+1) ! The resting interface heights, in depth units [Z ~> m],
101  ! usually negative because it is positive upward.
102  real :: e_pert(szk_(gv)+1) ! Interface height perturbations, positive upward,
103  ! in depth units [Z ~> m].
104  real :: eta1d(szk_(gv)+1) ! Interface height relative to the sea surface
105  ! positive upward, in depth units [Z ~> m].
106  real :: sst ! The initial sea surface temperature [degC].
107  real :: t_int ! The initial temperature of an interface [degC].
108  real :: ml_depth ! The specified initial mixed layer depth, in depth units [Z ~> m].
109  real :: thermocline_scale ! The e-folding scale of the thermocline, in depth units [Z ~> m].
110  real, dimension(SZK_(GV)) :: &
111  t0, s0, & ! Profiles of temperature [degC] and salinity [ppt]
112  rho_guess, & ! Potential density at T0 & S0 [R ~> kg m-3].
113  drho_dt, & ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1].
114  drho_ds ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1].
115  real :: pres(szk_(gv)) ! Reference pressure [R L2 T-2 ~> Pa].
116  real :: a_exp ! The fraction of the overall stratification that is exponential.
117  real :: i_ts, i_md ! Inverse lengthscales [Z-1 ~> m-1].
118  real :: t_frac ! A ratio of the interface temperature to the range
119  ! between SST and the bottom temperature.
120  real :: err, derr_dz ! The error between the profile's temperature and the
121  ! interface temperature for a given z and its derivative.
122  real :: pi, z
123  logical :: just_read
124  ! This include declares and sets the variable "version".
125 # include "version_variable.h"
126  character(len=40) :: mdl = "benchmark_initialize_thickness" ! This subroutine's name.
127  integer :: i, j, k, k1, is, ie, js, je, nz, itt
128 
129  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
130 
131  just_read = .false. ; if (present(just_read_params)) just_read = just_read_params
132  if (.not.just_read) call log_version(param_file, mdl, version, "")
133  call get_param(param_file, mdl, "BENCHMARK_ML_DEPTH_IC", ml_depth, &
134  "Initial mixed layer depth in the benchmark test case.", &
135  units='m', default=50.0, scale=us%m_to_Z, do_not_log=just_read)
136  call get_param(param_file, mdl, "BENCHMARK_THERMOCLINE_SCALE", thermocline_scale, &
137  "Initial thermocline depth scale in the benchmark test case.", &
138  default=500.0, units="m", scale=us%m_to_Z, do_not_log=just_read)
139 
140  if (just_read) return ! This subroutine has no run-time parameters.
141 
142  call mom_mesg(" benchmark_initialization.F90, benchmark_initialize_thickness: setting thickness", 5)
143 
144  k1 = gv%nk_rho_varies + 1
145 
146  a_exp = 0.9
147 
148 ! This block calculates T0(k) for the purpose of diagnosing where the
149 ! interfaces will be found.
150  do k=1,nz
151  pres(k) = p_ref ; s0(k) = 35.0
152  enddo
153  t0(k1) = 29.0
154  call calculate_density(t0(k1), s0(k1), pres(k1), rho_guess(k1), eqn_of_state)
155  call calculate_density_derivs(t0(k1), s0(k1), pres(k1), drho_dt(k1), drho_ds(k1), eqn_of_state)
156 
157 ! A first guess of the layers' temperatures.
158  do k=1,nz
159  t0(k) = t0(k1) + (gv%Rlay(k) - rho_guess(k1)) / drho_dt(k1)
160  enddo
161 
162 ! Refine the guesses for each layer.
163  do itt=1,6
164  call calculate_density(t0, s0, pres, rho_guess, eqn_of_state)
165  call calculate_density_derivs(t0, s0, pres, drho_dt, drho_ds, eqn_of_state)
166  do k=1,nz
167  t0(k) = t0(k) + (gv%Rlay(k) - rho_guess(k)) / drho_dt(k)
168  enddo
169  enddo
170 
171  pi = 4.0*atan(1.0)
172  i_ts = 1.0 / thermocline_scale
173  i_md = 1.0 / g%max_depth
174  do j=js,je ; do i=is,ie
175  sst = 0.5*(t0(k1)+t0(nz)) - 0.9*0.5*(t0(k1)-t0(nz)) * &
176  cos(pi*(g%geoLatT(i,j)-g%south_lat)/(g%len_lat))
177 
178  do k=1,nz ; e_pert(k) = 0.0 ; enddo
179 
180  ! This sets the initial thickness (in [H ~> m or kg m-2]) of the layers. The thicknesses
181  ! are set to insure that: 1. each layer is at least Gv%Angstrom_m thick, and
182  ! 2. the interfaces are where they should be based on the resting depths and interface
183  ! height perturbations, as long at this doesn't interfere with 1.
184  eta1d(nz+1) = -g%bathyT(i,j)
185 
186  do k=nz,2,-1
187  t_int = 0.5*(t0(k) + t0(k-1))
188  t_frac = (t_int - t0(nz)) / (sst - t0(nz))
189  ! Find the z such that T_frac = a exp(z/thermocline_scale) + (1-a) (z+D)/D
190  z = 0.0
191  do itt=1,6
192  err = a_exp * exp(z*i_ts) + (1.0 - a_exp) * (z*i_md + 1.0) - t_frac
193  derr_dz = a_exp * i_ts * exp(z*i_ts) + (1.0 - a_exp) * i_md
194  z = z - err / derr_dz
195  enddo
196  e0(k) = z
197 ! e0(K) = -ML_depth + thermocline_scale * log((T_int - T0(nz)) / (SST - T0(nz)))
198 
199  eta1d(k) = e0(k) + e_pert(k)
200 
201  if (eta1d(k) > -ml_depth) eta1d(k) = -ml_depth
202 
203  if (eta1d(k) < eta1d(k+1) + gv%Angstrom_Z) &
204  eta1d(k) = eta1d(k+1) + gv%Angstrom_Z
205 
206  h(i,j,k) = max(gv%Z_to_H * (eta1d(k) - eta1d(k+1)), gv%Angstrom_H)
207  enddo
208  h(i,j,1) = max(gv%Z_to_H * (0.0 - eta1d(2)), gv%Angstrom_H)
209 
210  enddo ; enddo
211 
212 end subroutine benchmark_initialize_thickness
213 
214 !> Initializes layer temperatures and salinities for benchmark
215 subroutine benchmark_init_temperature_salinity(T, S, G, GV, US, param_file, &
216  eqn_of_state, P_Ref, just_read_params)
217  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
218  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure.
219  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: t !< The potential temperature
220  !! that is being initialized.
221  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: s !< The salinity that is being
222  !! initialized.
223  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
224  type(param_file_type), intent(in) :: param_file !< A structure indicating the
225  !! open file to parse for
226  !! model parameter values.
227  type(eos_type), pointer :: eqn_of_state !< Equation of state structure
228  real, intent(in) :: p_ref !< The coordinate-density
229  !! reference pressure [R L2 T-2 ~> Pa].
230  logical, optional, intent(in) :: just_read_params !< If present and true, this call will
231  !! only read parameters without changing h.
232  ! Local variables
233  real :: t0(szk_(g)), s0(szk_(g))
234  real :: pres(szk_(g)) ! Reference pressure [R L2 T-2 ~> Pa].
235  real :: drho_dt(szk_(g)) ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1].
236  real :: drho_ds(szk_(g)) ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1].
237  real :: rho_guess(szk_(g)) ! Potential density at T0 & S0 [R ~> kg m-3].
238  real :: pi ! 3.1415926... calculated as 4*atan(1)
239  real :: sst ! The initial sea surface temperature [degC].
240  real :: lat
241  logical :: just_read ! If true, just read parameters but set nothing.
242  character(len=40) :: mdl = "benchmark_init_temperature_salinity" ! This subroutine's name.
243  integer :: i, j, k, k1, is, ie, js, je, nz, itt
244 
245  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
246 
247  just_read = .false. ; if (present(just_read_params)) just_read = just_read_params
248 
249  if (just_read) return ! All run-time parameters have been read, so return.
250 
251  k1 = gv%nk_rho_varies + 1
252 
253  do k=1,nz
254  pres(k) = p_ref ; s0(k) = 35.0
255  enddo
256 
257  t0(k1) = 29.0
258  call calculate_density(t0(k1), s0(k1), pres(k1), rho_guess(k1), eqn_of_state)
259  call calculate_density_derivs(t0, s0, pres, drho_dt, drho_ds, eqn_of_state, (/k1,k1/) )
260 
261 ! A first guess of the layers' temperatures. !
262  do k=1,nz
263  t0(k) = t0(k1) + (gv%Rlay(k) - rho_guess(k1)) / drho_dt(k1)
264  enddo
265 
266 ! Refine the guesses for each layer. !
267  do itt = 1,6
268  call calculate_density(t0, s0, pres, rho_guess, eqn_of_state)
269  call calculate_density_derivs(t0, s0, pres, drho_dt, drho_ds, eqn_of_state)
270  do k=1,nz
271  t0(k) = t0(k) + (gv%Rlay(k) - rho_guess(k)) / drho_dt(k)
272  enddo
273  enddo
274 
275  do k=1,nz ; do i=is,ie ; do j=js,je
276  t(i,j,k) = t0(k)
277  s(i,j,k) = s0(k)
278  enddo ; enddo ; enddo
279  pi = 4.0*atan(1.0)
280  do i=is,ie ; do j=js,je
281  sst = 0.5*(t0(k1)+t0(nz)) - 0.9*0.5*(t0(k1)-t0(nz)) * &
282  cos(pi*(g%geoLatT(i,j)-g%south_lat)/(g%len_lat))
283  do k=1,k1-1
284  t(i,j,k) = sst
285  enddo
286  enddo ; enddo
287 
288 end subroutine benchmark_init_temperature_salinity
289 
290 end module benchmark_initialization
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:68
Reads the only Fortran name list needed to boot-strap the model.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Definition: MOM_grid.F90:2
Describes the horizontal ocean grid with only dynamic memory arrays.
The MOM6 facility to parse input files for runtime parameters.
Describes various unit conversion factors.
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Type to carry basic tracer information.
Routines for error handling and I/O management.
This control structure holds memory and parameters for the MOM_sponge module.
Definition: MOM_sponge.F90:41
Implements sponge regions in isopycnal mode.
Definition: MOM_sponge.F90:2
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Definition: MOM_EOS.F90:81
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Initialization for the "bench mark" configuration.
Container for paths and parameter file names.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Contains a shareable dynamic type for describing horizontal grids and metric data and utilty routines...
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.
A control structure for the equation of state.
Definition: MOM_EOS.F90:108