ERS Workflows

This page covers the generic extreme response spectrum workflows in fdscore.

Time-Domain ERS

compute_ers_time(...) is the generic time-domain ERS engine. It evaluates the oscillator bank on a realized input history and returns the maximum observed response for the selected metric.

from fdscore import SDOFParams, compute_ers_time

sdof_ers = SDOFParams(q=10.0, metric="acc", fmin=10.0, fmax=200.0, df=5.0)
ers = compute_ers_time(x, fs, sdof=sdof_ers, detrend="linear")

When the metric and sampling setup match, compute_ers_time(...) can reuse a compatible FDSTimePlan.

Spectral Random ERS

compute_ers_spectral_psd(...) computes a random-vibration ERS directly from a one-sided acceleration PSD. Unlike compute_ers_time(...), this is not the maximum observed in a single realized record. It is the expected extreme response of a stationary Gaussian process over a specified duration.

from fdscore import SDOFParams, compute_ers_spectral_psd

sdof_ers = SDOFParams(q=10.0, metric="acc", fmin=10.0, fmax=200.0, df=5.0)
ers = compute_ers_spectral_psd(
    f_psd_hz=f_psd,
    psd_baseacc=Pyy,
    duration_s=24.0 * 3600.0,
    sdof=sdof_ers,
    nyquist_hz=fs / 2.0,
)

The spectral route builds the response PSD of each oscillator, computes its response moments, estimates a Gaussian peak rate, and returns the expected maximum over duration_s.

For metric="acc", the current implementation uses a Lalanne-style relative-displacement/random-peak backbone internally because it better matches classical random-vibration acceleration ERS practice. Other metrics use exact response-PSD moments of the selected response quantity.

Spectral convenience wrapper

compute_ers_spectral_time(...) is a convenience wrapper for the same random ERS concept. It first estimates a one-sided PSD with Welch and then delegates to compute_ers_spectral_psd(...).

from fdscore import PSDParams, compute_ers_spectral_time

psd = PSDParams(window="hann", nperseg=2048, noverlap=1024, onesided=True)
ers = compute_ers_spectral_time(
    x,
    fs,
    sdof=sdof_ers,
    psd=psd,
    duration_s=24.0 * 3600.0,
)

Edge correction

By default, the spectral ERS route applies an automatic high-frequency edge correction when the PSD is cropped below the original Nyquist limit. This is important near the top of the oscillator grid because truncated PSD exports can artificially suppress the response moments.

The correction is oscillator-local and based on the damping bandwidth:

  • delta_f = 2 * zeta * f_n

  • a raised-cosine taper is used from the last available PSD value down to zero over that span

When the PSD already reaches Nyquist, the correction is a no-op.

Deterministic ERS

The deterministic harmonic helpers parallel the deterministic FDS workflows.

Single sine

from fdscore import compute_ers_sine

ers = compute_ers_sine(freq_hz=80.0, amp=2.0, sdof=sdof_ers, input_motion="acc")

Dwell profiles

from fdscore import SineDwellSegment, compute_ers_dwell_profile

segments = [
    SineDwellSegment(freq_hz=40.0, amp=1.5, duration_s=600.0),
    SineDwellSegment(freq_hz=80.0, amp=2.0, duration_s=300.0),
]

ers_profile = compute_ers_dwell_profile(segments, sdof=sdof_ers)

Dwell-discretized sine sweeps

from fdscore import compute_ers_sine_sweep

ers_sweep = compute_ers_sine_sweep(
    f_start_hz=20.0,
    f_stop_hz=200.0,
    amp=2.0,
    duration_s=180.0,
    sdof=sdof_ers,
    spacing="log",
    n_steps=200,
)

ERS Envelope Composition

ERS mission composition is based on pointwise envelope, not summation.

from fdscore import envelope_ers

ers_env = envelope_ers([ers_run_1, ers_run_2, ers_run_3])

This differs intentionally from FDS, where mission composition follows damage summation.

ERS vs Shock Spectra

compute_ers_time(...) and the spectral/random ERS APIs are the generic ERS family.

Shock-oriented workflows such as compute_srs_time(...) and compute_pvss_time(...) use a separate recursive backend tailored to transient shock analysis and are documented in workflows/shock.md.