Source code for viiapackage.analyses.analysis_nlth

### ===================================================================================================================
###  Analysis NLTH
### ===================================================================================================================
# Copyright ©VIIA 2024

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

# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, List
import string

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.analyses import Analysis
from rhdhv_fem.materials import Timber, Steel
from rhdhv_fem.shapes import Lines, Surfaces
from rhdhv_fem.connections import BoundarySpring
from rhdhv_fem.abaqus_utils import _fem_generate_abaqus_base_shear_request
from rhdhv_fem.output_items import StatusOutputItem

# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject
from viiapackage.materials import viia_change_damping_explicit
from viiapackage.analyses.helper_functions import viia_find_piles_elements, viia_find_shallow_foundation_elements,\
    viia_find_linear_building_elements, viia_find_building_elements, viia_find_reference_soil_nodes, \
    viia_find_soilcolumn_elements, viia_set_base_node, viia_phased_analysis, viia_check_foundation_type, \
    viia_find_interface_mesh_elements, viia_find_linear_interface_elements, viia_find_wall_reference_nodes, \
    viia_get_time_steps_nlth
from viiapackage.analyses.helper_functions.viia_get_abaqus_output import viia_get_abaqus_output
from viiapackage.viiaSettings import ViiaSettings


### ===================================================================================================================
###   2. Function to create the NLTH analysis in DIANA
### ===================================================================================================================

[docs]def viia_create_analysis_nlth( project: ViiaProject, name: str, iteration_method_requested: str = 'newton-raphson', output_1c: bool = False, acceleration_nodes: Optional[List[int]] = None, nr_time_steps: Optional[int] = None) -> Analysis: """ This function creates the NLTH analysis. It depends on the software set, which will switch between explicit (ABAQUS) and implicit (DIANA) analysis. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - name (str): Name of the analysis to be created. - iteration_method_requested (str): The iteration method selected for the time-steps execute, the default value is 'newton-raphson'. Other options are 'secant' and 'linear-stiffness'. - output_1c (bool): Select to create output-block 1C for additional signal checking. Default value is False. - acceleration_nodes (List): A list of nodes that user specified to collect acceleration. - nr_time_steps (int): Overrule the number of time-steps to be used in the NLTH analysis. Default value None, time-steps are determined based on the length of the signal. Output: - Creates and returns the NLTH analysis object for the requested software with all settings for VIIA. """ # Follow separate procedure for ABAQUS software if project.software == 'abaqus': return viia_create_nlth_abaqus(project=project, name=name) # Check if the mesh is present if not project.collections.meshing: raise ValueError("ERROR: First load the mesh by creating the dat-file in DIANA.") # Select the requested output items shallow_foundation_elements_dict, shallow_foundation_nodes_dict, shallow_foundation_ref_elements, \ shallow_foundation_ref_nodes = viia_find_shallow_foundation_elements(project=project) shallow_foundation_elements = [] shallow_foundation_nodes = [] for key in shallow_foundation_elements_dict: shallow_foundation_elements.extend(shallow_foundation_elements_dict[key]) for key in shallow_foundation_nodes_dict: shallow_foundation_nodes.extend(shallow_foundation_nodes_dict[key]) pile_elements, pile_nodes, _, pile_spring_elem, pile_spring_nodes = viia_find_piles_elements(project=project) building_elements, building_nodes, = viia_find_building_elements(project=project) linear_building_elements_1d, linear_building_nodes_1d, linear_building_elements_2d, linear_building_nodes_2d = \ viia_find_linear_building_elements(project=project) linear_steel_timber_line_shapes = [ shape for shape in project.collections.beams + project.collections.columns if isinstance(shape.material, (Timber, Steel))] interface_elements, interface_nodes = viia_find_interface_mesh_elements(project=project) linear_interface_elements_0d, linear_interface_nodes_0d, linear_interface_elements_1d, linear_interface_nodes_1d, \ linear_interface_elements_2d, linear_interface_nodes_2d = viia_find_linear_interface_elements(project=project) if project.viia_settings.support_type == 'SoilBlock': reference_nodes = viia_find_reference_soil_nodes(project=project)[0] else: reference_nodes = None walls_reference_nodes = viia_find_wall_reference_nodes(project=project) # Collect reinforcements for output building_reinforcements = [shape for shape in project.collections.reinforcements if 'PAAL' not in shape.name] linear_building_reinforcements = [shape for shape in building_reinforcements if shape.material.is_linear] # Collect the pile reinforcements, depending on VIIA naming convention for 'PAAL' in name of reinforcement pile_reinforcements = [] for reinforcement in project.collections.line_reinforcements: if 'PAAL' in reinforcement.name: pile_reinforcements.append(reinforcement.name) if not pile_reinforcements: pile_reinforcements = None soilcolumn_nodes, soilcolumn_nodes_all, soilcolumn_elements = viia_find_soilcolumn_elements(project=project) # If user specifies nodes dictionary if acceleration_nodes: output_3_dict = {'user_defined': acceleration_nodes} else: from viiapackage.results.result_functions.viia_acceleration_graphs import viia_get_accel_graph_mesh_nodes output_3_dict = viia_get_accel_graph_mesh_nodes(project=project, has_foundation_nodes=False) # Unpack all the nodes output_3_nodes = [j for i in output_3_dict.values() for j in i] # Initialise a dictionary with different types of shape selections (nodes / elements / reinforcements) output_elements = { 'nodes': { 'building': building_nodes, 'walls_reference_points': walls_reference_nodes, 'reference_points': reference_nodes, 'building_linear_1d': linear_building_nodes_1d, 'building_linear_2d': linear_building_nodes_2d, 'interface_linear_0d': linear_interface_nodes_0d, 'interface_linear_1d': linear_interface_nodes_1d, 'interface_linear_2d': linear_interface_nodes_2d, 'interface': interface_nodes, 'fos': shallow_foundation_nodes, 'piles': pile_nodes, 'pile_springs': pile_spring_nodes, 'fos_reference': shallow_foundation_ref_nodes, 'indirect_method': shallow_foundation_nodes, 'soilcolumn_nodes': soilcolumn_nodes, 'soilcolumn': 'all', 'none': None, 'all': 'all'}, 'elements': { 'building': 'all', # building_elements, 'building_linear_1d': linear_building_elements_1d, 'building_linear_2d': linear_building_elements_2d, 'interface_linear_0d': linear_interface_elements_0d, 'interface_linear_1d': linear_interface_elements_1d, 'interface_linear_2d': linear_interface_elements_2d, 'interface': interface_elements, 'fos': shallow_foundation_elements, 'piles': pile_elements, 'pile_springs': pile_spring_elem, 'fos_reference': shallow_foundation_ref_elements, 'indirect_method': shallow_foundation_elements, 'soilcolumn': 'all', 'none': None, 'all': 'all'}, 'reinforcements': { 'building': [shape.name for shape in building_reinforcements], 'building_linear': [shape.name for shape in linear_building_reinforcements], 'piles': pile_reinforcements, 'none': None, 'all': 'all'}} # Set the base-node viia_set_base_node(project) # Get phasing # Create list with phasing based on name phases = viia_phased_analysis(project) phase_names = [ [f'Activate building layer {phase.layer.name}', f'Execute block {string.ascii_uppercase[i + 1]}'] for i, phase in enumerate(phases)] # Initialise collections analysis_block_name = 'Structural nonlinear' phase_blocks = [] execute_blocks = [] output_blocks = [] # Create the phase blocks and for each phase one static execute block and list of output blocks per # execute block physical_nonlinear_options = project.create_physical_nonlinear_options() for i in range(0, len(phases)): phase_blocks.append(project.create_phase_block( name=phase_names[i][0], active_shapes=phases[i].shapes, active_connections=phases[i].connections, active_supports=phases[i].support_set, auto_interface=False, auto_boundary=False)) # Add additional last phase block for the complete building i = len(phases) - 1 # Exclude the boundary springs applied in transient part of the analysis active_connections = [ con for con in phases[i].connections if not (isinstance(con, BoundarySpring) and 'StaticRotSupport' in con.name)] phase_blocks.append(project.create_phase_block( name='Complete building', active_shapes=phases[i].shapes, active_supports=phases[i].support_set, active_connections=active_connections + phases[i].tying, auto_interface=False, auto_boundary=False)) for i in range(0, len(phases) + 1): if i == 0: execute_blocks.append(project.create_specified_execute_nonlinear( name=phase_names[i][1], convergence_force=True, convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01, convergence_energy=False, convergence_displacement=False, continue_iteration=False, physical_nonlinear_options=physical_nonlinear_options, line_search=True, steps=project.create_start_steps( initial_stress=None, use_load_previous_phase=False, add_load_combination=project.viia_get(collection='load_combinations', name='DL'), add_load_combination_factor=1, steps=[[0.5, 2]]))) elif i != len(phases): execute_blocks.append(project.create_specified_execute_nonlinear( name=phase_names[i][1], convergence_force=True, convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01, convergence_energy=False, convergence_displacement=False, continue_iteration=False, physical_nonlinear_options=physical_nonlinear_options, line_search=True, steps=project.create_start_steps( initial_stress=None, use_load_previous_phase=True, add_load_combination=None, steps=[[0.5, 2]]))) else: execute_blocks.append(project.create_specified_execute_nonlinear( name=f'Execute block {string.ascii_uppercase[i + 1]}', convergence_force=True, convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01, convergence_energy=False, convergence_displacement=False, continue_iteration=False, physical_nonlinear_options=physical_nonlinear_options, line_search=True, steps=project.create_start_steps( initial_stress=None, use_load_previous_phase=True, add_load_combination=None, steps=[[1.0, 1]]))) # Create the required output blocks per phase location_option = project.create_element_output_item_options(location='integration points') output_blocks.append([]) base_node = project.base_point output_blocks[i].append( project.create_output_block_nonlinear( name='OUTPUT_STATIC-NL', output_items=[ project.create_output_item(output='displacements'), project.create_output_item(output='reaction forces'), project.create_output_item(output='residual forces'), project.create_output_item(output='status', output_type='engineering masonry section'), project.create_output_item( output='strain', output_type='crack width', theoretical_formulation='green-lagrange', operation='principal', options=location_option), project.create_output_item( output='strain', theoretical_formulation='relative displacement', operation='local', options=location_option), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='principal', options=location_option), project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option), project.create_output_item( output='stress', theoretical_formulation='distributed force', operation='local', options=location_option), project.create_output_item( output='stress', theoretical_formulation='distributed moment', operation='local', options=location_option), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option)], steps='All', output_device=None, base_node=base_node, steps_max=False, steps_min=False, output_filename=f'{project.name}_v{project.version}_OUTPUT_STATIC-NL')) # Add tabulated output for result plotting in python if project.viia_settings.python_result_plotting: output_items = [ _output_item for _output_item in output_blocks[i][-1].output_items if not isinstance(_output_item, StatusOutputItem)] output_blocks[i].append(project.create_output_block_nonlinear( name='OUTPUT_STATIC-NL_TB', output_items=output_items, steps='All', output_device='tabulated', base_node=base_node, steps_max=False, steps_min=False, output_filename=f'{project.name}_v{project.version}_OUTPUT_STATIC-NL_TB')) # Create the transient execute block time_steps = viia_get_time_steps_nlth(project=project, nr_time_steps=nr_time_steps) # Check interation method iteration_method = None iteration_method_type = None iteration_method_first_tangent = None max_iteration = None if iteration_method_requested == 'newton-raphson': iteration_method = 'newton-raphson' iteration_method_type = 'regular' iteration_method_first_tangent = 'tangential' max_iteration = 10 elif iteration_method_requested == 'secant': iteration_method = 'secant' iteration_method_type = 'bfgs' iteration_method_first_tangent = 'previous integration' max_iteration = 20 elif iteration_method_requested == 'linear stiffness': iteration_method = 'linear stiffness' max_iteration = 20 execute_block_transient = project.create_specified_execute_nonlinear( name=f'Execute block {string.ascii_uppercase[i + 2]}', physical_nonlinear_options=physical_nonlinear_options, line_search=True, maximum_number_iterations=max_iteration, iteration_method=iteration_method, iteration_method_type=iteration_method_type, iteration_method_first_tangent=iteration_method_first_tangent, convergence_energy=True, convergence_energy_tolerance=0.0001, convergence_energy_abort=1.0E+17, convergence_displacement=False, convergence_force=False, continue_iteration=False, steps=project.create_time_steps(steps=time_steps)) # Check if shallow foundation is present and if piles are present fos, pile = viia_check_foundation_type(project=project) # Create the transient output blocks output_blocks_transient = list() # Set up the general arguments for output base_node = project.base_point relative_to_base_option = project.create_node_output_item_options(relative_to_base=True) location_option_int_pts = project.create_element_output_item_options(location='integration points') location_option_nodes = project.create_element_output_item_options(location='nodes') # Change output-item for fixed base analysis output_item_fixedbase = None if project.viia_settings.support_type == 'FixedBase': output_item_fixedbase = [project.create_output_item('reaction forces')] # Create output-items for native DIANA output 1A and 1B output_items_dnb = [ project.create_output_item( output='displacements'), project.create_output_item( output='displacements', options=relative_to_base_option), project.create_output_item( output='strain', output_type='crack width', theoretical_formulation='green-lagrange', operation='principal', options=location_option_int_pts), project.create_output_item( output='strain', output_type='total', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='principal', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts), project.create_output_item( output='stress', output_type='total', theoretical_formulation='concentrated force', operation='local', options=location_option_nodes), project.create_output_item( output='stress', output_type='total', theoretical_formulation='distributed force', operation='local', options=location_option_int_pts), project.create_output_item( output='reaction forces'), project.create_output_item( output='residual forces'), project.create_output_item(output='status', output_type='engineering masonry section') ] if linear_steel_timber_line_shapes: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='local', options=location_option_int_pts)]) if building_reinforcements: if any([isinstance(shape, Lines) for shape in building_reinforcements]): if not linear_steel_timber_line_shapes: # Prevent duplicate if line shapes and reinforcements present output_items_dnb.append( project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts)) output_items_dnb.append( project.create_output_item( output='strain', theoretical_formulation='green-lagrange', operation='von mises', options=location_option_int_pts)) if any([isinstance(shape, Surfaces) for shape in building_reinforcements]): if not linear_steel_timber_line_shapes: # Prevent duplicate if line shapes and reinforcements present output_items_dnb.append( project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts)) output_items_dnb.append( project.create_output_item( output='strain', theoretical_formulation='green-lagrange', operation='local', options=location_option_int_pts)) # Tabulated output only when user selects result handling in python output_items_tb = [] if project.viia_settings.python_result_plotting: # Create output_items for tabulated output 1A and 1B output_items_tb = [ project.create_output_item( output='displacements', options=relative_to_base_option), project.create_output_item( output='strain', output_type='total', theoretical_formulation='relative displacement', operation='local', options=location_option_nodes), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='principal', options=location_option_nodes), project.create_output_item( output='stress', output_type='total', theoretical_formulation='distributed force', operation='local', options=location_option_nodes) ] # Output-block 1A MAX containing output items at integration points for DIANA native output_name = 'OUTPUT_1A_MAX' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_items_dnb, output_filename=output_filename, base_node=base_node, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=True, steps_min=False, manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=output_elements['reinforcements']['building'])) # Tabulated output only when user selects result handling in python if project.viia_settings.python_result_plotting: # Output-block 1A MAX containing output items at integration points for result handling in python output_blocks_transient.append(project.create_output_block_nonlinear( name=f'{output_name}_TB', output_items=output_items_tb, steps=ViiaSettings.output_steps(output_name=f'{output_name}_TB', nr_steps=time_steps[0][1]), output_device='tabulated', base_node=base_node, steps_max=True, steps_min=False, output_filename=f'{output_filename}_TB', manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=output_elements['reinforcements']['building'])) # Output-block 1B MIN containing output items at integration points for DIANA native output_name = 'OUTPUT_1B_MIN' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_items_dnb, output_filename=output_filename, base_node=base_node, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=True, manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=output_elements['reinforcements']['building'])) # Tabulated output only when user selects result handling in python if project.viia_settings.python_result_plotting: # Output-block 1B MAX containing output items at integration points for result handling in python output_blocks_transient.append(project.create_output_block_nonlinear( name=f'{output_name}_TB', output_items=output_items_tb, steps=ViiaSettings.output_steps(output_name=f'{output_name}_TB', nr_steps=time_steps[0][1]), output_device='tabulated', base_node=base_node, steps_max=True, steps_min=False, output_filename=f'{output_filename}_TB', manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=output_elements['reinforcements']['building'])) # If requested by user the output 1C is added if output_1c: # Create output-items for native DIANA output 1C output_items_1c_dnb = [ project.create_output_item( output='displacements'), project.create_output_item( output='displacements', options=relative_to_base_option), project.create_output_item( output='strain', output_type='crack width', theoretical_formulation='green-lagrange', operation='principal', options=location_option_int_pts), project.create_output_item( output='strain', output_type='total', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='principal', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts), project.create_output_item( output='reaction forces'), project.create_output_item( output='residual forces'), project.create_output_item( output='status', output_type='engineering masonry section'), project.create_output_item( output='nodal element force', output_type='element', theoretical_formulation='translation', operation='global')] output_name = 'OUTPUT_1C' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_items_1c_dnb, output_filename=output_filename, base_node=base_node, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name), steps_max=True, steps_min=True, manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=output_elements['reinforcements']['building'])) output_name = 'OUTPUT_2' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=[ project.create_output_item('displacements', component='x'), project.create_output_item('displacements', component='y'), project.create_output_item('displacements', component='z')], output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name), steps_max=False, steps_min=False, manual_nodes=output_elements['nodes']['walls_reference_points'], manual_elements=None, manual_reinforcements=None)) # Output for the generation of the acceleration graphs for different mesh-nodes on foundation and building output_name = 'OUTPUT_3' output_filename = f'{project.name}_v{project.version}_{output_name}' output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=[project.create_output_item('displacements')], output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=output_3_nodes, manual_elements=None, manual_reinforcements=None)) # Output for the linear elements output_name = 'OUTPUT_4' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_items_dnb = [] # output items for DIANA native output output_items_tb = [] # output items for tabulated output # Line-shapes with linear materials if not output_elements['elements']['building_linear_1d']: project.write_log( "INFO: No beams or columns are present in the model. Hence, the results 'Cross-Section Moments' and " "'Cross-Section Forces' will not be output in OUTPUT_4.") else: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='concentrated force', operation='local', options=location_option_nodes), project.create_output_item( output='stress', theoretical_formulation='concentrated moment', operation='local', options=location_option_nodes)]) output_items_tb.extend([ project.create_output_item( output='stress', theoretical_formulation='concentrated force', operation='local', options=location_option_nodes), project.create_output_item( output='stress', theoretical_formulation='concentrated moment', operation='local', options=location_option_nodes)]) if linear_steel_timber_line_shapes: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='local', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts)]) # Surface shapes with linear materials if not output_elements['elements']['building_linear_2d']: project.write_log( "INFO: No roofs and floors are present in the model. Hence, the results 'Distributed Moments' and " "'Distributed Forces' will not be output in OUTPUT_4.") else: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='distributed force', operation='local', options=location_option_int_pts), project.create_output_item( output='stress', theoretical_formulation='distributed moment', operation='local', options=location_option_int_pts)]) output_items_tb.extend([ project.create_output_item( output='stress', theoretical_formulation='distributed force', operation='local', options=location_option_nodes), project.create_output_item( output='stress', theoretical_formulation='distributed moment', operation='local', options=location_option_nodes)]) interface_elements = ( output_elements['elements']['interface_linear_0d'] + output_elements['elements']['interface_linear_1d'] + output_elements['elements']['interface_linear_2d']) interface_nodes = ( output_elements['nodes']['interface_linear_0d'] + output_elements['nodes']['interface_linear_1d'] + output_elements['nodes']['interface_linear_2d']) # Add interface elements if interface_elements: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts), project.create_output_item( output='strain', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts)]) output_items_tb.extend([ project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_nodes), project.create_output_item( output='strain', theoretical_formulation='relative displacement', operation='local', options=location_option_nodes)]) manual_nodes = ( output_elements['nodes']['building_linear_1d'] + output_elements['nodes']['building_linear_2d'] + interface_nodes) if not manual_nodes: manual_nodes = None manual_elements = ( output_elements['elements']['building_linear_1d'] + output_elements['elements']['building_linear_2d'] + interface_elements) if not manual_elements: manual_elements = None if linear_building_reinforcements: if not linear_steel_timber_line_shapes and \ any([isinstance(shape, Lines) for shape in linear_building_reinforcements]): output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts)]) output_items_tb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_int_pts)]) if any([isinstance(shape, Surfaces) for shape in linear_building_reinforcements]): if not linear_steel_timber_line_shapes: output_items_dnb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='local', options=location_option_int_pts)]) output_items_tb.append( project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='local', options=location_option_int_pts)) output_items_tb.append( project.create_output_item( output='strain', theoretical_formulation='green-lagrange', operation='local', options=location_option_int_pts)) # Add the DIANA native output for linear elements if present if output_items_dnb: output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_items_dnb, output_filename=output_filename, base_node=None, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=True, steps_min=True, manual_nodes=manual_nodes, manual_elements=manual_elements, manual_reinforcements=output_elements['reinforcements']['building_linear'])) # Tabulated output for plots from python calculated at integration points if output_items_tb: if project.viia_settings.python_result_plotting: output_blocks_transient.append(project.create_output_block_nonlinear( name=f'{output_name}_TB_INT', output_items=output_items_tb, output_filename=f'{output_filename}_TB', base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=f'{output_name}_TB_INT', nr_steps=time_steps[0][1]), steps_max=True, steps_min=True, manual_nodes=manual_nodes, manual_elements=manual_elements, manual_reinforcements=output_elements['reinforcements']['building_linear'])) # Tabulated output for plots from python calculated at nodes output_items_tb.extend([ project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='local', options=location_option_nodes), project.create_output_item( output='stress', theoretical_formulation='cauchy', operation='von mises', options=location_option_nodes), project.create_output_item( output='strain', theoretical_formulation='green-lagrange', operation='local', options=location_option_nodes)]) output_blocks_transient.append(project.create_output_block_nonlinear( name=f'{output_name}_TB', output_items=output_items_tb, output_filename=f'{output_filename}_TB', base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=f'{output_name}_TB', nr_steps=time_steps[0][1]), steps_max=True, steps_min=True, manual_nodes=manual_nodes, manual_elements=manual_elements, manual_reinforcements=output_elements['reinforcements']['building_linear'])) output_name = 'OUTPUT_4B' # output for interface table if interface_elements: output_items = [] output_items.extend([project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts)]) output_items.extend([project.create_output_item( output='strain', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts)]) output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_items, output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=interface_nodes, manual_elements=interface_elements, manual_reinforcements=None)) if fos: output_name = 'OUTPUT_5A' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_item = [project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts)] if output_item_fixedbase is not None: output_item = output_item_fixedbase output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=output_elements['nodes']['fos'], manual_elements=output_elements['elements']['fos'], manual_reinforcements=None)) if pile: output_name = 'OUTPUT_5B' output_filename = project.name + '_v' + str(project.version) + '_' + output_name if output_elements['nodes']['pile_springs'] and output_elements['elements']['pile_springs']: # Flexbase analysis pile_nodes = output_elements['nodes']['pile_springs'] pile_elements = output_elements['elements']['pile_springs'] elif not output_elements['nodes']['pile_springs'] and not output_elements['elements']['pile_springs']: # Fixedbase analysis pile_nodes = output_elements['nodes']['piles'] pile_elements = output_elements['elements']['piles'] else: raise ValueError("ERROR: Unexpected combination, please check with automation team.") output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=[ project.create_output_item( output='displacements', output_type='total', theoretical_formulation='translation', operation='global')], output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=pile_nodes, manual_elements=pile_elements, manual_reinforcements=None)) output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=[ project.create_output_item( output='nodal element force', output_type='total', theoretical_formulation='translation', operation='global')], output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=pile_nodes, manual_elements=pile_elements, manual_reinforcements=None)) # From here to OUTPUT_GEO_REF we are not changing the output item output_name = 'OUTPUT_GEO1' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_item = [project.create_output_item('stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts), project.create_output_item('strain', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts)] if output_item_fixedbase is not None: output_item = output_item_fixedbase output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=True, steps_min=False, manual_nodes=output_elements['nodes']['fos'], manual_elements=output_elements['elements']['fos'], manual_reinforcements=None)) output_name = 'OUTPUT_GEO2' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=True, manual_nodes=output_elements['nodes']['fos'], manual_elements=output_elements['elements']['fos'], manual_reinforcements=None)) output_name = 'OUTPUT_GEO3' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=output_elements['nodes']['fos'], manual_elements=output_elements['elements']['fos'], manual_reinforcements=None)) output_name = 'OUTPUT_GEO_REF' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=output_elements['nodes']['fos_reference'], manual_elements=output_elements['elements']['fos_reference'], manual_reinforcements=None)) output_name = 'OUTPUT_MOVIE' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=[project.create_output_item(output='displacements', options=relative_to_base_option)], output_filename=output_filename, base_node=base_node, output_device=None, steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=False, steps_min=False, manual_nodes=output_elements['nodes']['building'], manual_elements=output_elements['elements']['building'], manual_reinforcements=None)) if not output_elements['elements']['interface']: project.write_log( message="No interface elements found, OUTPUT_INTERFACE will not be made.", print_message=False) else: output_name = 'OUTPUT_INTERFACE' output_filename = project.name + '_v' + str(project.version) + '_' + output_name output_item = [ project.create_output_item( output='stress', theoretical_formulation='traction', operation='local', options=location_option_int_pts), project.create_output_item( output='strain', output_type='total', theoretical_formulation='relative displacement', operation='local', options=location_option_int_pts)] output_blocks_transient.append(project.create_output_block_nonlinear( name=output_name, output_items=output_item, output_filename=output_filename, base_node=None, output_device='tabulated', steps=ViiaSettings.output_steps(output_name=output_name, nr_steps=time_steps[0][1]), steps_max=True, steps_min=True, manual_nodes=None, manual_elements=output_elements['elements']['interface'], manual_reinforcements=None)) # Collect the analysis blocks analysis_blocks = [] # Set up the evaluation model evaluation_model = project.create_specified_evaluate_model_settings() # Set up the nonlinear settings physical_nonlinearity = project.create_specified_physical_nonlinearity() geometrical_nonlinearity = project.create_specified_geometrical_nonlinearity( geometrical_nonlinearity_type='Total Lagrange') mass_matrix_setting = project.create_mass_matrix_settings() damping_matrix_setting = project.create_damping_matrix_settings( use_current_stiffness_matrix_for_rayleigh_damping=False) dynamic_effect = project.create_dynamic_effects(mass_matrix_settings=mass_matrix_setting, damping_matrix_settings=damping_matrix_setting) transient_effects = project.create_specified_transient_effects( time_integration_type='Newmark', dynamic_effects=dynamic_effect) nonlinear_settings = project.create_specified_nonlinear_settings( physical_nonlinearity=physical_nonlinearity, geometrical_nonlinearity=geometrical_nonlinearity, transient_effects=transient_effects, linearisation=False, recomputation=False) for i in range(0, len(phases)+1): if i != len(phases): analysis_blocks.append(project.create_nonlinear_analysis_block( execute_blocks=[execute_blocks[i]], output_blocks=output_blocks[i], nonlinear_settings=nonlinear_settings, name=analysis_block_name + ' ' + str(i+1), evaluate_model=evaluation_model)) else: analysis_blocks.append(project.create_nonlinear_analysis_block( execute_blocks=[execute_blocks[i], execute_block_transient], output_blocks=output_blocks_transient, nonlinear_settings=nonlinear_settings, name=analysis_block_name + ' ' + str(i+1), evaluate_model=evaluation_model)) # Create the list in order of execution block_order = [] for i in range(0, len(phases) + 1): block_order.append(phase_blocks[i]) block_order.append(analysis_blocks[i]) # Creation of the analysis object return project.create_analysis(name=name, calculation_blocks=block_order)
### =================================================================================================================== ### 3. Function to create the NLTH analysis in ABAQUS ### ===================================================================================================================
[docs]def viia_create_nlth_abaqus(project: ViiaProject, name: str): """ This function creates the NLTH analysis for ABAQUS. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - name (str): Name of the analysis to be created. Output: - Creates and returns the NLTH analysis object for ABAQUS software with all settings for VIIA. """ viia_change_damping_explicit(project=project) output_item_dict = viia_get_abaqus_output(project=project) analyses_to_remove = [] for analysis in project.collections.analyses: if analysis.name in [ 'A12 - Niet-lineair seismische analyse met flexbase', 'A15 - Niet-lineair seismische analyse met flexbase met versterkingen']: analyses_to_remove.append(analysis) for analysis in range(len(analyses_to_remove), -1): analyses_to_remove[analysis].remove_analysis() self_weight = project.create_specified_execute_nonlinear_time_steps_explicit( name='Structural nonlinear 1', time_period=1, explicit_time_increment=project.create_fixed_explicit_time_increment(increment_size=5E-6), mass_scaling=project.create_specified_mass_scaling( mass_scaling_definitions=[project.create_semi_automatic_mass_scaling_definition()]), linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2, adiabatic_heat_effects=False) # Check time period for the signal time_period = None for load_combination in project.collections.load_combinations: if 'Earthquake X' in load_combination.name or 'Earthquake Y' in load_combination.name or \ 'Earthquake Z' in load_combination.name or 'Base motion X' in load_combination.name or \ 'Base motion Y' in load_combination.name or 'Base motion Z' in load_combination.name: time_period = load_combination.time_dependent_load_factors.time_series[-1] break nlth = project.create_specified_execute_nonlinear_time_steps_explicit( name='Structural nonlinear 2', time_period=time_period, explicit_time_increment=project.create_fixed_explicit_time_increment(increment_size=5E-6), mass_scaling=project.create_previous_step_mass_scaling(), linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2, adiabatic_heat_effects=False) # read output_item_dict to get different field outputs for A12 field_output_blocks = [] for field_output_name in output_item_dict['A12'].keys(): if 'field-' in field_output_name: field_name = field_output_name.split('-')[-1] if field_name == 'all': components = 'all' elif field_name == '1d': components = project.collections.beams + project.collections.columns + project.collections.lintels elif field_name == 'wall': components = project.collections.walls elif field_name == 'floor': components = project.collections.floors + project.collections.roofs elif field_name == 'connectors': components = 'OUTPUT-CONNECTORS' elif field_name == 'NFORC': # This is for the geo-output components_temp = [] foundation_shapes = [] if project.collections.fstrips is not None: foundation_shapes.extend(project.collections.fstrips) if project.collections.piles is not None: foundation_shapes.extend(project.collections.piles) for foundation_shape in foundation_shapes: for shape in foundation_shape.get_connecting_shapes(): components_temp.append(shape) components = list(dict.fromkeys(components_temp)) else: continue field_output_items = [] for output_item in output_item_dict['A12'][field_output_name]: field_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) field = project.create_output_block_nonlinear( name=f'OUTPUT_NONLINEAR_{field_name.upper()}', output_items=field_output_items, components=components, steps=0.02) field_output_blocks.append(field) envelop_max_output_items = [] for output_item in output_item_dict['A12']['max-relative-envelope']: envelop_max_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) env_1 = project.create_output_block_nonlinear( name='MAX_RELATIVE_ENVELOPE_OUTPUT_NONLINEAR', output_items=envelop_max_output_items, output_device='envelope', steps_max=True, base_node=project.collections.shape_nodes[0].id) envelop_max_output_items = [] for output_item in output_item_dict['A12']['max-envelope']: envelop_max_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) env_2 = project.create_output_block_nonlinear( name='MAX_ENVELOPE_OUTPUT_NONLINEAR', output_items=envelop_max_output_items, output_device='envelope', steps_max=True) envelop_abs_output_items = [] for output_item in output_item_dict['A12']['abs-envelope']: envelop_abs_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) env_3 = project.create_output_block_nonlinear( name='ABS_ENVELOPE_OUTPUT_NONLINEAR', output_items=envelop_abs_output_items, output_device='envelope', steps_max=True, steps_min=True) envelop_min_output_items = [] for output_item in output_item_dict['A12']['min-envelope']: envelop_min_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) env_4 = project.create_output_block_nonlinear( name='MIN_ENVELOPE_OUTPUT_NONLINEAR', output_items=envelop_min_output_items, output_device='envelope', steps_min=True) history_output_items = [] for output_item in output_item_dict['A12']['history']: history_output_items.append(project.create_output_item( output=output_item['output'], output_type=output_item['output_type'], theoretical_formulation=output_item['theoretical_formulation'], operation=output_item['operation'])) history = project.create_output_block_nonlinear( name='OUTPUT_NONLINEAR_HISTORY', output_items=history_output_items, output_device='history', steps=0.002) project.abaqus_settings.envelop_results.update({"general_settings": {"applicable_steps": ["NLTH"]}}) project.abaqus_settings.envelop_results.update(_fem_generate_abaqus_base_shear_request(project=project)) return project.create_analysis( name=name, calculation_blocks=[ project.create_nonlinear_analysis_block( name='Structural nonlinear 1', execute_blocks=[self_weight], output_blocks=[history, env_1, env_2, env_3, env_4] + field_output_blocks), project.create_nonlinear_analysis_block(name='Structural nonlinear 2', execute_blocks=[nlth])])
### =================================================================================================================== ### 3. End of script ### ===================================================================================================================