28 use mom_time_manager,
only : time_type,
operator(+),
operator(/), time_type_to_real
33 implicit none ;
private 35 #include <MOM_memory.h> 37 public idealized_hurricane_wind_init
39 public idealized_hurricane_wind_forcing
41 public scm_idealized_hurricane_wind_forcing
49 real :: pressure_ambient
50 real :: pressure_central
53 real :: hurr_translation_spd
54 real :: hurr_translation_dir
65 real :: holland_axbxdp
67 logical :: relative_tau
69 logical :: answers_2018
79 real :: dy_from_center
88 #include "version_variable.h" 90 character(len=40) :: mdl =
"idealized_hurricane" 95 subroutine idealized_hurricane_wind_init(Time, G, US, param_file, CS)
96 type(time_type),
intent(in) :: time
105 logical :: default_2018_answers
108 # include "version_variable.h" 110 if (
associated(cs))
then 111 call mom_error(fatal,
"idealized_hurricane_wind_init called "// &
112 "with an associated control structure.")
118 cs%pi = 4.0*atan(1.0)
119 cs%Deg2Rad = cs%pi/180.
125 call get_param(param_file, mdl,
"IDL_HURR_RHO_AIR", cs%rho_a, &
126 "Air density used to compute the idealized hurricane wind profile.", &
127 units=
'kg/m3', default=1.2, scale=us%kg_m3_to_R)
128 call get_param(param_file, mdl,
"IDL_HURR_AMBIENT_PRESSURE", cs%pressure_ambient, &
129 "Ambient pressure used in the idealized hurricane wind profile.", &
130 units=
'Pa', default=101200., scale=us%m_s_to_L_T**2*us%kg_m3_to_R)
131 call get_param(param_file, mdl,
"IDL_HURR_CENTRAL_PRESSURE", cs%pressure_central, &
132 "Central pressure used in the idealized hurricane wind profile.", &
133 units=
'Pa', default=96800., scale=us%m_s_to_L_T**2*us%kg_m3_to_R)
134 call get_param(param_file, mdl,
"IDL_HURR_RAD_MAX_WIND", &
135 cs%rad_max_wind,
"Radius of maximum winds used in the "//&
136 "idealized hurricane wind profile.", units=
'm', &
137 default=50.e3, scale=us%m_to_L)
138 call get_param(param_file, mdl,
"IDL_HURR_MAX_WIND", cs%max_windspeed, &
139 "Maximum wind speed used in the idealized hurricane"// &
140 "wind profile.", units=
'm/s', default=65., scale=us%m_s_to_L_T)
141 call get_param(param_file, mdl,
"IDL_HURR_TRAN_SPEED", cs%hurr_translation_spd, &
142 "Translation speed of hurricane used in the idealized "//&
143 "hurricane wind profile.", units=
'm/s', default=5.0, scale=us%m_s_to_L_T)
144 call get_param(param_file, mdl,
"IDL_HURR_TRAN_DIR", cs%hurr_translation_dir, &
145 "Translation direction (towards) of hurricane used in the "//&
146 "idealized hurricane wind profile.", units=
'degrees', &
147 default=180.0, scale=cs%Deg2Rad)
148 call get_param(param_file, mdl,
"IDL_HURR_X0", cs%Hurr_cen_X0, &
149 "Idealized Hurricane initial X position", &
150 units=
'm', default=0., scale=us%m_to_L)
151 call get_param(param_file, mdl,
"IDL_HURR_Y0", cs%Hurr_cen_Y0, &
152 "Idealized Hurricane initial Y position", &
153 units=
'm', default=0., scale=us%m_to_L)
154 call get_param(param_file, mdl,
"IDL_HURR_TAU_CURR_REL", cs%relative_tau, &
155 "Current relative stress switch "//&
156 "used in the idealized hurricane wind profile.", &
157 units=
'', default=.false.)
160 call get_param(param_file, mdl,
"IDL_HURR_SCM_BR_BENCH", cs%BR_BENCH, &
161 "Single column mode benchmark case switch, which is "// &
162 "invoking a modification (bug) in the wind profile meant to "//&
163 "reproduce a previous implementation.", units=
'', default=.false.)
164 call get_param(param_file, mdl,
"IDL_HURR_SCM", cs%SCM_MODE, &
165 "Single Column mode switch "//&
166 "used in the SCM idealized hurricane wind profile.", &
167 units=
'', default=.false.)
168 call get_param(param_file, mdl,
"IDL_HURR_SCM_LOCY", cs%dy_from_center, &
169 "Y distance of station used in the SCM idealized hurricane "//&
170 "wind profile.", units=
'm', default=50.e3, scale=us%m_to_L)
171 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
172 "This sets the default value for the various _2018_ANSWERS parameters.", &
174 call get_param(param_file, mdl,
"IDL_HURR_2018_ANSWERS", cs%answers_2018, &
175 "If true, use expressions driving the idealized hurricane test case that recover "//&
176 "the answers from the end of 2018. Otherwise use expressions that are rescalable "//&
177 "and respect rotational symmetry.", default=default_2018_answers)
182 call get_param(param_file, mdl,
"RHO_0", cs%Rho0, &
183 "The mean ocean density used with BOUSSINESQ true to "//&
184 "calculate accelerations and the mass for conservation "//&
185 "properties, or with BOUSSINSEQ false to convert some "//&
186 "parameters from vertical units of m to kg m-2.", &
187 units=
"kg m-3", default=1035.0, scale=us%kg_m3_to_R, do_not_log=.true.)
188 call get_param(param_file, mdl,
"GUST_CONST", cs%gustiness, &
189 "The background gustiness in the winds.", units=
"Pa", &
190 default=0.0, scale=us%kg_m3_to_R*us%m_s_to_L_T**2*us%L_to_Z, do_not_log=.true.)
192 if (cs%BR_BENCH)
then 193 cs%rho_a = 1.2*us%kg_m3_to_R
195 dp = cs%pressure_ambient - cs%pressure_central
196 if (cs%answers_2018)
then 197 c = cs%max_windspeed / sqrt( us%R_to_kg_m3 * dp )
198 cs%Holland_B = c**2 * us%R_to_kg_m3*cs%rho_a * exp(1.0)
200 cs%Holland_B = cs%max_windspeed**2 * cs%rho_a * exp(1.0) / dp
202 cs%Holland_A = (us%L_to_m*cs%rad_max_wind)**cs%Holland_B
203 cs%Holland_AxBxDP = cs%Holland_A*cs%Holland_B*dp
205 end subroutine idealized_hurricane_wind_init
208 subroutine idealized_hurricane_wind_forcing(sfc_state, forces, day, G, US, CS)
211 type(time_type),
intent(in) :: day
217 integer :: i, j, is, ie, js, je, isq, ieq, jsq, jeq
218 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb
232 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
233 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
234 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
235 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
240 if (cs%relative_tau)
then 247 xc = cs%Hurr_cen_X0 + (time_type_to_real(day)*us%s_to_T * cs%hurr_translation_spd * &
248 cos(cs%hurr_translation_dir))
249 yc = cs%Hurr_cen_Y0 + (time_type_to_real(day)*us%s_to_T * cs%hurr_translation_spd * &
250 sin(cs%hurr_translation_dir))
253 if (cs%BR_Bench)
then 255 fbench = 5.5659e-05 * us%T_to_s
265 uocn = sfc_state%u(i,j) * rel_tau_fac
266 if (cs%answers_2018)
then 267 vocn = 0.25*(sfc_state%v(i,j)+sfc_state%v(i+1,j-1)&
268 +sfc_state%v(i+1,j)+sfc_state%v(i,j-1))*rel_tau_fac
270 vocn =0.25*((sfc_state%v(i,j)+sfc_state%v(i+1,j-1)) +&
271 (sfc_state%v(i+1,j)+sfc_state%v(i,j-1))) * rel_tau_fac
273 f_local = abs(0.5*(g%CoriolisBu(i,j)+g%CoriolisBu(i,j-1)))*fbench_fac + fbench
275 if (cs%SCM_mode)
then 276 yy = yc + cs%dy_from_center
279 yy = g%geoLatCu(i,j)*1000.*us%m_to_L - yc
280 xx = g%geoLonCu(i,j)*1000.*us%m_to_L - xc
282 call idealized_hurricane_wind_profile(cs, us, f_local, yy, xx, uocn, vocn, tx, ty)
283 forces%taux(i,j) = g%mask2dCu(i,j) * tx
289 if (cs%answers_2018)
then 290 uocn = 0.25*(sfc_state%u(i,j)+sfc_state%u(i-1,j+1) + &
291 sfc_state%u(i-1,j)+sfc_state%u(i,j+1))*rel_tau_fac
293 uocn = 0.25*((sfc_state%u(i,j)+sfc_state%u(i-1,j+1)) + &
294 (sfc_state%u(i-1,j)+sfc_state%u(i,j+1))) * rel_tau_fac
296 vocn = sfc_state%v(i,j) * rel_tau_fac
297 f_local = abs(0.5*(g%CoriolisBu(i-1,j)+g%CoriolisBu(i,j)))*fbench_fac + fbench
299 if (cs%SCM_mode)
then 300 yy = yc + cs%dy_from_center
303 yy = g%geoLatCv(i,j)*1000.*us%m_to_L - yc
304 xx = g%geoLonCv(i,j)*1000.*us%m_to_L - xc
306 call idealized_hurricane_wind_profile(cs, us, f_local, yy, xx, uocn, vocn, tx, ty)
307 forces%tauy(i,j) = g%mask2dCv(i,j) * ty
315 forces%ustar(i,j) = g%mask2dT(i,j) * sqrt(us%L_to_Z * (cs%gustiness/cs%Rho0 + &
316 sqrt(0.5*(forces%taux(i-1,j)**2 + forces%taux(i,j)**2) + &
317 0.5*(forces%tauy(i,j-1)**2 + forces%tauy(i,j)**2))/cs%Rho0))
322 end subroutine idealized_hurricane_wind_forcing
325 subroutine idealized_hurricane_wind_profile(CS, US, absf, YY, XX, UOCN, VOCN, Tx, Ty)
333 real,
intent(in) :: absf
334 real,
intent(in) :: YY
335 real,
intent(in) :: XX
336 real,
intent(in) :: UOCN
337 real,
intent(in) :: VOCN
338 real,
intent(out) :: Tx
339 real,
intent(out) :: Ty
367 radius = sqrt(xx**2 + yy**2)
375 if (cs%BR_Bench)
then 376 radius_km = radius/1000.
381 radiusb = (us%L_to_m*radius)**cs%Holland_B
386 if (cs%answers_2018)
then 387 if ( (radius > 0.001*cs%rad_max_wind) .and. (radius < 10.*cs%rad_max_wind) )
then 388 u10 = sqrt(cs%Holland_AxBxDP*exp(-cs%Holland_A/radiusb) / (cs%rho_a*radiusb) + &
389 0.25*(radius_km*absf)**2) - 0.5*radius_km*absf
390 elseif ( (radius > 10.*cs%rad_max_wind) .and. (radius < 15.*cs%rad_max_wind) )
then 391 radius10 = cs%rad_max_wind*10.
392 if (cs%BR_Bench)
then 393 radius_km = radius10/1000.
397 radiusb = (us%L_to_m*radius10)**cs%Holland_B
399 u10 = (sqrt(cs%Holland_AxBxDp*exp(-cs%Holland_A/radiusb) / (cs%rho_a*radiusb) + &
400 0.25*(radius_km*absf)**2) - 0.5*radius_km*absf) &
401 * (15. - radius/cs%rad_max_wind)/5.
406 if ( (radius > 0.001*cs%rad_max_wind) .and. (radius < 10.*cs%rad_max_wind) )
then 407 tmp = ( 0.5*radius_km*absf) * (cs%rho_a*radiusb)
408 u10 = (cs%Holland_AxBxDP * exp(-cs%Holland_A/radiusb)) / &
409 ( tmp + sqrt(cs%Holland_AxBxDP*exp(-cs%Holland_A/radiusb) * (cs%rho_a*radiusb) + tmp**2) )
410 elseif ( (radius > 10.*cs%rad_max_wind) .and. (radius < 15.*cs%rad_max_wind) )
then 411 radius_km = 10.0 * cs%rad_max_wind
412 if (cs%BR_Bench) radius_km = radius_km/1000.
413 radiusb = (10.0*us%L_to_m*cs%rad_max_wind)**cs%Holland_B
414 tmp = ( 0.5*radius_km*absf) * (cs%rho_a*radiusb)
415 u10 = (3.0 - radius/(5.0*cs%rad_max_wind)) * (cs%Holland_AxBxDp*exp(-cs%Holland_A/radiusb) ) / &
416 ( tmp + sqrt(cs%Holland_AxBxDp*exp(-cs%Holland_A/radiusb) * (cs%rho_a*radiusb) + tmp**2) )
428 rstr = min(10., radius / cs%rad_max_wind)
429 a0 = -0.9*rstr - 0.09*us%L_T_to_m_s*cs%max_windspeed - 14.33
430 a1 = -a0*(0.04*rstr + 0.05*us%L_T_to_m_s*cs%hurr_translation_spd + 0.14)
431 p1 = (6.88*rstr - 9.60*us%L_T_to_m_s*cs%hurr_translation_spd + 85.31) * cs%Deg2Rad
432 alph = a0 - a1*cos(cs%hurr_translation_dir-adir-p1)
433 if ( (radius > 10.*cs%rad_max_wind) .and.&
434 (radius < 15.*cs%rad_max_wind) )
then 435 alph = alph*(15.0 - radius/cs%rad_max_wind)/5.
436 elseif (radius > 15.*cs%rad_max_wind)
then 439 alph = alph * cs%Deg2Rad
442 u_ts = cs%hurr_translation_spd * 0.5*cos(cs%hurr_translation_dir)
443 v_ts = cs%hurr_translation_spd * 0.5*sin(cs%hurr_translation_dir)
446 du = u10*sin(adir-cs%Pi-alph) - uocn + u_ts
447 dv = u10*cos(adir-alph) - vocn + v_ts
450 du10 = sqrt(du**2+dv**2)
451 if (du10 < 11.0*us%m_s_to_L_T)
then 453 elseif (du10 < 20.0*us%m_s_to_L_T)
then 454 if (cs%answers_2018)
then 455 cd = (0.49 + 0.065*us%L_T_to_m_s*u10)*1.e-3
457 cd = (0.49 + 0.065*us%L_T_to_m_s*du10)*1.e-3
464 tx = us%L_to_Z * cs%rho_a * cd * sqrt(du**2 + dv**2) * du
465 ty = us%L_to_Z * cs%rho_a * cd * sqrt(du**2 + dv**2) * dv
467 end subroutine idealized_hurricane_wind_profile
473 subroutine scm_idealized_hurricane_wind_forcing(sfc_state, forces, day, G, US, CS)
476 type(time_type),
intent(in) :: day
481 integer :: i, j, is, ie, js, je, isq, ieq, jsq, jeq
482 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb
498 real :: alph,rstr, a0, a1, p1, adir, transdir
502 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
503 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
504 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
505 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
510 pie = 4.0*atan(1.0) ; deg2rad = pie/180.
518 dp = cs%pressure_ambient - cs%pressure_central
519 if (cs%answers_2018)
then 520 c = cs%max_windspeed / sqrt( us%R_to_kg_m3*dp )
521 b = c**2 * us%R_to_kg_m3*cs%rho_a * exp(1.0)
523 b = c**2 * 1.2 * exp(1.0)
525 elseif (br_bench)
then 526 b = (cs%max_windspeed**2 / dp ) * 1.2*us%kg_m3_to_R * exp(1.0)
528 b = (cs%max_windspeed**2 /dp ) * cs%rho_a * exp(1.0)
531 a = (us%L_to_m*cs%rad_max_wind / 1000.)**b
532 f_local = g%CoriolisBu(is,js)
535 f_local = 5.5659e-05*us%T_to_s
539 xx = us%s_to_T*( t0 - time_type_to_real(day)) * cs%hurr_translation_spd * cos(transdir)
540 rad = sqrt(xx**2 + cs%dy_from_center**2)
549 rb = (us%L_to_m*rkm)**b
553 rb = (us%L_to_m*rad)**b
559 if (rad > 0.001*cs%rad_max_wind .AND. rad < 10.*cs%rad_max_wind)
then 560 u10 = sqrt( a*b*dp*exp(-a/rb)/(1.2*us%kg_m3_to_R*rb) + 0.25*(rkm*f_local)**2 ) - 0.5*rkm*f_local
561 elseif (rad > 10.*cs%rad_max_wind .AND. rad < 12.*cs%rad_max_wind)
then 562 rad=(cs%rad_max_wind)*10.
565 rb = (us%L_to_m*rkm)**b
568 rb = (us%L_to_m*rad)**b
570 u10 = ( sqrt( a*b*dp*exp(-a/rb)/(1.2*us%kg_m3_to_R*rb) + 0.25*(rkm*f_local)**2 ) - 0.5*rkm*f_local) &
571 * (12. - rad/cs%rad_max_wind)/2.
575 adir = atan2(cs%dy_from_center,xx)
580 rstr = min(10., rad / cs%rad_max_wind)
581 a0 = -0.9*rstr - 0.09*us%L_T_to_m_s*cs%max_windspeed - 14.33
582 a1 = -a0 *(0.04*rstr + 0.05*us%L_T_to_m_s*cs%hurr_translation_spd + 0.14)
583 p1 = (6.88*rstr - 9.60*us%L_T_to_m_s*cs%hurr_translation_spd + 85.31)*pie/180.
584 alph = a0 - a1*cos( (transdir - adir ) - p1)
585 if (rad > 10.*cs%rad_max_wind .AND. rad < 12.*cs%rad_max_wind)
then 586 alph = alph* (12. - rad/cs%rad_max_wind)/2.
587 elseif (rad > 12.*cs%rad_max_wind)
then 590 alph = alph * deg2rad
595 u_ts = cs%hurr_translation_spd*0.5*cos(transdir)
596 v_ts = cs%hurr_translation_spd*0.5*sin(transdir)
602 do j=js,je ;
do i=is-1,ieq
612 du = u10*sin(adir-pie-alph) - uocn + u_ts
613 dv = u10*cos(adir-alph) - vocn + v_ts
618 du10 = sqrt(du**2+dv**2)
619 if (du10 < 11.0*us%m_s_to_L_T)
then 621 elseif (du10 < 20.0*us%m_s_to_L_T)
then 622 if (cs%answers_2018)
then 623 cd = (0.49 + 0.065 * us%L_T_to_m_s*u10 )*0.001
625 cd = (0.49 + 0.065 * us%L_T_to_m_s*du10 )*0.001
630 forces%taux(i,j) = cs%rho_a * us%L_to_Z * g%mask2dCu(i,j) * cd*du10*du
634 do j=js-1,jeq ;
do i=is,ie
638 du = u10*sin(adir-pie-alph) - uocn + u_ts
639 dv = u10*cos(adir-alph) - vocn + v_ts
640 du10=sqrt(du**2+dv**2)
641 if (du10 < 11.0*us%m_s_to_L_T)
then 643 elseif (du10 < 20.0*us%m_s_to_L_T)
then 644 if (cs%answers_2018)
then 645 cd = (0.49 + 0.065 * us%L_T_to_m_s*u10 )*0.001
647 cd = (0.49 + 0.065 * us%L_T_to_m_s*du10 )*0.001
652 forces%tauy(i,j) = cs%rho_a * us%L_to_Z * g%mask2dCv(i,j) * cd*du10*dv
655 do j=js,je ;
do i=is,ie
657 forces%ustar(i,j) = g%mask2dT(i,j) * sqrt(us%L_to_Z * (cs%gustiness/cs%Rho0 + &
658 sqrt(0.5*(forces%taux(i-1,j)**2 + forces%taux(i,j)**2) + &
659 0.5*(forces%tauy(i,j-1)**2 + forces%tauy(i,j)**2))/cs%Rho0))
662 end subroutine scm_idealized_hurricane_wind_forcing
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Container for parameters describing idealized wind structure.
Wraps the FMS time manager functions.
This module implements boundary forcing for MOM6.
Ocean grid type. See mom_grid for details.
Allocate the fields of a mechanical forcing type, based on either a set of input flags for each group...
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
The MOM6 facility to parse input files for runtime parameters.
Structure that contains pointers to the mechanical forcing at the surface used to drive the liquid oc...
Allocate the fields of a (flux) forcing type, based on either a set of input flags for each group of ...
Allocate a pointer to a 1-d, 2-d or 3-d array.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Convenience functions for safely allocating memory without accidentally reallocating pointer and caus...
Routines for error handling and I/O management.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
Forcing for the idealized hurricane and SCM_idealized_hurricane examples.
An overloaded interface to read and log the values of various types of parameters.