### ===================================================================================================================
### 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
### ===================================================================================================================