Coverage for tests/test_attenuation.py: 0%

1 from hypothesis import given

2 import hypothesis.extra.numpy as npst

3 import numpy as np

4

5 import swiift.lib.att as att

6 from swiift.model.model import (

7 DiscreteSpectrum,

8 FloatingIce,

9 Ice,

10 Ocean,

11 WavesUnderElasticPlate,

12 WavesUnderIce,

13)

14 from tests.model_strategies import coupled_ocean_ice, spec_mono, spec_poly

15 from tests.physical_strategies import PHYSICAL_STRATEGIES

16

17 wavenumbers_strategy = npst.arrays(

18 float,

19 npst.array_shapes(min_dims=1, max_dims=1, min_side=1, max_side=10),

20 elements=PHYSICAL_STRATEGIES[("wave", "wavenumber")],

21)

22

23 frequencies_strategy = npst.arrays(

24 float,

25 npst.array_shapes(min_dims=1, max_dims=1, min_side=1, max_side=10),

26 elements=PHYSICAL_STRATEGIES[("wave", "frequency")],

27)

28

29

30 class TestNoAttenuation:

31 @staticmethod

32 def test_unit():

33 assert att.no_attenuation() == 0

34

35 @staticmethod

36 @given(**coupled_ocean_ice, wavenumbers=wavenumbers_strategy)

37 def test_integrated(ice, ocean, gravity, wavenumbers):

38 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

39 wup = WavesUnderElasticPlate(fi, wavenumbers)

40 wui = WavesUnderIce.without_attenuation(wup)

41 assert wui.attenuations == 0

42

43

44 class TestParam01:

45 @staticmethod

46 @given(

47 thickness=PHYSICAL_STRATEGIES[("ice", "thickness")],

48 wavenumbers=wavenumbers_strategy,

49 )

50 def test_unit(thickness, wavenumbers):

51 attenuations = wavenumbers**2 * thickness / 4

52 assert np.allclose(

53 attenuations - att.parameterisation_01(thickness, wavenumbers), 0

54 )

55

56 @staticmethod

57 @given(**coupled_ocean_ice, wavenumbers=wavenumbers_strategy)

58 def test_integrated(ice, ocean, gravity, wavenumbers):

59 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

60 wup = WavesUnderElasticPlate(fi, wavenumbers)

61 wui = WavesUnderIce.with_attenuation_01(wup)

62 assert np.allclose(

63 wui.attenuations - att.parameterisation_01(ice.thickness, wavenumbers), 0

64 )

65

66

67 class TestYu2022:

68 @staticmethod

69 @given(

70 thickness=PHYSICAL_STRATEGIES[("ice", "thickness")],

71 gravity=PHYSICAL_STRATEGIES[("gravity",)],

72 frequencies=frequencies_strategy,

73 )

74 def test_unit(thickness: float, gravity: float, frequencies: np.ndarray):

75 prefactor, exponent = 0.108, 4.46

76 ang_freqs = 2 * np.pi * frequencies

77 nondim_ang_freqs = ang_freqs * np.sqrt(thickness / gravity)

78 nondim_attenuations = prefactor * nondim_ang_freqs**exponent

79 attenuations = nondim_attenuations / thickness

80 assert np.allclose(

81 attenuations, att.parameterisation_yu2022(thickness, gravity, ang_freqs)

82 )

83

84 @staticmethod

85 @given(**coupled_ocean_ice, spectrum=spec_mono() | spec_poly())

86 def test_integrated(

87 ice: Ice, ocean: Ocean, gravity: float, spectrum: DiscreteSpectrum

88 ):

89

90 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

91 wup = WavesUnderElasticPlate.from_floating(fi, spectrum, gravity)

92 wui = WavesUnderIce.with_attenuation_yu2022(

93 wup, gravity, spectrum.angular_frequencies

94 )

95

96 assert np.allclose(

97 wui.attenuations,

98 att.parameterisation_yu2022(

99 ice.thickness, gravity, spectrum.angular_frequencies

100 ),

101 )

102

103

104 class TestGeneric:

105 # Test passing a generic attenuation function against the existing

106 # parameterisations.

107

108 @staticmethod

109 @given(**coupled_ocean_ice, wavenumbers=wavenumbers_strategy)

110 def test_no_attenuation(ice, ocean, gravity, wavenumbers):

111 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

112 wup = WavesUnderElasticPlate(fi, wavenumbers)

113 wui = WavesUnderIce.with_generic_attenuation(wup, lambda: 0)

114 wui_ref = WavesUnderIce.without_attenuation(wup)

115 assert wui.attenuations == wui_ref.attenuations

116

117 @staticmethod

118 @given(**coupled_ocean_ice, wavenumbers=wavenumbers_strategy)

119 def test_param01_args(ice, ocean, gravity, wavenumbers):

120 # Test Param01 providing arguments as a string

121 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

122 wup = WavesUnderElasticPlate(fi, wavenumbers)

123 wui = WavesUnderIce.with_generic_attenuation(

124 wup,

125 lambda thickness, wavenumbers: wavenumbers**2 * thickness / 4,

126 "ice.thickness wavenumbers",

127 )

128 wui_ref = WavesUnderIce.with_attenuation_01(wup)

129 assert np.allclose(wui.attenuations - wui_ref.attenuations, 0)

130

131 @staticmethod

132 @given(**coupled_ocean_ice, wavenumbers=wavenumbers_strategy)

133 def test_param01_kwargs(ice, ocean, gravity, wavenumbers):

134 # Test Param01 providing arguments as a dict

135 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

136 wup = WavesUnderElasticPlate(fi, wavenumbers)

137 wui = WavesUnderIce.with_generic_attenuation(

138 wup,

139 lambda thickness, wavenumbers: wavenumbers**2 * thickness / 4,

140 **{"thickness": ice.thickness, "wavenumbers": wavenumbers},

141 )

142 wui_ref = WavesUnderIce.with_attenuation_01(wup)

143 assert np.allclose(wui.attenuations - wui_ref.attenuations, 0)

144

145 @staticmethod

146 @given(**coupled_ocean_ice, spectrum=spec_mono() | spec_poly())

147 def test_yu2022(ice, ocean, gravity, spectrum: DiscreteSpectrum):

148 # Test Yu2022 providing arguments as a mix of string (accessible from

149 # WUI object) and dict (not accessible from WUI object).

150 fi = FloatingIce.from_ice_ocean(ice, ocean, gravity)

151 wup = WavesUnderElasticPlate.from_floating(fi, spectrum, gravity)

152 wui = WavesUnderIce.with_generic_attenuation(

153 wup,

154 lambda thickness, gravity, angfs: (

155 0.108 * (angfs * (thickness / gravity) ** 0.5) ** 4.46 / thickness

156 ),

157 "ice.thickness",

158 **{"gravity": gravity, "angfs": spectrum.angular_frequencies},

159 )

160 wui_ref = WavesUnderIce.with_attenuation_yu2022(

161 wup, gravity, spectrum.angular_frequencies

162 )

163 assert np.allclose(wui.attenuations, wui_ref.attenuations)