diff --git a/repyability/rbd/_point_availability.py b/repyability/rbd/_point_availability.py index dd94b58..5ce57a7 100644 --- a/repyability/rbd/_point_availability.py +++ b/repyability/rbd/_point_availability.py @@ -835,7 +835,9 @@ def __init__( # numbers about ``top ** 2``, so it is uncertain by a few units of # rounding in them (numpy 2.0 sums them to 1e-15 at a top of 5). if variance <= (1e-6 * self.top) ** 2: - self.fixed = mean + # A time known exactly is its atom's, not the mean's rounding. + atoms = _atoms(lambda s: 1.0 - sf(s), self.splits, self.top) + self.fixed = atoms[0][0] if len(atoms) == 1 else mean return from scipy.signal import fftconvolve diff --git a/repyability/tests/test_preventive_maintenance.py b/repyability/tests/test_preventive_maintenance.py index e4c2e2f..7b4a229 100644 --- a/repyability/tests/test_preventive_maintenance.py +++ b/repyability/tests/test_preventive_maintenance.py @@ -138,16 +138,19 @@ def test_maintenance_that_takes_time_is_a_planned_outage(): assert per_run(result, result.system_restorations) == 9 assert result.system_failures == 0 assert result.mean_up_time == 40.0 - assert result.cost.by_category == { - "repair": 0.0, - "replace": 0.0, - "preventive": 50.0, - "inspection": 0.0, - "component_downtime": 60.0, - "system_downtime": 140.0, - "setup": 0.0, - } - assert result.cost.by_component == {"c": 110.0} + # The costs are the exact means, integrated: to rounding. + assert result.cost.by_category == pytest.approx( + { + "repair": 0.0, + "replace": 0.0, + "preventive": 50.0, + "inspection": 0.0, + "component_downtime": 60.0, + "system_downtime": 140.0, + "setup": 0.0, + } + ) + assert result.cost.by_component == pytest.approx({"c": 110.0}) fci = result.criticalities.failure_criticality_index # Planned outages are not failures. assert fci.per_system_failure.get("c", 0) == 0