Coverage for tests/test_param_spectra.py: 100%

50 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-09-11 16:30 +0200

1from hypothesis import given, strategies as st 

2import numpy as np 

3import pytest 

4import scipy.integrate as integrate 

5 

6import swiift.api.spectra as spectra 

7from swiift.lib.constants import PI_2 

8from tests.physical_strategies import PHYSICAL_STRATEGIES 

9 

10_freqencies = ( 

11 np.array([1, 2]), 

12 np.array([0.5, 1.2]), 

13 np.linspace(0.3, 0.7, 10), 

14 0.3, 

15) 

16 

17generic_spectra = ( 

18 spectra.PiersonMoskowitz.from_peak_frequency(0.2, 9.8), 

19 spectra.Bretschneider.from_peak_frequency_swh(0.18, 2.1), 

20 spectra.JONSWAP.from_parameters(0.21, 3.3, 9.8), 

21) 

22 

23 

24@pytest.mark.parametrize("frequencies", _freqencies) 

25@pytest.mark.parametrize("spectrum", generic_spectra) 

26def test_angular_density(frequencies, spectrum: spectra._ParametrisedSpectrum): 

27 density_from_frequency = spectrum.density(frequencies) 1d

28 angular_frequencies = PI_2 * frequencies 1d

29 density_from_ang_frequency = spectrum._density_ang(angular_frequencies) 1d

30 

31 # The density should be equal up to the scaling factor 2pi. 

32 assert np.allclose(density_from_frequency, density_from_ang_frequency * PI_2) 1d

33 

34 # Integrating the densities wrt their arguments 

35 # should yield identical results. 

36 if len(np.atleast_1d(frequencies)) > 1: 1d

37 assert np.isclose( 1d

38 spectrum.discrete_energy(frequencies), 

39 np.trapezoid(density_from_ang_frequency, angular_frequencies), 

40 ) 

41 

42 

43@pytest.mark.parametrize("spectrum", generic_spectra) 

44def test_total_energy(spectrum): 

45 res, _ = integrate.quad(spectrum.density, 0, np.inf) 1c

46 swh_num = 4 * np.sqrt(res) 1c

47 target = spectrum.swh 1c

48 

49 if isinstance(spectrum, spectra.JONSWAP): 1c

50 # Twice the greatest absolute error from the ITTC polynomial 

51 # approximation, with respect to the density numerically 

52 # integrated "in-house". 

53 jonswap_atol = 9e-3 1c

54 assert np.isclose(swh_num, target, atol=jonswap_atol) 1c

55 else: 

56 assert np.isclose(swh_num, target) 1c

57 

58 

59@pytest.mark.parametrize("spectrum", generic_spectra) 

60def test_properties(spectrum): 

61 fp = spectrum.peak_frequency 1e

62 

63 assert np.isclose(spectrum.peak_period, 1 / fp) 1e

64 assert np.isclose(spectrum.peak_ang_frequency, PI_2 * fp) 1e

65 

66 

67class TestPiersonMoskowitz: 

68 @staticmethod 

69 @given( 1ab

70 swh=PHYSICAL_STRATEGIES[("wave", "amplitude")], 

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

72 ) 

73 def test_recover_swh(swh: float, gravity: float): 

74 spectrum = spectra.PiersonMoskowitz.from_swh(swh, gravity) 1b

75 assert np.isclose(spectrum.swh, swh) 1b

76 

77 @staticmethod 

78 @given( 1ab

79 peak_frequency=PHYSICAL_STRATEGIES[("wave", "frequency")], 

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

81 ) 

82 def test_recover_peak_frequency(peak_frequency: float, gravity: float): 

83 spectrum = spectra.PiersonMoskowitz.from_peak_frequency(peak_frequency, gravity) 1b

84 assert np.isclose(spectrum.peak_frequency, peak_frequency) 1b

85 

86 

87class TestBretschneider: 

88 @staticmethod 

89 @given( 1ab

90 peak_frequency=PHYSICAL_STRATEGIES[("wave", "frequency")], 

91 swh=PHYSICAL_STRATEGIES[("wave", "amplitude")], 

92 ) 

93 def test_recover_physicak_values(peak_frequency, swh): 

94 spectrum = spectra.Bretschneider.from_peak_frequency_swh(peak_frequency, swh) 1b

95 assert np.isclose(spectrum.peak_frequency, peak_frequency) 1b

96 assert np.isclose(spectrum.swh, swh) 1b