Reinforced Concrete 3D Frame
January 2022, By Amir Hossein Namadchi
This notebook is adapted from https://github.com/AmirHosseinNamadchi/OpenSeesPy-Examples/blob/master/Reinforced%20Concrete%203D%20Frame%20(FGU).ipynb
In this notebook, a 3-Dimensional one story Reinforced Concrete moment resisting frame is modeled. This is an OpenSeesPy simulation of TCL version of the model, presented by Fernando Gutiérrez Urzúa in his YouTube channel. Some minor modifications are made by me in the python version. According to his, modeling assumptions are:
- Columns & Beams are modeled as distributed plasticity elements
To have cleaner code, all of the neccessary functions are written in a single .py file named RC3DF.py
. The file contains:
build_RC_rect_section
: Build fiber rectangular RC sectionbuild_model
: Builds the 3D RC Frame modelrun_gravity
: Runs gravity analysisrun_modal
: Runs Modal analysisrun_pushover
: Runs Pushover analysisrun_time_history
: Runs Time history analysisreset_analysis
: Resets the analysis by setting time to 0,removing the recorders and wiping the analysis.
Some additional function arguments are provided to be able to tweak model parameters. Please note that some functions use data obtained by running other functions. For example, in order to run time-history analysis, some of the system’s natural frequencies are required which can be obtained by running run_modal
function.
The model has been idealized as follows:
Beam and Column sections are defined as:
Dependencies
import time
import sys
import os
import opensees.openseespy as ops
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import RC3DF as RC
Model Data
Units (Silvia’s Style)
m = 1.0 # Meters
KN = 1.0 # KiloNewtons
sec = 1.0 # Seconds
mm = 0.001*m # Milimeters
cm = 0.01*m # Centimeters
ton = KN*(sec**2)/m # mass unit (derived)
g = 9.81*(m/sec**2) # gravitational constant (derived)
MPa = 1e3*(KN/m**2) # Mega Pascal
GPa = 1e6*(KN/m**2) # Giga Pascal
Geometric Dimensions
L_X = 6.0*m # Span in X-direction
L_Y = 7.0*m # Span in Y-direction
L_Z = 3.5*m # Story height
Material Definition
f_c_1 = -25*MPa # f'c in compression for unconfined concrete
f_c_2 = -28*MPa # f'c in compression for confined concrete
eps_c = -0.002 # strain at maximum stress in compression
eps_u = -0.02 # strain at ultimate stress in compression
f_y = 420.0*MPa # fy for reinforcing steel
E_s = 210.0*GPa # E for reinforcing steel
Section Definition
rebar = 0.25*np.pi*(25*mm)**2
# uniaxial Kent-Scott-Park concrete material with degraded linear unloading/reloading
mat_KSP_unconf = {'ID':'Concrete02',
'matTag': 1,
'fpc': f_c_1,
'epsc0': eps_c,
'fpcu': 0.2*f_c_1,
'epsU': eps_u,
'lamda': 0.1,
'ft': -0.1*f_c_1,
'Ets': (-0.1*f_c_1)/0.002}
# uniaxial Kent-Scott-Park concrete material with degraded linear unloading/reloading
mat_KSP_conf = {'ID':'Concrete02',
'matTag': 2,
'fpc': f_c_2,
'epsc0': eps_c,
'fpcu': 0.2*f_c_2,
'epsU': eps_u,
'lamda': 0.1,
'ft': -0.1*f_c_2,
'Ets': (-0.1*f_c_2)/0.002}
# uniaxial Giuffre-Menegotto-Pinto steel with isotropic strain hardening
mat_GMP = {'ID':'Steel02',
'matTag':3,
'Fy': f_y,
'E0': E_s,
'b':0.005,
'R0': 20.0,
'cR1': 0.925,
'cR2': 0.15}
sections = {'Beam':{'B':300*mm,
'H':600*mm,
'cover':40*mm,
'n_bars_top':3,
'n_bars_bot':3,
'n_bars_int_tot':4,
'bar_area_top':rebar,
'bar_area_bot':rebar,
'bar_area_int':rebar},
'Column':{'B':300*mm,
'H':400*mm,
'cover':40*mm,
'n_bars_top':3,
'n_bars_bot':3,
'n_bars_int_tot':4,
'bar_area_top':rebar,
'bar_area_bot':rebar,
'bar_area_int':rebar}
}
Loading
C_L = 80.0*(KN) # Concentrated load
m_1 = 200.0*ton # lumped mass 1
Analysis
Gravity analysis
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_gravity(m)
Output:
Model Built Successfully!
Gravity analysis Done!
Modal analysis
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_modal(m)
Output:
Model Built Successfully!
Modal analysis Done!
Pushover analysis in X directions
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_gravity(m)
RC.reset_analysis(m)
RC.run_pushover(m, m_1, direction='X')
Output:
Model Built Successfully!
Gravity analysis Done!
Pushover Analysis in X Done in 37.95 seconds
Pushover analysis in Y directions
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_gravity(m)
RC.reset_analysis(m)
RC.run_pushover(m, m_1, direction='Y')
Output:
Model Built Successfully!
Gravity analysis Done!
Pushover Analysis in Y Done in 38.59 seconds
Time history analysis in X directions
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_gravity(m)
RC.reset_analysis(m)
RC.run_time_history(m, direction='X')
Output:
Model Built Successfully!
Gravity analysis Done!
Running Time-History analysis with lambda= 1
Time-History Analysis in X Done in 46.35 seconds
Time history analysis in Y directions
m = RC.build_model(L_X, L_Y, L_Z, mat_KSP_unconf, mat_KSP_conf, mat_GMP, sections, C_L, m_1)
RC.run_gravity(m)
RC.reset_analysis(m)
RC.run_time_history(m,direction='Y')
Output:
Model Built Successfully!
Gravity analysis Done!
Running Time-History analysis with lambda= 1
Time-History Analysis in Y Done in 45.58 seconds
Visualization
Pushover Curve
df_R_X = pd.read_table('assets/Pushover_Horizontal_ReactionsX.out', sep = " ", header = None,
names=["Pseudo-Time","R1_X","R2_X","R3_X","R4_X"])
df_R_Y = pd.read_table('assets/Pushover_Horizontal_ReactionsY.out', sep = " ", header = None,
names=["Pseudo-Time","R1_Y","R2_Y","R3_Y","R4_Y"])
df_R_X['sum_R'] = df_R_X.values[:,1:5].sum(axis =1)
df_R_Y['sum_R'] = df_R_Y.values[:,1:5].sum(axis =1)
df_D_X = pd.read_table('assets/Pushover_Story_DisplacementX.out', sep = " ", header = None,
names=["Pseudo-Time","D1_X","D2_X","D3_X","D4_X"])
df_D_Y = pd.read_table('assets/Pushover_Story_DisplacementY.out', sep = " ", header = None,
names=["Pseudo-Time","D1_Y","D2_Y","D3_Y","D4_Y"])
df_D_X['avg_D'] = df_D_X.values[:,1:5].mean(axis = 1)
df_D_Y['avg_D'] = df_D_Y.values[:,1:5].mean(axis = 1)
plt.figure(figsize=(10,5))
plt.plot(df_D_X['avg_D'], -df_R_X['sum_R'], color = '#C0392B', linewidth=1.5)
plt.plot(df_D_Y['avg_D'], -df_R_Y['sum_R'], color = '#27AE60', linewidth=1.5)
plt.ylabel('Base Shear (KN)', {'fontstyle':'italic','size':14})
plt.xlabel('Average of Roof Displacement (m)', {'fontstyle':'italic','size':14})
plt.grid(which='both')
plt.title('Pushover Curve',{'fontstyle':'normal','size':16})
plt.yticks(fontsize = 14)
plt.xticks(fontsize = 14);
plt.legend(['X-Direction', 'Y-Direction'],prop={'size':14});
Output:
<Figure size 1000x500 with 1 Axes>
Ground Motion histroy
G_M =np.loadtxt('assets/acc_1.txt')
times = np.arange(0,0.02*len(G_M),0.02)
plt.figure(figsize=(12,4))
plt.plot(times,G_M, color = '#6495ED', linewidth=1.2)
plt.ylabel('Acceleration (m/s2)', {'fontstyle':'italic','size':14})
plt.xlabel('Time (sec)', {'fontstyle':'italic','size':14})
plt.grid(which='both')
plt.title('Time history of Ground Motion record',{'fontstyle':'normal','size':16})
plt.yticks(fontsize = 14);
Output:
<Figure size 1200x400 with 1 Axes>
Time history of displacement and acceleration
story_disp_X = np.loadtxt('assets/TimeHistory_Story_DisplacementX1.1.out')
story_disp_Y = np.loadtxt('assets/TimeHistory_Story_DisplacementY1.1.out')
plt.figure(figsize=(12,5))
plt.plot(story_disp_X[:,0], story_disp_X[:,1], color = '#DE3163', linewidth=1.2)
plt.plot(story_disp_Y[:,0], story_disp_Y[:,2], color = '#FFBF00', linewidth=1.2)
plt.ylabel('Horizontal Displacement (m)', {'fontstyle':'italic','size':14})
plt.xlabel('Time (sec)', {'fontstyle':'italic','size':14})
plt.grid(which='both')
plt.title('Time history of horizontal dispacement',{'fontstyle':'normal','size':16})
plt.yticks(fontsize = 14);
plt.xticks(fontsize = 14);
plt.legend(['X-Direction', 'Y-Direction'], prop={'size':14});
Output:
<Figure size 1200x500 with 1 Axes>
story_accel_X = np.loadtxt('assets/TimeHistory_Story_AccelerationX1.1.out')
story_accel_Y = np.loadtxt('assets/TimeHistory_Story_AccelerationY1.1.out')
plt.figure(figsize=(12,5))
plt.plot(story_accel_X[:,0], story_accel_X[:,1], color = '#DE3163', linewidth=1.2)
plt.plot(story_accel_Y[:,0], story_accel_Y[:,2], color = '#FFBF00', linewidth=1.2)
plt.ylabel('Horizontal Acceleration (m/s2)', {'fontstyle':'italic','size':14})
plt.xlabel('Time (sec)', {'fontstyle':'italic','size':14})
plt.grid(which='both')
plt.title('Time history of horizontal acceleration',{'fontstyle':'normal','size':16})
plt.yticks(fontsize = 14);
plt.xticks(fontsize = 14);
plt.legend(['X-Direction', 'Y-Direction'], prop={'size':14});
Output:
<Figure size 1200x500 with 1 Axes>
References
-
Fernando Gutiérrez Urzúa's YouTube channel (https://www.youtube.com/user/lfgurzua)
-
OpenseesPy Documentation (https://openseespydoc.readthedocs.io/en/latest/)