MOM6
dumbbell_surface_forcing.F90
1 !> Surface forcing for the dumbbell test case
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_diag_mediator, only : post_data, query_averaging_enabled
7 use mom_diag_mediator, only : register_diag_field, diag_ctrl
8 use mom_domains, only : pass_var, pass_vector, agrid
9 use mom_error_handler, only : mom_error, fatal, warning, is_root_pe
12 use mom_grid, only : ocean_grid_type
13 use mom_io, only : file_exists, read_data
15 use mom_time_manager, only : time_type, operator(+), operator(/), get_time
16 use mom_tracer_flow_control, only : call_tracer_set_forcing
19 use mom_variables, only : surface
20 
21 implicit none ; private
22 
23 public dumbbell_dynamic_forcing, dumbbell_buoyancy_forcing, dumbbell_surface_forcing_init
24 
25 !> Control structure for the dumbbell test case forcing
26 type, public :: dumbbell_surface_forcing_cs ; private
27  logical :: use_temperature !< If true, temperature and salinity are used as state variables.
28  logical :: restorebuoy !< If true, use restoring surface buoyancy forcing.
29  real :: rho0 !< The density used in the Boussinesq approximation [R ~> kg m-3].
30  real :: g_earth !< The gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
31  real :: flux_const !< The restoring rate at the surface [Z T-1 ~> m s-1].
32 ! real :: gust_const !< A constant unresolved background gustiness
33 ! !! that contributes to ustar [R L Z T-2 ~> Pa].
34  real :: slp_amplitude !< The amplitude of pressure loading [R L2 T-2 ~> Pa] applied
35  !! to the reservoirs
36  real :: slp_period !< Period of sinusoidal pressure wave [days]
37  real, dimension(:,:), allocatable :: &
38  forcing_mask !< A mask regulating where forcing occurs
39  real, dimension(:,:), allocatable :: &
40  s_restore !< The surface salinity field toward which to restore [ppt].
41  type(diag_ctrl), pointer :: diag => null() !< A structure that is used to regulate the
42  !! timing of diagnostic output.
44 
45 contains
46 
47 !> Surface buoyancy (heat and fresh water) fluxes for the dumbbell test case
48 subroutine dumbbell_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS)
49  type(surface), intent(inout) :: sfc_state !< A structure containing fields that
50  !! describe the surface state of the ocean.
51  type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
52  !! possible forcing fields. Unused fields
53  !! have NULL ptrs.
54  type(time_type), intent(in) :: day !< Time of the fluxes.
55  real, intent(in) :: dt !< The amount of time over which
56  !! the fluxes apply [s]
57  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
58  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
59  type(dumbbell_surface_forcing_cs), pointer :: cs !< A control structure returned by a previous
60  !! call to dumbbell_surface_forcing_init
61  ! Local variables
62  real :: temp_restore ! The temperature that is being restored toward [degC].
63  real :: salin_restore ! The salinity that is being restored toward [ppt].
64  integer :: i, j, is, ie, js, je
65  integer :: isd, ied, jsd, jed
66 
67  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
68  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
69 
70 
71  ! Allocate and zero out the forcing arrays, as necessary.
72  if (cs%use_temperature) then
73  call safe_alloc_ptr(fluxes%evap, isd, ied, jsd, jed)
74  call safe_alloc_ptr(fluxes%lprec, isd, ied, jsd, jed)
75  call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed)
76  call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed)
77  call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed)
78  call safe_alloc_ptr(fluxes%vprec, isd, ied, jsd, jed)
79 
80  call safe_alloc_ptr(fluxes%sw, isd, ied, jsd, jed)
81  call safe_alloc_ptr(fluxes%lw, isd, ied, jsd, jed)
82  call safe_alloc_ptr(fluxes%latent, isd, ied, jsd, jed)
83  call safe_alloc_ptr(fluxes%sens, isd, ied, jsd, jed)
84  else ! This is the buoyancy only mode.
85  call safe_alloc_ptr(fluxes%buoy, isd, ied, jsd, jed)
86  endif
87 
88 
89  ! MODIFY THE CODE IN THE FOLLOWING LOOPS TO SET THE BUOYANCY FORCING TERMS.
90 
91  if ( cs%use_temperature ) then
92  ! Set whichever fluxes are to be used here. Any fluxes that
93  ! are always zero do not need to be changed here.
94  do j=js,je ; do i=is,ie
95  ! Fluxes of fresh water through the surface are in units of [R Z T-1 ~> kg m-2 s-1]
96  ! and are positive downward - i.e. evaporation should be negative.
97  fluxes%evap(i,j) = -0.0 * g%mask2dT(i,j)
98  fluxes%lprec(i,j) = 0.0 * g%mask2dT(i,j)
99 
100  ! vprec will be set later, if it is needed for salinity restoring.
101  fluxes%vprec(i,j) = 0.0
102 
103  ! Heat fluxes are in units of [Q R Z T-1 ~> W m-2] and are positive into the ocean.
104  fluxes%lw(i,j) = 0.0 * g%mask2dT(i,j)
105  fluxes%latent(i,j) = 0.0 * g%mask2dT(i,j)
106  fluxes%sens(i,j) = 0.0 * g%mask2dT(i,j)
107  fluxes%sw(i,j) = 0.0 * g%mask2dT(i,j)
108  enddo ; enddo
109  else ! This is the buoyancy only mode.
110  do j=js,je ; do i=is,ie
111  ! fluxes%buoy is the buoyancy flux into the ocean [L2 T-3 ~> m2 s-3]. A positive
112  ! buoyancy flux is of the same sign as heating the ocean.
113  fluxes%buoy(i,j) = 0.0 * g%mask2dT(i,j)
114  enddo ; enddo
115  endif
116 
117  if (cs%use_temperature .and. cs%restorebuoy) then
118  do j=js,je ; do i=is,ie
119  if (cs%forcing_mask(i,j)>0.) then
120  fluxes%vprec(i,j) = - (g%mask2dT(i,j) * (cs%Rho0*cs%Flux_const)) * &
121  ((cs%S_restore(i,j) - sfc_state%SSS(i,j)) / (0.5 * (cs%S_restore(i,j) + sfc_state%SSS(i,j))))
122 
123  endif
124  enddo ; enddo
125  endif
126 
127 end subroutine dumbbell_buoyancy_forcing
128 
129 !> Dynamic forcing for the dumbbell test case
130 subroutine dumbbell_dynamic_forcing(sfc_state, fluxes, day, dt, G, CS)
131  type(surface), intent(inout) :: sfc_state !< A structure containing fields that
132  !! describe the surface state of the ocean.
133  type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
134  !! possible forcing fields. Unused fields
135  !! have NULL ptrs.
136  type(time_type), intent(in) :: day !< Time of the fluxes.
137  real, intent(in) :: dt !< The amount of time over which
138  !! the fluxes apply [s]
139  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
140  type(dumbbell_surface_forcing_cs), pointer :: cs !< A control structure returned by a previous
141  !! call to dumbbell_surface_forcing_init
142  ! Local variables
143  integer :: i, j, is, ie, js, je
144  integer :: isd, ied, jsd, jed
145  integer :: idays, isecs
146  real :: deg_rad, rdays
147 
148 
149  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
150  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
151 
152  deg_rad = atan(1.0)*4.0/180.
153 
154  call get_time(day,isecs,idays)
155  rdays = real(idays) + real(isecs)/8.64e4
156  ! This could be: rdays = time_type_to_real(day)/8.64e4
157 
158  ! Allocate and zero out the forcing arrays, as necessary.
159  call safe_alloc_ptr(fluxes%p_surf, isd, ied, jsd, jed)
160  call safe_alloc_ptr(fluxes%p_surf_full, isd, ied, jsd, jed)
161 
162  do j=js,je ; do i=is,ie
163  fluxes%p_surf(i,j) = cs%forcing_mask(i,j)* cs%slp_amplitude * &
164  g%mask2dT(i,j) * sin(deg_rad*(rdays/cs%slp_period))
165  fluxes%p_surf_full(i,j) = cs%forcing_mask(i,j) * cs%slp_amplitude * &
166  g%mask2dT(i,j) * sin(deg_rad*(rdays/cs%slp_period))
167  enddo ; enddo
168 
169 end subroutine dumbbell_dynamic_forcing
170 
171 !> Reads and sets up the forcing for the dumbbell test case
172 subroutine dumbbell_surface_forcing_init(Time, G, US, param_file, diag, CS)
173  type(time_type), intent(in) :: time !< The current model time.
174  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
175  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
176  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
177  type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to
178  !! regulate diagnostic output.
180  pointer :: cs !< A pointer to the control structure for this module
181  ! Local variables
182  real :: s_surf, s_range
183  real :: x, y
184  integer :: i, j
185  logical :: dbrotate ! If true, rotate the domain.
186 #include "version_variable.h"
187  character(len=40) :: mdl = "dumbbell_surface_forcing" ! This module's name.
188 
189  if (associated(cs)) then
190  call mom_error(warning, "dumbbell_surface_forcing_init called with an associated "// &
191  "control structure.")
192  return
193  endif
194  allocate(cs)
195  cs%diag => diag
196 
197  ! Read all relevant parameters and write them to the model log.
198  call log_version(param_file, mdl, version, "")
199  call get_param(param_file, mdl, "ENABLE_THERMODYNAMICS", cs%use_temperature, &
200  "If true, Temperature and salinity are used as state variables.", default=.true.)
201 
202  call get_param(param_file, mdl, "G_EARTH", cs%G_Earth, &
203  "The gravitational acceleration of the Earth.", &
204  units="m s-2", default = 9.80, scale=us%m_to_L**2*us%Z_to_m*us%T_to_s**2)
205  call get_param(param_file, mdl, "RHO_0", cs%Rho0, &
206  "The mean ocean density used with BOUSSINESQ true to "//&
207  "calculate accelerations and the mass for conservation "//&
208  "properties, or with BOUSSINSEQ false to convert some "//&
209  "parameters from vertical units of m to kg m-2.", &
210  units="kg m-3", default=1035.0, scale=us%kg_m3_to_R)
211  call get_param(param_file, mdl, "DUMBBELL_SLP_AMP", cs%slp_amplitude, &
212  "Amplitude of SLP forcing in reservoirs.", &
213  units="Pa", default = 10000.0, scale=us%kg_m3_to_R*us%m_s_to_L_T**2)
214  call get_param(param_file, mdl, "DUMBBELL_SLP_PERIOD", cs%slp_period, &
215  "Periodicity of SLP forcing in reservoirs.", &
216  units="days", default = 1.0)
217  call get_param(param_file, mdl, "DUMBBELL_ROTATION", dbrotate, &
218  'Logical for rotation of dumbbell domain.',&
219  units='nondim', default=.false., do_not_log=.true.)
220  call get_param(param_file, mdl,"INITIAL_SSS", s_surf, &
221  "Initial surface salinity", units="1e-3", default=34.0, do_not_log=.true.)
222  call get_param(param_file, mdl,"INITIAL_S_RANGE", s_range, &
223  "Initial salinity range (bottom - surface)", units="1e-3", &
224  default=2., do_not_log=.true.)
225 
226  call get_param(param_file, mdl, "RESTOREBUOY", cs%restorebuoy, &
227  "If true, the buoyancy fluxes drive the model back "//&
228  "toward some specified surface state with a rate "//&
229  "given by FLUXCONST.", default= .false.)
230  if (cs%restorebuoy) then
231  call get_param(param_file, mdl, "FLUXCONST", cs%Flux_const, &
232  "The constant that relates the restoring surface fluxes to the relative "//&
233  "surface anomalies (akin to a piston velocity). Note the non-MKS units.", &
234  default=0.0, units="m day-1", scale=us%m_to_Z*us%T_to_s)
235  ! Convert CS%Flux_const from m day-1 to m s-1.
236  cs%Flux_const = cs%Flux_const / 86400.0
237 
238 
239  allocate(cs%forcing_mask(g%isd:g%ied, g%jsd:g%jed)); cs%forcing_mask(:,:)=0.0
240  allocate(cs%S_restore(g%isd:g%ied, g%jsd:g%jed))
241 
242  do j=g%jsc,g%jec
243  do i=g%isc,g%iec
244  ! Compute normalized zonal coordinates (x,y=0 at center of domain)
245 ! x = ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon - 0.5
246 ! y = ( G%geoLatT(i,j) - G%south_lat ) / G%len_lat - 0.5
247  if (dbrotate) then
248  ! This is really y in the rotated case
249  x = ( g%geoLatT(i,j) - g%south_lat ) / g%len_lat - 0.5
250  else
251  x = ( g%geoLonT(i,j) - g%west_lon ) / g%len_lon - 0.5
252  endif
253  cs%forcing_mask(i,j)=0
254  cs%S_restore(i,j) = s_surf
255  if ((x>0.25)) then
256  cs%forcing_mask(i,j) = 1
257  cs%S_restore(i,j) = s_surf + s_range
258  elseif ((x<-0.25)) then
259  cs%forcing_mask(i,j) = 1
260  cs%S_restore(i,j) = s_surf - s_range
261  endif
262  enddo
263  enddo
264  endif
265 
266 end subroutine dumbbell_surface_forcing_init
267 
268 end module dumbbell_surface_forcing
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
mom_variables::surface
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Definition: MOM_variables.F90:41
mom_safe_alloc
Convenience functions for safely allocating memory without accidentally reallocating pointer and caus...
Definition: MOM_safe_alloc.F90:3
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_domains::pass_var
Do a halo update on an array.
Definition: MOM_domains.F90:54
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_domains::pass_vector
Do a halo update on a pair of arrays representing the two components of a vector.
Definition: MOM_domains.F90:59
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_forcing_type::allocate_forcing_type
Allocate the fields of a (flux) forcing type, based on either a set of input flags for each group of ...
Definition: MOM_forcing_type.F90:43
mom_domains
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_tracer_flow_control
Orchestrates the registration and calling of tracer packages.
Definition: MOM_tracer_flow_control.F90:2
dumbbell_surface_forcing
Surface forcing for the dumbbell test case.
Definition: dumbbell_surface_forcing.F90:2
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_tracer_flow_control::tracer_flow_control_cs
The control structure for orchestrating the calling of tracer packages.
Definition: MOM_tracer_flow_control.F90:73
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:66
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
dumbbell_surface_forcing::dumbbell_surface_forcing_cs
Control structure for the dumbbell test case forcing.
Definition: dumbbell_surface_forcing.F90:26
mom_safe_alloc::safe_alloc_ptr
Allocate a pointer to a 1-d, 2-d or 3-d array.
Definition: MOM_safe_alloc.F90:12
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:240