Source code for viiapackage.reporting.helper_functions.get_acceptance_criteria

### ===================================================================================================================
###  FUNCTION: Collect the acceptance criteria for the elements in the NLTH model
### ===================================================================================================================
# Copyright ©2026 Haskoning Nederland B.V.
# For use by VIIA

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

# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, List, Dict
import re

# References for functions and classes in the haskoning-structural package
from haskoning_structural.materials import Concrete, Timber, Masonry, Steel
from haskoning_structural.geometries.geometry_models import IsotropicThickness
from haskoning_structural.fem_tools import fem_compare_objects

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


### ===================================================================================================================
###  2. Function to collect the applicable acceptance criteria in the NLTH model
### ===================================================================================================================

[docs]def viia_get_acceptance_criteria(project: ViiaProject, shape_type: str = 'floors') -> List[Dict[str, str]]: """ Function to collect the acceptance criteria per shape type in the model of the object. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - shape_type (string): The type of shape that should be considered. Possible are 'floors', 'roofs', 'beams' and 'columns'. Default is 'floors'. Output: - Returns a list with dictionaries with the acceptance criteria per shape. """ if shape_type in ['floors', 'roofs']: return _get_acceptance_criteria_floors_roofs(project=project, shape_type=shape_type) if shape_type in ['beams', 'columns']: return _get_acceptance_criteria_beams_columns(project=project, shape_type=shape_type) raise ValueError( "ERROR: Provided input for shape_type should be one of ['floors', 'roofs', 'beams', 'columns']. " f"Provided was: {shape_type}" )
def _get_acceptance_criteria_floors_roofs(project: ViiaProject, shape_type: str = 'floors') -> List[Dict[str, str]]: """ Function to collect the acceptance criteria per shape in the model of the object, for which a NLTH analysis is performed. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - shape_type (string): The type of shape that should be considered. Possible are 'floors', 'roofs', 'beams' and 'columns'. Default is 'floors'. Output: - Returns a list with dictionaries with the acceptance criteria per shape. """ shape_types = ['floors', 'roofs'] if shape_type not in shape_types: raise ValueError( f"ERROR: Provided input for shape_type should be one of {shape_types}. Provided was: {shape_type}") _table_dict = {'floors': 'floor', 'roofs': 'roof'} #Collect the relevant shapes collection = getattr(project.collections, shape_type) if not collection: return [] check_combinations = {} list_shapes_dict = [] for shape in collection: _relevant_properties = '' _dict = {} material = shape.material geometry = shape.geometry # Check if the material is already in the list (without looking at added mass) material_check = [fem_compare_objects( material, check_material, list_excluded_keys=["added_mass"]) for check_material in check_combinations] # Additional check for geometry (only for entry with the same material) geometry_check = [geometry in check_combinations[check_material] for check_material, correct_material in zip(check_combinations, material_check) if correct_material] # if both checks are true, skip shape if any(material_check) and any(geometry_check): continue # Get shape type and properties if isinstance(material, Concrete): _dict['type'] = f"Concrete {_table_dict[shape_type]}" if isinstance(geometry.geometry_model, IsotropicThickness): _relevant_properties += f'Thickness = {int(geometry.geometry_model.thickness*1000)} mm' # Find relevant properties # Ugly regex that finds strength classes like 'S355', 'B500', 'C14' and 'C20/25' strength_class_match = re.search(r'-([CSB]\d+/?\d+)', material.name) if strength_class_match: strength_class = strength_class_match.group(1) _relevant_properties += strength_class # Fill in concrete class for standard LIN-BETON (when no strength class is found) elif 'LIN-BETON' in material.name: if _relevant_properties: _relevant_properties += '\n' _relevant_properties += 'C20/25' # Exclude dummy plates from table elif 'DUMMY' in material.name: continue elif isinstance(material, Timber): if 'PLANKEN' in material.name: _dict['type'] = f"Timber {_table_dict[shape_type]} with joists and planks" properties = viia_get_timberfloor_dimensions(shape=shape)['thickness'] _relevant_properties += f'Plank thickness = {int(properties*1000)} mm' elif 'PLATEN' in material.name: _dict['type'] = f"Timber {_table_dict[shape_type]} with joists and plates" properties = viia_get_timberfloor_dimensions(shape=shape)['thickness'] thickness = int(properties*1000) _relevant_properties += f'Plate thickness = {thickness} mm' else: _dict['type'] = f"{material.name} {_table_dict[shape_type]}" project.write_log(f"WARNING: No acceptance criteria found for shape {shape.name}.") _dict['relevant_properties'] = _relevant_properties # Get the required limits _dict['in_plane_shear_limit'] = '' limit = viia_find_limits_NLTH(project=project, shape=shape) if limit and 'N_in' in limit: _dict['in_plane_shear_limit'] = round(limit['N_in'] / 1000, 1) list_shapes_dict.append(_dict) if material not in check_combinations: check_combinations[material] = [] check_combinations[material].append(geometry) return list_shapes_dict def _get_acceptance_criteria_beams_columns(project: ViiaProject, shape_type: str = 'beams') -> List[Dict[str, str]]: """ Function to collect the acceptance criteria per shape in the model of the object, for which a NLTH analysis is performed. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - shape_type (string): The type of shape that should be considered. Possible are 'floors', 'roofs', 'beams' and 'columns'. Default is 'floors'. Output: - Returns a list with dictionaries with the acceptance criteria per shape. """ shape_types = ['beams', 'columns'] if shape_type not in shape_types: raise ValueError( f"ERROR: Provided input for shape_type should be one of {shape_types}. Provided was: {shape_type}") _table_dict = {'beams': 'beam', 'columns': 'column'} #Collect the relevant shapes collection = getattr(project.collections, shape_type) if not collection: return [] check_combinations = [] list_shapes_dict = [] for shape in collection: _relevant_properties = '' _dict = {} material = shape.material # If we have the material in the list already, skip if any( [fem_compare_objects( material, check_material, list_excluded_keys=["added_mass"]) for check_material in check_combinations] ): continue # Concrete materials if isinstance(material, Concrete): _dict['type'] = f"Concrete {_table_dict[shape_type]}" # Find relevant properties # Ugly regex that finds strength classes like 'S355', 'B500', 'C14' and 'C20/25' strength_class_match = re.search(r'-([CSB]\d+/?\d+)', material.name) if strength_class_match: strength_class = strength_class_match.group(1) _relevant_properties += strength_class # Fill in concrete class for standard LIN-BETON (when no strength class is found) elif 'LIN-BETON' in material.name: _relevant_properties += 'C20/25' _dict['relevant_properties'] = _relevant_properties #Find limit concrete materials _dict['limit'] = '' limit = viia_find_limits_NLTH(project=project, shape=shape) if limit and shape_type == 'beams' and 'f_t' in limit: _dict['limit'] = "{:.1f}".format(limit['f_t']/1E6) + " N/mm\u00b2" #N/m2 to N/mm2 elif limit and shape_type == 'columns': _dict['limit'] = "{:.1f}".format(-limit['f_c']/1E6) + " N/mm\u00b2" #N/m2 to N/mm2 # Timber materials elif isinstance(material, Timber): _dict['type'] = f"Timber {_table_dict[shape_type]}" # Find relevant properties # Ugly regex that finds strength classes like 'S355', 'B500', 'C14' and 'C20/25' strength_class_match = re.search(r'-([CSB]\d+/?\d+)', material.name) if strength_class_match: strength_class = strength_class_match.group(1) _relevant_properties += strength_class # Catch laminated timber elif 'LAM' in material.name: _dict['type'] = "Laminated " + _dict['type'].lower() _relevant_properties += f'GL24C' # Fill in timber class for standard LIN-HOUT (when no strength class is found) elif 'LIN-HOUT' in material.name and 'PLAAT' not in material.name: _relevant_properties += 'C18' _dict['relevant_properties'] = _relevant_properties # Find limit timber materials _dict['limit'] = '' limit = viia_find_limits_NLTH(project=project, shape=shape) if limit and shape_type == 'beams': _dict['limit'] = "{:.1f}".format(limit['f_b'] / 1E6) + " N/mm\u00b2" # N/m2 to N/mm2 elif limit and shape_type == 'columns': _dict['limit'] = "{:.1f}".format(-limit['f_b']/1E6) + " N/mm\u00b2" #N/m2 to N/mm2 # Steel materials elif isinstance(material, Steel): _dict['type'] = f"Steel {_table_dict[shape_type]}" # Find relevant properties # Ugly regex that finds strength classes like 'S355', 'B500', 'C14' and 'C20/25' strength_class_match = re.search(r'-([CSB]\d+/?\d+)', material.name) if strength_class_match: strength_class = strength_class_match.group(1) _relevant_properties += strength_class # Fill in steel class for standard LIN-STAAL (when no strength class is found) elif 'LIN-STAAL' in material.name: _relevant_properties += 'S235' _dict['relevant_properties'] = _relevant_properties # Find limit steel materials _dict['limit'] = '' limit = viia_find_limits_NLTH(project=project, shape=shape) if limit: _dict['limit'] = "{:.1f}".format(limit['f_vm'] / 1E6) + " N/mm\u00b2" # N/m2 to N/mm2 elif isinstance(material, Masonry): _dict['type'] = f"Masonry {_table_dict[shape_type]}" _dict['relevant_properties'] = _relevant_properties _dict['limit'] = '' project.write_log(f"WARNING: No acceptance criteria found for shape {shape.name}.") # Fallback, show raw name of material in table else: _dict['type'] = f"{material.name} {_table_dict[shape_type]}" _dict['relevant_properties'] = _relevant_properties _dict['limit'] = '' project.write_log(f"WARNING: No acceptance criteria found for shape {shape.name}.") # Add acceptance criteria to the list list_shapes_dict.append(_dict) # Add material to checked materials check_combinations.append(material) return list_shapes_dict ### =================================================================================================================== ### 3. End of script ### ===================================================================================================================