Coverage for tests/test_fracture.py: 99%

1 import pathlib

2 import warnings

3

4 import numpy as np

5 import pytest

6

7 import flexfrac1d.lib.phase_shift as ps

8 import flexfrac1d.model.frac_handlers as fh

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

10

11 fracture_handler_types = (

12 fh.BinaryFracture,

13 fh.BinaryStrainFracture,

14 fh.MultipleStrainFracture,

15)

16 scattering_handler_types = (

17 ps.ContinuousScatteringHandler,

18 ps.UniformScatteringHandler,

19 ps.PerturbationScatteringHandler,

20)

21

22 PATH_FRACTURE_TARGETS = pathlib.Path("tests/target/fracture")

23 binary_energy_no_growth_target = np.loadtxt(

24 PATH_FRACTURE_TARGETS.joinpath("binary_fracture.ssv")

25)

26 binary_strain_no_growth_target = np.loadtxt(

27 PATH_FRACTURE_TARGETS.joinpath("binary_strain_fracture.ssv")

28)

29 multi_strain_no_growth_archive = np.load(

30 PATH_FRACTURE_TARGETS.joinpath("multi_strain_fracture.npz")

31)

32 multi_strain_no_growth_target = (

33 (row, multi_strain_no_growth_archive[f"res{i:02d}"])

34 for i, row in enumerate(multi_strain_no_growth_archive["params"])

35)

36

37

38 def make_wuf(array, growth_params):

39 (

40 frac_toughness,

41 strain_threshold,

42 thickness,

43 youngs_modulus,

44 depth,

45 gravity,

46 amplitude,

47 frequency,

48 length,

49 left_edge,

50 phase,

51 ) = array

52

53 ice = Ice(

54 frac_toughness=frac_toughness,

55 strain_threshold=strain_threshold,

56 thickness=thickness,

57 youngs_modulus=youngs_modulus,

58 )

59 ocean = Ocean(depth=depth)

60 spectrum = DiscreteSpectrum(

61 amplitudes=amplitude, frequencies=frequency, phases=phase

62 )

63 domain = Domain.from_discrete(gravity, spectrum, ocean, None, growth_params)

64 floe = Floe(left_edge=left_edge, length=length, ice=ice)

65 domain.add_floes(floe)

66 return domain.subdomains[0]

67

68

69 def test_abstract():

70 # Abstract classes, should not be instantiated

71 with pytest.raises(TypeError):

72 fh._FractureHandler()

73 with pytest.raises(TypeError):

74 fh._StrainFracture()

75

76

77@pytest.mark.parametrize("fracture_handler_type", fracture_handler_types)

78@pytest.mark.parametrize("scattering_spec_type", scattering_handler_types)

79 def test_initialisation_scattering(fracture_handler_type, scattering_spec_type):

80 rng_seed = 13

81

82 loc, scale = 0.3, 0.005

83

84 if scattering_spec_type == ps.ContinuousScatteringHandler:

85 scattering_spec = scattering_spec_type()

86 elif scattering_spec_type == ps.UniformScatteringHandler:

87 scattering_spec = scattering_spec_type.from_seed(rng_seed)

88 elif scattering_spec_type == ps.PerturbationScatteringHandler: 88 ↛ 91line 88 didn't jump to line 91, because the condition on line 88 was never false

89 scattering_spec = scattering_spec_type.from_seed(rng_seed, loc, scale)

90

91 fracture_handler: fh._FractureHandler = fracture_handler_type(

92 scattering_handler=scattering_spec

93 )

94 assert isinstance(fracture_handler, fracture_handler_type)

95 assert isinstance(fracture_handler.scattering_handler, scattering_spec_type)

96

97

98@pytest.mark.slow

99@pytest.mark.parametrize("row", binary_energy_no_growth_target)

100 def test_binary_energy_no_growth(row):

101 growth_params = None

102 an_sol = True

103 binary_handler = fh.BinaryFracture()

104

105 wuf = make_wuf(row[:-1], growth_params)

106 xf = binary_handler.search(wuf, growth_params, an_sol, None)

107 if xf is not None:

108 # HACK: tests pass locally but need to be tweeked for CI

109 try:

110 assert np.allclose(row[-1] - xf, 0)

111 except AssertionError: # pragma: no cover

112 assert np.allclose(row[-1] - xf, 0, atol=1e-5)

113 warnings.warn(

114 f"Absolute error greater than 1e-8: target {row[-1]}, computed {xf}, "

115 f"diff is {row[-1] - xf}",

116 stacklevel=2,

117 )

118 else:

119 assert np.isnan(row[-1])

120

121

122@pytest.mark.parametrize("row", binary_strain_no_growth_target)

123 def test_binary_strain_no_growth(row):

124 growth_params = None

125 an_sol = True

126 binary_handler = fh.BinaryStrainFracture()

127

128 wuf = make_wuf(row[:-1], growth_params)

129 xf = binary_handler.search(wuf, growth_params, an_sol, None)

130 if xf is not None:

131 assert np.allclose(row[-1] - xf, 0)

132 else:

133 assert np.isnan(row[-1])

134

135

136@pytest.mark.parametrize("row, target", multi_strain_no_growth_target)

137 def test_multi_strain_no_growth(row, target):

138 growth_params = None

139 an_sol = True

140 handler = fh.MultipleStrainFracture()

141

142 wuf = make_wuf(row, growth_params)

143 xfs = handler.search(wuf, growth_params, an_sol, None)

144 if xfs is not None:

145 assert np.allclose(target - xfs, 0)

146 else:

147 assert np.isnan(target)