Skip to content

Commit 3c39818

Browse files
+*Obsolete WIND_CONFIG = "SCM_ideal_hurr" (#770)
Changed the code to issue a fatal error message when WIND_CONFIG = "SCM_ideal_hurr", with the message including instructions on how to recover mathematically equivalent solutions, and eliminated the subroutine SCM_idealized_hurricane_wind_forcing() from the Idealized_hurricane module. The ocean_only MOM_parameter_doc files have also been modified to reflect that "SCM_ideal_hurr" is no longer a valid setting for WIND_CONFIG. All answers are bitwise identical in any cases that run, but some cases may fail during initialization with instructions on how to fix them.
1 parent 61e3bcf commit 3c39818

File tree

2 files changed

+13
-203
lines changed

2 files changed

+13
-203
lines changed

config_src/drivers/solo_driver/MOM_surface_forcing.F90

+12-8
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ module MOM_surface_forcing
4545
use user_surface_forcing, only : USER_surface_forcing_init, user_surface_forcing_CS
4646
use user_revise_forcing, only : user_alter_forcing, user_revise_forcing_init
4747
use user_revise_forcing, only : user_revise_forcing_CS
48-
use idealized_hurricane, only : idealized_hurricane_wind_init
49-
use idealized_hurricane, only : idealized_hurricane_wind_forcing, SCM_idealized_hurricane_wind_forcing
50-
use idealized_hurricane, only : idealized_hurricane_CS
48+
use idealized_hurricane, only : idealized_hurricane_wind_forcing
49+
use idealized_hurricane, only : idealized_hurricane_wind_init, idealized_hurricane_CS
5150
use SCM_CVmix_tests, only : SCM_CVmix_tests_surface_forcing_init
5251
use SCM_CVmix_tests, only : SCM_CVmix_tests_wind_forcing
5352
use SCM_CVmix_tests, only : SCM_CVmix_tests_buoyancy_forcing
@@ -297,7 +296,8 @@ subroutine set_forcing(sfc_state, forces, fluxes, day_start, day_interval, G, US
297296
elseif (trim(CS%wind_config) == "ideal_hurr") then
298297
call idealized_hurricane_wind_forcing(sfc_state, forces, day_center, G, US, CS%idealized_hurricane_CSp)
299298
elseif (trim(CS%wind_config) == "SCM_ideal_hurr") then
300-
call SCM_idealized_hurricane_wind_forcing(sfc_state, forces, day_center, G, US, CS%idealized_hurricane_CSp)
299+
call MOM_error(FATAL, "MOM_surface_forcing (set_forcing): "//&
300+
'WIND_CONFIG = "SCM_ideal_hurr" is a depricated option.')
301301
elseif (trim(CS%wind_config) == "SCM_CVmix_tests") then
302302
call SCM_CVmix_tests_wind_forcing(sfc_state, forces, day_center, G, US, CS%SCM_CVmix_tests_CSp)
303303
elseif (trim(CS%wind_config) == "USER") then
@@ -1780,8 +1780,8 @@ subroutine surface_forcing_init(Time, G, US, param_file, diag, CS, tracer_flow_C
17801780
call get_param(param_file, mdl, "WIND_CONFIG", CS%wind_config, &
17811781
"The character string that indicates how wind forcing is specified. Valid "//&
17821782
"options include (file), (data_override), (2gyre), (1gyre), (gyres), (zero), "//&
1783-
"(const), (Neverworld), (scurves), (ideal_hurr), (SCM_ideal_hurr), "//&
1784-
"(SCM_CVmix_tests) and (USER).", default="zero")
1783+
"(const), (Neverworld), (scurves), (ideal_hurr), (SCM_CVmix_tests) and (USER).", &
1784+
default="zero")
17851785
if (trim(CS%wind_config) == "file") then
17861786
call get_param(param_file, mdl, "WIND_FILE", CS%wind_file, &
17871787
"The file in which the wind stresses are found in "//&
@@ -1990,9 +1990,13 @@ subroutine surface_forcing_init(Time, G, US, param_file, diag, CS, tracer_flow_C
19901990
call dumbbell_surface_forcing_init(Time, G, US, param_file, diag, CS%dumbbell_forcing_CSp)
19911991
elseif (trim(CS%wind_config) == "MESO" .or. trim(CS%buoy_config) == "MESO" ) then
19921992
call MESO_surface_forcing_init(Time, G, US, param_file, diag, CS%MESO_forcing_CSp)
1993-
elseif (trim(CS%wind_config) == "ideal_hurr" .or.&
1994-
trim(CS%wind_config) == "SCM_ideal_hurr") then
1993+
elseif (trim(CS%wind_config) == "ideal_hurr") then
19951994
call idealized_hurricane_wind_init(Time, G, US, param_file, CS%idealized_hurricane_CSp)
1995+
elseif (trim(CS%wind_config) == "SCM_ideal_hurr") then
1996+
call MOM_error(FATAL, "MOM_surface_forcing (surface_forcing_init): "//&
1997+
'WIND_CONFIG = "SCM_ideal_hurr" is a depricated option. '//&
1998+
'To obtain mathematically equivalent results set '//&
1999+
'WIND_CONFIG = "ideal_hurr", IDL_HURR_SCM = True and IDL_HURR_X0 = 6.48e+05.')
19962000
elseif (trim(CS%wind_config) == "const") then
19972001
call get_param(param_file, mdl, "CONST_WIND_TAUX", CS%tau_x0, &
19982002
"With wind_config const, this is the constant zonal wind-stress", &

src/user/Idealized_Hurricane.F90

+1-195
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ module Idealized_hurricane
1414
! w/ T/S initializations in CVMix_tests (which should be moved
1515
! into the main state_initialization to their utility
1616
! for multiple example cases).
17-
! To do
18-
! 1. Remove the legacy SCM_idealized_hurricane_wind_forcing code
19-
!
17+
! December 2024: Removed the legacy subroutine SCM_idealized_hurricane_wind_forcing
2018

2119
use MOM_error_handler, only : MOM_error, FATAL
2220
use MOM_file_parser, only : get_param, log_version, param_file_type
@@ -37,8 +35,6 @@ module Idealized_hurricane
3735
! hurricane wind profile.
3836
public idealized_hurricane_wind_forcing !Public interface to update the idealized
3937
! hurricane wind profile.
40-
public SCM_idealized_hurricane_wind_forcing !Public interface to the legacy idealized
41-
! hurricane wind profile for SCM.
4238

4339
!> Container for parameters describing idealized wind structure
4440
type, public :: idealized_hurricane_CS ; private
@@ -656,196 +652,6 @@ subroutine idealized_hurricane_wind_profile(CS, US, absf, YY, XX, UOCN, VOCN, Tx
656652
TY = US%L_to_Z * CS%rho_a * Cd * du10 * dV
657653
end subroutine idealized_hurricane_wind_profile
658654

659-
!> This subroutine is primarily needed as a legacy for reproducing answers.
660-
!! It is included as an additional subroutine rather than padded into the previous
661-
!! routine with flags to ease its eventual removal. Its functionality is replaced
662-
!! with the new routines and it can be deleted when answer changes are acceptable.
663-
subroutine SCM_idealized_hurricane_wind_forcing(sfc_state, forces, day, G, US, CS)
664-
type(surface), intent(in) :: sfc_state !< Surface state structure
665-
type(mech_forcing), intent(inout) :: forces !< A structure with the driving mechanical forces
666-
type(time_type), intent(in) :: day !< Time in days
667-
type(ocean_grid_type), intent(inout) :: G !< Grid structure
668-
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
669-
type(idealized_hurricane_CS), pointer :: CS !< Container for SCM parameters
670-
! Local variables
671-
integer :: i, j, is, ie, js, je, Isq, Ieq, Jsq, Jeq
672-
integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
673-
real :: du10 ! The magnitude of the difference between the 10 m wind and the ocean flow [L T-1 ~> m s-1]
674-
real :: U10 ! The 10 m wind speed [L T-1 ~> m s-1]
675-
real :: A ! The radius of the maximum winds raised to the power given by B, used in the
676-
! wind profile expression, in [km^B]
677-
real :: B ! A power used in the wind profile expression [nondim]
678-
real :: C ! A temporary variable in units of the square root of a specific volume [sqrt(m3 kg-1)]
679-
real :: rad ! The distance from the hurricane center [L ~> m]
680-
real :: radius10 ! The distance from the hurricane center to its edge [L ~> m]
681-
real :: rkm ! The distance from the hurricane center, sometimes scaled to km [L ~> m] or [1000 L ~> km]
682-
real :: f_local ! The local Coriolis parameter [T-1 ~> s-1]
683-
real :: xx ! x-position [L ~> m]
684-
real :: t0 ! Time at which the eye crosses the origin [T ~> s]
685-
real :: dP ! The pressure difference across the hurricane [R L2 T-2 ~> Pa]
686-
real :: rB ! The distance from the center raised to the power given by B, in [m^B]
687-
! or [km^B] if BR_Bench is true.
688-
real :: Cd ! Air-sea drag coefficient [nondim]
689-
real :: Uocn, Vocn ! Surface ocean velocity components [L T-1 ~> m s-1]
690-
real :: dU, dV ! Air-sea differential motion [L T-1 ~> m s-1]
691-
! Wind angle variables
692-
real :: Alph ! The wind inflow angle (positive outward) [radians]
693-
real :: Rstr ! A function of the position normalized by the radius of maximum winds [nondim]
694-
real :: A0 ! The axisymmetric inflow angle [degrees]
695-
real :: A1 ! The inflow angle asymmetry [degrees]
696-
real :: P1 ! The angle difference between the translation direction and the inflow direction [radians]
697-
real :: Adir ! The angle of the direction from the center to a point [radians]
698-
real :: transdir ! Translation direction [radians]
699-
real :: V_TS, U_TS ! Components of the translation speed [L T-1 ~> m s-1]
700-
701-
! Bounds for loops and memory allocation
702-
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec
703-
Isq = G%IscB ; Ieq = G%IecB ; Jsq = G%JscB ; Jeq = G%JecB
704-
isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed
705-
IsdB = G%IsdB ; IedB = G%IedB ; JsdB = G%JsdB ; JedB = G%JedB
706-
707-
! Allocate the forcing arrays, if necessary.
708-
call allocate_mech_forcing(G, forces, stress=.true., ustar=.true., tau_mag=.true.)
709-
710-
! Implementing Holland (1980) parameteric wind profile
711-
!------------------------------------------------------------|
712-
t0 = 129600.*US%s_to_T ! TC 'eye' crosses (0,0) at 36 hours |
713-
transdir = CS%pi ! translation direction (-x) |
714-
!------------------------------------------------------------|
715-
dP = CS%pressure_ambient - CS%pressure_central
716-
if (CS%answer_date < 20190101) then
717-
C = CS%max_windspeed / sqrt( US%R_to_kg_m3*dP )
718-
B = C**2 * US%R_to_kg_m3*CS%rho_a * exp(1.0)
719-
if (CS%BR_Bench) then ! rho_a reset to value used in generated wind for benchmark test
720-
B = C**2 * 1.2 * exp(1.0)
721-
endif
722-
else
723-
B = (CS%max_windspeed**2 / dP ) * CS%rho_a * exp(1.0)
724-
endif
725-
726-
if (CS%BR_Bench) then
727-
A = (US%L_to_m*CS%rad_max_wind / 1000.)**B
728-
else
729-
A = (US%L_to_m*CS%rad_max_wind)**B
730-
endif
731-
! f_local = f(x,y), but in the SCM it is constant
732-
if (CS%BR_Bench) then ! (CS%SCM_mode) then
733-
f_local = CS%f_column
734-
else
735-
f_local = G%CoriolisBu(is,js)
736-
endif
737-
738-
! Calculate x position relative to hurricane center as a function of time.
739-
xx = (t0 - time_type_to_real(day)*US%s_to_T) * CS%hurr_translation_spd * cos(transdir)
740-
rad = sqrt((xx**2) + (CS%dy_from_center**2))
741-
742-
! rkm - rad converted to km for Holland prof.
743-
! used in km due to error, correct implementation should
744-
! not need rkm, but to match winds w/ experiment this must
745-
! be maintained. Causes winds far from storm center to be a
746-
! couple of m/s higher than the correct Holland prof.
747-
if (CS%BR_Bench) then
748-
rkm = rad/1000.
749-
rB = (US%L_to_m*rkm)**B
750-
else
751-
! if not comparing to benchmark, then use correct Holland prof.
752-
rkm = rad
753-
rB = (US%L_to_m*rad)**B
754-
endif
755-
756-
! Calculate U10 in the interior (inside of the hurricane edge radius),
757-
! while adjusting U10 to 0 outside of the ambient wind radius.
758-
if (rad > 0.001*CS%rad_max_wind .AND. rad < CS%rad_edge*CS%rad_max_wind) then
759-
U10 = sqrt( A*B*dP*exp(-A/rB)/(CS%rho_a*rB) + 0.25*(rkm*f_local)**2 ) - 0.5*rkm*f_local
760-
elseif (rad > CS%rad_edge*CS%rad_max_wind .AND. rad < CS%rad_ambient*CS%rad_max_wind) then
761-
radius10 = CS%rad_max_wind*CS%rad_edge
762-
if (CS%BR_Bench) then
763-
rkm = radius10/1000.
764-
rB = (US%L_to_m*rkm)**B
765-
else
766-
rkm = radius10
767-
rB = (US%L_to_m*radius10)**B
768-
endif
769-
if (CS%edge_taper_bug) rad = radius10
770-
U10 = ( sqrt( A*B*dP*exp(-A/rB)/(CS%rho_a*rB) + 0.25*(rkm*f_local)**2 ) - 0.5*rkm*f_local) &
771-
* (CS%rad_ambient - rad/CS%rad_max_wind)/(CS%rad_ambient - CS%rad_edge)
772-
else
773-
U10 = 0.
774-
endif
775-
Adir = atan2(CS%dy_from_center,xx)
776-
777-
! Wind angle model following Zhang and Ulhorn (2012)
778-
! ALPH is inflow angle positive outward.
779-
RSTR = min(CS%rad_edge, rad / CS%rad_max_wind)
780-
A0 = CS%A0_Rnorm*RSTR + CS%A0_speed*CS%max_windspeed + CS%A0_0
781-
A1 = -A0*(CS%A1_Rnorm*RSTR + CS%A1_speed*CS%hurr_translation_spd + CS%A1_0)
782-
P1 = (CS%P1_Rnorm*RSTR + CS%P1_speed*CS%hurr_translation_spd + CS%P1_0) * CS%pi/180.
783-
ALPH = A0 - A1*cos( (TRANSDIR - ADIR ) - P1)
784-
if (rad > CS%rad_edge*CS%rad_max_wind .AND. rad < CS%rad_ambient*CS%rad_max_wind) then
785-
ALPH = ALPH* (CS%rad_ambient - rad/CS%rad_max_wind) / (CS%rad_ambient - CS%rad_edge)
786-
elseif (rad > CS%rad_ambient*CS%rad_max_wind) then
787-
ALPH = 0.0
788-
endif
789-
ALPH = ALPH * CS%Deg2Rad
790-
791-
! Prepare for wind calculation
792-
! X_TS is component of translation speed added to wind vector
793-
! due to background steering wind.
794-
U_TS = CS%hurr_translation_spd*0.5*cos(transdir)
795-
V_TS = CS%hurr_translation_spd*0.5*sin(transdir)
796-
797-
! Set the surface wind stresses, in [R L Z T-2 ~> Pa]. A positive taux
798-
! accelerates the ocean to the (pseudo-)east.
799-
! The i-loop extends to is-1 so that taux can be used later in the
800-
! calculation of ustar - otherwise the lower bound would be Isq.
801-
do j=js,je ; do I=is-1,Ieq
802-
! Turn off surface current for stress calculation to be
803-
! consistent with test case.
804-
Uocn = 0. ! sfc_state%u(I,j)
805-
Vocn = 0. ! 0.25*( (sfc_state%v(i,J) + sfc_state%v(i+1,J-1)) + &
806-
! (sfc_state%v(i+1,J) + sfc_state%v(i,J-1)) )
807-
! Wind vector calculated from location/direction (sin/cos flipped b/c
808-
! cyclonic wind is 90 deg. phase shifted from position angle).
809-
dU = U10*sin(Adir - CS%pi - Alph) - Uocn + U_TS
810-
dV = U10*cos(Adir - Alph) - Vocn + V_TS
811-
!/----------------------------------------------------|
812-
! Add a simple drag coefficient as a function of U10 |
813-
!/----------------------------------------------------|
814-
du10 = sqrt((du**2) + (dv**2))
815-
Cd = simple_wind_scaled_Cd(u10, du10, CS)
816-
817-
forces%taux(I,j) = CS%rho_a * US%L_to_Z * G%mask2dCu(I,j) * Cd*du10*dU
818-
enddo ; enddo
819-
820-
! See notes above
821-
do J=js-1,Jeq ; do i=is,ie
822-
Uocn = 0. ! 0.25*( (sfc_state%u(I,j) + sfc_state%u(I-1,j+1)) + &
823-
! (sfc_state%u(I-1,j) + sfc_state%u(I,j+1)) )
824-
Vocn = 0. ! sfc_state%v(i,J)
825-
dU = U10*sin(Adir - CS%pi - Alph) - Uocn + U_TS
826-
dV = U10*cos(Adir-Alph) - Vocn + V_TS
827-
du10 = sqrt((du**2) + (dv**2))
828-
Cd = simple_wind_scaled_Cd(u10, du10, CS)
829-
forces%tauy(I,j) = CS%rho_a * US%L_to_Z * G%mask2dCv(I,j) * Cd*dU10*dV
830-
enddo ; enddo
831-
832-
! Set the surface friction velocity [Z T-1 ~> m s-1]. ustar is always positive.
833-
if (associated(forces%ustar)) then ; do j=js,je ; do i=is,ie
834-
! This expression can be changed if desired, but need not be.
835-
forces%ustar(i,j) = G%mask2dT(i,j) * sqrt(US%L_to_Z * (CS%gustiness/CS%Rho0 + &
836-
sqrt(0.5*((forces%taux(I-1,j)**2) + (forces%taux(I,j)**2)) + &
837-
0.5*((forces%tauy(i,J-1)**2) + (forces%tauy(i,J)**2)))/CS%Rho0))
838-
enddo ; enddo ; endif
839-
840-
!> Set magnitude of the wind stress [R L Z T-2 ~> Pa]
841-
if (associated(forces%tau_mag)) then ; do j=js,je ; do i=is,ie
842-
forces%tau_mag(i,j) = G%mask2dT(i,j) * (CS%gustiness + &
843-
sqrt(0.5*((forces%taux(I-1,j)**2) + (forces%taux(I,j)**2)) + &
844-
0.5*((forces%tauy(i,J-1)**2) + (forces%tauy(i,J)**2))))
845-
enddo ; enddo ; endif
846-
847-
end subroutine SCM_idealized_hurricane_wind_forcing
848-
849655
!> This function returns the air-sea drag coefficient using a simple function of the air-sea velocity difference.
850656
function simple_wind_scaled_Cd(u10, du10, CS) result(Cd)
851657
real, intent(in) :: U10 !< The 10 m wind speed [L T-1 ~> m s-1]

0 commit comments

Comments
 (0)