Skip to content
This documentation describes version 4.0.0, which is not released yet. The current version on PyPI is 3.3.0 and does not carry everything described here.

vibration.structural.building_response

Predicting the fundamental frequency of a building (ISO 4866 Annex D).

A vibration measurement on a building is read against the building’s own response, and that response starts with one number: the lowest natural frequency of the fundamental translation mode. Measure it when you can, says ISO 4866; Annex D is what to do when a direct measurement cannot be made, or when high damping, subcomponent resonances or other practical problems limit how useful it is.

The annex offers four empirical predictors and is candid about all of them. The simplest is the storey count, hertz, the same rule DIN 4150-3 prints in its 6.4 and this library already publishes as storey_fundamental_frequency. The other three are the forms the period takes in national codes, each with a coefficient the codes disagree about:

with the height and the width parallel to the force, both in metres. The coefficients range over 0,014 to 0,03, over 0,087 to 0,109 and over 0,06 to 0,08 respectively, so the choice of code moves the answer by more than a factor of two in the first form alone.

D.2 closes by fitting one curve to measurements instead of to codes: hertz ( seconds) from a sample of 163 rectangular-plan buildings, printed as Figure D.1 with the data around it. Errors of ± 50 % are not uncommon, and D.2 says that is typical of what an empirical formula can do. D.3 then says something worth repeating, since it is the opposite of what a reader expects: computer models correlate worse with measured frequencies than does, because the model is only as good as its idea of what the building is made of.

Damping (D.4) has no predictor at all. Measured values between 0,5 % and 2,1 % of critical are what the annex reports for buildings where soil-structure interaction was negligible, and the two orthogonal translation modes of one building can differ widely. Damping is partly a function of how the building was put together, so anticipate large errors.

Everything here is an estimate with a stated error, which is the only honest way to use it: as the answer to “is the excitation anywhere near the building’s own frequency”, not as a frequency to design against.

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

BuildingFrequencyEstimate(
frequency_hz: float,
period_s: float,
model: str,
coefficient: float | None,
height_m: float | None,
)

One predicted fundamental frequency, with the error it carries.

Attributes

NameDescription
frequency_hzThe predicted fundamental frequency.
period_sThe same prediction as a period.
modelWhich of PERIOD_MODELS produced it.
coefficientThe code coefficient used, or None for the storey model, which has none.
height_mThe height it was computed from, where the model uses one.

property

The ± 50 % band of D.2 around frequency_hz.

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

Draw Figure D.1 with this estimate on it.

The f = 46/h line against height on logarithmic axes, the ± 50 % band around it, and this estimate as a point.

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

Parameters

NameDescription
axExisting axes, or None to create a figure.
languageLabel language, "en" (default) or "es".
kwargsForwarded to phonometry._plot.vibration.plot_building_frequency.

Raises

ExceptionWhen
ValueErrorIf the estimate came from the storey model, which has no height to place a point at.

Constant (tuple).

DAMPING_RATIO_RANGE = (0.005, 0.021)
empirical_frequency_bounds(frequency_hz: float) -> tuple[float, float]

The ± 50 % band D.2 puts around an empirical prediction, in hertz.

Parameters

NameDescription
frequency_hzA predicted fundamental frequency, in hertz.

Returns: (lower, upper), the band the annex says is not uncommon.

Raises

ExceptionWhen
ValueErrorIf the frequency is not positive and finite.

Constant (float).

EMPIRICAL_FREQUENCY_TOLERANCE = 0.5
estimate_fundamental_frequency(
model: PeriodModel | str,
*,
storeys: int | None = None,
height_m: float | None = None,
width_m: float | None = None,
coefficient: float | None = None,
) -> BuildingFrequencyEstimate

One prediction, bundled with the coefficient and the error band.

Parameters

NameDescription
modelOne of PERIOD_MODELS.
storeysNumber of storeys n, for the storey model.
height_mHeight h above the base, in metres.
width_mWidth b parallel to the force, in metres.
coefficientThe code coefficient, or None for the midpoint.

Returns: The prediction, as a BuildingFrequencyEstimate.

Raises

ExceptionWhen
ValueErrorFor anything fundamental_period refuses.
fundamental_frequency(
model: PeriodModel | str,
*,
storeys: int | None = None,
height_m: float | None = None,
width_m: float | None = None,
coefficient: float | None = None,
) -> float

The reciprocal of fundamental_period, in hertz.

Arguments and errors are that function’s; this exists because the annex states two of its four predictors as frequencies and two as periods, and a reader should not have to remember which.

Parameters

NameDescription
modelOne of PERIOD_MODELS.
storeysNumber of storeys n, for the storey model.
height_mHeight h above the base, in metres.
width_mWidth b parallel to the force, in metres.
coefficientThe code coefficient, or None for the midpoint.

Returns: The fundamental frequency, in hertz.

fundamental_period(
model: PeriodModel | str,
*,
storeys: int | None = None,
height_m: float | None = None,
width_m: float | None = None,
coefficient: float | None = None,
) -> float

The fundamental translation period of a building, in seconds (D.2).

Four predictors, and which arguments are needed depends on which:

  • "storeys" needs storeys: .
  • "height" needs height_m: .
  • "height_width" needs both and width_m: .
  • "slenderness" needs both: .

The coefficient defaults to the midpoint of the range D.2 prints for that form, since the annex gives a range and no way to choose inside it; state coefficient to use the value of a particular code.

Parameters

NameDescription
modelOne of PERIOD_MODELS.
storeysNumber of storeys n, for the storey model.
height_mHeight h above the base, in metres.
width_mWidth b parallel to the force, in metres.
coefficientThe code coefficient, or None for the midpoint of PERIOD_COEFFICIENT_RANGES. Not accepted by the storey model, which has no coefficient to choose.

Returns: The fundamental period, in seconds.

Raises

ExceptionWhen
ValueErrorIf the model is not one of the four, if an argument the model needs is missing or not positive, or if an argument the model does not use is given.

Constant (float).

HEIGHT_FREQUENCY_CONSTANT_HZ_M = 46.0
height_fundamental_frequency(height: ArrayLike) -> np.ndarray | float

The f = 46/h fit D.2 closes with, in hertz.

Fitted to 163 rectangular-plan buildings rather than taken from a code, which is why it is here on its own: D.3 goes on to report that computed frequencies correlate with measurement worse than this line does.

Parameters

NameDescription
heightHeight h above the base, in metres (scalar or array).

Returns: The predicted fundamental frequency, in hertz.

Raises

ExceptionWhen
ValueErrorIf a height is not positive and finite.

Constant (float).

HEIGHT_PERIOD_COEFFICIENT_S_PER_M = 0.022

Constant (mapping).

PERIOD_COEFFICIENT_RANGES = {'height': (0.014, 0.03), 'height_width': (0.087, 0.109), 'slenderness': (0.06, 0.08)}

Constant (tuple).

PERIOD_MODELS = ('storeys', 'height', 'height_width', 'slenderness')

Constant (float).

STOREY_PERIOD_COEFFICIENT_S = 0.1