Coverage for tests/test_experiment.py: 100%

1 from hypothesis import given

2 import numpy as np

3 import pytest

4 from sortedcontainers import SortedList

5

6 from flexfrac1d.api.api import Experiment

7 import flexfrac1d.lib.att as att

8 import flexfrac1d.lib.phase_shift as ps

9 import flexfrac1d.model.frac_handlers as fh

10 from flexfrac1d.model.model import DiscreteSpectrum, Domain, Floe, Ice, Ocean

11

12 from .conftest import coupled_ocean_ice, ocean_and_mono_spectrum, spec_mono

13

14 fracture_handlers = (

15 fh.BinaryFracture,

16 fh.BinaryStrainFracture,

17 fh.MultipleStrainFracture,

18)

19 attenuation_parameterisations = att.AttenuationParameterisation

20 growth_params = (None, (-13, None), (-28, 75), (np.array([-45]), None))

21

22

23@given(**ocean_and_mono_spectrum)

24 def test_initialisation(gravity, spectrum, ocean):

25 experiment = Experiment.from_discrete(gravity, spectrum, ocean)

26

27 assert experiment.time == 0

28 assert isinstance(experiment.domain, Domain)

29 assert experiment.domain.growth_params is None

30 assert (

31 isinstance(experiment.domain.subdomains, SortedList)

32 and len(experiment.domain.subdomains) == 0

33 )

34 assert (

35 isinstance(experiment.domain.attenuation, att.AttenuationParameterisation)

36 and experiment.domain.attenuation == att.AttenuationParameterisation.PARAM_01

37 )

38 assert isinstance(

39 experiment.fracture_handler.scattering_handler, ps.ContinuousScatteringHandler

40 )

41 assert isinstance(experiment.history, dict) and len(experiment.history) == 0

42 assert isinstance(experiment.fracture_handler, fh.BinaryFracture)

43

44

45@given(**ocean_and_mono_spectrum)

46@pytest.mark.parametrize("growth_params", growth_params)

47@pytest.mark.parametrize("fracture_handler_type", fracture_handlers)

48@pytest.mark.parametrize("att_spec", att.AttenuationParameterisation)

49 def test_initialisation_with_opt_params(

50 gravity,

51 spectrum,

52 ocean,

53 growth_params,

54 fracture_handler_type,

55 att_spec,

56):

57 fracture_handler = fracture_handler_type()

58 experiment = Experiment.from_discrete(

59 gravity,

60 spectrum,

61 ocean,

62 growth_params=growth_params,

63 fracture_handler=fracture_handler,

64 attenuation_spec=att_spec,

65 )

66

67 if growth_params is None:

68 assert experiment.domain.growth_params is None

69 else:

70 assert len(experiment.domain.growth_params) == 2

71 assert experiment.domain.growth_params[0] == growth_params[0]

72 assert experiment.domain.growth_params[1] is not None

73 assert isinstance(experiment.fracture_handler, fracture_handler_type)

74 assert isinstance(experiment.domain.attenuation, att.AttenuationParameterisation)

75 assert experiment.domain.attenuation == att_spec

76

77

78@given(spectrum=spec_mono(), **coupled_ocean_ice)

79 def test_add_floes_single(gravity, spectrum, ocean, ice):

80 floe = Floe(left_edge=0, length=100, ice=ice)

81 experiment = Experiment.from_discrete(gravity, spectrum, ocean)

82 assert len(experiment.history) == 0

83 assert len(experiment.domain.subdomains) == 0

84 assert len(experiment.domain.cached_wuis) == 0

85 experiment.add_floes(floe)

86 assert len(experiment.history) == 1

87 assert len(experiment.domain.subdomains) == 1

88 assert experiment.domain.subdomains[0].left_edge == floe.left_edge

89 assert experiment.domain.subdomains[0].length == floe.length

90 assert ice in experiment.domain.cached_wuis

91 assert experiment.history[0].subdomains[0] == experiment.domain.subdomains[0]

92

93

94@given(spectrum=spec_mono(), **coupled_ocean_ice)

95 def test_add_floes_collection(gravity, spectrum, ocean, ice):

96 floe1 = Floe(left_edge=0, length=100, ice=ice)

97 floe2 = Floe(left_edge=100, length=100, ice=ice)

98 experiment = Experiment.from_discrete(gravity, spectrum, ocean)

99 experiment.add_floes((floe1, floe2))

100 assert len(experiment.history) == 1

101 assert len(experiment.history[0].subdomains) == 2

102 assert len(experiment.domain.subdomains) == 2

103

104

105@given(spectrum=spec_mono(), **coupled_ocean_ice)

106 def test_add_floes_overlap(gravity, spectrum, ocean, ice):

107 floe1 = Floe(left_edge=0, length=100, ice=ice)

108 floe2 = Floe(left_edge=80, length=100, ice=ice)

109 experiment = Experiment.from_discrete(gravity, spectrum, ocean)

110 with pytest.raises(ValueError):

111 experiment.add_floes((floe1, floe2))

112

113

114 def total_length_comparison(subdomains, floe: Floe):

115 total_length = sum(wuf.length for wuf in subdomains)

116 return np.allclose(total_length - floe.length, 0)

117

118

119 def test_step():

120 amplitude = 2

121 period = 7

122 spectrum = DiscreteSpectrum(amplitude, 1 / period)

123 thickness = 0.5

124 ice = Ice(thickness=thickness)

125 depth = np.inf

126 ocean = Ocean(depth=depth)

127 gravity = 9.8

128

129 experiment = Experiment.from_discrete(gravity, spectrum, ocean)

130 floe = Floe(left_edge=0, length=200, ice=ice)

131 experiment.add_floes(floe)

132 assert len(experiment.history) == 1

133 assert len(experiment.domain.subdomains) == 1

134

135 # NOTE: use an integer here to avoid floating point precision issues down the line

136 delta_t = 1

137 experiment.step(delta_t, True)

138 assert np.allclose(experiment.time - delta_t, 0)

139 assert len(experiment.history) == 2

140 assert (

141 len(experiment.domain.subdomains) == 2

142 ) # this floe should definitely have fractured in these conditions

143 assert total_length_comparison(experiment.domain.subdomains, floe)

144 assert delta_t in experiment.domain.cached_phases

145

146 number_of_additional_steps = 5

147 for _ in range(number_of_additional_steps):

148 experiment.step(delta_t)

149

150 assert np.allclose(experiment.time - (number_of_additional_steps + 1) * delta_t, 0)

151 assert len(experiment.history) == number_of_additional_steps + 2

152 assert total_length_comparison(experiment.domain.subdomains, floe)

153 last_step = experiment.last_step()

154 assert experiment.history[(number_of_additional_steps + 1) * delta_t] == last_step