### ===================================================================================================================
### Analysis non-linear static
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING
import warnings
import string
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.analyses import Analysis
# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
from viiapackage.analyses.helper_functions import viia_find_piles_elements, viia_find_shallow_foundation_elements, \
viia_check_foundation_type, viia_phased_analysis
from viiapackage.materials import viia_change_damping_explicit
### ===================================================================================================================
### 2. Function to create the non-linear static analysis
### ===================================================================================================================
[docs]def viia_create_analysis_nl_static(project: ViiaProject, name: str) -> Analysis:
"""
This function creates the non-linear static analysis for VIIA. 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.
Output:
- Creates and returns the non-linera static analysis object for the requested software with all settings for
VIIA workflow.
"""
# Collect analysis number
analysis_nr = name.split(' - ')[-1]
# Validate requirements for non-linear static analysis
# Check for flex-base support condition
if project.viia_settings.support_type not in ['FlexBaseGlobal', 'FlexBaseFinal']:
raise ValueError(
f"ERROR: The {analysis_nr} analysis requires flexbase supports. The model support-type is currently set "
f"to {project.viia_settings.support_type}.")
# Check if imposed loads are present in the model and the load-combination for variable loads
if 'VAR' not in [load_combination.name for load_combination in project.collections.load_combinations]:
warnings.warn(
f"WARNING: The {analysis_nr} analysis requires imposed loads. The model does not contain any "
f"load-combination complying to the naming convention for imposed loads (VAR). The load-combination "
f"present in the model are: "
f"{', '.join([load_combination.name for load_combination in project.collections.load_combinations])}. "
f"When you continue, you might encounter unexpected behaviour or errors in code.")
# Software specific for ABAQUS
if project.software == 'abaqus':
return viia_create_non_linear_static_abaqus(project=project, name=name)
# Create list with phasing based on name
phases = viia_phased_analysis(project=project)
phase_names = []
for i, phase in enumerate(phases):
if phase.layer.name == 'F':
phase_names.append(['Activate foundation', f'Execute block {string.ascii_uppercase[i+1]}'])
else:
phase_names.append(
[f'Activate building layer {phase.layer.name}', f'Execute block {string.ascii_uppercase[i+1]}'])
# Create the phase blocks, execute blocks and output blocks
analysis_block_name = 'Structural nonlinear'
phase_blocks = []
execute_blocks = []
output_blocks = []
physical_nonlinear_options = project.create_physical_nonlinear_options()
for i in range(len(phases)):
phase_blocks.append(project.create_phase_block(
name=phase_names[i][0], active_shapes=phases[i].shapes,
active_connections=phases[i].connections + phases[i].tying, active_supports=phases[i].support_set,
auto_interface=False, auto_boundary=False))
if i == 0:
execute_blocks.append(project.create_specified_execute_nonlinear(
name=phase_names[i][1], physical_nonlinear_options=physical_nonlinear_options, line_search=True,
convergence_force=True, convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01,
convergence_energy=False, convergence_displacement=False, maximum_number_iterations=10,
steps=project.create_start_steps(
initial_stress=None, use_load_previous_phase=False, add_load_combination_factor=1,
add_load_combination=project.viia_get('load_combinations', name='DL'), steps=[[0.5, 2]])))
else:
execute_blocks.append(project.create_specified_execute_nonlinear(
name=phase_names[i][1], physical_nonlinear_options=physical_nonlinear_options, line_search=True,
convergence_force=True, convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01,
convergence_energy=False, convergence_displacement=False, maximum_number_iterations=10,
steps=project.create_start_steps(
initial_stress=None, use_load_previous_phase=True, add_load_combination=None, steps=[[0.5, 2]])))
if i == len(phases) - 1 and \
'VAR' in [load_combination.name for load_combination in project.collections.load_combinations]:
execute_blocks.append(project.create_specified_execute_nonlinear(
name=f'Execute block {string.ascii_uppercase[len(phases) + 1]}',
physical_nonlinear_options=physical_nonlinear_options, line_search=True, convergence_force=True,
convergence_force_abort=1.0E+17, convergence_force_tolerance=0.01, convergence_energy=False,
convergence_displacement=False, maximum_number_iterations=20, iteration_method='newton-raphson',
steps=project.create_load_steps(
load_combination=project.viia_get('load_combinations', name='VAR'), steps=[[0.5, 2]])))
# Check if shallow foundation is present and if piles are present
fos, pile = viia_check_foundation_type(project=project)
for i in range(0, len(phases)):
steps = 'ALL'
# Create the required output blocks per phase
location_option = project.create_element_output_item_options(location='integration points')
output_blocks.append([])
output_blocks[i].append(
project.create_output_block_nonlinear(
name='OUTPUT_STATIC-NL', steps=steps, output_device=None, base_node=None, steps_max=False,
steps_min=False, output_filename=f'{project.name}_v{project.version}_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)]))
# Add tabulated output for result plotting in python
if project.viia_settings.python_result_plotting:
output_blocks[i].append(project.create_output_block_nonlinear(
name='OUTPUT_STATIC-NL_TB', output_items=output_blocks[i][-1].output_items,
steps=steps, output_device='tabulated', base_node=None, steps_max=False, steps_min=False,
output_filename=f'{project.name}_v{project.version}_OUTPUT_STATIC-NL_TB'))
# Add output required for shallow foundation geotechnical assessment
if fos:
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])
output_blocks[i].append(
project.create_output_block_nonlinear(
name='OUTPUT_5A', steps=steps, output_device='tabulated', base_node=None, steps_max=False,
steps_min=False, manual_nodes=shallow_foundation_nodes, manual_elements=shallow_foundation_elements,
output_filename=f'{project.name}_v{project.version}_OUTPUT_5A',
output_items=[
project.create_output_item(
output='stress', theoretical_formulation='traction', operation='local',
options=location_option)]))
output_blocks[i].append(
project.create_output_block_nonlinear(
name='OUTPUT_GEO_BASE_SHEAR_TB', steps=steps, output_device='tabulated', base_node=None,
steps_max=False, steps_min=False, manual_nodes=shallow_foundation_nodes,
manual_elements=shallow_foundation_elements,
output_filename=f'{project.name}_v{project.version}_OUTPUT_GEO_BASE_SHEAR_TB',
output_items=[project.create_output_item(output='reaction forces')]))
# Add output required for pile foundation geotechnical assessment
if pile:
_, pile_nodes, pile_reinforcements, pile_spring_elements, _ = viia_find_piles_elements(project=project)
output_blocks[i].append(
project.create_output_block_nonlinear(
name='OUTPUT_5B', steps='All', output_device='tabulated', base_node=None, steps_max=False,
steps_min=False, manual_nodes=pile_nodes, manual_elements=pile_spring_elements,
output_filename=f'{project.name}_v{project.version}_OUTPUT_5B',
output_items=[
project.create_output_item(
output='nodal element force', output_type='total', theoretical_formulation='translation',
operation='global')]))
# Combine the execute blocks and output blocks in the analysis block
analysis_blocks = []
# Set up the nonlinear settings
physical_nonlinearity = project.create_specified_physical_nonlinearity()
geometrical_nonlinearity = project.create_specified_geometrical_nonlinearity(
geometrical_nonlinearity_type='Total Lagrange')
nonlinear_settings = project.create_specified_nonlinear_settings(
physical_nonlinearity=physical_nonlinearity, geometrical_nonlinearity=geometrical_nonlinearity,
transient_effects=None, linearisation=False, recomputation=False)
# Set up the evaluation model
evaluation_model = project.create_specified_evaluate_model_settings()
for i in range(len(phases)):
if i == len(phases) - 1 and \
'VAR' in [load_combination.name for load_combination in project.collections.load_combinations]:
analysis_blocks.append(project.create_nonlinear_analysis_block(
execute_blocks=[execute_blocks[i], execute_blocks[i+1]], output_blocks=output_blocks[i],
nonlinear_settings=nonlinear_settings, name=f'{analysis_block_name} {i + 1}',
evaluate_model=evaluation_model))
else:
analysis_blocks.append(project.create_nonlinear_analysis_block(
execute_blocks=[execute_blocks[i]], output_blocks=output_blocks[i],
nonlinear_settings=nonlinear_settings, name=f'{analysis_block_name} {i + 1}',
evaluate_model=evaluation_model))
# Create the list in order of execution
block_order = []
for i in range(0, len(phases)):
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 non-linear static analysis for ABAQUS
### ===================================================================================================================
[docs]def viia_create_non_linear_static_abaqus(project: ViiaProject, name: str) -> Analysis:
"""
This function creates the non-linear static analysis for explicit calculation (ABAQUS).
Input:
- project (obj): VIIA project object containing collections of fem objects and project variables.
- name (str): Name of the A10 analysis.
Output:
- Creates and returns the A10 analysis object for ABAQUS with all settings for VIIA.
"""
viia_change_damping_explicit(project=project)
mass_scaling = project.create_specified_mass_scaling(mass_scaling_definitions=[
project.create_semi_automatic_mass_scaling_definition()])
location_option = project.create_element_output_item_options(location='integration points')
output_blocks = [
project.create_output_block_nonlinear(
name='OUTPUT_STATIC-NL', steps=0.02, base_node=None, steps_max=False, steps_min=False,
output_filename=f"{project.name}_v{project.version}_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='nodal element force', output_type='element', theoretical_formulation='translation',
operation='global'),
project.create_output_item(output='status', output_type='engineering masonry section'),
project.create_output_item(output='status', output_type='mass scaling factor'),
project.create_output_item(
output='strain', output_type='crack width', theoretical_formulation='green-lagrange',
operation='principal', 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)]),
project.create_output_block_nonlinear(
name='OUTPUT_5A', steps=0.02, base_node=None, steps_max=False, steps_min=False,
output_filename=f'{project.name}_v{project.version}_OUTPUT_5A',
output_items=[project.create_output_item(
output='stress', theoretical_formulation='traction', operation='local', options=location_option)]),
project.create_output_block_nonlinear(
name='OUTPUT_5B', steps=0.02, base_node=None, steps_max=False, steps_min=False,
output_filename=f'{project.name}_v{project.version}_OUTPUT_5B',
output_items=[project.create_output_item(
output='nodal element force', output_type='total', theoretical_formulation='translation',
operation='global')]),
project.create_output_block_nonlinear(
name='OUTPUT_GEO_BASE_SHEAR_TB', steps=0.02, base_node=None, steps_max=False, steps_min=False,
output_filename=f'{project.name}_v{project.version}_OUTPUT_GEO_BASE_SHEAR_TB',
output_items=[project.create_output_item(output='reaction forces')])]
self_weight = project.create_specified_execute_nonlinear_time_steps_explicit(
name='Execute block SW', time_period=1,
explicit_time_increment=project.create_fixed_explicit_time_increment(increment_size=5E-6),
mass_scaling=mass_scaling, linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2,
adiabatic_heat_effects=False)
live_loads = project.create_specified_execute_nonlinear_time_steps_explicit(
name='Execute block LL', time_period=1,
explicit_time_increment=project.create_fixed_explicit_time_increment(increment_size=5E-6),
mass_scaling=mass_scaling, linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2,
adiabatic_heat_effects=False)
return project.create_analysis(
name=name,
calculation_blocks=[
project.create_nonlinear_analysis_block(
name='Structural nonlinear 1', execute_blocks=[self_weight], output_blocks=output_blocks),
project.create_nonlinear_analysis_block(
name='Structural nonlinear 2', execute_blocks=[live_loads], output_blocks=None)])
### ===================================================================================================================
### 4. End of script
### ===================================================================================================================