Skip to content

Commit 8249510

Browse files
committed
+Refactor MOM_opacity to replace hard-coded params
Refactored MOM_opacity to replace hard-coded dimensional parameters for the Manizza and Morel opacity fits with run-time parameters, and also added the runtime parameter OPACITY_BAND_WAVELENGTHS to provide the ability to set the wavelengths of the bands, even though these are not actually used in MOM6. By default, these parameters are all set to the previous hard-coded values, using the recently added defaults argument to get_param_real_array(). The bounds of the frequency band label arrays with the MANIZZA_05 opacity scheme were also corrected when PEN_SW_NBANDS > 3, but it would not be typical to use so many bands for no purpose and these labeling arrays (optics%min_wavelength_band and optics%max_wavelength_band) do not appear to be used anywhere. In addition, the unused publicly visible routines opacity_manizza and opacity_morel were eliminated or made private. All answers are bitwise identical, but there are new entries in some MOM_parameter_doc files.
1 parent 8e0b83c commit 8249510

File tree

1 file changed

+149
-47
lines changed

1 file changed

+149
-47
lines changed

src/parameterizations/vertical/MOM_opacity.F90

+149-47
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module MOM_opacity
1717

1818
#include <MOM_memory.h>
1919

20-
public set_opacity, opacity_init, opacity_end, opacity_manizza, opacity_morel
20+
public set_opacity, opacity_init, opacity_end
2121
public extract_optics_slice, extract_optics_fields, optics_nbands
2222
public absorbRemainingSW, sumSWoverBands
2323

@@ -66,8 +66,21 @@ module MOM_opacity
6666
!! radiation that is in the blue band [nondim].
6767
real :: opacity_land_value !< The value to use for opacity over land [Z-1 ~> m-1].
6868
!! The default is 10 m-1 - a value for muddy water.
69+
real, allocatable, dimension(:,:) &
70+
:: opacity_coef !< Groups of coefficients, in [Z-1 ~> m-1] or [Z ~> m] depending on the
71+
!! scheme, in expressions for opacity, with the second index being the
72+
!! wavelength band. For example, when OPACITY_SCHEME = MANIZZA_05,
73+
!! these are coef_1 and coef_2 in the
74+
!! expression opacity = coef_1 + coef_2 * chl**pow.
75+
real, allocatable, dimension(:) &
76+
:: sw_pen_frac_coef !< Coefficients in the expression for the penetrating shortwave
77+
!! fracetion [nondim]
78+
real, allocatable, dimension(:) &
79+
:: chl_power !< Powers of chlorophyll [nondim] for each band for expressions for
80+
!! opacity of the form opacity = coef_1 + coef_2 * chl**pow.
6981
type(diag_ctrl), pointer :: diag => NULL() !< A structure that is used to
7082
!! regulate the timing of diagnostic output.
83+
integer :: chl_dep_bands !< The number of bands that depend on the Chlorophyll concentrations.
7184
logical :: warning_issued !< A flag that is used to avoid repetitive warnings.
7285

7386
!>@{ Diagnostic IDs
@@ -344,9 +357,9 @@ subroutine opacity_from_chl(optics, sw_total, sw_vis_dir, sw_vis_dif, sw_nir_dir
344357
SW_pen_tot = 0.0
345358
if (G%mask2dT(i,j) > 0.0) then
346359
if (multiband_vis_input) then
347-
SW_pen_tot = SW_pen_frac_morel(chl_data(i,j)) * (sw_vis_dir(i,j) + sw_vis_dif(i,j))
360+
SW_pen_tot = SW_pen_frac_morel(chl_data(i,j), CS) * (sw_vis_dir(i,j) + sw_vis_dif(i,j))
348361
elseif (total_sw_input) then
349-
SW_pen_tot = SW_pen_frac_morel(chl_data(i,j)) * 0.5*sw_total(i,j)
362+
SW_pen_tot = SW_pen_frac_morel(chl_data(i,j), CS) * 0.5*sw_total(i,j)
350363
endif
351364
endif
352365

@@ -372,19 +385,21 @@ subroutine opacity_from_chl(optics, sw_total, sw_vis_dir, sw_vis_dif, sw_nir_dir
372385
optics%opacity_band(n,i,j,k) = CS%opacity_land_value
373386
enddo
374387
else
375-
! Band 1 is Manizza blue.
376-
optics%opacity_band(1,i,j,k) = (0.0232 + 0.074*chl_data(i,j)**0.674) * US%Z_to_m
377-
if (nbands >= 2) & ! Band 2 is Manizza red.
378-
optics%opacity_band(2,i,j,k) = (0.225 + 0.037*chl_data(i,j)**0.629) * US%Z_to_m
379-
! All remaining bands are NIR, for lack of something better to do.
380-
do n=3,nbands ; optics%opacity_band(n,i,j,k) = 2.86*US%Z_to_m ; enddo
388+
do n=1,CS%chl_dep_bands
389+
optics%opacity_band(n,i,j,k) = CS%opacity_coef(1,n) + &
390+
CS%opacity_coef(2,n) * chl_data(i,j)**CS%chl_power(n)
391+
enddo
392+
do n=CS%chl_dep_bands+1,optics%nbands ! These bands do not depend on the chlorophyll.
393+
! Any nonzero values that were in opacity_coef(2,n) have been added to opacity_coef(1,n).
394+
optics%opacity_band(n,i,j,k) = CS%opacity_coef(1,n)
395+
enddo
381396
endif
382397
enddo ; enddo
383398
case (MOREL_88)
384399
do j=js,je ; do i=is,ie
385400
optics%opacity_band(1,i,j,k) = CS%opacity_land_value
386401
if (G%mask2dT(i,j) > 0.0) &
387-
optics%opacity_band(1,i,j,k) = US%Z_to_m * opacity_morel(chl_data(i,j))
402+
optics%opacity_band(1,i,j,k) = opacity_morel(chl_data(i,j), CS)
388403

389404
do n=2,optics%nbands
390405
optics%opacity_band(n,i,j,k) = optics%opacity_band(1,i,j,k)
@@ -401,28 +416,25 @@ end subroutine opacity_from_chl
401416

402417
!> This sets the blue-wavelength opacity according to the scheme proposed by
403418
!! Morel and Antoine (1994).
404-
function opacity_morel(chl_data)
419+
function opacity_morel(chl_data, CS)
405420
real, intent(in) :: chl_data !< The chlorophyll-A concentration in [mg m-3]
406-
real :: opacity_morel !< The returned opacity [m-1]
421+
type(opacity_CS) :: CS !< Opacity control structure
422+
real :: opacity_morel !< The returned opacity [Z-1 ~> m-1]
407423

408-
! The following are coefficients for the optical model taken from Morel and
409-
! Antoine (1994). These coefficients represent a non uniform distribution of
410-
! chlorophyll-a through the water column. Other approaches may be more
411-
! appropriate when using an interactive ecosystem model that predicts
412-
! three-dimensional chl-a values.
413-
real, dimension(6), parameter :: &
414-
Z2_coef = (/7.925, -6.644, 3.662, -1.815, -0.218, 0.502/) ! Extinction length coefficients [m]
415424
real :: Chl, Chl2 ! The log10 of chl_data (in mg m-3), and Chl^2 [nondim]
416425

417426
Chl = log10(min(max(chl_data,0.02),60.0)) ; Chl2 = Chl*Chl
418-
opacity_morel = 1.0 / ( (Z2_coef(1) + Z2_coef(2)*Chl) + Chl2 * &
419-
((Z2_coef(3) + Chl*Z2_coef(4)) + Chl2*(Z2_coef(5) + Chl*Z2_coef(6))) )
420-
end function
427+
! All frequency bands currently use the same opacities.
428+
opacity_morel = 1.0 / ( (CS%opacity_coef(1,1) + CS%opacity_coef(2,1)*Chl) + Chl2 * &
429+
((CS%opacity_coef(3,1) + Chl*CS%opacity_coef(4,1)) + &
430+
Chl2*(CS%opacity_coef(5,1) + Chl*CS%opacity_coef(6,1))) )
431+
end function opacity_morel
421432

422433
!> This sets the penetrating shortwave fraction according to the scheme proposed by
423434
!! Morel and Antoine (1994).
424-
function SW_pen_frac_morel(chl_data)
435+
function SW_pen_frac_morel(chl_data, CS)
425436
real, intent(in) :: chl_data !< The chlorophyll-A concentration [mg m-3]
437+
type(opacity_CS) :: CS !< Opacity control structure
426438
real :: SW_pen_frac_morel !< The returned penetrating shortwave fraction [nondim]
427439

428440
! The following are coefficients for the optical model taken from Morel and
@@ -431,24 +443,13 @@ function SW_pen_frac_morel(chl_data)
431443
! appropriate when using an interactive ecosystem model that predicts
432444
! three-dimensional chl-a values.
433445
real :: Chl, Chl2 ! The log10 of chl_data in mg m-3, and Chl^2 [nondim]
434-
real, dimension(6), parameter :: &
435-
V1_coef = (/0.321, 0.008, 0.132, 0.038, -0.017, -0.007/) ! Penetrating fraction coefficients [nondim]
436446

437447
Chl = log10(min(max(chl_data,0.02),60.0)) ; Chl2 = Chl*Chl
438-
SW_pen_frac_morel = 1.0 - ( (V1_coef(1) + V1_coef(2)*Chl) + Chl2 * &
439-
((V1_coef(3) + Chl*V1_coef(4)) + Chl2*(V1_coef(5) + Chl*V1_coef(6))) )
448+
SW_pen_frac_morel = 1.0 - ( (CS%SW_pen_frac_coef(1) + CS%SW_pen_frac_coef(2)*Chl) + Chl2 * &
449+
((CS%SW_pen_frac_coef(3) + Chl*CS%SW_pen_frac_coef(4)) + &
450+
Chl2*(CS%SW_pen_frac_coef(5) + Chl*CS%SW_pen_frac_coef(6))) )
440451
end function SW_pen_frac_morel
441452

442-
!> This sets the blue-wavelength opacity according to the scheme proposed by
443-
!! Manizza, M. et al, 2005.
444-
function opacity_manizza(chl_data)
445-
real, intent(in) :: chl_data !< The chlorophyll-A concentration [mg m-3]
446-
real :: opacity_manizza !< The returned opacity [m-1]
447-
! This sets the blue-wavelength opacity according to the scheme proposed by Manizza, M. et al, 2005.
448-
449-
opacity_manizza = 0.0232 + 0.074*chl_data**0.674
450-
end function
451-
452453
!> This subroutine returns a 2-d slice at constant j of fields from an optics_type, with the potential
453454
!! for rescaling these fields.
454455
subroutine extract_optics_slice(optics, j, G, GV, opacity, opacity_scale, penSW_top, penSW_scale, SpV_avg)
@@ -973,9 +974,25 @@ subroutine opacity_init(Time, G, GV, US, param_file, diag, CS, optics)
973974
character(len=40) :: scheme_string
974975
! This include declares and sets the variable "version".
975976
# include "version_variable.h"
977+
real :: opacity_coefs(6) ! Pairs of opacity coefficients [Z-1 ~> m-1] for blue, red and
978+
! near-infrared radiation with parameterizations following the
979+
! functional form from Manizza et al., GRL 2005, namely in the form
980+
! opacity = coef_1 + coef_2 * chl**pow for each band.
981+
real :: opacity_powers(3) ! Powers of chlorophyll [nondim] for blue, red and near-infrared
982+
! radiation bands, in expressions for opacity of the form
983+
! opacity = coef_1 + coef_2 * chl**pow.
984+
real :: extinction_coefs(6) ! Extinction length coefficients [Z ~> m] for penetrating shortwave
985+
! radiation in the form proposed by Morel and Antoine (1994), namely
986+
! opacity = 1 / (sum(n=1:6, Coef(n) * log10(Chl)**(n-1)))
987+
real :: sw_pen_frac_coefs(6) ! Coefficients for the shortwave radiation fraction [nondim] in a
988+
! fifth order polynomial fit as a funciton of log10(Chlorophyll).
976989
real :: PenSW_absorb_minthick ! A thickness that is used to absorb the remaining shortwave heat
977990
! flux when that flux drops below PEN_SW_FLUX_ABSORB [H ~> m or kg m-2]
978-
real :: PenSW_minthick_dflt ! The default for PenSW_absorb_minthick [m]
991+
real :: PenSW_minthick_dflt ! The default for PenSW_absorb_minthick [m]
992+
real :: I_NIR_bands ! The inverse of the number of near-infrared bands being used [nondim]
993+
real, allocatable :: band_wavelengths(:) ! The bounding wavelengths for the penetrating shortwave
994+
! radiation bands [nm]
995+
real, allocatable :: band_wavelen_default(:) ! The defaults for band_wavelengths [nm]
979996
integer :: default_answer_date ! The default setting for the various ANSWER_DATE flags
980997
integer :: isd, ied, jsd, jed, nz, n
981998
isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed ; nz = GV%ke
@@ -1098,25 +1115,104 @@ subroutine opacity_init(Time, G, GV, US, param_file, diag, CS, optics)
10981115
default=PenSW_minthick_dflt, units="m", scale=GV%m_to_H)
10991116
optics%PenSW_absorb_Invlen = 1.0 / (PenSW_absorb_minthick + GV%H_subroundoff)
11001117

1118+
! The defaults for the following coefficients are taken from Manizza et al., GRL, 2005.
1119+
call get_param(param_file, mdl, "OPACITY_VALUES_MANIZZA", opacity_coefs, &
1120+
"Pairs of opacity coefficients for blue, red and near-infrared radiation with "//&
1121+
"parameterizations following the functional form from Manizza et al., GRL 2005, "//&
1122+
"namely in the form opacity = coef_1 + coef_2 * chl**pow for each band. Although "//&
1123+
"coefficients are set for 3 bands, more or less bands may actually be used, with "//&
1124+
"extra bands following the same properties as band 3.", &
1125+
units="m-1", scale=US%Z_to_m, defaults=(/0.0232, 0.074, 0.225, 0.037, 2.86, 0.0/), &
1126+
do_not_log=(CS%opacity_scheme/=MANIZZA_05))
1127+
call get_param(param_file, mdl, "CHOROPHYLL_POWER_MANIZZA", opacity_powers, &
1128+
"Powers of chlorophyll for blue, red and near-infrared radiation bands in "//&
1129+
"expressions for opacity of the form opacity = coef_1 + coef_2 * chl**pow.", &
1130+
units="nondim", defaults=(/0.674, 0.629, 0.0/), &
1131+
do_not_log=(CS%opacity_scheme/=MANIZZA_05))
1132+
1133+
! The defaults for the following coefficients are taken from Morel and Antoine (1994).
1134+
call get_param(param_file, mdl, "OPACITY_VALUES_MOREL", extinction_coefs, &
1135+
"Shortwave extinction length coefficients for shortwave radiation in the form "//&
1136+
"proposed by Morel (1988), opacity = 1 / (sum(Coef(n) * log10(Chl)**(n-1))).", &
1137+
units="m", scale=US%m_to_Z, defaults=(/7.925, -6.644, 3.662, -1.815, -0.218, 0.502/), &
1138+
do_not_log=(CS%opacity_scheme/=MOREL_88))
1139+
call get_param(param_file, mdl, "SW_PEN_FRAC_COEFS_MOREL", sw_pen_frac_coefs, &
1140+
"Coefficients for the shortwave radiation fraction in a fifth order polynomial "//&
1141+
"fit as a function of log10(Chlorophyll).", &
1142+
units="nondim", defaults=(/0.321, 0.008, 0.132, 0.038, -0.017, -0.007/), &
1143+
do_not_log=(CS%opacity_scheme/=MOREL_88))
1144+
11011145
if (.not.allocated(optics%min_wavelength_band)) &
11021146
allocate(optics%min_wavelength_band(optics%nbands))
11031147
if (.not.allocated(optics%max_wavelength_band)) &
11041148
allocate(optics%max_wavelength_band(optics%nbands))
11051149

1150+
! Set the wavelengths of the opacity bands
1151+
allocate(band_wavelengths(optics%nbands+1), source=0.0)
1152+
allocate(band_wavelen_default(optics%nbands+1), source=0.0)
11061153
if (CS%opacity_scheme == MANIZZA_05) then
1107-
optics%min_wavelength_band(1) =0
1108-
optics%max_wavelength_band(1) =550
1109-
if (optics%nbands >= 2) then
1110-
optics%min_wavelength_band(2)=550
1111-
optics%max_wavelength_band(2)=700
1112-
endif
1113-
if (optics%nbands > 2) then
1154+
if (optics%nbands >= 1) band_wavelen_default(2) = 550.0
1155+
if (optics%nbands >= 2) band_wavelen_default(3) = 700.0
1156+
if (optics%nbands >= 3) then
1157+
I_NIR_bands = 1.0 / real(optics%nbands - 2)
11141158
do n=3,optics%nbands
1115-
optics%min_wavelength_band(n) =700
1116-
optics%max_wavelength_band(n) =2800
1159+
band_wavelen_default(n+1) = 2800. - (optics%nbands-n)*2100.0*I_NIR_bands
11171160
enddo
11181161
endif
11191162
endif
1163+
call get_param(param_file, mdl, "OPACITY_BAND_WAVELENGTHS", band_wavelengths, &
1164+
"The bounding wavelengths for the various bands of shortwave radiation, with "//&
1165+
"defaults that depend on the setting for OPACITY_SCHEME.", &
1166+
units="nm", defaults=band_wavelen_default, do_not_log=(optics%nbands<2))
1167+
do n=1,optics%nbands
1168+
optics%min_wavelength_band(n) = band_wavelengths(n)
1169+
optics%max_wavelength_band(n) = band_wavelengths(n+1)
1170+
enddo
1171+
deallocate(band_wavelengths, band_wavelen_default)
1172+
1173+
! Set opacity scheme dependent parameters.
1174+
1175+
if (CS%opacity_scheme == MANIZZA_05) then
1176+
allocate(CS%opacity_coef(2,optics%nbands))
1177+
allocate(CS%chl_power(optics%nbands))
1178+
do n=1,min(3,optics%nbands)
1179+
CS%opacity_coef(1,n) = opacity_coefs(2*n-1) ; CS%opacity_coef(2,n) = opacity_coefs(2*n)
1180+
CS%chl_power(n) = opacity_powers(n)
1181+
enddo
1182+
! All remaining bands use the same properties as NIR, for lack of something better to do.
1183+
do n=4,optics%nbands
1184+
CS%opacity_coef(1,n) = CS%opacity_coef(1,n-1) ; CS%opacity_coef(2,n) = CS%opacity_coef(2,n-1)
1185+
CS%chl_power(n) = CS%chl_power(n-1)
1186+
enddo
1187+
! Determine the last band that is dependent on chlorophyll.
1188+
CS%chl_dep_bands = optics%nbands
1189+
do n=optics%nbands,1,-1
1190+
if (CS%chl_power(n) /= 0.0) exit
1191+
CS%chl_dep_bands = n - 1
1192+
enddo
1193+
do n=CS%chl_dep_bands+1,optics%nbands
1194+
if (CS%opacity_coef(2,n) /= 0.0) then
1195+
call MOM_error(WARNING, "set_opacity: A non-zero value of the chlorophyll dependence in "//&
1196+
"OPACITY_VALUES_MANIZZA was set for a band with zero power in its chlorophyll dependence "//&
1197+
"as set by CHOROPHYLL_POWER_MANIZZA.")
1198+
CS%opacity_coef(1,n) = CS%opacity_coef(1,n) + CS%opacity_coef(2,n)
1199+
CS%opacity_coef(2,n) = 0.0
1200+
endif
1201+
enddo
1202+
1203+
elseif (CS%opacity_scheme == MOREL_88) then
1204+
! The Morel opacity scheme represents a non uniform distribution of chlorophyll-a through the
1205+
! water column. Other approaches may be more appropriate when using an interactive ecosystem
1206+
! model that predicts three-dimensional chl-a values.
1207+
allocate(CS%opacity_coef(6, optics%nbands))
1208+
allocate(CS%sw_pen_frac_coef(6))
1209+
1210+
! As presently implemented, all frequency bands use the same opacities.
1211+
do n=1,optics%nbands
1212+
CS%opacity_coef(1:6,n) = extinction_coefs(1:6)
1213+
enddo
1214+
CS%sw_pen_frac_coef(:) = sw_pen_frac_coefs(:)
1215+
endif
11201216

11211217
call get_param(param_file, mdl, "OPACITY_LAND_VALUE", CS%opacity_land_value, &
11221218
"The value to use for opacity over land. The default is "//&
@@ -1152,6 +1248,12 @@ subroutine opacity_end(CS, optics)
11521248

11531249
if (allocated(CS%id_opacity)) &
11541250
deallocate(CS%id_opacity)
1251+
if (allocated(CS%opacity_coef)) &
1252+
deallocate(CS%opacity_coef)
1253+
if (allocated(CS%sw_pen_frac_coef)) &
1254+
deallocate(CS%sw_pen_frac_coef)
1255+
if (allocated(CS%chl_power)) &
1256+
deallocate(CS%chl_power)
11551257
if (allocated(optics%sw_pen_band)) &
11561258
deallocate(optics%sw_pen_band)
11571259
if (allocated(optics%opacity_band)) &

0 commit comments

Comments
 (0)