Source code for viiapackage.analyses.analysis_nl_static

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