Low-rise Modular Steel Building#
Note: This section is based on the work of Batukan & Mercan (2023) and Fathieh & Mercan (2016). Please see References page for more information.
Layout of the building is defined in a dictionary. The dictionary is defined in a separate file and imported into the main script. The dictionary is defined as follows:
layout = {
"1-4": {
1: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "south-west",
"brace": [
{"side": "south", "range": "entire", "type": "X"},
],
"sw-coord": [0.0, 0.0],
},
2: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-1",
"brace": [
{"side": "west", "range": "entire", "type": "X"},
],
},
3: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-2",
"brace": [
{"side": "north", "range": "entire", "type": "X"},
],
},
4: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "east-1",
"brace": None,
},
5: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-4",
"brace": None,
},
6: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-5",
"brace": None,
},
7: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "east-4",
"brace": None,
},
8: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-7",
"brace": None,
},
9: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-8",
"brace": None,
},
10: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "east-7",
"brace": [
{"side": "south", "range": "entire", "type": "X"},
],
},
11: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-10",
"brace": [
{"side": "east", "range": "entire", "type": "X"},
],
},
12: {
"we-dir": 3.5,
"sn-dir": 4,
"location": "north-11",
"brace": [
{"side": "north", "range": "entire", "type": "X"},
],
},
},
}
Height of the building is defined in a separate file and imported into the main script. The height is defined as follows:
height = {
"ground_level": 0.0,
"1": {"module": 3.5, "vert_con": 0.25},
"2-4": {"module": 3.5, "vert_con": 0.25},
}
Sections of the columns and beams are defined in a separate file and imported into the main script. The sections are defined as follows:
sections = {
"ceiling_beam": {
"regular": [
{"story": "all", "length": [0.0, 1e9], "section": "W100X19.3"},
],
"braced": [
{"story": "all", "length": "all", "section": "W100X19.3"},
],
},
"floor_beam": {
"regular": [
{"story": "all", "length": [0.0, 1e9], "section": "W100X19.3"},
],
"braced": [
{"story": "all", "length": "all", "section": "W100X19.3"},
],
},
"brace": [
{"story": [1, 1], "length": "all", "section": "HSS76.2X76.2X4.8"},
{"story": [2, 2], "length": "all", "section": "HSS76.2X76.2X4.8"},
{"story": [3, 3], "length": "all", "section": "HSS50.8X50.8X4.8"},
{"story": [4, 4], "length": "all", "section": "HSS50.8X50.8X4.8"},
],
"column": [
{"story": [1, 1], "section": "HSS127X127X4.8"},
{"story": [2, 2], "section": "HSS101.6X101.6X6.4"},
{"story": [3, 3], "section": "HSS101.6X101.6X6.4"},
{"story": [4, 4], "section": "HSS76.2X76.2X4.8"},
],
}
Loads are defined in a separate file and imported into the main script. The loads are defined as follows:
loads_and_factors = {
"load": {
"all": {
"ceiling": {
"dead": 0.083,
"live": 0.0,
"snow": 0.0,
"superimposed_dead": 0.7,
},
"floor": {
"dead": 2.4,
"live": 4.8,
"snow": 0.0,
"superimposed_dead": 0.75,
},
},
"modify": {
"4": {
"ceiling": {
"all": {
"dead": 0.083,
"live": 1.9,
"snow": 1.0,
"superimposed_dead": 0.32,
}
},
},
},
},
"factor": {
"dead": [1.4, 1.25, 0.9, 1.25, 0.9, 1.25, 0.9, 1.0],
"live": [0.0, 1.5, 1.5, 1.0, 0.0, 0.5, 0.0, 0.5],
"snow": [0.0, 1.0, 0.0, 1.5, 1.5, 0.0, 0.5, 0.25],
"wind": [0.0, 0.0, 0.4, 0.0, 0.4, 1.4, 1.4, 0.0],
"earthquake": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
},
}
Lastly, connection properties are defined in a separate file and imported into the main script. The connection properties are defined as follows:
connections = {
"vertical": {
"braced-frame": "Annan2009-Rigid", # Default connection model
"unbraced-frame": "Annan2009-Rigid", # Default connection model
},
# Default connection model
"horizontal": {
"model": "Lawson2014",
"type": "clip_angle",
# "location": "corner",
"location": "point",
"position_braced": ["ceiling", "floor"],
"position_unbraced": ["ceiling", "floor"],
},
}
Once the layout, height, sections, loads, and connections are defined, the building can be created as follows:
import modularbuildingpy as mbpy
# Define the directory where the model will be created
project_path = os.environ["HOME"]
directory = f"{project_path}/tests/test_model"
# Create an instance of the class
# logging options = "debug", "info", "warning", "error", "critical", mode = "w" or "a"
model = mbpy.Model(
name="CaseStudy4",
directory=directory,
analyze_kwargs={"nprocs": 1},
logger_kwargs={"console": "info", "file": "debug", "mode": "w"},
)
generate = model.get_generate()
generate.layout(layouts=layout,horizontal_spacing=0.35)
generate.height(height=height)
generate.node(base_constraint="pinned")
generate.diaphragm()
generate.geo_transf()
generate.section_material()
generate.element(section=sections)
generate.connection(connection=connections)
generate.load(load_and_factor=loads_and_factors)
generate.partition()
This will create dataframes for nodes, elements, connections, loads, and partitions. These dataframes can be accessed as follows:
# define OpenSeesPy instance
ops = mbpy.OpenSeesPy()
# get the analyze instance from the model
analyze = model.get_analyze()
analyze.initialize_ops()
analyze.declare_global_var()
analyze.assign_section_material()
analyze.assign_geo_transf()
analyze.assign_node()
analyze.assign_diaphragm()
analyze.assign_element()
analyze.add_mass()
analyze.add_gravity()
analyze.run(
analysis_name="Eigenvalue",
analysis_type="eigenvalue",
kwargs_eigenvalue={"num_values": 10},
time_job=4 * 60,
)