Load Calibration for Non Linear Limit State Functions (LSFs)#
This tutorial demonstrates how Pystra
can calibrate safety and combination factors for Non-Linear limit state functions.
Import Libraries#
[1]:
import pystra as ra
import numpy as np
Define the limit state function for calibration#
The LSF to be supplied in LoadCombination
can be any valid Pystra LSF with one additional argument: a scalar design parameter for a random variable (generally, the resistance). Note that: 1. The design parameter must be specified as a Pystra
constant with any arbitrary default value, such as 1.0
. 2. Only a single design parameter for the resistance random variable can be calibrated at a time.
Keeping with the LoadCombination
example, the design parameter for resistance, denoted \(z\), is added to the LSF. The LSF contains additional random variables wR
and wS
to account for the uncertainties within the resistance and the load effects, respectively. The non-linearity of the LSF is evident as the degree of random variables in each term of the LSF is two.
[2]:
def lsf(z, wR, wS, R, Q1, Q2):
gX = z * wR * R - wS * (Q1 + Q2)
return gX
Define the Load and Resistance distributions#
Next follow the creation of load combination object, as explained for the LoadCombination
class.
[3]:
wR = ra.Lognormal("wR", 1.0, 0.05)
wS = ra.Lognormal("wS", 1.0, 0.10)
R = ra.Normal("R", 60, 6) # [units]
Q1_max = ra.Normal("Q1", 30, 3) # [units]
Q2_max = ra.Normal("Q2", 20, 2) # [units]
Q1_pit = ra.Normal("Q1", 15, 3) # [units]
Q2_pit = ra.Normal("Q2", 10, 2) # [units]
z = ra.Constant("z", 1)
Set up Load Combinations#
Specify nominal values & combinations#
[4]:
rvs_all = ['wR', 'wS', 'R', 'Q1', 'Q2']
dict_nom = dict(zip(rvs_all, np.array([1.0, 1.0, R.ppf(0.05),
Q1_max.ppf(0.95),
Q2_max.ppf(0.95)])))
Q_dict = {'Q1': {'max': Q1_max, 'pit': Q1_pit},
'Q2': {'max': Q2_max, 'pit': Q2_pit}}
[5]:
loadcombinations = {'Q1_max':['Q1'], 'Q2_max':['Q2']}
Instantiate LoadCombination
object#
[6]:
lc = ra.LoadCombination(lsf, dict_dist_comb=Q_dict, list_dist_other=[wS],
list_dist_resist=[R, wR], list_const = [z],
dict_comb_cases=loadcombinations)
Note that since wR
is associated with the resistance, it is specified in list_dist_resist
; while wS
is specified in list_dist_other
as it is associated with the load effects but it’s not a load combination variable.
Load calibration#
[7]:
betaT = 3.7
calib1 = ra.Calibration(lc, target_beta=betaT, dict_nom_vals=
dict_nom, calib_var='z',
est_method="matrix", calib_method="optimize")
calib1.run()
calib1.print_detailed_output()
======================================================
X* =
R wR wS Q1 Q2 z
Q1_max 44.40 0.95 1.2 33.81 11.69 1.30
Q2_max 44.76 0.95 1.2 19.16 21.85 1.16
phi =
R wR
Q1_max 0.89 0.95
Q2_max 0.89 0.95
gamma =
wS Q1 Q2
Q1_max 1.2 0.97 0.94
Q2_max 1.2 0.97 0.94
psi =
wS Q1 Q2
Q1_max 1.0 1.00 0.54
Q2_max 1.0 0.57 1.00
======================================================
Design Check#
[8]:
design_z1 = calib1.get_design_param_factor()
design_beta1 = calib1.calc_beta_design_param(np.max(design_z1))
print(f"Design reliabilities = {design_beta1.round(2)}")
print(f"Design Check = {design_beta1.round(2)>=betaT}")
Design reliabilities = [3.7 4.28]
Design Check = [ True True]