29 implicit none ;
private 31 #include <MOM_memory.h> 44 logical :: use_abs_lat
58 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
63 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(inout) :: Kd
65 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
optional,
intent(inout) :: Kd_int
67 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(in) :: T_f
69 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional,
intent(in) :: S_f
71 real,
dimension(:,:,:),
optional,
pointer :: Kd_int_add
75 real :: Rcv(szi_(g),szk_(g))
76 real :: p_ref(szi_(g))
81 logical :: store_Kd_add
82 integer :: i, j, k, is, ie, js, je, nz
83 integer :: isd, ied, jsd, jed
87 character(len=200) :: mesg
89 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
90 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
92 if (.not.
associated(cs))
call mom_error(fatal,
"user_set_diffusivity: "//&
93 "Module must be initialized before it is used.")
95 use_eos =
associated(tv%eqn_of_state)
96 if (.not.use_eos)
return 97 store_kd_add = .false.
98 if (
present(kd_int_add)) store_kd_add =
associated(kd_int_add)
100 if (.not.
range_ok(cs%lat_range))
then 101 write(mesg,
'(4(1pe15.6))') cs%lat_range(1:4)
102 call mom_error(fatal,
"user_set_diffusivity: bad latitude range: \n "//&
105 if (.not.
range_ok(cs%rho_range))
then 106 write(mesg,
'(4(1pe15.6))') cs%rho_range(1:4)
107 call mom_error(fatal,
"user_set_diffusivity: bad density range: \n "//&
111 if (store_kd_add) kd_int_add(:,:,:) = 0.0
113 do i=is,ie ; p_ref(i) = tv%P_Ref ;
enddo 115 if (
present(t_f) .and.
present(s_f))
then 118 is,ie-is+1,tv%eqn_of_state)
123 is,ie-is+1,tv%eqn_of_state)
127 if (
present(kd))
then 128 do k=1,nz ;
do i=is,ie
129 if (cs%use_abs_lat)
then 130 lat_fn =
val_weights(abs(g%geoLatT(i,j)), cs%lat_range)
135 if (rho_fn * lat_fn > 0.0) &
136 kd(i,j,k) = kd(i,j,k) + cs%Kd_add * rho_fn * lat_fn
139 if (
present(kd_int))
then 140 do k=2,nz ;
do i=is,ie
141 if (cs%use_abs_lat)
then 142 lat_fn =
val_weights(abs(g%geoLatT(i,j)), cs%lat_range)
147 rho_fn =
val_weights( 0.5*(rcv(i,k-1) + rcv(i,k)), cs%rho_range)
148 if (rho_fn * lat_fn > 0.0)
then 149 kd_int(i,j,k) = kd_int(i,j,k) + cs%Kd_add * rho_fn * lat_fn
150 if (store_kd_add) kd_int_add(i,j,k) = cs%Kd_add * rho_fn * lat_fn
160 real,
dimension(4),
intent(in) :: range
164 ok = ((range(1) <= range(2)) .and. (range(2) <= range(3)) .and. &
165 (range(3) <= range(4)))
175 real,
intent(in) :: val
176 real,
dimension(4),
intent(in) :: range
182 if ((val > range(1)) .and. (val < range(4)))
then 183 if (val < range(2))
then 185 x = (val - range(1)) / (range(2) - range(1))
186 ans = x**2 * (3.0 - 2.0 * x)
187 elseif (val > range(3))
then 189 x = (range(4) - val) / (range(4) - range(3))
190 ans = x**2 * (3.0 - 2.0 * x)
200 type(time_type),
intent(in) :: Time
205 type(
diag_ctrl),
target,
intent(inout) :: diag
212 #include "version_variable.h" 213 character(len=40) :: mdl =
"user_set_diffusivity" 214 character(len=200) :: mesg
215 integer :: i, j, is, ie, js, je
217 if (
associated(cs))
then 218 call mom_error(warning,
"diabatic_entrain_init called with an associated "// &
219 "control structure.")
224 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
230 call get_param(param_file, mdl,
"USER_KD_ADD", cs%Kd_add, &
231 "A user-specified additional diffusivity over a range of \n"//&
232 "latitude and density.", units=
"m2 s-1", default=0.0)
233 if (cs%Kd_add /= 0.0)
then 234 call get_param(param_file, mdl,
"USER_KD_ADD_LAT_RANGE", cs%lat_range(:), &
235 "Four successive values that define a range of latitudes \n"//&
236 "over which the user-specified extra diffusivity is \n"//&
237 "applied. The four values specify the latitudes at \n"//&
238 "which the extra diffusivity starts to increase from 0, \n"//&
239 "hits its full value, starts to decrease again, and is \n"//&
240 "back to 0.", units=
"degree", default=-1.0e9)
241 call get_param(param_file, mdl,
"USER_KD_ADD_RHO_RANGE", cs%rho_range(:), &
242 "Four successive values that define a range of potential \n"//&
243 "densities over which the user-given extra diffusivity \n"//&
244 "is applied. The four values specify the density at \n"//&
245 "which the extra diffusivity starts to increase from 0, \n"//&
246 "hits its full value, starts to decrease again, and is \n"//&
247 "back to 0.", units=
"kg m-3", default=-1.0e9)
248 call get_param(param_file, mdl,
"USER_KD_ADD_USE_ABS_LAT", cs%use_abs_lat, &
249 "If true, use the absolute value of latitude when \n"//&
250 "checking whether a point fits into range of latitudes.", &
254 if (.not.
range_ok(cs%lat_range))
then 255 write(mesg,
'(4(1pe15.6))') cs%lat_range(1:4)
256 call mom_error(fatal,
"user_set_diffusivity: bad latitude range: \n "//&
259 if (.not.
range_ok(cs%rho_range))
then 260 write(mesg,
'(4(1pe15.6))') cs%rho_range(1:4)
261 call mom_error(fatal,
"user_set_diffusivity: bad density range: \n "//&
273 if (
associated(cs))
deallocate(cs)
logical function range_ok(range)
This subroutine checks whether the 4 values of range are in ascending order.
subroutine, public user_change_diff_end(CS)
Clean up the module control structure.
real function val_weights(val, range)
This subroutine returns a value that goes smoothly from 0 to 1, stays at 1, and then goes smoothly ba...
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
Provides the ocean grid type.
The vertvisc_type structure contains vertical viscosities, drag coefficients, and related fields...
subroutine, public user_change_diff_init(Time, G, param_file, diag, CS)
Set up the module control structure.
logical function, public is_root_pe()
Provides subroutines for quantities specific to the equation of state.
subroutine, public user_change_diff(h, tv, G, CS, Kd, Kd_int, T_f, S_f, Kd_int_add)
This subroutine provides an interface for a user to use to modify the main code to alter the diffusiv...
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
By Robert Hallberg, May 2012.
subroutine, public mom_error(level, message, all_print)