### ===================================================================================================================
### FUNCTION: Collect information for the inspection report
### ===================================================================================================================
# Copyright ©VIIA 2025
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, List
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.connections import Interface
from rhdhv_fem.fem_math import fem_distance_coordinates
from rhdhv_fem.analyses.analysis_reference import SteppedAnalysisReference
# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
from viiapackage.connections import viia_get_line_interfaces
### ===================================================================================================================
### 2. Function get_l2_measure_results
### ===================================================================================================================
[docs]def get_l2_measure_results(project: ViiaProject, interfaces: List[Interface] = None) -> dict:
"""
Get the results of L2 measures.
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
- interfaces (list of obj): List of interfaces objects that needs to be considered. When None all the interfaces
will be considered. Default is None.
Output:
- A dict with the result information of the L2 measures
"""
def get_average_stress_result(project, interface, output_results, output_item, analysis_references):
avg_values = []
max_values = []
min_values = []
lengths = {mesh_element: mesh_element.length for mesh_element in interface.mesh.mesh_elements}
total_length = sum(lengths.values())
for analysis_reference in analysis_references:
result_dict = output_results.get_result_dict(
output_item=output_item, analysis_reference=analysis_reference, software=project.software).results
avg_value = 0
max_value = []
min_value = []
for key, value in result_dict.items():
if not isinstance(value, dict):
raise ValueError(
f"ERROR: Results should be stored at the integration points. Not at the nodes. Check the "
f"results of {interface.name}.")
if len(value.keys()) != 2 or not all([isinstance(val, int) for val in value.keys()]):
raise ValueError(
f"ERROR: Results should be stored at the 2 integration points. Check the results of "
f"{interface.name}.")
max_value.append(max(value.values()))
min_value.append(min(value.values()))
avg_value += lengths[key]*sum(value.values()) / 2
avg_values.append(avg_value/total_length)
max_values.append(max(max_value))
min_values.append(min(min_value))
return {
'max_avg': sum(max_values) / len(max_values),
'avg': sum(avg_values) / len(avg_values),
'min_avg': sum(min_values) / len(min_values)}
def get_max_min_envelope(project, thickness, output_results, output_item, analysis_references):
element_max = {}
element_min = {}
for analysis_reference in analysis_references:
result_dictionary = output_results.get_result_dict(
output_item=output_item, analysis_reference=analysis_reference, software=project.software).results
for mesh_element, result_values in result_dictionary.items():
if mesh_element not in element_max:
element_max[mesh_element] = {}
if mesh_element not in element_min:
element_min[mesh_element] = {}
for integration_point, result_value in result_values.items():
if integration_point not in element_max[mesh_element]:
element_max[mesh_element][integration_point] = 0
if integration_point not in element_min[mesh_element]:
element_min[mesh_element][integration_point] = 0
if result_value > element_max[mesh_element][integration_point]:
element_max[mesh_element][integration_point] = result_value
if result_value < element_min[mesh_element][integration_point]:
element_min[mesh_element][integration_point] = result_value
for mesh_element, result_values in element_max.items():
for integration_point, result_value in result_values.items():
element_max[mesh_element][integration_point] = result_value * thickness
for mesh_element, result_values in element_min.items():
for integration_point, result_value in result_values.items():
element_min[mesh_element][integration_point] = result_value * thickness
return element_max, element_min
data = {}
if interfaces is None:
interfaces = viia_get_line_interfaces(project=project)
if not interfaces:
return data
# get the analysis_references for average results
all_analysis_references = [
analysis_reference for analysis_reference in interfaces[0].results.get_analysis_references()
if isinstance(analysis_reference, SteppedAnalysisReference)]
average_analysis_references = [
analysis_reference for analysis_reference in all_analysis_references
if isinstance(analysis_reference, SteppedAnalysisReference) and analysis_reference.historic_envelope is None]
envelope_analysis_references = [
analysis_reference for analysis_reference in all_analysis_references
if isinstance(analysis_reference, SteppedAnalysisReference) and analysis_reference.historic_envelope is not None]
if average_analysis_references:
average_analysis_references = sorted(
average_analysis_references, key=lambda analysis_reference: analysis_reference.step_nr)
if envelope_analysis_references:
envelope_analysis_references = sorted(
envelope_analysis_references, key=lambda analysis_reference: analysis_reference.step_nr)
# Get output items
stress_types = {'t_x_tot_intp': None, 't_y_tot_intp': None, 't_z_tot_intp': None}
for key in stress_types.keys():
if average_analysis_references:
stress_types[key] = interfaces[0].results.get_output_item(
engineering_notation=key, analysis_reference=average_analysis_references[0], software=project.software)
elif envelope_analysis_references:
stress_types[key] = interfaces[0].results.get_output_item(
engineering_notation=key, analysis_reference=envelope_analysis_references[0], software=project.software)
strain_types = {'du_x_tot_intp': None, 'du_y_tot_intp': None, 'du_z_tot_intp': None}
for key in strain_types.keys():
if average_analysis_references:
strain_types[key] = interfaces[0].results.get_output_item(
engineering_notation=key, analysis_reference=average_analysis_references[0], software=project.software)
elif envelope_analysis_references:
strain_types[key] = interfaces[0].results.get_output_item(
engineering_notation=key, analysis_reference=envelope_analysis_references[0], software=project.software)
# Loops through the interfaces and retrieves the stresses and thickness to calculate the forces
for interface in interfaces:
results = interface.results
if results is None:
continue
if not results.result_collections:
continue
# Exclude point and surface interfaces, axis system is different
if not interface.connection_type == 'line-line':
continue
thickness = None
if hasattr(interface.geometry.geometry_model.line_interface_type, 'thickness'):
thickness = interface.geometry.geometry_model.line_interface_type.thickness
else:
obj = interface.geometry.geometry_model.line_interface_type.line_geometry
thickness = getattr(obj, 'perimeter', None)
if thickness is None:
thickness = getattr(obj, 'thickness', None)
if thickness is None:
raise AttributeError(f"ERROR: Thickness could not be retrieved for interface {interface.name}.")
result_data = {}
for stress_type in stress_types.keys():
# Minimum and maximum result is the min/max result on the interface over all steps
minimum_result = results.get_minimum_result(outputs=stress_type)
maximum_result = results.get_maximum_result(outputs=stress_type)
result_data[f'min_{stress_type}'] = [minimum_result[0], minimum_result[1] * thickness]
result_data[f'max_{stress_type}'] = [maximum_result[0], maximum_result[1] * thickness]
if average_analysis_references:
average_stress_results = get_average_stress_result(
project=project, interface=interface, output_results=results, output_item=stress_type,
analysis_references=average_analysis_references)
result_data[f'min_avg_{stress_type}'] = average_stress_results['min_avg'] * thickness
result_data[f'avg_{stress_type}'] = average_stress_results['avg'] * thickness
result_data[f'max_avg_{stress_type}'] = average_stress_results['max_avg'] * thickness
# Maximum/minimum envelope
element_max_results, element_min_results = get_max_min_envelope(
project=project, thickness=thickness, output_results=results, output_item=stress_type,
analysis_references=average_analysis_references)
result_data[f'element_max_{stress_type}'] = element_max_results
result_data[f'element_min_{stress_type}'] = element_min_results
for strain_type in strain_types.keys():
minimum_result = results.get_minimum_result(outputs=strain_type)
maximum_result = results.get_maximum_result(outputs=strain_type)
result_data[f'min_{strain_type}'] = [minimum_result[0], minimum_result[1]]
result_data[f'max_{strain_type}'] = [maximum_result[0], maximum_result[1]]
data[interface] = result_data
return data
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================