Source code for viiapackage.pictures.result_pictures.helper_functions.get_limits

### ===================================================================================================================
###  FUNCTION: Get limits for VIIA pictures
### ===================================================================================================================
# Copyright ©VIIA 2024

### ===================================================================================================================
###   1. Import modules
### ===================================================================================================================

# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, Union, Dict, List, Tuple, Optional

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.shapes import Shapes, Reinforcements
from rhdhv_fem.output_items import OutputItem, StrainOutputItem, StressOutputItem

# References for function and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject
from viiapackage.results.result_functions.viia_limits import viia_find_limits_NLTH


### ===================================================================================================================
###   2. Function to get the VIIA limits for result pictures
### ===================================================================================================================

[docs]def viia_get_limits( project: ViiaProject, shape_set: Union[Dict, List], output_item: OutputItem, pic_type: str, scope: str, component: str, material: str = None) -> Tuple[Optional[float], Optional[float], Optional[bool]]: """ This function returns the limit values (maximum and minimum) for the NLTH result pictures. The limits comply to the check mentioned in the most recent Bass of Design report. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - shape_set (dictionary or list): List of shapes or dictionary with subdivisions for different sets of shapes or connections. - output_item (obj): Instance of output item for what the limits should be found. - pic_type (str): The result type of the result picture, this is defined in the viia-result_pictures yaml-file. - scope (str): The scope of the result picture, this is defined in the viia-result_pictures yaml-file. - component (str): Component of the plot result type. - material (str): Material name of the shape. Default value is None. Output: - Returns the maximum and minimum value for different scope and shape sets. """ # Get limits for different scope max_value, min_value = None, None limit_found = True if scope == 'Building' or scope == 'Floors-interstorey': max_value, min_value = None, None elif scope == 'Walls-storey' and 'CrackWidth' not in pic_type: limits = [] ran = [] for shape in shape_set: if shape.material.name.lower() in ["lin-dummy-plate"]: continue limits.append(viia_find_limits_NLTH(project=project, shape=shape)) if component == material.split('_')[1] and component in ['x', 'y']: for limit in limits: if 'In-plane' in limit: ran.append(limit['In-plane']) else: for limit in limits: if 'Out-of-plane' in limit: ran.append(limit['Out-of-plane']) if not ran: project.write_log( f"WARNING: Could not find proper limit value for result picture {scope}, component {component}. The " f"shapes in the picture are: {', '.join([shape.name for shape in shape_set])}. Limits found: {limits}.") return None, None, False if pic_type.split('-')[-1] == 'Max': max_value = min(ran) min_value = 0 else: max_value = 0 min_value = -min(ran) elif scope == 'Walls-storey' and 'CrackWidth' in pic_type: thickness = [float(wall.geometry.name.split('-')[1]) for wall in shape_set] max_value = 0.05*min(thickness)/1000 min_value = 0 elif scope == 'Beams-Material-storey': limit = None for shape in shape_set: if shape.material.name.lower() in ["lin-dummy-plate"]: continue limit = viia_find_limits_NLTH(project=project, shape=shape) if limit: break if not limit: limit_found = False elif all(val not in limit for val in ('f_t', 'f_b', 'f_vm')): limit_found = False project.write_log( f"WARNING: Could not find proper limit value for result picture {scope}, component {component}. The " f"shapes in the picture are: {', '.join([shape.name for shape in shape_set])}. Limits found: {limit}.") else: min_value = 0 if material == 'LIN-BETON': max_value = limit['f_t'] elif 'LIN-HOUT' in material: max_value = limit['f_b'] elif 'LIN-STAAL' in material: max_value = limit['f_vm'] elif scope == 'Columns-Material-storey': limit = None for shape in shape_set: if shape.material.name.lower() in ["lin-dummy-plate"]: continue limit = viia_find_limits_NLTH(project=project, shape=shape) if limit: break if not limit: limit_found = False elif all(val not in limit for val in ('f_c', 'f_b', 'f_vm')): limit_found = False project.write_log( f"WARNING: Could not find proper limit value for result picture {scope}, component {component}. The " f"shapes in the picture are: {', '.join([shape.name for shape in shape_set])}. Limits found: {limit}.") else: max_value = 0 if material == 'LIN-BETON': min_value = -limit['f_c'] elif 'LIN-HOUT' in material: min_value = -limit['f_b'] elif 'LIN-STAAL' in material: max_value = limit['f_vm'] min_value = 0 elif scope == 'Reinforcements-storey': limits = {} for shape in [item for item in shape_set if isinstance(item, Reinforcements) and isinstance(item, Shapes)]: limits = viia_find_limits_NLTH(project=project, shape=shape) if limits: break # Return if no limits are found if not limits: limit_found = False elif 'f_y' in limits: if 'Max' in pic_type: max_value = limits['f_y'] min_value = 0 elif 'Min' in pic_type: max_value = 0 min_value = -limits['f_y'] elif 'e_u' in limits: if 'Max' in pic_type: max_value = limits['e_u'] min_value = 0 elif 'Min' in pic_type: max_value = 0 min_value = -limits['e_u'] elif scope in ['Floors-Material-storey', 'Roofs-Material-storey', 'Roofs-Timber'] and \ isinstance(output_item, StressOutputItem): limits = {} for shape in shape_set: material = shape.material.name if material.lower() in ["lin-dummy-plate"]: continue limits = viia_find_limits_NLTH(project=project, shape=shape) if limits: break # Return if no limits are found if not limits: limit_found = False elif 'N_in' not in limits: limit_found = False project.write_log( f"WARNING: Could not find proper limit value for result picture {scope}, component {component}. The " f"shapes in the picture are: {', '.join([shape.name for shape in shape_set])}. Limits found: {limits}.") else: if 'Max' in pic_type: max_value = limits['N_in'] min_value = 0 else: min_value = -limits['N_in'] max_value = 0 elif scope in ['Floors-Timber-storey', 'Roofs-Timber'] and isinstance(output_item, StrainOutputItem): if 'Max' in pic_type: max_value = 2.5E-02 min_value = 0 elif 'Min' in pic_type: min_value = -2.5E-02 max_value = 0 # Not all interfaces have upper and lower bound limits and therefore the checks are for particular interfaces elif scope == 'Interfaces-storey-Line': maximum = [] minimum = [] for shape in shape_set: if shape.name.split('-')[3] in ['D2.01', 'D2.02', 'D2.13'] and component == 'z' and \ isinstance(output_item, StrainOutputItem) and output_item.output_type == 'total' and \ output_item.theoretical_formulation == 'relative displacement' and output_item.operation == 'local': thickness = float(shape.connecting_shapes['source_connecting_shape'].name.split('-')[-2])/1000 if 'Max' in pic_type: maximum.append(thickness/2) minimum.append(0) elif 'Min' in pic_type: maximum.append(0) minimum.append(-thickness/2) else: project.write_log( f"WARNING: No limits are applicable for the {shape.name} interface and for the {pic_type} " f"component.") # Remove duplicates and select the minimum value for conservative purpose if maximum and minimum: max_value = min(list(dict.fromkeys(maximum))) min_value = max(list(dict.fromkeys(minimum))) elif scope == 'Interfaces-storey-Point': maximum = [] minimum = [] for shape in shape_set: if shape.name.split('-')[3] == 'D2.01B' and component == 'y' and \ isinstance(output_item, StrainOutputItem) and output_item.output_type == 'total' and \ output_item.theoretical_formulation == 'relative displacement' and output_item.operation == 'local': thickness = float(shape.connecting_shapes['source_connecting_shape'].name.split('-')[-2]) / 1000 if 'Max' in pic_type: maximum.append(thickness / 2) minimum.append(0) elif 'Min' in pic_type: maximum.append(0) minimum.append(-thickness / 2) else: project.write_log( f'No limits are applicable for the {shape.name} interface and for the {pic_type} component.') # Remove duplicates and select the minimum value for conservative purpose if maximum and minimum: max_value = min(list(dict.fromkeys(maximum))) min_value = max(list(dict.fromkeys(minimum))) if (max_value is None and min_value is not None) or (min_value is None and max_value is not None): max_value = None min_value = None limit_found = False project.write_log( f"WARNING: One of limits (max or min) value are not found/applicable for the shape set {shape_set} with " f"material {material}in the scope {scope}. Both max and min limits are set to default as None, and results " f"pictures are saved in the Non-standard materials sub-folder.") return max_value, min_value, limit_found
### =================================================================================================================== ### 3. End of script ### ===================================================================================================================