<!-- canonical: https://jmrplens.github.io/phonometry/reference/api/building/resilient-layers/ -->
Source: https://jmrplens.github.io/phonometry/reference/api/building/resilient-layers/

Prediction of resilient-layer performance: tapping force, floor coverings,
floating floors.

The measurement modules of this domain report what a resilient layer *achieved*
([`phonometry.building.measurement.floor_covering_improvement`](/phonometry/reference/api/building/floor-covering-improvement/) for the ISO 16251-1
mock-up, [`phonometry.materials.resilient.dynamic_stiffness`](/phonometry/reference/api/materials/dynamic-stiffness/) for the EN 29052-1
dynamic stiffness). This module is their **prediction** counterpart: it walks
the physical chain from the material data to the improvement spectrum, so a
covering or a floating floor can be sized before anything is built.

The chain is one story told in three steps.

**1. The excitation (Hopkins 3.6.3).** The ISO tapping machine drops a 0.5 kg
hammer from 40 mm, ten impacts per second, so the impact velocity is
$v_o = \sqrt{2 g h} = 0.886$ m/s (Eq. 3.85) and, for a short impact, the
peak force per Fourier line is $|F_n| = 2 m v_o/T_i$ (Eq. 3.90), giving
the band mean-square force $F_\mathrm{rms}^{2} = 3.9 B$ (Eq. 3.92). Real floors
are not that simple: the hammer, the contact stiffness `K` it deforms and the
floor's driving-point impedance `Zdp` form a mass-spring-dashpot (Fig. 3.28)
whose force pulse ([`force_pulse`](/phonometry/reference/api/building/resilient-layers/#force_pulse), Eqs. 3.95/3.96) is **over-critical**
when $K m \ge 4 Z_\mathrm{dp}^{2}$ (a single positive pulse, no rebound) and
**under-critical** otherwise (a rebound; only the first positive lobe is
transformed). Its spectrum ([`tapping_force_spectrum`](/phonometry/reference/api/building/resilient-layers/#tapping_force_spectrum)) is flat up to the
cut-off `fco` (Eqs. 3.101/3.102) and falls above it, and it asymptotes at low
frequency between $|F_n|_{\text{lower}} = m v_o/T_i$ and
$|F_n|_{\text{upper}} = 2 m v_o/T_i$, 6 dB apart in mean square
(Eqs. 3.99/3.100).

**2. Soft floor coverings (Hopkins 4.4.3.1).** A soft covering on a heavyweight
floor changes nothing but the force input, so its improvement is the force
ratio $\Delta L = 20 \log_{10}(|F_n|_{\text{without}}/|F_n|_{\text{with}})$
(Eq. 4.114). The covering's contact stiffness $K = E \pi r^{2}/d$
(Eq. 3.98) sets its cut-off, against the bare plate's
$K = 2 r E/(1 - \nu^{2})$ (Eq. 3.97), which is why a two-line estimate,
$\Delta L \approx 0$ below `fco` and 12 dB/octave above it, captures
the whole design question ([`covering_improvement`](/phonometry/reference/api/building/resilient-layers/#covering_improvement)).

**3. Floating floors (Hopkins 4.4.4, ISO 12354-2 Annex C, Vigran 8.4).** Above
the mass-spring resonance $f_o = 160 \sqrt{s'/m'}$ (Formula C.2) the
improvement follows one of three laws
([`floating_floor_improvement_spectrum`](/phonometry/reference/api/building/resilient-layers/#floating_floor_improvement_spectrum)): the infinite-plate result of
Cremer, $\Delta L = 40 \log_{10}(f/f_o)$ (Eq. 4.119, Vigran Eq. 8.40), the
empirical $\Delta L = 30 \log_{10}(f/f_o)$ that EN 12354-2 adopted for
sand-cement screeds (Formula C.1, Eq. 4.124), and the same 40 lg law with the
hammer-impedance term $10 \log_{10}[1 + (f/f_\mathrm{limit})^{2}]$ that a lightweight
walking surface needs (Eq. 4.123, Vigran Eq. 8.48). A floating floor on
discrete mounts instead of a continuous layer is a two-subsystem SEA problem
([`resilient_mount_improvement`](/phonometry/reference/api/building/resilient-layers/#resilient_mount_improvement), Vér's model as Hopkins Eq. 4.118 and
Vigran Eq. 8.45) and rises at 30 dB/decade, not 40. Two floating floors stacked
give two resonances ([`double_floating_floor_resonances`](/phonometry/reference/api/building/resilient-layers/#double_floating_floor_resonances), Eq. 4.125), and
the weighted single number follows from `m'` and `s'` directly
([`weighted_floating_floor_improvement`](/phonometry/reference/api/building/resilient-layers/#weighted_floating_floor_improvement), Formulae C.4/C.5).

The wall and ceiling linings of ISO 12354-1 Annex D, which used to close this
file, are in [`phonometry.building.prediction.linings`](/phonometry/reference/api/building/linings/): they are added to a
wall rather than laid on a floor, and the annex rates them from a resonance
frequency instead of from the tapping machine's force.

Citations are to ISO 12354-2:2017, to Hopkins, *Sound Insulation* (2007) and to
Vigran, *Building Acoustics* (2008). Where the two books state the same model in
different algebra the test suite pins the identity rather than either
transcription. One printed defect is relevant here and is recorded in
`docs/ERRATA.md`: the carpet stiffness in the caption of Vigran's Fig. 8.37.

One relation used here carries no published worked example, so it is
implemented as printed and checked only for self-consistency: the asphalt fit
of Formula (C.5). The guide "Predicting Resilient-Layer Performance" says which
pieces have an oracle and which do not.

> Auto-generated from the source docstrings by `scripts/generate_api_docs.py` (`make api-docs`). Do not edit by hand.

## combined_dynamic_stiffness

```python
combined_dynamic_stiffness(layers: ArrayLike) -> float
```

Total dynamic stiffness of stacked resilient layers (Formula C.6).

$s'_\mathrm{tot} = (\sum 1/s'_i)^{-1}$, springs in series (Hopkins
Eq. 4.121 states the same rule). ISO 12354-2:2017 warns that it holds only
if every layer covers the whole floor without cuts for pipes or electrical
devices.

**Parameters**

| Name | Description |
| :--- | :--- |
| `layers` | Dynamic stiffnesses per unit area `s'i`, in N/m³ (any 1-D array-like). |

**Returns:** The total dynamic stiffness `s'tot`, in N/m³.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If `layers` is empty or holds a non-positive value. |

## covering_contact_stiffness

```python
covering_contact_stiffness(
    youngs_modulus: float,
    thickness: float,
    *,
    radius: float = 0.015,
) -> float
```

Contact stiffness of a soft floor covering
$K = E \pi r^{2}/d$ (Eq. 3.98).

The covering is treated as a linear spring of area $\pi r^{2}$
under the hammer, so only the ratio $E/d$ matters. Vigran's
Eq. (8.51) is the same expression written with the hammer area `Sh`,
quoted there as 7 cm² against the 7.07 cm² of a 15 mm radius.

**Parameters**

| Name | Description |
| :--- | :--- |
| `youngs_modulus` | Young's modulus `E` of the covering, in Pa. |
| `thickness` | Covering thickness `d`, in m. |
| `radius` | Contact radius `r`, in m (Default: 0,015). |

**Returns:** The contact stiffness `K`, in N/m.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## covering_improvement

```python
covering_improvement(
    frequencies: ArrayLike,
    covering_stiffness: float,
    plate_stiffness: float,
    impedance: float,
    *,
    mass: float = 0.5,
    impact_rate: float = 10.0,
    band: BandWidth = 'third',
) -> CoveringImprovementResult
```

Improvement of impact sound insulation by a soft covering (Eq. 4.114).

On a heavyweight base floor a soft covering has a negligible effect on the
mass, bending stiffness and total loss factor of the slab, so it alters
only the force the hammer injects. The improvement is then the ratio of
the two force spectra,
$\Delta L = 20 \log_{10}(|F_n|_{\text{without}}/|F_n|_{\text{with}})$,
computed here from [`tapping_force_spectrum`](/phonometry/reference/api/building/resilient-layers/#tapping_force_spectrum) with the covering's
contact stiffness (Eq. 3.98) and with the plate's (Eq. 3.97).

The tapping machine excites a **line** spectrum, at multiples of the 10 Hz
impact rate, so Eq. (4.114) is a statement about one Fourier component and
the band value is the ratio of the band mean-square forces (Eq. 3.91),
that is the sum over the lines that fall in the band. `improvement` is
that band value and `line_improvement` is the per-line ratio. The
distinction matters: the undamped model's transform has exact nulls at odd
multiples of `fco`, so a band centre that happens to land on one reads
tens of dB high. With the 100 Hz cut-off of Hopkins's covering No. 2, the
line ratio at 500 Hz is 66.8 dB against a two-line estimate of 27.9 dB,
while the band value is 33.3 dB. Hopkins notes below Fig. 4.64 that the
troughs vanish once the covering's internal damping is included and the
spectrum is averaged into bands.

`two_line` is Hopkins's design estimate: $\Delta L \approx 0$
below the covering's cut-off and a straight 12 dB/octave above it, that
is $40 \log_{10}(f/f_\mathrm{co})$.
Real coverings behave as non-linear springs under the tapping machine's
high force and show two or three slopes between 5 and 22 dB/octave, so the
model identifies the general features rather than replacing a measurement.

**Parameters**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `covering_stiffness` | Contact stiffness `K` of the covering, in N/m ([`covering_contact_stiffness`](/phonometry/reference/api/building/resilient-layers/#covering_contact_stiffness)). |
| `plate_stiffness` | Contact stiffness `K` of the bare plate, in N/m ([`plate_contact_stiffness`](/phonometry/reference/api/building/resilient-layers/#plate_contact_stiffness)). |
| `impedance` | Driving-point impedance `Zdp` of the base floor, in N.s/m; unchanged by the covering. |
| `mass` | Hammer mass `m`, in kg (Default: 0,5). |
| `impact_rate` | Impact repetition rate `fi`, in Hz (Default: 10); it sets the spacing of the Fourier lines the bands average over. |
| `band` | `"third"` or `"octave"`. |

**Returns:** A [`CoveringImprovementResult`](/phonometry/reference/api/building/resilient-layers/#coveringimprovementresult).

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or `band` is unknown. |

## CoveringImprovementResult

```python
CoveringImprovementResult(
    frequencies: np.ndarray,
    improvement: np.ndarray,
    two_line: np.ndarray,
    cut_off_frequency: float,
    bare_cut_off_frequency: float,
    lines: np.ndarray,
    line_improvement: np.ndarray,
    bare: TappingForceResult,
    covered: TappingForceResult,
)
```

Predicted improvement `ΔL` of a soft floor covering
(Hopkins 4.4.3.1).

**Attributes**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `improvement` | Band improvement `ΔL`, in dB: Eq. (4.114) evaluated over the tapping machine's Fourier lines and summed in mean square across each band, $10 \log_{10}(\sum \lvert F_n \rvert^{2}_{\text{without}}/\sum \lvert F_n \rvert^{2}_{\text{with}})$. |
| `two_line` | The two-line estimate, in dB: 0 below `fco` and 12 dB/octave (40 dB/decade) above it. |
| `cut_off_frequency` | Cut-off frequency `fco` of the covered floor, in Hz. |
| `bare_cut_off_frequency` | Cut-off frequency of the bare plate, in Hz. |
| `lines` | Fourier line frequencies $n f_i$ of the tapping machine, in Hz, covering every band in `frequencies`. |
| `line_improvement` | The per-line ratio $\Delta L = 20 \log_{10}(\lvert F_n \rvert_{\text{without}}/\lvert F_n \rvert_{\text{with}})$ of Eq. (4.114) at `lines`, in dB. It carries the deep troughs at odd multiples of `fco` that Hopkins notes below Fig. 4.64, which are an artefact of the undamped model and disappear from `improvement`. |
| `bare` | The bare-plate [`TappingForceResult`](/phonometry/reference/api/building/resilient-layers/#tappingforceresult), at `lines`. |
| `covered` | The [`TappingForceResult`](/phonometry/reference/api/building/resilient-layers/#tappingforceresult) with the covering, at `lines`. |

### CoveringImprovementResult.plot()

```python
CoveringImprovementResult.plot(
    ax: Axes | None = None,
    *,
    language: str = 'en',
    **kwargs: Any,
) -> Axes
```

Plot `ΔL(f)` from the force ratio beside the two-line estimate.

Requires matplotlib (`pip install phonometry[plot]`); returns the
`Axes`.

## double_floating_floor_resonances

```python
double_floating_floor_resonances(
    lower_stiffness: float,
    lower_mass_per_area: float,
    upper_stiffness: float,
    upper_mass_per_area: float,
) -> tuple[float, float]
```

The two resonances of a double floating floor (Hopkins Eq. 4.125).

One floating floor on top of another over a heavyweight base is a
mass-spring-mass-spring system with

$$
f_\mathrm{msms} = \frac{1}{2^{3/2} \pi} \sqrt{X \pm \sqrt{X^{2} - \frac{4 s_1 s_2}{\rho_{\mathrm{s}1} \rho_{\mathrm{s}2}}}}, \qquad X = \frac{s_1}{\rho_{\mathrm{s}1}} + \frac{s_2}{\rho_{\mathrm{s}1}} + \frac{s_2}{\rho_{\mathrm{s}2}}
$$

subscript 1 being the lower floating floor (on the resilient layer that
rests on the base) and 2 the upper one. The double floor avoids the single
floor's dip at `fms`, but the steep rise in `ΔL` only starts above the
higher of the two resonances. For two identical floors the roots are
$f_\mathrm{ms} \sqrt{(3 \pm \sqrt{5})/2}$, that is $0.618 f_\mathrm{ms}$
and $1.618 f_\mathrm{ms}$.

**Parameters**

| Name | Description |
| :--- | :--- |
| `lower_stiffness` | Dynamic stiffness per unit area `s1` of the lower resilient layer, in N/m³. |
| `lower_mass_per_area` | Mass per unit area `ρs1` of the lower floating floor, in kg/m². |
| `upper_stiffness` | Dynamic stiffness per unit area `s2` of the upper resilient layer, in N/m³. |
| `upper_mass_per_area` | Mass per unit area `ρs2` of the upper floating floor, in kg/m². |

**Returns:** `(lower, upper)` resonance frequencies, in Hz.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## floating_floor_improvement_spectrum

```python
floating_floor_improvement_spectrum(
    frequencies: ArrayLike,
    *,
    resonance_frequency: float,
    model: FloatingFloorModel = 'en12354',
    limiting_frequency: float | None = None,
    mass_per_area: float | None = None,
    dynamic_stiffness: float | None = None,
) -> FloatingFloorImprovementResult
```

Improvement `ΔL(f)` of a floating floor on a heavyweight base floor.

Three laws share the same anchor, the mass-spring resonance `fo` of the
walking surface on the resilient layer ([`floating_floor_resonance_frequency`](/phonometry/reference/api/building/resilient-layers/#floating_floor_resonance_frequency)),
and all give $\Delta L = 0$ at and below it (in the band containing
`fo`, `ΔL` is in practice between −5 dB and 0 dB):

* `"cremer"`: $\Delta L = 40 \log_{10}(f/f_o)$, Cremer's 1952 result for
  two infinite, locally reacting plates coupled by a spring layer (Hopkins
  Eq. 4.119, Vigran Eq. 8.40), i.e. 12 dB per octave. It holds for
  constructions with high internal damping, such as asphalt screeds, and is
  the branch ISO 12354-2 Formula (C.3) prescribes for asphalt and dry
  floating floors.
* `"en12354"` (default): $\Delta L = 30 \log_{10}(f/f_o)$, the empirical
  law of ISO 12354-2 Formula (C.1) for sand-cement and calcium-sulfate
  screeds (Hopkins Eq. 4.124). Sand-cement screeds have a low internal
  loss factor and act as finite plates with a reverberant bending field,
  for which the 40 lg law overestimates `ΔL`.
* `"cremer_hammer"`:
  $\Delta L = 40 \log_{10}(f/f_o) + 10 \log_{10}[1 + (f/f_\mathrm{limit})^{2}]$, the
  40 lg law with the reduction in power input above the limiting frequency
  of the hammer's own impedance (Hopkins Eq. 4.123, Vigran Eq. 8.48). A
  lightweight walking surface such as chipboard needs it, and tends to
  18 dB per octave well above `flimit`.

The laws are stated as valid above `fo`, and Cremer's derivation is
reported to hold in $f_o < f < 4 f_o$.

**Parameters**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `resonance_frequency` | Mass-spring resonance `fo`, in Hz. |
| `model` | `"en12354"`, `"cremer"` or `"cremer_hammer"`. |
| `limiting_frequency` | Limiting frequency `flimit`, in Hz; required by `"cremer_hammer"` and ignored otherwise ([`hammer_limiting_frequency`](/phonometry/reference/api/building/resilient-layers/#hammer_limiting_frequency)). |
| `mass_per_area` | Optional `m'` of the floating floor, in kg/m². |
| `dynamic_stiffness` | Optional `s'` of the resilient layer, in N/m³; supplied together with `mass_per_area` it adds `ΔLw` to the result, from Formula (C.4) for `"en12354"` (screeds) and Formula (C.5) for the other two models (asphalt and dry floating floors). |

**Returns:** A [`FloatingFloorImprovementResult`](/phonometry/reference/api/building/resilient-layers/#floatingfloorimprovementresult).

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, `model` is unknown, or `"cremer_hammer"` is used without a limiting frequency. |

## floating_floor_resonance_frequency

```python
floating_floor_resonance_frequency(
    dynamic_stiffness: float,
    mass_per_area: float,
) -> float
```

Resonance $f_o = 160 \sqrt{s'/m'}$ of a floating floor
(Formula C.2).

ISO 12354-2:2017 Formula (C.2), with `s'` the EN 29052-1 dynamic
stiffness per unit area of the resilient layer measured without pre-load
and `m'` the mass per unit area of the floating floor. The printed
constant 160 rounds the exact mass-spring value
$1000/(2 \pi) = 159.15$ that
[`phonometry.materials.natural_frequency`](/phonometry/reference/api/materials/dynamic-stiffness/#natural_frequency) applies, so the two differ
by 0.5 %; this function reproduces the standard, whose own Annex G
example prints $f_o = 52.8$ Hz for $s' = 8$ MN/m³,
$m' = 73.5$ kg/m².

**Parameters**

| Name | Description |
| :--- | :--- |
| `dynamic_stiffness` | Dynamic stiffness per unit area `s'`, in N/m³ (i.e. 8e6 for the 8 MN/m³ of the standard's example). |
| `mass_per_area` | Mass per unit area `m'` of the floating floor, in kg/m². |

**Returns:** The resonance frequency `fo`, in Hz.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## FloatingFloorImprovementResult

```python
FloatingFloorImprovementResult(
    frequencies: np.ndarray,
    improvement: np.ndarray,
    resonance_frequency: float,
    model: str,
    slope: float,
    limiting_frequency: float | None = None,
    delta_lw: float | None = None,
)
```

Predicted improvement `ΔL(f)` of a floating floor.

**Attributes**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `improvement` | Improvement `ΔL` per band, in dB (0 at and below `resonance_frequency`). |
| `resonance_frequency` | Mass-spring resonance `fo`, in Hz. |
| `model` | `"en12354"`, `"cremer"` or `"cremer_hammer"`. |
| `slope` | Slope of the law, in dB per decade (30 or 40). |
| `limiting_frequency` | Limiting frequency `flimit` of the hammer term, in Hz, or `None` when the term is not applied. |
| `delta_lw` | Weighted improvement `ΔLw`, in dB, or `None` when the floor data were not supplied: Formula (C.4) for the `"en12354"` model, Formula (C.5) for the other two. |

### FloatingFloorImprovementResult.plot()

```python
FloatingFloorImprovementResult.plot(
    ax: Axes | None = None,
    *,
    language: str = 'en',
    **kwargs: Any,
) -> Axes
```

Plot `ΔL(f)` with the resonance and the asymptotic slope marked.

Requires matplotlib (`pip install phonometry[plot]`); returns the
`Axes`.

## force_pulse

```python
force_pulse(
    time: ArrayLike,
    contact_stiffness: float,
    impedance: float,
    *,
    mass: float = 0.5,
    impact_velocity: float | None = None,
) -> np.ndarray
```

Force pulse `F1(t)` of a single hammer impact (Eqs. 3.95/3.96).

Lindblad's solution of the mass-spring-dashpot of Hopkins Fig. 3.28, the
hammer mass `m` on the contact stiffness `K` in series with the floor's
driving-point impedance `Zdp`. For an **over-critical** oscillation
($K m \ge 4 Z_\mathrm{dp}^{2}$) the pulse decays to zero without changing
sign (Eq. 3.95); for an **under-critical** one it is a decaying sinusoid
(Eq. 3.96) whose first positive lobe is the impact proper. Hopkins's rule
is stated in terms of the sign of the force rather than of any mechanism:
"only the initial force pulse that has zero or positive force values is
used to determine the force spectrum, with all subsequent values of F1(t)
due to the oscillations set to zero before taking the Fourier transform",
the hammer having rebounded from the plate. That truncation is applied
here, so the under-critical pulse is returned as zero beyond its
first zero crossing at $t = \pi/\beta$; it is the same truncation
[`tapping_force_spectrum`](/phonometry/reference/api/building/resilient-layers/#tapping_force_spectrum) transforms, so integrating this pulse over
$0 \le t \le \pi/\beta$ reproduces that spectrum.

The over-critical pulse has no such cut and decays for all `t`; it is
evaluated in a form that stays finite over the whole 0,1 s between
impacts rather than one that overflows partway through it.

**Parameters**

| Name | Description |
| :--- | :--- |
| `time` | Time `t` since the impact, in s (scalar or array, $\ge 0$). |
| `contact_stiffness` | Contact stiffness `K`, in N/m. |
| `impedance` | Driving-point impedance `Zdp`, in N.s/m. |
| `mass` | Hammer mass `m`, in kg (Default: 0,5). |
| `impact_velocity` | Impact velocity `vo`, in m/s (Default: [`hammer_impact_velocity`](/phonometry/reference/api/building/resilient-layers/#hammer_impact_velocity)). |

**Returns:** The force `F1(t)`, in N, with the same shape as `time`; never negative.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or `time` contains a negative value. |

## hammer_impact_velocity

```python
hammer_impact_velocity(
    drop_height: float = 0.04,
    *,
    gravity: float = 9.81,
) -> float
```

Hammer velocity at impact $v_o = \sqrt{2 g h}$ (Hopkins
Eq. 3.85).

The ISO tapping machine's nominal 40 mm drop gives
$v_o = 0.886$ m/s.

**Parameters**

| Name | Description |
| :--- | :--- |
| `drop_height` | Drop height `h`, in m (Default: 0,04). |
| `gravity` | Acceleration of free fall `g`, in m/s² (Default: 9,81). |

**Returns:** The impact velocity `vo`, in m/s.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## hammer_limiting_frequency

```python
hammer_limiting_frequency(impedance: float, *, mass: float = 0.5) -> float
```

Limiting frequency $f_\mathrm{limit} = Z_\mathrm{dp}/(2 \pi m)$ (Hopkins
Eq. 3.106).

The frequency at which the floor's driving-point impedance equals the
magnitude of the hammer's own mass impedance $|Z_\mathrm{h}| = \omega m$;
above it the hammer mass, not the floor, limits the injected power, and
the power input stops rising at 3 dB per doubling of frequency. Vigran's
Eq. (8.48) writes the same frequency as
$f_z = 4 \sqrt{m_1 B_1}/(\pi m_\mathrm{h})$.

**Parameters**

| Name | Description |
| :--- | :--- |
| `impedance` | Driving-point impedance `Zdp`, in N.s/m. |
| `mass` | Hammer mass `m`, in kg (Default: 0,5). |

**Returns:** The limiting frequency `flimit`, in Hz.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## plate_contact_stiffness

```python
plate_contact_stiffness(
    youngs_modulus: float,
    *,
    poisson_ratio: float = 0.2,
    radius: float = 0.015,
) -> float
```

Contact stiffness of a plate material
$K = 2 r E/(1 - \nu^{2})$ (Eq. 3.97).

The stiffness the hammer deforms when it lands on the bare walking surface
(Timoshenko and Goodier's Hertzian contact for a flat circular punch), as
opposed to [`covering_contact_stiffness`](/phonometry/reference/api/building/resilient-layers/#covering_contact_stiffness) for a soft covering laid on
top of it.

**Parameters**

| Name | Description |
| :--- | :--- |
| `youngs_modulus` | Young's modulus `E` of the plate, in Pa. |
| `poisson_ratio` | Poisson's ratio `ν` of the plate (Default: 0,2, the value Hopkins Table A2 estimates for concrete and masonry). |
| `radius` | Contact radius `r`, in m (Default: 0,015). |

**Returns:** The contact stiffness `K`, in N/m.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or $\lvert \nu \rvert \ge 1$. |

## resilient_mount_improvement

```python
resilient_mount_improvement(
    frequencies: ArrayLike,
    *,
    impedance: float,
    mass_per_area: float,
    loss_factor: ArrayLike,
    mount_stiffness: float,
    mount_density: float,
) -> np.ndarray
```

Improvement of a floating floor on discrete resilient mounts (Vér).

Vér's two-subsystem SEA model of a walking surface carrying a reverberant
bending-wave field, connected to a heavyweight base floor by `N` mounts
per unit area of stiffness `k` each, with all transmission through the
mounts and none through the cavity. Hopkins Eq. (4.118) writes it as

$$
\Delta L \approx 10 \log_{10}\!\left( \frac{2.3 \rho_{\mathrm{s}1}^{2} c_{\mathrm{L}1} h_1 \eta_1 S_1 \omega^{3}}{N k^{2}} \right)
$$

where `k` is the dynamic stiffness of each mount, `N` the **number** of
mounts and `S1` the area of the walking surface. Since
$2.3 \rho_{\mathrm{s}1}^{2} c_{\mathrm{L}1} h_1 = Z_{\mathrm{dp}1} \rho_{\mathrm{s}1}$ for
$Z_{\mathrm{dp}1} = 2.3 \rho c_\mathrm{L} h^{2}$ (Eq. 2.190), the same expression
reads $10 \log_{10}(Z_{\mathrm{dp}1} \rho_{\mathrm{s}1} \eta_1 \omega^{3}/(N/S_1 \cdot k^{2}))$, which is the form evaluated here: this function takes the mount
**density** `N/S1`, not the count.

Vigran's Eq. (8.45) is a sum of three terms, $Z_1/Z_2$,
$m_1 \eta_1/(m_2 \eta_2)$ and
$Z_1 \eta_1 N f^{3}/(2 \pi m_1 f_o^{4})$ with
$f_o = \sqrt{N k/m_1}/(2 \pi)$. Only the
**third** of them is the model implemented here, and that term is
algebraically identical to Hopkins Eq. (4.118); the first two are the
low-frequency floor, negligible once the third dominates, which is the
regime Vigran states the 9 dB per octave slope for. The dominant-term form
used here therefore rises at **30 dB per decade** (9 dB per octave),
against the 40 dB per decade of a continuous resilient layer: fewer mounts,
a thicker walking surface or more internal damping all raise `ΔL`.

Vigran's simplified Eq. (8.46) inserts `Z1` into that third term and
prints the coefficient as $2/(\sqrt{3} \pi) = 0.3676$, which is the
same number as the $2.3094/(2 \pi) = 0.3676$ the substitution
gives; the two forms agree.

**Parameters**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `impedance` | Driving-point impedance `Zdp1` of the walking surface, in N.s/m. |
| `mass_per_area` | Mass per unit area `ρs1` of the walking surface, in kg/m². |
| `loss_factor` | Total loss factor `η1` of the walking surface (scalar or per band). |
| `mount_stiffness` | Dynamic stiffness `k` of one mount, in N/m. |
| `mount_density` | Number of mounts per unit area `N/S1`, in 1/m² (Vigran's `N`, which is already a density). |

**Returns:** The improvement `ΔL` per band, in dB, and 0 dB at and below `fo`.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## short_pulse_mean_square_force

```python
short_pulse_mean_square_force(
    frequencies: ArrayLike,
    *,
    band: BandWidth = 'third',
) -> np.ndarray
```

Band mean-square force of a short impact
$F_\mathrm{rms}^{2} = 3.9 B$ (Eq. 3.92).

The limiting case in which the impact is short enough that the hammer's
momentum alone sets the force: combining $|F_n| = 2 m v_o/T_i$
(Eq. 3.90) with $F_\mathrm{rms}^{2} = |F_n|^{2} B/(2 f_i)$ (Eq. 3.91)
gives 3.925 B, printed as 3.9 B. Hopkins finds it adequate for bare
concrete slabs of at least 100 mm.

**Parameters**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `band` | `"third"` ($B = 0.23 f$) or `"octave"` ($B = 0.707 f$). |

**Returns:** The band mean-square force `F²rms`, in N².

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or `band` is unknown. |

## tapping_cut_off_frequency

```python
tapping_cut_off_frequency(
    contact_stiffness: float,
    impedance: float,
    *,
    mass: float = 0.5,
) -> float
```

Cut-off frequency `fco` of the force spectrum (Eqs. 3.101/3.102).

Above `fco` the tapping machine's force spectrum is no longer flat and
the force falls away. For an under-critical oscillation
($K m < 4 Z_\mathrm{dp}^{2}$, the case of a concrete slab with or without
a soft covering) it is the undamped mass-spring value
$f_\mathrm{co} = \sqrt{K/m}/(2 \pi)$ (Eq. 3.102); for an over-critical one
(a lightweight walking surface) it is the lower root
$[K/(2 Z_\mathrm{dp}) - \sqrt{(K/(2 Z_\mathrm{dp}))^{2} - K/m}]/(2 \pi)$
(Eq. 3.101).

**Parameters**

| Name | Description |
| :--- | :--- |
| `contact_stiffness` | Contact stiffness `K`, in N/m (see [`plate_contact_stiffness`](/phonometry/reference/api/building/resilient-layers/#plate_contact_stiffness) / [`covering_contact_stiffness`](/phonometry/reference/api/building/resilient-layers/#covering_contact_stiffness)). |
| `impedance` | Driving-point impedance `Zdp` of the floor, in N.s/m (for a homogeneous plate, [`phonometry.vibration.infinite_plate_impedance`](/phonometry/reference/api/vibration/point-mobility/#infinite_plate_impedance)). |
| `mass` | Hammer mass `m`, in kg (Default: 0,5). |

**Returns:** The cut-off frequency `fco`, in Hz.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite. |

## TAPPING_DROP_HEIGHT

*Constant* (`float`).

```python
TAPPING_DROP_HEIGHT = 0.04
```

## tapping_force_spectrum

```python
tapping_force_spectrum(
    frequencies: ArrayLike,
    contact_stiffness: float,
    impedance: float,
    *,
    mass: float = 0.5,
    impact_rate: float = 10.0,
    impact_velocity: float | None = None,
    band: BandWidth = 'third',
) -> TappingForceResult
```

Force spectrum of the ISO tapping machine on a floor (Hopkins 3.6.3.1).

The Fourier transform of the single-impact force pulse
([`force_pulse`](/phonometry/reference/api/building/resilient-layers/#force_pulse)), scaled by the impact repetition rate. Writing
$a = K/(2 Z_\mathrm{dp})$ and $\omega_o^{2} = K/m$, the transform of
Eqs. (3.95)/(3.96) is the same rational function in both critical cases,
$\hat{F}(\omega) = v_o K/(\omega_o^{2} - \omega^{2} + 2 i a \omega)$,
multiplied for the under-critical case by
$1 + e^{-a \pi/\beta} e^{-i \omega \pi/\beta}$ because only the
first positive lobe (of duration $\pi/\beta$) is transformed. That
truncation is what produces the deep troughs at $n f_\mathrm{co}$,
$n = 3, 5, 7$ that Hopkins notes below Fig. 4.64; they vanish once
the covering's internal damping is included and the spectrum is averaged
into bands.

The transform is normalised so that the low-frequency asymptote is
$m v_o/T_i$ for an over-critical impact (no rebound) and
$2 m v_o/T_i$ for a lightly damped under-critical one (full
rebound), the two limits of Eqs. (3.99)/(3.100).

**Parameters**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `contact_stiffness` | Contact stiffness `K`, in N/m. |
| `impedance` | Driving-point impedance `Zdp` of the floor, in N.s/m. |
| `mass` | Hammer mass `m`, in kg (Default: 0,5). |
| `impact_rate` | Impact repetition rate `fi`, in Hz (Default: 10). |
| `impact_velocity` | Impact velocity `vo`, in m/s (Default: [`hammer_impact_velocity`](/phonometry/reference/api/building/resilient-layers/#hammer_impact_velocity)). |
| `band` | `"third"` or `"octave"`, the band width of Eq. (3.91). |

**Returns:** A [`TappingForceResult`](/phonometry/reference/api/building/resilient-layers/#tappingforceresult).

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or `band` is unknown. |

## TAPPING_HAMMER_MASS

*Constant* (`float`).

```python
TAPPING_HAMMER_MASS = 0.5
```

## TAPPING_HAMMER_RADIUS

*Constant* (`float`).

```python
TAPPING_HAMMER_RADIUS = 0.015
```

## TAPPING_IMPACT_RATE

*Constant* (`float`).

```python
TAPPING_IMPACT_RATE = 10.0
```

## TappingForceResult

```python
TappingForceResult(
    frequencies: np.ndarray,
    peak_force: np.ndarray,
    mean_square_force: np.ndarray,
    power_input: np.ndarray,
    cut_off_frequency: float,
    limiting_frequency: float,
    over_critical: bool,
    contact_stiffness: float,
    impedance: float,
    lower_limit: float,
    upper_limit: float,
    band: str = 'third',
)
```

Force spectrum of the ISO tapping machine on one walking surface.

**Attributes**

| Name | Description |
| :--- | :--- |
| `frequencies` | Band centre frequencies `f`, in Hz. |
| `peak_force` | Magnitude of the Fourier force component `\|Fn\|`, in N (Hopkins Fig. 3.32). |
| `mean_square_force` | Band mean-square force `F²rms`, in N² (Eq. 3.91). |
| `power_input` | Power injected into the floor $W_\mathrm{in} = F_\mathrm{rms}^{2}/Z_\mathrm{dp}$, in W (Eq. 3.103). |
| `cut_off_frequency` | Cut-off frequency `fco`, in Hz (Eqs. 3.101/3.102). |
| `limiting_frequency` | Limiting frequency `flimit`, in Hz (Eq. 3.106). |
| `over_critical` | `True` when $K m \ge 4 Z_\mathrm{dp}^{2}$, i.e. the hammer does not rebound. |
| `contact_stiffness` | Contact stiffness `K` used, in N/m. |
| `impedance` | Driving-point impedance `Zdp` used, in N.s/m. |
| `lower_limit` | Low-frequency asymptote $\lvert F_n \rvert_{\text{lower}} = m v_o/T_i$, in N (Eq. 3.99). |
| `upper_limit` | Low-frequency asymptote $\lvert F_n \rvert_{\text{upper}} = 2 m v_o/T_i$, in N (Eq. 3.100); 6 dB above `lower_limit` in mean square. |
| `band` | Band width used for `mean_square_force`. |

### TappingForceResult.plot()

```python
TappingForceResult.plot(
    ax: Axes | None = None,
    *,
    language: str = 'en',
    **kwargs: Any,
) -> Axes
```

Plot the force spectrum `|Fn|` with its asymptotes and `fco`.

Requires matplotlib (`pip install phonometry[plot]`); returns the
`Axes`.

### TappingForceResult.power_input_level

*property*

Power input level $10 \log_{10}(W_\mathrm{in}/1~\text{pW})$, in dB
(Hopkins Fig. 3.33).

## weighted_floating_floor_improvement

```python
weighted_floating_floor_improvement(
    mass_per_area: float,
    dynamic_stiffness: float,
    *,
    floor: FloorType = 'screed',
) -> float
```

Weighted improvement `ΔLw` of a floating floor (Formulae C.4/C.5).

The single number that feeds the simplified prediction
([`phonometry.predicted_impact_insulation`](/phonometry/reference/api/building/simplified-model/#predicted_impact_insulation)), read directly from the
floating floor's mass per unit area and the resilient layer's dynamic
stiffness. ISO 12354-2:2017 gives it as the two nomograms of Figures C.1
and C.2 and prints the fits:

* `floor="screed"` (sand-cement or calcium-sulfate screeds, Formula C.4):
  $\Delta L_\mathrm{w} = 13 \log_{10}(m') - 14.2 \log_{10}(s') + 20.8$;
* `floor="asphalt"` (asphalt or dry floating floors, Formula C.5):
  $\Delta L_\mathrm{w} = (-0.21 m' - 5.45) \log_{10}(s') + 0.46 m' + 23.8$.

**Parameters**

| Name | Description |
| :--- | :--- |
| `mass_per_area` | Mass per unit area `m'` of the floating floor, in kg/m². |
| `dynamic_stiffness` | Dynamic stiffness per unit area `s'`, in N/m³. |
| `floor` | `"screed"` (Formula C.4) or `"asphalt"` (Formula C.5). |

**Returns:** The weighted improvement `ΔLw`, in dB.

**Raises**

| Exception | When |
| :--- | :--- |
| ValueError | If an input is not positive and finite, or `floor` is unknown. |
