-
Notifications
You must be signed in to change notification settings - Fork 1
smt_model
The SMT modeling team developed probabilistic susceptibility, triggering, and manifestation models that are implemented using the functions below. The SMT model is described by Ulmer et al. (2024)
| function | description |
|---|---|
smt_model(depth, qt, fs, amax, m, pa=101.325, **kwargs) |
Computes probabilities of susceptibility, triggering, and manifestation |
smt_model_fragility(depth, qt, fs, amax, m, pa=101.325, **kwargs) |
Computes a set of fragility functions representing probability of profile manifestation as a function of amax and m |
get_pfs(Ic) |
Computes probability factor for liquefaction susceptibility |
get_pfts(csrm_hat, crr_hat) |
Computes probability factor for liquefaction triggering conditional on susceptibility |
get_pfmt(ztop, Ic) |
Computes probability factor for manifestation of a layer conditional on triggering of the layer |
get_pmp(pfmt, pfts, pfs, Ksat, t) |
Computes probability of manifestation at surface of profile |
The functions developed by the SMT use the following helper functions.
| function | description |
|---|---|
get_FC_from_Ic(Ic, epsilon=0.0) |
Computes fines content from soil behavior type index following the method by Hudson et al. (2024) |
get_Ic_Qtn_Fr(qt, fs, sigmav, sigmavp, pa=101.325, maxiter=30) |
computes soil behavior type index, Ic, overburden-corrected dimensionless cone tip resistance, Qtn, and dimensionless friction ratio, Fr |
get_qc1N_qc1Ncs(qt, fs, sigmav, sigmavp, FC, pa=101.325, maxiter=30) |
computes overburden-corrected dimensionless cone tip resistance qc1N that uses qc1Ncs to set exponent for overburden correction, and overburden- and fines-corrected cone tip resistance qc1Ncs |
box_cox(x, lam) |
Computes Box-Cox transform. |
inv_box_cox(x_hat, lam) |
Computes inverse Box-Cox transform |
get_crr_hat(qc1Ncs) |
Computes Box-Cox transformed cyclic resistance ratio |
get_csrm(amax, m, sigmav, sigmavp, depth, qc1Ncs, pa=101.325) |
Computes cyclic stress ratio corrected for magnitude and overburden |
Note
For Box-Cox transforms,
This function computes the probabilities of susceptibility, triggering, and manifestation and returns a tuple of relevant quantities. It is a wrapper function that parses user inputs, then calls other functions contained in the SMT software package. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| depth | Numpy array [dtype = float] | Depth values. |
| qt | Numpy array [dtype = float] | Cone tip resistance values in same units as pa. |
| fs | Numpy array [dtype = float] | Cone sleeve friction values in same units as pa. |
| amax | float | Maximum horizontal surface acceleration in g. |
| m | float | Earthquake magnitude. |
| pa | float | Atmospheric pressure. Optional. Default = 101.325 kPa. |
| kwarg | format | description |
|---|---|---|
| gamma | float | Soil total unit weight |
| dGWT | float | Depth to groundwater table. |
| gammaw | float | Unit weight of water. Optional. Default = 9.81 kN/m3 |
| sigmav | Numpy array [dtype=float] | Vertical total stress in same units as pa. |
| sigmavp | Numpy array [dtype=float] | Vertical effective stress in same units as pa. |
| Ksat | Numpy array [dtype=float] | Saturation factor to multiply probability of triggering. |
The function returns a tuple containing the following variables.
| variable | format | description |
|---|---|---|
| Ic | Numpy array [dtype=float] | Soil behavior type index |
| qt_inv | Numpy array [dtype=float] | Inverse-filtered cone tip resistance. |
| fs_inv | Numpy array [dtype=float] | Inverse-filtered sleeve friction. |
| qc1Ncs_inv | Numpy array [dtype=float] | Inverse-filtered overburden- and fines-corrected cone tip resistance. |
| Ic_inv | Numpy array [dtype=float] | Inverse-filtered soil behavior type index. |
| FC | Numpy array [dtype=float] | Fines content computed from Ic_inv. |
| qc1Ncs | Numpy array [dtype=float] | Overburden- and fines-corrected cone tip resistance. |
| ztop | Numpy array [dtype=float] | Depth to top of layers. |
| zbot | Numpy array [dtype=float] | Depth to bottom of layers. |
| qc1Ncs_lay | Numpy array [dtype=float] | Overburden- and fines-corrected cone tip resistance for layers. |
| Ic_lay | Numpy array [dtype=float] | Soil behavior type index for layers. |
| Ksat_lay | Numpy array [dtype=float] | Ksat value for layers. |
| pfs | Numpy array [dtype=float] | Probability factor for susceptibility of layers. |
| pfts | Numpy array [dtype=float] | Probability factor for triggering conditioned on susceptibility. |
| pft | Numpy array [dtype=float] | Probability factor for triggering of layers. |
| pfmt | Numpy array [dtype=float] | Probability factor for manifestation conditioned on triggering. |
| pfm | Numpy array [dtype=float] | Probability factor for manifestation of layers. |
| pmp | Float | Probability of profile manifestation. |
Note
- Either dGWT and gamma must be specified, or sigmav and sigmavp must be specified.
- If sigmav, sigmavp, and gamma are specified, gamma is ignored.
- If sigmav and sigmavp are specified and dGWT is not specified, dGWT is computed as the deepest point where sigmav = sigmavp.
- After the layering algorithm is completed, a layer interface is imposed at dGWT if the following conditions are met: (i) dGWT does not already coincide with a layer interface, (ii) dGWT is below the ground surface, and (iii) dGWT is above the bottom of the profile.
- If sigmav, sigmavp, and dGWT are specified, no checks are performed to make sure they are consistent.
- If Ksat is not specified, it is be computed as 0.0 above dGWT and 1.0 below dGWT.
- If Ksat and dGWT are both specified, no checks are performed to make sure they are consistent.
- All input Numpy arrays must have the same length.
- The following output Numpy arrays have the same length as the input Numpy arrays: qt_inv, fs_inv, Ic_inv, FC, qc1Ncs.
- The following output Numpy arrays have a length equal to the number of layers identified by the layering algorithm: ztop, zbot, qc1Ncs_lay, Ic_lay, Ksat_lay, pfs, pfts, pft, pfmt, pfm.
This function computes liquefaction fragility defining P[MP] as a function of amax and M. It is a wrapper function that parses user inputs, then calls other functions contained in the SMT software package, and returns a 2D array of P[MP] values. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| depth | Numpy array [dtype = float] | Depth values. |
| qt | Numpy array [dtype = float] | Cone tip resistance values in same units as pa. |
| fs | Numpy array [dtype = float] | Cone sleeve friction values in same units as pa. |
| amax | Numpy array [dtype = float] | Maximum horizontal surface acceleration in g. |
| m | Numpy array [dtype = float] | Earthquake magnitude. |
| pa | float | Atmospheric pressure. Optional. Default = 101.325 kPa. |
| kwarg | format | description |
|---|---|---|
| gamma | float | Soil total unit weight |
| dGWT | float | Depth to groundwater table. |
| gammaw | float | Unit weight of water. Optional. Default = 9.81 kN/m3 |
| sigmav | Numpy array [dtype=float] | Vertical total stress in same units as pa. |
| sigmavp | Numpy array [dtype=float] | Vertical effective stress in same units as pa. |
| Ksat | Numpy array [dtype=float] | Saturation factor to multiply probability of triggering. |
| variable | format | description |
|---|---|---|
| pmp | Numpy ndarray [dtype=float] | Probability of profile manifestation corresponding to arrays of amax and m. |
Note
Dimensions of pmp are (len(m), len(amax)).
This function computes the probability of liquefaction susceptibility conditioned on soil behavior type index. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| Ic | float or Numpy array [dtype = float] | Soil behavior type index |
| variable | format | description |
|---|---|---|
| pfs | float or Numpy array [dtype = float] | Probability factor for susceptibility. |
Note
This function returns the probability factor of liquefaction triggering conditional on susceptibility. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| csrm_hat | float or Numpy array [dtype=float] | Box-Cox transformed overburden- and magnitude-corrected cyclic stress ratio |
| crr_hat | float or Numpy array [dtype=float] | Box-Cox transformed cyclic resistance ratio |
| variable | format | description |
|---|---|---|
| pfts | float or Numpy array [dtype=float] | Probability factor for liquefaction triggering conditional on susceptibility |
Note
This function returns the probability factor for manifestation conditional on liquefaction triggering. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| ztop | float or Numpy array [dtype=float] | Depth to the top of the layer of interest in meters |
| Ic | float or Numpy array [dtype=float] | Median soil behavior type index of the layer of interest |
Note
| variable | format | description |
|---|---|---|
| pfmt | float or Numpy array [dtype=float] | Probability factor for manifestation of a layer conditional on liquefaction triggering of the layer |
This function returns the probability of manifestation of a profile. Equations are from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| pfmt | Numpy array [dtype=float] | Probability factor of manifestation conditional on triggering |
| pfts | Numpy array [dtype=float] | Probability factor of triggering conditional on susceptibility |
| pfs | Numpy array [dtype=float] | Probability factor of susceptibility |
| Ksat | Numpy array [dtype=float] | Saturation factor. Ksat = 0.0 above groundwater table and 1.0 below groundwater table |
| t | Numpy array [dtype=float] | Layer thickness in meters |
| variable | format | description |
|---|---|---|
| pmp | float | Probability of manifestation of the profile in percent |
Note
This function computes fines content from soil behavior type index following the method by Hudson et al. (2024).
| argument | format | description |
|---|---|---|
| Ic | float, or Numpy array [dtype = float] | Soil behavior type index |
| <epsilon> | float, or Numpy array [dtype = float] | Number of standard deviations. Optional. Default = 0.0 |
| variable | format | description |
|---|---|---|
| FC | float, or Numpy array [dtype = float] | Fines content in percent |
Note
FC will be a scalar valued float if Ic and epsilon are scalar valued floats, and will be a Numpy array if either Ic and / or epsilon are Numpy arrays. If Ic and epsilon are both Numpy arrays, they must have the same length or an error will be returned.
This function computes Ic, Qtn, Fr, qc1N, and qc1Ncs. Iterations are required to solve for these parameters because relationships among Ic, Qtn, Fr, qc1N, and qc1Ncs are implicit. Equations are from Robertson (2016).
| argument | format | description |
|---|---|---|
| qt | Numpy array [dtype = float] | Cone tip resistance |
| fs | Numpy array [dtype = float] | Cone sleeve friction |
| sigmav | Numpy array [dtype = float] | Vertical total stress |
| sigmavp | Numpy array [dtype = float] | Vertical effective stress |
| <pa> | float | Atmospheric pressure in same units as qt, fs, sigmav, and sigmavp. Optional. Default = 101.325 kPa |
| <maxiter> | int | Maximum number of iterations |
| variable | format | description |
|---|---|---|
| Ic | Numpy array [dtype = float] | Soil behavior type index. |
| Qtn | Numpy array [dtype = float] | Dimensionless cone tip resistance. |
| Fr | Numpy array [dtype = float] | Dimensionless cone sleeve friction. |
Note
Values of qt, fs, sigmav, and sigmavp that are less than or equal to zero will cause errors due to the logarithms that must be computed. Such values are set to 0.001*pa before computing Ic, Qtn, and Fr. A warning is not issued when this occurs.
This function computes qc1N, and qc1Ncs. Iterations are required to solve for these parameters. The equations are implicit because the stress normalization exponent depends on the fines correction. Equations used herein are from Boulanger and Idriss (2016).
| argument | format | description |
|---|---|---|
| qt | Numpy array [dtype = float] | Cone tip resistance |
| fs | Numpy array [dtype = float] | Cone sleeve friction |
| sigmav | Numpy array [dtype = float] | Vertical total stress |
| sigmavp | Numpy array [dtype = float] | Vertical effective stress |
| FC | Numpy array [dtype = float] | Fines content in percent |
| <pa> | float | Atmospheric pressure in same units as qt, fs, sigmav, and sigmavp. Optional. Default = 101.325 kPa |
| <maxiter> | int | Maximum number of iterations |
| variable | format | description |
|---|---|---|
| qc1N | Numpy array [dtype = float] | Overburden corrected cone tip resistance, where exponent for overburden correction is a function of qc1Ncs. |
| qc1Ncs | Numpy array [dtype = float] | Overburden- and fines-corrected cone tip resistance |
Note
Values of qt, fs, sigmav, and sigmavp that are less than or equal to zero will cause errors due to the logarithms that must be computed. Such values are set to 0.001*pa before computing qc1N, and qc1Ncs. A warning is not issued when this occurs.
This function computes the Box-Cox transformation of a variable following Box and Cox (1964).
| argument | format | description |
|---|---|---|
| x | float or Numpy array [dtype = float] | Variable to be transformed |
| labmda | float | Exponent term used in transform |
| variable | format | description |
|---|---|---|
| x_hat | float or Numpy array [dtype = float] | Transformed variable |
Note
x_hat will have the same type as x.
This function computes the inverse Box-Cox transformation of a variable following Box and Cox (1964).
| argument | format | description |
|---|---|---|
| x_hat | float or Numpy array [dtype = float] | Variable to be inverse transformed |
| labmda | float | Exponent term used in transform |
| variable | format | description |
|---|---|---|
| x | float or Numpy array [dtype = float] | Inverse transformed variable |
Note
x will have the same type as x_hat.
This function computes the Box-Cox transformed value of cyclic resistance ratio based on overburden- and fines-corrected cone tip resistance. qc1Ncs is converted to relative density using equations from Idriss and Boulanger (2008), and cyclic resistance is computed using equations from Ulmer et al. (2024).
| argument | format | description |
|---|---|---|
| qc1Ncs | float or Numpy array [dtype = float] | Overburden- and fines-corrected cone tip resistance |
| variable | format | description |
|---|---|---|
| crr_hat | float or Numpy array [dtype = float] | Box-Cox transformed cyclic resistance ratio |
Note
crr_hat will have the same type as qc1Ncs.
This function returns magnitude- and overburden corrected cyclic stress ratio. Depth-reduction factor,
| argument | format | description |
|---|---|---|
| amax | float | Peak horizontal surface acceleration in g |
| m | float | Earthquake magnitude |
| sigmav | Numpy array [dtype = float] | Vertical total stress |
| sigmavp | Numpy array [dtype = float] | Vertical effective stress |
| depth | Numpy array [dtype = float] | Depth values |
| qc1Ncs | Numpy array [dtype = float] | Overburden- and fines-corrected cone tip resistance |
| <pa> | float | Atmospheric pressure in same units as sigmav and sigmavp. Optional. Default = 101.325 kPa |
Note
*sigmav, sigmavp, depth and qc1Ncs must be Numpy arrays of the same length. An error will result if they are not Numpy arrays or if they are Numpy arrays of different length.
| variable | format | description |
|---|---|---|
| csrm | Numpy array [dtype = float] | Peak horizontal surface acceleration in g |
To download the files below, right click the link and use "Save Link As".
Data file example_cpt.csv
Jupyter notebook smt_model_example.ipynb
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import pandas as pd
import ngl_tools.smt as smt
def interleave(v1, v2):
vout = np.empty(2 * len(v1), dtype=float)
vout[0::2] = v1
vout[1::2] = v2
return vout
# Ready example CPT file and extract data into Numpy arrays
df = pd.read_csv('example_cpt.csv')
depth = df['depth'].values
qt = df['qt'].values
fs = df['fs'].values
# Define earthquake loading conditions
amax = 0.3
m = 7.0
gamma = 19
dGWT = 2.0
Ic, qt_inv, fs_inv, qc1Ncs_inv, Ic_inv, FC, qc1Ncs, \
ztop, zbot, qc1Ncs_lay, Ic_lay, Ksat_lay, \
pfs, pfts, pft, pfmt, pfm, pmp = smt.smt_model(depth, qt, fs, amax, m, dGWT=dGWT, gamma=gamma)
fig = plt.figure(figsize=(10,10))
gs = GridSpec(2, 12, figure=fig, wspace=0.8)
ax = []
ax.append(fig.add_subplot(gs[0, 0:3]))
ax.append(fig.add_subplot(gs[0, 3:6], sharey=ax[0]))
ax.append(fig.add_subplot(gs[0, 6:9], sharey=ax[0]))
ax.append(fig.add_subplot(gs[0, 9:12], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 0:2], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 2:4], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 4:6], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 6:8], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 8:10], sharey=ax[0]))
ax.append(fig.add_subplot(gs[1, 10:12], sharey=ax[0]))
for i, a in enumerate(ax):
if((i!=0) and (i!=4)):
plt.setp(ax[i].get_yticklabels(), visible=False)
ax[0].plot(qt/1000, depth)
ax[0].plot(qt_inv/1000, depth)
ax[1].plot(fs/1000, depth)
ax[1].plot(fs_inv/1000, depth)
ax[2].plot(Ic, depth, label='measured')
ax[2].plot(Ic_inv, depth, label='inverse filtered')
ax[3].plot(qc1Ncs, depth)
ax[3].plot(qc1Ncs_inv, depth)
ax[4].plot(interleave(pfs, pfs), interleave(ztop,zbot))
ax[4].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(pfs, pfs), facecolor='C0', alpha=0.2)
ax[5].plot(interleave(pfts, pfts), interleave(ztop,zbot))
ax[5].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(pfts, pfts), facecolor='C0', alpha=0.2)
ax[6].plot(interleave(pft, pft), interleave(ztop,zbot))
ax[6].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(pft, pft), facecolor='C0', alpha=0.2)
ax[7].plot(interleave(pfmt, pfmt), interleave(ztop,zbot))
ax[7].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(pfmt, pfmt), facecolor='C0', alpha=0.2)
ax[8].plot(interleave(Ksat_lay, Ksat_lay), interleave(ztop,zbot))
ax[8].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(Ksat_lay, Ksat_lay), facecolor='C0', alpha=0.2)
ax[9].plot(interleave(pfm, pfm), interleave(ztop,zbot))
ax[9].fill_betweenx(interleave(ztop, zbot), np.zeros(2*len(ztop)), interleave(pfm, pfm), facecolor='C0', alpha=0.2)
ax[2].axvspan(1,1.31,alpha=0.3,color='darkorange')
ax[2].axvspan(1.31,2.05,alpha=0.3,color='peru')
ax[2].axvspan(2.05,2.6,alpha=0.3,color='palegreen')
ax[2].axvspan(2.6,2.95,alpha=0.3,color='mediumaquamarine')
ax[2].axvspan(2.95,3.6,alpha=0.3,color='navy')
ax[2].axvspan(3.6,4.0,alpha=0.3,color='saddlebrown')
ax[0].set_ylabel('depth [m]')
ax[4].set_ylabel('depth [m]')
ax[0].set_xlabel(r'$q_c$ [MPa]')
ax[1].set_xlabel(r'$f_s$ [MPa]')
ax[2].set_xlabel(r'$I_c$ [-]')
ax[3].set_xlabel(r'$q_{c1Ncs}$ [-]')
ax[4].set_xlabel(r'$PF_S$')
ax[5].set_xlabel(r'$PF_{T|S}$')
ax[6].set_xlabel(r'$PF_T$')
ax[7].set_xlabel(r'$PF_{M|T}$')
ax[8].set_xlabel(r'$K_{sat}$')
ax[9].set_xlabel(r'$PF_M$')
for a in ax:
a.grid(True, alpha=0.5)
ax[2].plot(interleave(Ic_lay,Ic_lay), interleave(ztop,zbot), color='black', zorder=2, linewidth=0.5, label='layered')
ax[3].plot(interleave(qc1Ncs_lay,qc1Ncs_lay), interleave(ztop,zbot), color='black', zorder=2, linewidth=0.5)
ax[0].invert_yaxis()
ax[2].set_xlim(1.0,4.0)
ax[5].set_xlim(0.0,1.0)
ax[6].set_xlim(0.0,1.0)
ax[7].set_xlim(0.0,1.0)
ax[8].set_xlim(0.0,1.0)
ax[9].set_xlim(0.0,1.0)
ax[2].legend(loc='upper center', bbox_to_anchor=(0.9,1.15), ncol=3, fancybox=True, shadow=True)
#fig.suptitle(r'$P[M_P]$ = ' + str(np.round(pmp*100, 1)) + ' %')
ax[9].annotate(r'$P[M_P]$=' + str(np.round(pmp*100, 1)) + '%', xy=(0.03,0.03), xycoords='axes fraction')
To download the files below, right click the link and use "Save Link As".
Data file example_cpt.csv
Jupyter notebook smt_model_fragility_example.ipynb
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import pandas as pd
import ngl_tools.smt as smt
# Ready example CPT file and extract data into Numpy arrays
df = pd.read_csv('example_cpt.csv')
depth = df['depth'].values
qt = df['qt'].values
fs = df['fs'].values
# Define earthquake loading conditions
amax = np.logspace(-2, 1, 100)
m = np.asarray([5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0])
gamma = 19
dGWT = 2.0
pmp = smt.smt_model_fragility(depth, qt, fs, amax, m, dGWT=dGWT, gamma=gamma)
fig, ax = plt.subplots()
for i in range(len(m)):
ax.plot(amax, pmp[i], label=m[i])
ax.set_xscale('log')
ax.grid(True, alpha=0.5, which='both')
ax.legend(title='M')
ax.set_xlabel(r'$a_{max}$ [g]')
ax.set_ylabel(r'$P[M_P]$')
ax.set_ylim(-0.05, 1.05)