### ===================================================================================================================
### FUNCTION: Get the execute block and stepnumber or mode
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from typing import Optional, List, Union, Tuple, Dict
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.analyses import Analysis, AnalysisBlock, SpecifiedExecuteNonlinear, LoadSteps, TimeSteps, StartSteps
### ===================================================================================================================
### 2. Function to get the result case for result pictures
### ===================================================================================================================
[docs]def viia_get_resultcase_info(
analysis: Analysis, analysis_block: AnalysisBlock, case: Optional[str] = None,
eigenfrequencies: Optional[Dict[int, List[float]]] = None) -> \
Tuple[Tuple[float, Union[float, str]], AnalysisBlock]:
"""
Function returns the input for step in the result picture create function.
Input:
- analysis (obj): Object reference of analysis.
- analysis_block (obj): Object reference of the analysis-block of which results are to be plotted.
- case (str): Specifying the case or scope to be collected. Optional parameter, should be provided for LTH and
NLTH: select from 'last timestep' or 'last loadstep'. It should be provided for the eigenvalue analysis result
pictures: select from 'ModeGovX1', 'ModeGovX1-NoRoof', 'ModeGovX2', 'ModeGovX2-NoRoof', 'ModeGovY1',
'ModeGovY1-NoRoof', 'ModeGovY2', 'ModeGovY2-NoRoof', 'ModeGovZ' or 'ModeGovZ-NoRoof'.
These are defined in the viia-result_pictures yaml file. Default value is None.
- eigenfrequencies (list): List with modes and eigenfrequencies. Only used for eigenvalue result pictures
(analysis A3 and A7). Default value is None.
Output:
- Returns a tuple of two items. The first item is the step or a tuple with mode and eigenfrequency.
The second item is the execute block to be used for the result picture.
"""
def find_max_secmax_mass_participation(case_input: str, eigen_inputs: Dict[int, List[float]]) -> Tuple[int, float]:
"""Function to retrieve the frequencies and modes of the largest and second-largest effective mass."""
# Collect specific modes
max_mode_1 = 0
max_mode_2 = 0
eigenfrequency_1 = 1
eigenfrequency_2 = 1
mode_nr_dom_1 = 0
mode_nr_dom_2 = 0
if 'modegovx' in case_input:
direction_index = 1
elif 'modegovy' in case_input:
direction_index = 2
elif 'modegovz' in case_input:
for mode_nr in eigen_inputs:
if eigen_inputs[mode_nr][3] > max_mode_1 and mode_nr <= 10:
max_mode_1 = eigen_inputs[mode_nr][3]
eigenfrequency_1 = eigen_inputs[mode_nr][0]
mode_nr_dom_1 = int(mode_nr)
return mode_nr_dom_1, eigenfrequency_1
else:
mode_nr = int(case_input.split('-NoRoof')[0].split('Mode')[-1])
eigenfrequency = eigen_inputs[mode_nr][0]
return mode_nr, eigenfrequency
for mode_nr in eigen_inputs:
if eigen_inputs[mode_nr][direction_index] > max_mode_1:
max_mode_2 = max_mode_1
eigenfrequency_2 = eigenfrequency_1
mode_nr_dom_2 = mode_nr_dom_1
max_mode_1 = eigen_inputs[mode_nr][direction_index]
eigenfrequency_1 = eigen_inputs[mode_nr][0]
mode_nr_dom_1 = int(mode_nr)
elif eigen_inputs[mode_nr][direction_index] > max_mode_2:
max_mode_2 = eigen_inputs[mode_nr][direction_index]
eigenfrequency_2 = eigen_inputs[mode_nr][0]
mode_nr_dom_2 = int(mode_nr)
if 'govx1' in case_input or 'govy1' in case_input:
return mode_nr_dom_1, eigenfrequency_1
elif 'govx2' in case_input or 'govy2' in case_input:
return mode_nr_dom_2, eigenfrequency_2
# Eigenvalue analysis
if 'A3 -' in analysis.name or 'A7 -' in analysis.name:
# Check input for case
if case is None or not isinstance(case, str):
raise ValueError(
"ERROR: Please provide the case for the result-picture for the eigenvalue result pictures.")
case = case.lower()
# Check the presence of eigenfrequencies
if not eigenfrequencies:
raise ValueError(
"ERROR: Please provide the eigenfrequencies for the collecting the result pictures for the eigenvalue "
"analysis. This should be done with reading the out-file before running this function.")
mode, frequency = find_max_secmax_mass_participation(case_input=case, eigen_inputs=eigenfrequencies)
return (mode, frequency), analysis_block.execute
# Nonlinear static analysis
elif 'A10 -' in analysis.name or 'A13 -' in analysis.name:
# Get the last loadstep in ExecuteLoadStepsNonlinear block
start_execute_blocks = [block for block in analysis_block.execute_blocks
if isinstance(block, SpecifiedExecuteNonlinear) and isinstance(block.steps, StartSteps)]
load_execute_blocks = [
block for block in analysis_block.execute_blocks
if isinstance(block, SpecifiedExecuteNonlinear) and isinstance(block.steps, LoadSteps)]
if len(load_execute_blocks) != 1:
raise ValueError(
"ERROR: The execute block with loadsteps could not be retrieved. Please check the analysis object.")
if len(start_execute_blocks) == 0:
raise ValueError(
"ERROR: The execute block with startsteps could not be retrieved. Please check the analysis object.")
# Add the number of start steps to load step in Nonlinear static analysis
last_step = start_execute_blocks[-1].steps.total_nr_of_steps + load_execute_blocks[0].steps.total_nr_of_steps
return (last_step, '1.0000'), load_execute_blocks[0]
# Linear and nonlinear time-history analysis
elif 'A4 -' in analysis.name or 'A12 -' in analysis.name or 'A15 -' in analysis.name:
# Check input for case
if case is None or not isinstance(case, str):
raise ValueError(
"ERROR: Please provide the case for the result-picture for the result pictures for the NLTH.")
case = case.lower()
# Check for any start steps
startstep_execute_blocks = [
block for block in analysis_block.execute_blocks
if isinstance(block, SpecifiedExecuteNonlinear) and isinstance(block.steps, StartSteps)]
if len(startstep_execute_blocks) > 1:
raise ValueError(
"ERROR: The execute block has multiple startsteps, this was not expected. "
"Please check the analysis object.")
start_steps = 0
for startstep_block in startstep_execute_blocks:
start_steps += startstep_block.steps.total_nr_of_steps
# Get the last timestep in ExecuteTimeStepsNonlinear block
if case == 'last timestep':
times_execute_blocks = [
block for block in analysis_block.execute_blocks
if isinstance(block, SpecifiedExecuteNonlinear) and isinstance(block.steps, TimeSteps)]
if len(times_execute_blocks) != 1:
raise ValueError(
"ERROR: The execute block with time-steps could not be retrieved. Please check the analysis "
"object.")
last_step = times_execute_blocks[0].steps.total_nr_of_steps
return last_step + start_steps, times_execute_blocks[0]
# Get the last loadstep in ExecuteLoadStepsNonlinear block
elif case == 'last loadstep':
load_execute_blocks = [
block for block in analysis_block.execute_blocks
if isinstance(block, SpecifiedExecuteNonlinear) and isinstance(block.steps, LoadSteps)]
if len(load_execute_blocks) != 1:
raise ValueError(
"ERROR: The execute block with loadsteps could not be retrieved. Please check the analysis object.")
last_step = load_execute_blocks[0].steps.total_nr_of_steps
return last_step + start_steps, load_execute_blocks[0]
# Other cases have not yet been implemented
raise NotImplementedError(f"ERROR: The case {case} is not available for NLTH analysis.")
# Other analysis have not yet been implemented
raise NotImplementedError(
f"ERROR: Result pictures for analysis {analysis.name.split(' - ')[0]} is not yet available.")
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================