Source code for viiapackage.geometries.viia_get_geometry_model_properties

### ===================================================================================================================
###   Function to get the properties of the geometry-model
### ===================================================================================================================
# Copyright ©VIIA 2024

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

# General imports
from __future__ import annotations
import math
from typing import TYPE_CHECKING, Dict, Union
from copy import deepcopy

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.fem_config import Config
from rhdhv_fem.geometries import fem_get_profile_from_database

# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject


### ===================================================================================================================
###    2. Get the geometry-model properties based on geomtery-name and geometry-group
### ===================================================================================================================

[docs]def viia_get_geometry_model_properties( project: ViiaProject, geometry_name: str, geometry_group: str) -> Dict[str, Union[str, float, int]]: """ This function collects the geometry-model properties, based on the geometry name according to VIIA naming conventions. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - geometry_name (str): Name of the element geometry. - geometry_group (str): Name of the geometry-group. Output: - Returns a dictionary with the properties for the geometry model. """ # Initialise the output dictionaries geometry_model = dict() geometry_model_properties = dict() # Geometry models for volumes if geometry_group == 'volumes': if not geometry_model: if 'RUBBER' in geometry_name: geometry_model['model'] = 'rubber solid elements' else: geometry_model['model'] = 'regular structural solids elements' # Geometry models for surfaces elif geometry_group == 'surfaces': if not geometry_model: if 'FOS' in geometry_name: geometry_model['model'] = 'structural surface interface elements' elif 'VLOERHBV' in geometry_name or 'WANDHSB' in geometry_name: geometry_model['model'] = 'regular flat shell elements' else: geometry_model['model'] = 'regular curved shell elements' if geometry_model['model'] in [ 'flat plate elements', 'regular flat shell elements', 'flat shell with drilling dof']: geometry_model['orthotropic thickness'] = False if geometry_model['model'] in [ 'regular curved shell elements', 'curved shell with drilling dof', 'layered shell elements', 'layered shell with drilling dof', 'structural surface interface elements']: geometry_model['underlying geometry'] = False if geometry_model['model'] == 'boundary surface elements': geometry_model['free field specifications'] = False # Geometry models for surface reinforcements elif geometry_group == 'surface-reinforcements': geometry_model['model'] = 'grid reinforcement' if 'CFRPMESH' in geometry_name: geometry_model['thickness'] = 'direct input' else: geometry_model['thickness'] = 'diameter and spacing' # Geometry models for lines elif geometry_group == 'lines': if not geometry_model: if 'STAAF' in geometry_name: geometry_model['model'] = '3d is_simplified truss element' elif 'DISCREET' in geometry_name: geometry_model['model'] = 'distributed line mass' else: geometry_model['model'] = '3d class-iii beam elements' if geometry_model['model'] == '3d class-i beam elements': geometry_model['cross-section definition type'] = 'predefined profiles' if geometry_model['model'] in [ '3d class-ii beam elements', '3d class-iii beam elements', '3d is_simplified truss element', 'distributed line mass'] or (geometry_model['model'] == '3d class-i beam elements' and geometry_model['cross-section definition type'] == 'predefined profiles'): geometry_model_properties = _viia_cross_section_shape(project, geometry_name) if geometry_model['model'] == '3d line interface elements (2 normal, 1 shear)': geometry_model['line geometry'] = 'diameter' if geometry_model['model'] == 'shell line interface elements': geometry_model['shape definition type'] = 'flat' # Geometry models for line reinforcements without bond slip elif geometry_group == 'line-reinforcements': geometry_model['model'] = 'bar reinforcement' geometry_model['reinforcement type'] = 'embedded' # Geometry models for line reinforcements with bond slip elif geometry_group == 'line-reinforcements-with-bondslip': geometry_model['model'] = 'bar reinforcement' geometry_model['reinforcement type'] = 'truss bondslip' # Geometry models for points elif geometry_group == 'points': if not geometry_model: if 'ROTVEER' in geometry_name: geometry_model['model'] = 'rotation springs/dashpots' elif 'PUNTIF' in geometry_name: geometry_model['model'] = '3d point interface' elif 'PUNTMASSA' in geometry_name: geometry_model['model'] = '3d point mass' else: geometry_model['model'] = 'translation springs/dashpots' # Create the geometry dictionary geometry_model_properties = {**deepcopy(geometry_model), **geometry_model_properties} # Extend properties with some additional information for shells and reinforcement geometry_model_properties = \ _viia_extend_geometry_model_properties( project=project, geometry_name=geometry_name, geometry_model_properties=geometry_model_properties) # Return the variable with the geometry_model with all options selected return geometry_model_properties
[docs]def _viia_cross_section_shape(project: ViiaProject, geometry_name: str) -> Dict[str, Union[str, float, int]]: """ This function filters the cross-sectional properties from the name of the geometry. The function will retrieve the properties for class I, class II and class III beams. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - geometry_name (str): Name of the element geometry of a line element. Output: - A dictionary is returned with the key 'shape' indicating the type of cross-section and the other entries are the cross-sectional dimensions, depending on the type of shape. """ # Note that the order of the section checks is important # Isolate the profile specifications in geometry name # Example of expected name: 'KOLOM-R70-(1,0,0)' geometry = '-'.join(geometry_name.split('-')[1:]).split('-(')[0] if 'LIJNMASSA' in geometry_name: if 'DISCREET' in geometry_name: return {'predefined': False, 'class': 'LineMassGM'} return { 'predefined': False, 'profile_name': project.project_specific['dummy_profile_linemass'], 'class': 'Rectangle', 'height': project.project_specific['dummy_dimension_linemass'], 'width': project.project_specific['dummy_dimension_linemass']} # If geometry in database, only return as profile name in shape dictionary if fem_get_profile_from_database(data_name=geometry) is not None: return { 'predefined': True, 'profile_name': geometry} # The section is not in the database and should be retrieved by the properties in the name (VIIA naming convention) shape_dictionary = { 'predefined': False, 'profile_name': deepcopy(geometry)} geometry = geometry.lower() # Check for truss-shapes sections # Example of expected geometry_name: 'STAAF-10000' if 'staaf' in geometry_name.lower(): shape_dictionary['class'] = 'TrussProfile' geometry = geometry.replace('o', '').replace('staaf', '') shape_dictionary['cross-section'] = float(geometry) / 1000000 return shape_dictionary # Check for L-shapes sections elif 'l' in geometry: shape_dictionary['class'] = 'LShape' # Naming convention is: 'L30x30x5' or 'L30x30x5x8' # Dimensions in geometry name are in [mm], these are converted to [m] geometry = [int(float(dim)) / 1000 for dim in geometry.replace('l', '').split('x')] # Determine the properties based on the number of items seperated by 'x' if len(geometry) == 2: # If only 2 dimensions are given: body and leg have same thickness and length, e.g. 'L30x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[0] shape_dictionary['thickness_flange_bottom'] = geometry[1] shape_dictionary['thickness_left_leg'] = geometry[1] elif len(geometry) == 3: # If only 3 dimensions are given: body and leg have same thickness, e.g. 'L30x30x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[1] shape_dictionary['thickness_flange_bottom'] = geometry[2] shape_dictionary['thickness_left_leg'] = geometry[2] elif len(geometry) == 4: # If 4 dimensions are given: all required dimensions are specified, e.g. 'L30x30x5x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[1] shape_dictionary['thickness_flange_bottom'] = geometry[2] shape_dictionary['thickness_left_leg'] = geometry[3] else: # Error if parameters are not clear raise ValueError( f"ERROR: A L-shape section is detected, but parameters are unknown for geometry: {geometry_name}.") # Return the dictionary with geometrical properties of the L-shape return shape_dictionary # Check for T-shapes sections elif 't' in geometry: shape_dictionary['class'] = 'TShape' # Naming convention is: 'T20x20x3' or 'T20x20x3x5' # Dimensions in geometry name are in [mm], these are converted to [m] geometry = [int(float(dim)) / 1000 for dim in geometry.replace('t', '').split('x')] # Determine the properties based on the number of items seperated by 'x' if len(geometry) == 2: # If only 2 dimensions are given: body and leg have same thickness and length, e.g. 'T20x3' shape_dictionary['height'] = geometry[0] shape_dictionary['width_flange_top'] = geometry[0] shape_dictionary['thickness_flange_top'] = geometry[1] shape_dictionary['thickness_web'] = geometry[1] elif len(geometry) == 3: # If only 3 dimensions are given: body and leg have same thickness, e.g. 'T20x20x3' shape_dictionary['height'] = geometry[0] shape_dictionary['width_flange_top'] = geometry[1] shape_dictionary['thickness_flange_top'] = geometry[2] shape_dictionary['thickness_web'] = geometry[2] elif len(geometry) == 4: # If 4 dimensions are given: all required dimensions are specified, e.g. 'T20x20x3x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width_flange_top'] = geometry[1] shape_dictionary['thickness_flange_top'] = geometry[2] shape_dictionary['thickness_web'] = geometry[3] else: # Error if parameters are not clear raise ValueError( f"ERROR: A T-shape section is detected, but parameters are unknown for geometry: {geometry_name}.") # Return the dictionary with geometrical properties of the T-shape return shape_dictionary # Check for circular hollow sections (or tube) elif ('d' in geometry or 'rd' in geometry or 'chs' in geometry) and 'x' in geometry: shape_dictionary['class'] = 'Pipe' # Naming convention is: 'D40x4', 'RD40x4' or 'CHS193.7x7.1' # Dimensions in geometry name are in [mm], these are converted to [m] geometry = [ int(float(dim)) / 1000 for dim in geometry.replace('rd', '').replace('d', '').replace('chs', '').split('x')] # Determine the properties based on the number of items seperated by 'x' if len(geometry) == 2: # If 2 dimensions are given: all required dimensions are specified, e.g. 'D40x4' shape_dictionary['diameter'] = geometry[0] shape_dictionary['thickness'] = geometry[1] else: # Error if parameters are not clear raise ValueError( f"ERROR: A hollow shape section (tube) is detected, but parameters are unknown for geometry: " f"{geometry_name}.") # Return the dictionary with geometrical properties of the tube shape return shape_dictionary # Check for square hollow sections (or rectangular box) elif geometry[0] == 'k' or geometry[:3] == 'rhs': shape_dictionary['class'] = 'Box' # Naming convention is 'K40x40x3' or 'K40x40x3x5' or 'RHS193.7x7.1' # Indication of cold formed profiles is removed ('CF') # Dimensions in geometry name are in [mm], these are converted to [m] geometry = [ int(float(dim)) / 1000 for dim in geometry.replace('k', '').replace('rhs', '').replace('cf', '').split('x')] # Determine the properties based on the number of items seperated by 'x' if len(geometry) == 2: # If only 2 dimensions are given: bodies and flanges have same height and thickness, e.g. 'K30x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[0] shape_dictionary['thickness_flange_top'] = geometry[1] shape_dictionary['thickness_flange_bottom'] = geometry[1] shape_dictionary['thickness_left_web'] = geometry[1] shape_dictionary['thickness_right_web'] = geometry[1] elif len(geometry) == 3: # If only 3 dimensions are given: bodies and flanges have same thickness, e.g. 'K40x30x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[1] shape_dictionary['thickness_flange_top'] = geometry[2] shape_dictionary['thickness_flange_bottom'] = geometry[2] shape_dictionary['thickness_left_web'] = geometry[2] shape_dictionary['thickness_right_web'] = geometry[2] elif len(geometry) == 4: # If only 4 dimensions are given: thickness of flanges and of web are equal, e.g. 'K50x30x10x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[1] shape_dictionary['thickness_flange_top'] = geometry[2] shape_dictionary['thickness_flange_bottom'] = geometry[2] shape_dictionary['thickness_left_web'] = geometry[3] shape_dictionary['thickness_right_web'] = geometry[3] elif len(geometry) == 6: # If all6 dimensions are given: all required dimensions are specified, e.g. 'K50x30x12x10x8x5' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[1] shape_dictionary['thickness_flange_top'] = geometry[2] shape_dictionary['thickness_flange_bottom'] = geometry[3] shape_dictionary['thickness_left_web'] = geometry[4] shape_dictionary['thickness_right_web'] = geometry[5] else: # Error if parameters are not clear raise ValueError( f"ERROR: A rectangular box (hollow square section) is detected, but parameters are unknown " f"for geometry: {geometry_name}.") # Return the dictionary with geometrical properties of the rectangular box shape return shape_dictionary # Check for circular sections (or bar) elif 'd' in geometry or 'r' in geometry or 'rd' in geometry: shape_dictionary['class'] = 'CircleProfile' # Naming convention is: 'D10' or 'RD280' geometry = geometry.replace('d', '').replace('r', '') # Dimensions in geometry name are in [mm], these are converted to [m] try: shape_dictionary['diameter'] = int(float(geometry)) / 1000 except ValueError: # Error if parameters are not clear print(f"ERROR: A circular cross-section is detected, but parameters are unknown for geometry: " f"{geometry_name}.") raise # Return the dictionary with geometrical properties of the circular cross-section shape return shape_dictionary # Check for rectangular sections elif geometry.count('x') == 1 or geometry.isdigit(): shape_dictionary['class'] = 'Rectangle' # Naming convention is '500x400' # Dimensions in geometry name are in [mm], these are converted to [m] geometry = [int(float(dim)) / 1000 for dim in geometry.split('x')] # Determine the properties based on the number of items seperated by 'x' if len(geometry) == 1: # If only 1 dimension is given: height and width are equal, e.g. '400' shape_dictionary['height'] = geometry[0] shape_dictionary['width'] = geometry[0] elif len(geometry) == 2: # If 2 dimensions are given: all required dimensions have been specified, e.g. '500x400' shape_dictionary['width'] = geometry[0] shape_dictionary['height'] = geometry[1] else: # Error if parameters are not clear raise ValueError( f"ERROR: A rectangular section is detected, but parameters are unknown for geometry: {geometry_name}.") # Return the dictionary with geometrical properties of the rectangular shape return shape_dictionary else: # Profile is not (clearly) defined, notification is given project.write_log(f"ERROR: {geometry_name} profile is not defined properly.") shape_dictionary['class'] = 'unknown' # Return the dictionary with geometrical properties of the shape return shape_dictionary
[docs]def _viia_extend_geometry_model_properties( project: ViiaProject, geometry_name: str, geometry_model_properties: Dict[str, Union[str, float, int]]) \ -> Dict[str, Union[str, float, int]]: """ This function extends the geometry properties dictionary for additional information for orthotropic surfaces and reinforcements. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - geometry_name (str): Name of the element geometry of a line element. - geometry_model_properties (dict): Dictionary with the geometry properties, which will be extended. Output: - The dictionary with geometry properties is returned with the added keys for shell or reinforcement. """ if geometry_model_properties['model'] == 'regular curved shell elements' or \ geometry_model_properties['model'] == 'curved shell with drilling dof' or \ geometry_model_properties['model'] == 'layered shell elements' or \ geometry_model_properties['model'] == 'layered shell with drilling dof': if geometry_name in ['RIB-FLEVO-VLOER', 'RIB-CVP-VLOER', 'RIB-OMNIA-VLOER']: material_name = 'LIN-' + geometry_name.replace('-VLOER', '') geometry_model_properties['thickness'] = \ project.viia_get_material(material_name, 'LinearOrthotropic')['thickness'] else: geometry_model_properties['thickness'] = float(geometry_name.split('-')[1]) / 1000 elif geometry_model_properties['model'] == 'regular flat shell elements': geometry_model_properties['shape factor'] = 1 thickness = float(geometry_name.split('(')[0].split('-')[1]) / 1000 # Example name 'VLOERHBV-30.5-(1,0,0)' geometry_model_properties['orthotropic thickness'] = thickness geometry_model_properties['thickness'] = thickness elif geometry_model_properties['model'] == 'grid reinforcement': # Check for type of rebar if 'CFRPMESH' in geometry_name: # Example: 'WANDEN-L5P-CFRPMESH' geometry_model_properties['equivalent_thickness_x'] =\ project.project_specific['strengthening_measures']['L5-P']['vertical_mesh'] geometry_model_properties['equivalent_thickness_y'] =\ project.project_specific['strengthening_measures']['L5-P']['horizontal_mesh'] else: # Find part of geometry_name in which the reinforcement is defined geometry_name_split = geometry_name.split('-') # Example: 'R12_150xR12_150' (horizontal x vertical) rebar = None for i in range(0, len(geometry_name_split)-1): if 'WAP' in geometry_name_split[i]: rebar = geometry_name_split[i + 1] break horizontal_rebar = rebar.split('x')[0] vertical_rebar = rebar.split('x')[1] if horizontal_rebar[0] == 'R': number_of_bars_horizontal = 1 else: number_of_bars_horizontal = int(horizontal_rebar.split('R')[0]) if vertical_rebar[0] == 'R': number_of_bars_vertical = 1 else: number_of_bars_vertical = int(vertical_rebar.split('R')[0]) diameter_horizontal = float(horizontal_rebar.split('R')[1].split('_')[0]) / 1000 diameter_vertical = float(vertical_rebar.split('R')[1].split('_')[0]) / 1000 # Round equivalent diameter with check_precision, which is more precise than round_precision. equivalent_diameter_horizontal = \ round(math.sqrt(number_of_bars_horizontal * diameter_horizontal ** 2), Config.CHECK_PRECISION) equivalent_diameter_vertical = \ round(math.sqrt(number_of_bars_vertical * diameter_vertical ** 2), Config.CHECK_PRECISION) geometry_model_properties['bar_diameter_x'] = equivalent_diameter_horizontal geometry_model_properties['bar_diameter_y'] = equivalent_diameter_vertical geometry_model_properties['spacing_x'] = \ round(float(horizontal_rebar.split('_')[1]) / 1000, Config.CHECK_PRECISION) geometry_model_properties['spacing_y'] = \ round(float(vertical_rebar.split('_')[1]) / 1000, Config.CHECK_PRECISION) elif geometry_model_properties['model'] == 'bar reinforcement': # Adding properties for CFRPSTRIP if 'CFRPSTRIP' in geometry_name: strip_section = geometry_name.split('-')[-1] geometry_model_properties['truss_name'] = geometry_name geometry_model_properties['cross_section_area'] = \ project.project_specific['strengthening_measures']['L4-O']['cross section'][strip_section] geometry_model_properties['contact_perimeter'] = \ project.project_specific['strengthening_measures']['L4-O']['contact perimeter'][strip_section] # Returns the updated parameters in the geometry dictionary return geometry_model_properties
### =================================================================================================================== ### 3. End of script ### ===================================================================================================================