MOM6
dumbbell_surface_forcing Module Reference

Detailed Description

Surface forcing for the dumbbell test case.

Data Types

type  dumbbell_surface_forcing_cs
 Control structure for the dumbbell test case forcing. More...
 

Functions/Subroutines

subroutine, public dumbbell_buoyancy_forcing (sfc_state, fluxes, day, dt, G, US, CS)
 Surface buoyancy (heat and fresh water) fluxes for the dumbbell test case. More...
 
subroutine, public dumbbell_dynamic_forcing (sfc_state, fluxes, day, dt, G, CS)
 Dynamic forcing for the dumbbell test case. More...
 
subroutine, public dumbbell_surface_forcing_init (Time, G, US, param_file, diag, CS)
 Reads and sets up the forcing for the dumbbell test case. More...
 

Function/Subroutine Documentation

◆ dumbbell_buoyancy_forcing()

subroutine, public dumbbell_surface_forcing::dumbbell_buoyancy_forcing ( type(surface), intent(inout)  sfc_state,
type(forcing), intent(inout)  fluxes,
type(time_type), intent(in)  day,
real, intent(in)  dt,
type(ocean_grid_type), intent(in)  G,
type(unit_scale_type), intent(in)  US,
type(dumbbell_surface_forcing_cs), pointer  CS 
)

Surface buoyancy (heat and fresh water) fluxes for the dumbbell test case.

Parameters
[in,out]sfc_stateA structure containing fields that describe the surface state of the ocean.
[in,out]fluxesA structure containing pointers to any possible forcing fields. Unused fields have NULL ptrs.
[in]dayTime of the fluxes.
[in]dtThe amount of time over which the fluxes apply [s]
[in]gThe ocean's grid structure
[in]usA dimensional unit scaling type
csA control structure returned by a previous call to dumbbell_surface_forcing_init

Definition at line 49 of file dumbbell_surface_forcing.F90.

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 

◆ dumbbell_dynamic_forcing()

subroutine, public dumbbell_surface_forcing::dumbbell_dynamic_forcing ( type(surface), intent(inout)  sfc_state,
type(forcing), intent(inout)  fluxes,
type(time_type), intent(in)  day,
real, intent(in)  dt,
type(ocean_grid_type), intent(in)  G,
type(dumbbell_surface_forcing_cs), pointer  CS 
)

Dynamic forcing for the dumbbell test case.

Parameters
[in,out]sfc_stateA structure containing fields that describe the surface state of the ocean.
[in,out]fluxesA structure containing pointers to any possible forcing fields. Unused fields have NULL ptrs.
[in]dayTime of the fluxes.
[in]dtThe amount of time over which the fluxes apply [s]
[in]gThe ocean's grid structure
csA control structure returned by a previous call to dumbbell_surface_forcing_init

Definition at line 131 of file dumbbell_surface_forcing.F90.

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 

◆ dumbbell_surface_forcing_init()

subroutine, public dumbbell_surface_forcing::dumbbell_surface_forcing_init ( type(time_type), intent(in)  Time,
type(ocean_grid_type), intent(in)  G,
type(unit_scale_type), intent(in)  US,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(in), target  diag,
type(dumbbell_surface_forcing_cs), pointer  CS 
)

Reads and sets up the forcing for the dumbbell test case.

Parameters
[in]timeThe current model time.
[in]gThe ocean's grid structure
[in]usA dimensional unit scaling type
[in]param_fileA structure to parse for run-time parameters
[in]diagA structure that is used to regulate diagnostic output.
csA pointer to the control structure for this module

Definition at line 173 of file dumbbell_surface_forcing.F90.

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.
179  type(dumbbell_surface_forcing_CS), &
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