Introduction#

Welcome to the REDi (Resilient Design for the Next Generation of Buildings) seismic engine documentation developed at ARUP. This documentation provides an overview of the code and features within the REDi GitHub repository and PyREDi, the official Python package of REDi.

REDi introduces a comprehensive resilience-based earthquake design framework for holistic “beyond-code” design, planning, and assessment. While the building code provides reassurance that loss of life will be minimal, REDi focuses on quantifying the indirect losses due to downtime, or the inability of people to return to their homes or their jobs after a disaster. This empowers researchers and practitioners to incorporate resilience-based earthquake design into their projects, achieving much higher performance of their buildings than if they were to follow basic building code guidelines.

Specifically, REDi can be employed to quantify the resilience and performance of an earthquake-damaged building by estimating the realistic downtime that considers impeding factors such as inspection delays, financing delays, and long-lead times for repair material procurement. The results from REDi can be employed to assess how design changes impact post-disaster recovery in new construction, and to plan for the recovery of existing buildings to potential future disasters.

Our goals of making REDi opensource are to foster a collaborative environment and to reduce the effort required for implementation of REDi into your workflow. Our hope is that researchers and practitioners will adopt, improve on, and contribute to the REDi codebase for the greater good of the recovery and resilience community.

Quickstart#

REDi can be run as a Python package (PyREDi) or as a script through the command line.

Install through PyPi#

  1. Install PyRedi through PyPi

    pip install pyredi or python -m pip install pyredi

You should now be able to use REDi in your Python code, as shown below in the Usage section.

Install and run from source#

  1. Download the source code from the REDi GitHub repository by running the following in your command line interface:

    git clone https://github.com/arup-group/REDi.git

  2. Navigate into the folder where REDi was cloned:

    cd REDi

  3. Install the required Python packages:

    pip install -r requirements.txt

You should now be able to use REDi in your Python environment, as shown below in the Usage section.

Usage#

The REDi engine can be run via the PyREDi Python package or through a command line interface. Both methods require installation as outlined above.

PyREDi Python Package#

To run the REDi engine from the PyREDi package, you need to import the PyREDi package into your Python script and run the go_redi function with the building_dict as input, as shown below:

import json

from REDi.go_redi import go_redi

building_dict = json.load(open('./examples/example_building.json'))

res = go_redi(building_dict=building_dict, seed=2023)

print('Total downtime :',res['building_total_downtime'],'\n')

You should see the following output:

******* Running REDi™ for building example_building *******

Analysis done!

Time to full recovery [days] 496.56187582116473
Time to functional recovery [days]  475.5133725965221
Time to immediate occupancy [days]  231.80657475175408

Total downtime : [496.56187582 475.5133726  231.80657475]

Note that if you omit the seed value (seed=2023) from the input parameters to go_redi, your results will be different.

The building_dict object is a dictionary that should contain all inputs required by REDi. The inputs are explained below in the Inputs section. An example building_dict is also provided in the examples/example_building.json file. If importing the examples/example_building.json file as shown above, you must provide the absolute path to the examples/example_building.json file. The res object from the code-block above is a dictionary containing the outputs described below.

Important

If you do not provide the seed and/or burn-in options, the output will vary every run, i.e., the output will be non-deterministic. REDi is tested on Python version 3.11. It may or may not work in other versions of Python.

Command line interface#

The REDi engine can be executed from the command line using the following syntax:

python main.py [-h] [-a A] [-c C] [-r R] [-s S] [-b B]

where:

- h, help - show the help message
- a A - Path to the asset JSON file [str] (required)
- r R - Path of the results file (include the .json suffix in path) [str] (required)
- c C - Path to the components JSON file [str] (optional - REDi will use built-in FEMA P-58 component library if blank)
- s S - Seed for the random number generator, for deterministic output [int] (optional - leave blank for stochastic output)
- b B - Burn-in number, i.e., how many times to generate and discard random numbers at random number generator initialization [int] (optional - mainly for testing purposes)

To run the example building, execute the following in command line:

python main.py -a "examples/example_building.json" -r "REDi_output.json" -s 2023

You should see the following output:

******* Running REDi™ for building example_building *******

Analysis done!

Time to full recovery [days] 496.56187582116473
Time to functional recovery [days]  475.5133725965221
Time to immediate occupancy [days]  231.80657475175408

Total downtime : [496.56187582 475.5133726  231.80657475]

Note that if you omit the seed value (-s 2023) from the input parameters, your results will be different.

Important

If you do not provide the seed and/or burn-in options, the output will vary every run, i.e., the output will be non-deterministic. REDi is tested on Python version 3.11. It may or may not work in other versions of Python.

Background#

REDi is underpinned by the performance-based engineering methodology introduced by FEMA. Namely, the component-based FEMA P-58 methodology: Development of Next Generation Performance-Based Seismic Design Procedures for New and Existing Buildings. REDi uses a modified version of the component library from the FEMA P-58 PACT tool. A prepackaged component library is provided as a json file in the repository: data\component_library.json. REDi’s version of the FEMA P-58 component library employs the same naming convention as FEMA, e.g., B1031.001. The main difference between the two libraries is that each component in REDi’s library contains additional seq, long_lead, and rds parameters that are desribed below.

  • seq - list that defines the repair sequence for that component. The length of the seq list is always 2.

  • long_lead - list that specifies the long-lead times for repair materials for the component. The length of the long_lead list is always 3.

  • rds - list that provides the repair class for each damage state. The length of the rds list should be the same as the number of damage states.

There are 3 repair goals in REDi: 1) full recovery; 2) functional recovery; and 3) re-occupancy. Moreover, there are 8 repair sequences; 7 that are non-structural and 1 that is structural.

Inputs and outputs#

The following sections outline the necessary inputs for the REDi engine and its corresponding outputs.

Inputs#

More information about the following inputs can be found in Section A4.3 “Downtime Assessment Methodology” in the REDi guidelines. As a reference, an example building input file is provided in the examples folder of the repository: REDi/examples/example_building.json. Note that the building input file is required to be in the json format.

A high-level summary of REDi inputs is:

  • _id - a unique name that can be employed to identify the building

  • nFloor - number of floors or stories in the building (excluding the roof), e.g., 4

  • replacement_cost - building replacement cost in millions of dollars, e.g, 5.25

  • replacement_time - building replacement time in days, e.g., 1240

  • risk_parameters - dictionary of various input parameters that define repair resources and scheduling (explained in further detail below)

  • components - list of building components that identify the component type and quantity (explained in further detail below)

  • floor_areas - list of the floor areas, including the roof, e.g., if nFloor = 5, the floor_areas list should have 6 items when the roof area is included. Each item in the list is the area for that floor in square feet.

  • component_damage - dictionary of components where each key is a component id and the corresponding value provides quantities of the damaged components (explained in further detail here)

  • total_consequences - dictionary of components where each key is a component id and the corresponding value provides quantities of the consequences, e.g., repair time and cost (explained in further detail below)

Risk parameters#

This section highlights the various “risk parameters” that are employed as inputs into the REDi engine. Note that some of the risk parameters are defined as random variables while some are constants. Broadly speaking, the risk parameters are grouped into 3 types: 1) repair; 2) impeding_factors; and 3) business.

  1. Repair risk parameters

    The “repair” risk parameters are related to the physical repair processes. Examples include the number of repair workers, the severity of the repair, and possible repair sequences.

    The required repair risk parameters include:

    • repair_class_fragility - dictionary containing the random variable distribution parameters for the repair class fragility function. “Repair Classes” describe how the extent and severity of damage to types of building components may hinder specific recovery states.

    Table 3 in Section A4.3 from REDi Downtime Assessment Methodology

    Table 3 in Section A4.3 from REDi Downtime Assessment Methodology.#

    • nwork_perfloor_divider - list containing the number of workers per floor, for each non-structural repair sequence. The nwork_perfloor_divider will always contain 7 items (the number of non-structural repair sequences).

    • nworkers_recommended_mean - list that describes the mean number of recommended workers, for each non-structural repair sequence. The nworkers_recommended_mean will always contain 7 items (the number of non-structural repair sequences).

    • nworkers_recommended_mean_struct - mean number of recommended workers for the structural repair sequence. Since there is only one structural repair sequences, the nworkers_recommended_mean_struct will be a single number.

    • max_workers_per_building - a dictionary containing parameters that define a function to calculate the mean and sigma of a probability distribution as follows in the function get_max_workers from the file go_redi.py

    def get_max_workers(building : Building):
    
        totalArea = building.total_floor_area
    
        # Extract relevant risk parameters
        max_workers_minimum = building.max_workers_minimum
        max_workers_slope = building.max_workers_slope
        max_workers_x_cutoff = building.max_workers_x_cutoff
        max_workers_sigma = building.max_workers_sigma
    
        # Calculate mean
        mean = max_workers_minimum + max(0, totalArea - max_workers_x_cutoff) * max_workers_slope
    
        # Sample max workers
        return sample_dist("Normal", mean, max_workers_sigma)
    
    • max_workers_per_struct_divider - number of workers per floor for the structural repair sequence.

    • workers_capacity - dictionary containing the random variable distribution parameters for the worker capacity. The worker capacity is a constraint on the number of workers that can work on the same type of component, floor, etc.

    • max_workers_by_sequence - list of a list that describes the maximum workers per repair goal, per repair sequence. The highest-level list of length 3 corresponds to the 3 repair goals: 1) full recovery; 2) functional recovery; and 3) re-occupancy. The second-level list corresponds to the 7 non-structural repair sequences. A repair sequence defines the order of repairs that are to be conducted. For example, partitions can be replaced only once pipes and HVAC ducts have been repaired. Some repairs can occur simultaneously. Component repairs at a particular floor level need to be ordered in a manner that reflects the sequence of repairs that are likely to be undertaken by the contractor. The suggested repair sequences at a particular floor are presented in Figure 8 below.

    Figure 8 in Section A4.3 from REDi Downtime Assessment Methodology

    Figure 8 in Section A4.3 from REDi Downtime Assessment Methodology.#

  2. Impeding factors risk parameters

    The “impeding factors” risk parameters are related to potential delays in scheduling inspections, workers, and materials to site. Other impeding factors include the time that it takes to get financing for the repairs. Example values for the impeding factors can be found in A4.3 in the REDi guidelines.

    The required impeding factors parameters include:

    • inspection_delay - dictionary containing the random variable distribution parameters for the inspection delay, i.e., the delay in days of getting a municipal building inspector to inspect the repair work

    • financing_delay - dictionary containing the random variable distribution parameters for the delay in financing of the repair. Note that there are different parameters for delays in issuing insurance funds (default) and for private loans in the case where the repair cost is more than the insurance limit.

    • longlead - dictionary containing the random variable distribution parameters for the long-lead times of acquiring repair materials. There are some building components which require long procurement lead times – they are not readily available even in normal circumstances. These components include elevators, mechanical equipment, and non-standard and custom made components including structural elements, facades, mission-critical contents, etc. The long-lead times should be quantified from information provided by manufacturers, maintenance professionals, contractors, and/or cost estimators.

    • permit_delay_seismic - dictionary containing the random variable distribution parameters for the repair permit delays. The repair permit delays account for the time it takes to procure the required building permits from the local municipality. Note that there are different permit delay parameters for the different repair classes.

    • contractor_mobilization_delay_seismic - dictionary containing the random variable distribution parameters for the contractor mobilization delay. The contractor mobilization delay is the time it takes for a repair contractor to start the repair, i.e., schedule workers and account for potential shortage of workers, bidding phase for contract procurement, etc. Note that there are different contractor mobilization delay parameters for the different repair classes.

    • engineer_mobilization_delay_seismic - dictionary containing the random variable distribution parameters for the engineer mobilization delay. The engineer mobilization delay is the time it takes for an engineer to arrive at the site and assess the damage. An engineer would need to be consulted if there is structural damage to the building and the repair of minor structural damage (Repair Class 1) would likely require an engineer to stamp and approve the proposed repair strategy. Note that there are different engineer mobilization delay parameters for the different repair classes. Contractors and engineers will likely be in scarce supply after a major earthquake and retaining them on an annual basis to perform post-earthquake repairs could save weeks of downtime.

  3. Business risk parameters

    The “business” risk parameters include stake-holder specific information that can impact the repair. Examples include whether there are sufficient funds available for repair, the fraction of the total repair cost that is insured and at what deductible, and whether any private financing will be needed to cover the difference between the total repair cost and the insured amount. The required business parameters include:

    • finance_method - string that describes the financing method for funding the recovery and repair. The two options are insurance or other.

    • insur_limit_ratio - fraction of the building replacement cost that is insured, e.g., 0.5

    • loss_thresh_ratio - fraction of the building replacement cost after which total loss occurs, e.g., 0.7. Total loss means that the total repair cost exceeds the loss threshold and no repairs occur (sum(repair_costs)>replacement_cost*loss_thresh_ratio). Instead, a complete redesign, reconstruction, and replacement of the entire building takes place.

    • available_fund_ratio - fraction of the building replacement cost that is available for funding building repairs, e.g., 0.5

    • deductible_ratio - fraction of the building replacement cost that is equal to the insurance deductible, e.g., 0.2

Components#

The components object is a list of lists. The highest-level, outer list contains nFloor + 1 lists, where each sub-list contains all components on a particular floor (including any components on the roof). Note that index 0 corresponds to the first story, index 1 to the second story, and so on until the last index which corresponds to the roof.

Each component in the sub-list for each floor is a dictionary containing the component tag NISTR and an array of quantities Qty in each direction, i.e., [dir_1, dir_2]. The NISTR id corresponds to the FEMA P-58 component id in the supplied component dictionary.

# the length of the "components" list is equal to nFloor + 1, or the number of stories plus the roof
"components" :[floor_1, floor_2, ..., floor_n]

where

# the length of the "floor_n" list is equal to the number of different components on that floor
floor_n = [
             {'NISTR' : nistr_id_1, # NISTR id, e.g., B1033.061b
             'Qty' : [dir_1, dir_2]}, # component quantity in each direction, e.g.,  [11.5, 11.5]
             ...,
             {'NISTR' : nistr_id_n,
             'Qty' : [dir_1, dir_2]}
          ]

Component damage#

The component_damage object is a dictionary where each key is a component tag NISTR and the values is a list of a list. The highest level, outer list is associated with the number of damage states while the inner list corresponds to the number of floors.

# the length of the "component_damage" dictionary will be equal to the number of different types of damaged components in the building
"component_damage": {
        # the length of the "NISTR" list below is equal to the number of damage states for that particular component
        "NISTR": [
                ds_1,
                ...,
                ds_n
        ],
        ...,
        }

where

        # the length of the "ds_n" list is equal to the number of floors, or **nFloor** + 1
        ds_n = [
           num_dmg_units_floor_1, # the quantity of damaged components of the type NISTR, in damage state ds_n, on floor_n
           num_dmg_units_floor_2,
           ...,
           num_dmg_units_floor_n
        ]

Total consequences#

The total_consequences object is a dictionary where each key is a component tag NISTR and the values are a list of lists of lists. The highest-level list (always length 4) corresponds to the 4 types of consequences at the component level: 1) repair cost [dollars]; 2) repair time [worker days]; 3) occupant injuries; and 4) occupant fatalities. The second-level list contains the number of floors, or nFloor + 1, so a list with length 5 will be a 4-story building with a roof. The third-level list is based on the number of damage states (not including Damage State 0, i.e., undamaged).

# the length of the "total_consequences" dictionary will be equal to the number of the different types of damaged components in the building
"total_consequences": {
        # the length of the "NISTR" list below is equal to the number of damage states for that particular component
        "NISTR": [
                repair_cost_list,
                repair_time_list,
                injury_list,
                fatalities_list
        ],
        ...,
        }

where

        # the length of the "repair_cost_list" list is equal to the number of floors, or **nFloor** + 1
        repair_cost_list = [
           floor_1_list,
           floor_1_list,
           ...,
           floor_n_list
        ]

        # the length of the "floor_n_list" is equal to the number of damage states in the component (not including damage state 0)
        floor_n_list = [
           ds_1_qty, # Quantity of the consequence "repair cost", at floor_n, for ds_1
           ds_2_qty,
           ...,
           ds_n_qty
        ]

Outputs#

The outputs of PyREDi are provided in .json format. Each key in the dictionary is an output.

A summary of REDi outputs is as follows:

  • building_total_downtime - array of downtime quantities for each of the 3 repair goals. Namely, the time in days for full recovery, functional recovery, and re-occupancy:

    • The first item in the array is full recovery, whcih includes restoring the building back to its pre-damage functionality and aesthetic condition. For example, repairing cracked partitions and facades

    • The second item in the array is represents functional recovery, or the time required to establish re-occupancy and regain the facility’s primary function. Although non-functional aesthetic elements may still be damaged, the building should be operational according to its original intent, which involves reinstating power, water, fire sprinklers, lighting, elevators, and HVAC systems.

    • The third item in the array is re-occupancy, or the time required to repair major structural damage so that the building is safe enough to be used for shelter.

    Note that re-occupancy can occur before functionality is restored. In this case lighting, heating/air-conditioning, and water may not be available.

  • component_qty - a dictionary containing the sum of all components quantities where the key is the NISTR component tag and the corresponding values are the quantity of that component.

  • consequence_by_component_by_floor - a dictionary containing lists of the consequences arranged by floor. The key is the NISTR component tag and the values are a list of a list. The highest-level list corresponds to the number of consequences, while the inner list corresponds to each floor. The number of consquences is always 4 (1. repair cost [dollars]; 2. repair time [worker days]; 3. occupant injuries; and 4. occupant fatalities), while the number of floors is equal to the number of stories plus the roof (nFloor + 1)

  • damage_by_component_all_DS - a dictionary containing a list of the quantity of damaged components arranged by the damage state. The key is the NISTR component tag and the values are a list

  • impeding_delays - a dictionary containing the delay quantities from each impeding factor. Specifically, the engineering mobilization delay, financing delay, inspection delay, structural and non-structural contractor mobilization delays, and permit delay.

  • max_delay - the maximum delay in days of all impeding factors.

  • repair_class - a dictionary containing the repair class of each component. The key is the NISTR component tag and the value is the repair class.

  • repair_schedule - a list of size 3 containing dictionaries of the repair schedules for the 3 repair goals, i.e., full recovery, functional recovery, and re-occupancy (explained in further detail below).

Repair schedule#

The repair_schedule output is a list of size 3 containing dictionaries of the repair schedules for the 3 downtime states, i.e., full recovery, functional recovery, and re-occupancy. The first dictionary in the list corresponds to full recovery, the second to functional recovery, and the third to re-occupancy.

Each dictionary contains the following information:

  • struct_repairs - number of days to complete the structural repairs.

  • total_span - total span of the repair schedule in days. Note that this value will be the same as the corresponding value in the building_total_downtime array.

Contribution guidelines#

REDi strives to operate as a community-driven opensource initiative, embracing contributions from all individuals interested in enriching the project and becoming part of our community. Whether you’re inclined to enhance PyREDi, introduce valuable new features, or you’ve identified a bug, we invite you to submit a pull request. Your involvement is greatly appreciated and fosters the collaborative spirit of REDi.

All contributions through REDi are handled via pull requests on GitHub. Once a pull request is submitted, it must be approved by a member of REDi’s contributors team to ensure that the code matches the design and style of the rest of REDi code and that the core functionality is working.

License#

REDi is licensed under the Apache License, Version 2.0. The full license text can be found in the LICENSE.txt file found here in the GitHub repository.

Contact#

REDi represents the collaborative result of more than a decade of implementation and research into building recovery at Arup’s Risk + Resilience team (formerly Advanced Technology + Research) in San Francisco.

PyREDi Code Contribution team#

  • Stevan Gavrilovic

  • Kenny Buyco

  • Nicole Paul

  • Ben Shao

  • Casie Venable

  • Ji Su Lee

REDi Technical background team#

  • Ibbi Almufti

  • Sean Merrifield

  • Mike Mieler

  • Tamika Bassman

  • Meg Ackerson

  • Jimmy Zhang

  • Jinal Mehta

Contact Us#

This documentation is a continuous work in progress. To report any errors or omissions, please contact Dr. Stevan Gavrilovic, Arup, Risk + Resilience Team, San Francisco.

Stevan Gavrilovic