### ===================================================================================================================
### FUNCTION: Check the eccentricity for NLPO according VIIA requirements
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, Dict
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.fem_math import fem_greater, fem_smaller
# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
from viiapackage.analyses.nlpo_helper_functions.viia_center_of_mass_nlpo import viia_center_of_mass_nlpo
from viiapackage.analyses.nlpo_helper_functions.viia_center_of_rigidity import viia_center_of_rigidity
from viiapackage.analyses.nlpo_helper_functions.viia_locate_piers import viia_locate_piers
from viiapackage.analyses.nlpo_helper_functions.viia_effective_pier_shear_stiffness import \
viia_effective_pier_shear_stiffness
### ===================================================================================================================
### 2. Function viia_eccentricity_check
### ===================================================================================================================
[docs]def viia_eccentricity_check(project: ViiaProject) -> Dict[str, Dict[str, Dict[str, float]]]:
"""
This function checks whether the eccentricity of a building is sufficiently small in order for the NPR to allow
pushover analysis.
Input:
- project (obj): VIIA project object containing collections of fem objects and project variables.
Output:
- Returns dictionary containing the results of all eccentricity checks performed.
"""
center_of_mass = viia_center_of_mass_nlpo(project=project)
walls_n0 = []
for wall in project.collections.walls:
if "N0" in wall.name:
walls_n0.append(wall)
piers = viia_locate_piers(project=project, walls=walls_n0)
viia_effective_pier_shear_stiffness(project=project, piers=piers)
center_of_rigidity = viia_center_of_rigidity(piers=piers)
# TODO consider all the levels including the levels with [0,0,0] or they will be removed after you return
# Calculate the eccentricity for each level
eccentricity_dict = {}
for level in center_of_mass:
ecc_x = max(abs(center_of_mass[level]['x'] - center_of_rigidity['x']['Y_pos']),
abs(center_of_mass[level]['x'] - center_of_rigidity['x']['Y_neg']))
ecc_y = max(abs(center_of_mass[level]['y'] - center_of_rigidity['y']['X_pos']),
abs(center_of_mass[level]['y'] - center_of_rigidity['y']['X_neg']))
eccentricity_dict.update({level: [ecc_x, ecc_y]})
# Find the building width in x and y directions
building_width_in_x = max([i.get_ref_point()[1] for i in project.collections.shape_nodes]) - \
min([i.get_ref_point()[1]for i in project.collections.shape_nodes])
building_width_in_y = max([i.get_ref_point()[0] for i in project.collections.shape_nodes]) - \
min([i.get_ref_point()[0]for i in project.collections.shape_nodes])
# TODO the definition of the x- and y- direction width needed to be confirmed
accidental_eccentricity_x = 0.05 * building_width_in_x
accidental_eccentricity_y = 0.05 * building_width_in_y
# Calculate the threshold values of eccentricity level
x_02b = 0.2 * building_width_in_x
x_04b = 0.4 * building_width_in_x
y_02b = 0.2 * building_width_in_y
y_04b = 0.4 * building_width_in_y
# Set the output dictionary for each level of x- and y- direction
x_eccentricity_dict = {}
y_eccentricity_dict = {}
# Define the output parameters in x direction
for level, value in eccentricity_dict.items():
x_eccentricity_dict[level] = {}
if fem_smaller(value[1], x_02b):
# TODO the definition of the x- and y- direction width needed to be confirmed
x_eccentricity_dict[level].update({'Eccentricity type': 'Negligible'})
x_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[1], 3)})
try:
x_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
x_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_x, 3)})
except ZeroDivisionError:
x_eccentricity_dict[level].update({'Eccentricity percentage of b': 0.0})
project.write_log(
f"The level of {level} is not existing, 0 will be returned as eccentricity for this level.")
elif fem_greater(value[1], x_02b) and fem_smaller(value[1], y_04b):
# TODO the definition of the x- and y- direction width needed to be confirmed
x_eccentricity_dict[level].update({'Eccentricity type': 'Significant'})
x_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[1] + accidental_eccentricity_x, 3)})
x_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
x_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_x, 3)})
elif fem_greater(value[1], x_04b):
# TODO the definition of the x- and y- direction width needed to be confirmed
x_eccentricity_dict[level].update({'Eccentricity type': 'Severe'})
x_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[1] + accidental_eccentricity_x, 3)})
x_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
x_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_x, 3)})
# Define the output parameters in y direction
for level, value in eccentricity_dict.items():
y_eccentricity_dict[level] = {}
if fem_smaller(value[0], y_02b):
# TODO the definition of the x- and y- direction width needed to be confirmed
y_eccentricity_dict[level].update({'Eccentricity type': 'Negligible'})
y_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[0], 3)})
try:
y_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
y_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_y, 3)})
except ZeroDivisionError:
y_eccentricity_dict[level].update({'Eccentricity percentage of b': 0.0})
project.write_log(
f"The level of {level} is not existing, 0 will be returned as eccentricity for this level.")
elif fem_greater(value[0], y_02b) and fem_smaller(value[1], y_04b):
# TODO the definition of the x- and y- direction width needed to be confirmed
y_eccentricity_dict[level].update({'Eccentricity type': 'Significant'})
y_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[0] + accidental_eccentricity_y, 3)})
y_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
y_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_y, 3)})
elif fem_greater(value[0], y_04b):
# TODO the definition of the x- and y- direction width needed to be confirmed
y_eccentricity_dict[level].update({'Eccentricity type': 'Severe'})
y_eccentricity_dict[level].update({'Eccentricity magnitude': round(value[0] + accidental_eccentricity_y, 3)})
y_eccentricity_dict[level].update({'Eccentricity percentage of b': round(
y_eccentricity_dict[level]['Eccentricity magnitude'] / building_width_in_y, 3)})
return {'X_direction': x_eccentricity_dict, 'Y_direction': y_eccentricity_dict}
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================