Quick Start: Basic Simulation Example#

This example demonstrates how to calibrate a stochastic model to a recorded ground motion. We utilize the ModelInverter class to obtain a fitted StochasticModel, which is then used to generate synthetic ground motion simulations.

Step 1: Import Libraries and Load the Target Ground Motion#

Import necessary sgsim classes along with necessary libraries. Load an existing accelerogram record to serve as the target for the simulation.

# %% import libraries
import numpy as np
import matplotlib.pyplot as plt
import time
from sgsim import GroundMotion, ModelInverter, Functions

# %% Prepare the target ground motion
# Change the path to the file
gm = GroundMotion.load_from(source='nga', file='RSN123_Example.AT2')
# If necessary, preprocess the ground motion (e.g., trimming, baseline correction, tapering and filtering), otherwise skip this step
gm = gm.trim_by_energy((0.001, 0.999)).taper(0.05).butterworth_filter((0.05, 100.0))
# An alterantive to triming gm for just model inversion is to use fit_range in the inverter.fit() method to specify the time range for fitting (e.g., fit_range=(0.01, 0.99) for 1% to 99% cumulative energy)

Step 2: Perform Model Inversion#

Use the ModelInverter class to fit a stochastic model to the target ground motion. Use Functions to define the functional forms for the model parameters (amplitude, frequency, and damping evolution with time).

# %% Specify the stochastic model functional forms
q = Functions.BetaCentroidSpread()  # Modulating function
wu = Functions.Constant()           # Upper frequency
zu = Functions.Constant()           # Upper damping
wl = Functions.Constant()           # Lower frequency
zl = Functions.Constant()           # Lower damping

inverter = ModelInverter(ground_motion=gm, modulating=q,
                         upper_frequency=wu, upper_damping=zu,
                         lower_frequency=wl, lower_damping=zl)

# Optional: Provide initial guesses and fix parameters using tight bounds
# Here we fix upper_damping to 0.707 and lower_damping to 1.0 by making min/max bounds equal
ig = {
    "upper_frequency": [10.0],
    "upper_damping": [0.707],
    "lower_frequency": [0.3],
    "lower_damping": [1.0],
}

bs = {
    "upper_frequency": [(0.1, 40.0)],
    "upper_damping": [(0.707, 0.707)], # Fixed parameter
    "lower_frequency": [(0.01, 0.99)],
    "lower_damping": [(1.0, 1.0)],     # Fixed parameter
}

# Fit to the target ground motion and measure execution time
start = time.time()
model = inverter.fit(initial_guess=ig, bounds=bs, fit_range=(0.01, 0.99), mode='stepwise')  # stepwide mode is faster and lead to unique solution, while joint mode is more robust but slower and may lead to multiple local minima. Adjust fit_range as needed to focus on specific time windows of the ground motion.
end = time.time()

print(f"Execution time: {end - start:.2f} seconds")

# Print a summary of the fitted parameters
model.summary()

Step 3: Generate Simulations#

Generate synthetic ground motions using the fitted stochastic model parameters. The resulting simulations are returned as a GroundMotion object.

See also

For more details on working with ground motions, refer to Quick Start: Basic Ground Motion Analysis Example.

# %% Generate 20 simulated ground motions
sm = model.simulate(n=20)

# %% View available IMs
sm.list_IMs()

Step 4: Visualize the Results#

You can use standard libraries like matplotlib to visualize the model, simulations, and the target.

Tip

See Quick Start: Basic Ground Motion Analysis Example for plotting response spectra and other intensity measures.

# 1. Compare Acceleration Time Series
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 6), gridspec_kw={'hspace': 0.15})

# Target Ground Motion
axes[0].plot(gm.t, gm.ac, color='black', lw=1, label='Target')
axes[0].plot(model.t, model.q, color='red', ls='--', lw=1.2, label='Model Envelope')
axes[0].plot(model.t, -model.q, color='red', ls='--', lw=1.2)
axes[0].set_ylabel('Acceleration (g)')
axes[0].legend(frameon=False)
axes[0].set_title('Target vs Simulation - Acceleration')

# First Simulation
axes[1].plot(sm.t, sm.ac[0], color='tab:blue', lw=1, label='Simulation #1')
axes[1].set_ylabel('Acceleration (g)')
axes[1].set_xlabel('Time (s)')
axes[1].legend(frameon=False)

plt.show()

# 2. Compare Displacement Time Series
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(10, 6), gridspec_kw={'hspace': 0.15})

# Target Ground Motion
axes[0].plot(gm.t, gm.disp, color='black', lw=1, label='Target')
axes[0].set_ylabel('Displacement (cm)')
axes[0].legend(frameon=False)
axes[0].set_title('Target vs Simulation - Displacement')

# First Simulation
axes[1].plot(sm.t, sm.disp[0], color='tab:blue', lw=1, label='Simulation #1')
axes[1].set_ylabel('Displacement (cm)')
axes[1].set_xlabel('Time (s)')
axes[1].legend(frameon=False)

plt.show()

# 3. Compare Fourier Amplitude Spectra (FAS)
plt.figure(figsize=(7, 4))
plt.loglog(sm.freq, sm.fas.T, color='gray', alpha=0.3, lw=0.7)  # 20 FAS simulations
plt.loglog(sm.freq, np.mean(sm.fas, axis=0), color='red', ls='--', lw=2, label='Simulation Mean')
plt.loglog(gm.freq, gm.fas, color='black', lw=1.5, label='Target')
plt.loglog(model.freq / (2 * np.pi), model.fas, color='Blue', lw=1.5, label='Model')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Fourier Amplitude')
plt.legend(frameon=False)
plt.grid(True, which="both", ls=":", alpha=0.3)
plt.title('Fourier Amplitude Spectra')
plt.ylim(1e-4, 1e1)  # if necessary, adjust y-axis limits for better visualization
plt.show()

# 4. Compare Response Spectra (5% Damping)
tp = np.arange(0.0, 10.0, 0.1)
_, _, sa = gm.response_spectra(tp)
_, _, sm_sa = sm.response_spectra(tp)

plt.figure(figsize=(7, 4))
plt.loglog(tp, sm_sa.T, color='gray', alpha=0.3, lw=0.7)
plt.loglog(tp, np.mean(sm_sa, axis=0), color='red', ls='--', lw=2, label='Simulation Mean')
plt.loglog(tp, sa, color='black', lw=1.5, label='Target')
plt.xlabel('Period (s)')
plt.ylabel('Spectral Acceleration (g)')
plt.legend(frameon=False)
plt.grid(True, which="both", ls=":", alpha=0.3)
plt.title('Response Spectra (5% Damping)')
plt.show()

Step 6: Export Simulations#

Tip

See Quick Start: Basic Ground Motion Analysis Example for saving and plotting results. The simulated ground motions are GroundMotion objects and can be saved or processed similarly.