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,
)