Source code for viiapackage.viiaAnalysis

### =============================================================================================================== ###
###                                                                                                                 ###
###                                                 viiaAnalysis.py                                                 ###
###                                                                                                                 ###
### =============================================================================================================== ###
# The module ``viiaAnalysis`` contains the functions to prepare the model for analysis.
# The default analysis configurations can be loaded, and procedures for collecting specific requested output items.

# VIIA_QE_R376 Basis of Design Retrofit Advice NLTH, v11.0, d.d. 29 August 2024
# VIIA_QE_R376 Basis of Design Step-by-Step MRS, v1.0, d.d. 21 January 2022
# VIIA_QE_R1674 Uitgangspuntenrapport engineering NLPO, v1.0, d.d. 1 August 2019

# This script was based upon the Constitution For Python At VIIA
# For use by VIIA
# Copyright RHDHV

### ===================================================================================================================
###    Contents
### ===================================================================================================================

#  1. Import modules

#  2. Create dat-file in DIANA and load mesh information

#  3. Create, perform and handle the results of the analysis for VIIA workflow

#  4. Functionality to modify the analysis before performing the analysis for VIIA workflow

#  5. Functionality to convert analysis created for DIANA to analysis for ABAQUS

#  6. Run analysis in DIANA command-box

#  7. End of script

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

# General imports
from __future__ import annotations
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, Optional, Union, List

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.analyses import Analysis
from rhdhv_fem.fem_DIANAutils import fem_run_diana_command_box

# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject
from viiapackage.analyses import viia_create_analysis_a12, viia_create_analysis_a15, viia_analysis_folder, \
    viia_create_analysis_files, viia_run_analysis, viia_mrs_nmodes, viia_get_abaqus_output
from viiapackage.software_specific.DIANA import viia_create_signal_batchfile_diana, viia_create_main_batchfile_diana


### ===================================================================================================================
###   2. Create dat-file in DIANA and load mesh information
### ===================================================================================================================

[docs]def viia_create_datfile(project: ViiaProject, mesh: bool = True, load: bool = True) -> Optional[Path]: """ This function creates a dat-file in the current analysis folder, or if this is not specified in the working directory. It will read the dat-file and collect the mesh information from it to update the model in py-memory. If software is not set to DIANA, nothing will be done. In DIANA the mesh will be regenerated when this function is applied, prior to generating the dat-file. .. warning:: The model should be meshed in DIANA. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - mesh (bool): Select if the model should be meshed first. Default set to 'True'. - load (bool): Select if the dat-file for DIANA should be loaded. This is not required if it was already loaded previously and no changes to the model have been made in the meantime. Default value is True. Output: - A dat-file is written by DIANA. - The path of the dat-file is returned. """ if project.rhdhvDIANA.model_created: # Clear mesh project.rhdhvDIANA.clearMesh() # Determine the name of the dat-file dat_file_name = '' if 'current signal' in project.project_specific['signal'] and \ project.project_specific['signal']['current signal'] is not None: if project.project_specific['signal']['current signal']: # If a signal has been selected dat_file_name = \ f"{project.name}_{project.project_specific['signal']['current signal']}_v{project.version}.dat" else: # If no signal has been selected dat_file_name = f"{project.name}_v{project.version}.dat" # Create the dat-file in the working folder folder = project.workfolder_location.absolute().as_posix() # Creation of the dat-file is performed in the fem-package dat_file_path = project.create_diana_datfile(folder=folder, datfile_name=dat_file_name, mesh=mesh) if dat_file_path: project.diana_settings.latest_dat_file = dat_file_path # Read the dat-file if project.diana_settings.latest_dat_file is not None and load: project.from_diana() # Return the path of the dat-file created return project.diana_settings.latest_dat_file
### =================================================================================================================== ### 3. Create, perform and handle the results of the analysis for VIIA workflow ### ===================================================================================================================
[docs]def viia_analysis( project: ViiaProject, analysis_nr: str, run: bool = False, signals: Optional[Union[List[str], str]] = None, directions: Optional[Union[List[str], str]] = None, nmodes: Optional[int] = None, ac_pivots: Optional[str] = None, combox: str = 'server', iteration_method_requested: str = 'newton-raphson', output_1c: Optional[bool] = False, nr_time_steps: Optional[int] = None, suppress_analysis: Optional[bool] = False, mod_param: Optional[List[List[Union[str, List]]]] = None, save_mode_pictures: Optional[int] = 5, load_datfile: bool = True, geo_output: bool = True): """ This function will create the analysis required, and if selected runs the analysis directly when running in DIANA. In that case the default output items are handled and created in the analysis folder. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - analysis_nr (str): Current analysis referencing the numbers in the viiaStatus. For example 'A1'. - run (bool): Select if the analysis should be performed directly, also result handling will be performed. The default value is set to 'False', indicating that the analysis and result handling is not performed while running the mainscript. - signals (list of str): A list of the signals can be provided for the signals of which the analysis should be prepared. If the default signals need to be applied select 'Default'. The default value of the argument is None, indicating no signals to be applied. Apply random selection of signals for example: ['S1', 'S6'], apply VIIA naming convention for signals (in viiaStatus). - directions (list of str): A list of the directions can be provided for the directions of which the analysis should be prepared. If the default directions need to be applied select 'Default'. The default value of the argument is None, indicating no directions to be applied. Apply random selection of directions for example: ['X_neg', 'Y_neg'], apply VIIA naming convention for directions (in viiaStatus). - nmodes (int): For Eigen value analysis (analysis type 'EIGEN', analysis_nr 'A3' or 'A7') - nmodes refer to the number of mode shapes to get in your analysis. For Modal Response Spectrum analysis (analysis type 'MRS', analysis_nr 'A5') - nmodes refer to the maximum of x- and y- direction mode shape at which cumulative modal participation factor reaches 70%. If eigen value analysis (A3 or A7) results are present in the workfolder then script will search for nmodes automatically (if 70% value is not reached then a warning is printed instead). If eigenvalue analysis are not present in the workfolder then nmodes should be specified manually. - ac_pivots (str): Name of method of obtaining arc-length control pivots or a sequence of node numbers in string format. - combox (str): Set the location where to run the dcf if the calculation is not performed directly. The dcf is by default prepared for running on the server (adding the initialisation of the filos file and input and for flexbase will add the user subroutine dll location). - 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): Default False. If true the 1c output block will be returned. Only applicable for NLTH analysis. - 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. Only applicable for NLTH analysis. - suppress_analysis (bool): If set to True, this will stop the creation of analysis and dcf files and function will return an analysis that can be adjusted. After adjustment, it will be possible to create analysis and write dcf files. - mod_param (List[List[Union(str, List)]]): a list of parameters which will be used to modify analysis object. - save_mode_pictures (int): This refers to number of modes, for which the result items displacement DispXYZ and rotation RotXYZ is plotted for the entire structure. Default value is set to 5 based on the template for Appendix C2. - load_datfile (bool): Select if the dat-file for DIANA should be loaded. This is not required if it was already loaded previously and no changes to the model have been made in the meantime. Default value is True. - geo_output (bool): This allows the user to choose if the geo output needs to be created (only when the analysis and result handling is selected to be executed). Default value is True. Output: - The required analysis is prepared in a specific folder. - If selected the analysis is directly performed and results are handled. """ if project.software == 'abaqus': suppress_analysis = True project.rhdhvABQ.write_input_file = True # Check input argument for analysis_nr (VIIA reference for analysis, for example 'A1') if analysis_nr not in project.diana_settings.analysis_settings: project.write_log(f"ERROR: Analysis not recognised, please check input: {analysis_nr}.") return # Create the required analysis analysis_type = project.diana_settings.analysis_settings[analysis_nr]['type'] # Check if signals are requested, this can be list or string if signals and 'NLTH' in analysis_type: if signals == 'Default': signals = project.diana_settings.analysis_settings[analysis_nr]['signals'] if not isinstance(signals, list): raise ValueError(f"ERROR: Signals not recognised, please check input: {signals}.") # Check if signals are requested, this can be list or string if directions and 'NLPO' in analysis_type: if directions == 'Default': directions = project.diana_settings.analysis_settings[analysis_nr]['directions'] if not isinstance(signals, list): raise ValueError(f"ERROR: Directions not recognised, please check input: {directions}.") # Select if dcf-file should be updated for running in DIANA command box if run: combox = None # Procedure for single analysis if not signals and not directions: # Create required folders viia_analysis_folder(project=project, analysis_nr=analysis_nr) # Mesh Generation project.viia_create_datfile() # Create analysis if analysis_type == 'EIGEN' or analysis_type == 'MRS': # Exception for ABAQUS if project.software == 'abaqus' and not nmodes: project.write_log( "WARNING: Please provide the number of modes when using ABAQUS. Script continues with 100 modes. " "Please update for correct number of modes.") nmodes = 100 if nmodes: # Create the instance of Analysis class analysis_obj = project.viia_create_analysis(analysis_nr=analysis_nr, nmodes=nmodes) # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis_obj, combox_location=combox) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis_obj) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, save_mode_pictures=save_mode_pictures, load_model=False, geo_output=geo_output) else: # Create the instance of Analysis class nmodes = viia_mrs_nmodes(project=project) if nmodes is None: project.write_log( r"WARNING: 70% cumulative modal participation not yet achieved in eigen value " "analysis (A3 or A7), please run eigen value analysis with more modes.") return analysis_obj = project.viia_create_analysis(analysis_nr=analysis_nr, nmodes=nmodes) # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis_obj, combox_location=combox) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis_obj) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, save_mode_pictures=save_mode_pictures, load_model=False) else: # Create the analysis files analysis_obj = project.viia_create_analysis(analysis_nr) # Suppress further proces if the analysis object needs to be updated if suppress_analysis: return analysis_obj # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis_obj, combox_location=combox) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis_obj) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, save_mode_pictures=save_mode_pictures, load_model=False, geo_output=geo_output) # Procedure for multiple analysis (signals and directions) else: # Collecting analyses for batch file collect_analyses = list() folder = None # Create time-stamp time_reference = datetime.now().strftime('%Y%m%d%H%M%S') # Create the analysis for the NLPO if 'NLPO' in analysis_type and directions: from viiapackage.analyses.nlpo_helper_functions import viia_identify_pushover_load_combination # Regular NLPO for direction in directions: # Set the current direction project.project_specific['direction']['current direction'] = direction # Identify the modelled load-combination load_nr, load_type = viia_identify_pushover_load_combination(project=project, direction=direction) project.project_specific['load_combination']['current load_combination'] = load_type # Create required folder folder = viia_analysis_folder( project=project, analysis_nr=analysis_nr, direction=direction, loadtype=load_type, time_reference=time_reference) # Mesh generation dat_file = project.viia_create_datfile() if not dat_file: dat_file = 'DATFILE_NOT_GENERATED.dat' else: dat_file = dat_file.filename + '.dat' # Create the analysis analysis_obj = project.viia_create_analysis( analysis_nr=analysis_nr, direction=direction, loadnr=load_nr, ac_pivots=ac_pivots, modal_pushover_flag=load_type == 'modal') # Collect information for batch-file collect_analyses.append({ 'folder': folder.parent.name, 'subfolder': folder.name, 'analysis_file': f'{analysis_obj.name}_v{str(project.version).zfill(3)}.dcf', 'dat_file': dat_file}) # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis_obj, combox_location=combox) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis_obj) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, save_mode_pictures=save_mode_pictures, load_model=False, geo_output=geo_output) # Create the analysis for the NLTH elif 'NLTH' in analysis_type and signals: analysis_obj = None for i, signal in enumerate(signals): # Check if signal provided is available if signal not in project.project_specific['signal']: project.write_log( f"WARNING: The signal {signal} is not available. Analysis for signal {signal} is not created " f"and/or executed.") continue # Check if base-signal is loaded if signal not in [t.name.split('_')[-1] for t in project.collections.timeseries_combinations]: project.write_log( f"WARNING: The base-motions for {signal} are not loaded in the project. Please add them first. " f"Analysis for signal {signal} is not created and/or executed.") continue # Create required folders folder = viia_analysis_folder( project=project, analysis_nr=analysis_nr, signal=signal, time_reference=time_reference) # Check current signal if project.project_specific['signal']['current signal'] != signal: project.viia_change_signal(new_signal=signal, nr_time_steps=nr_time_steps) # Create dat-file and load mesh if i == 0 and load_datfile: dat_file = project.viia_create_datfile(load=True) else: dat_file = project.viia_create_datfile(load=False) # Create the required analysis if not analysis_obj: analysis_obj = project.viia_create_analysis( analysis_nr=analysis_nr, iteration_method_requested=iteration_method_requested, output_1c=output_1c, nr_time_steps=nr_time_steps) else: analysis_obj.write_dcf_analysis() # Collect information for main batch-file collect_analyses.append({ 'folder': folder.parent.name, 'subfolder': folder.name}) # Create batch file of current signal if project.software == 'diana': viia_create_signal_batchfile_diana( batch_file=folder/'VIIA-SIGNAL-BATCH.bat', dat_file=dat_file.name, dcf_file=dat_file.name.replace('dat', 'dcf'), viia_object_number=project.name, analysis_name=analysis_obj.name) if dat_file: collect_analyses[-1]['analysis_file'] = dat_file.name.replace('dat', 'dcf') collect_analyses[-1]['dat_file'] = dat_file.name # Suppress further process if the analysis object needs to be updated if suppress_analysis: return analysis_obj # Create the analysis files if project.software != 'abaqus' and not mod_param: # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis_obj, combox_location=combox, signal=signal) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis_obj) # Save the dpf-file in the workfolder and close the project in DIANA dpf_file_name = f'{project.name}_v{project.version}.dpf' dpf_file_workfolder = project.workfolder_location / dpf_file_name project.rhdhvDIANA.saveProjectAs(dpf_file_workfolder.as_posix()) project.rhdhvDIANA.closeProject() # Open the dpf-file in the analysis-folder for correct result handling dpf_file = project.current_analysis_folder / dpf_file_name project.rhdhvDIANA.openProject(dpf_file.as_posix()) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, geo_output=geo_output, save_mode_pictures=save_mode_pictures, load_model=False, signal=signal) # Close the dpf-file in the analysis-folder and open the project in workfolder for further # modelling and/or analyses project.rhdhvDIANA.closeProject() project.rhdhvDIANA.openProject(dpf_file_workfolder.as_posix()) elif mod_param: project.viia_modify_analysis( mod_param=mod_param, analysis=analysis_obj, run_analysis=run, combox=combox) if collect_analyses and project.software == 'diana': batch_file = folder.parent / 'VIIA-MAIN-BATCH.bat' viia_create_main_batchfile_diana(batch_file=batch_file, collect_analyses=collect_analyses)
### =================================================================================================================== ### 4. Functionality to modify the analysis before performing the analysis for VIIA workflow ### ===================================================================================================================
[docs]def viia_modify_analysis( project: ViiaProject, mod_param: List[List[str]], analysis: Analysis, run: bool = False, combox: str = 'Server', create_files: bool = True, save_mode_pictures: Optional[int] = None): """ This function will modify the analysis object, create analysis object in DIANA and save model and Analysis files (dat, dpf and dcf-files) in the analysis sub-folder. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - mod_param (list(list)): parameters containing arguments for modifying the analysis object - analysis (obj): Object reference of 'Analysis' class. only work with Analysis object of A10 and A12 analysis. - run_analysis (bool): Bool to define whether to run analysis or not. 'False' by default. - combox (str): string that define whether analysis will be run. set to 'Server' by default. - create_files (bool): Bool to define if dcf, json, dat, and dpf files should be created. By default, set to True. If set to False, then new files will not be created. - save_mode_pictures (int): This refers to number of modes, for which the result items displacement DispXYZ and rotation RotXYZ is plotted for the entire structure. Useful for A3/A7 analysis. Default in this situation is set to None. Output: - The analysis object is modified, is returned and all the relevant files are created in the project workfolder. Examples: .. code-block:: python analysis_A10 = project.viia_analysis(analysis_nr='A10', run=False, suppress_analysis=True) project.viia_modify_analysis(analysis=analysis_A10, mod_param=[ ['Structural nonlinear 4', 'Execute block E', 'equilibrium iteration','maximum number of iterations', 100], ['Structural nonlinear 6', 'OUTPUT_STATIC-NL', 'user selection','nodes', [28,173,990,1783]]]) """ analysis_nr = analysis.name.split(' ')[0] # Correcting keywords in mod_param for item in mod_param: for i, value in enumerate(item): if isinstance(value, str): if 'newton' in value.lower(): item[i] = 'newton-raphson' elif 'stiffness' in value.lower(): item[i] = 'linear stiffness' elif 'constant' in value.lower(): item[i] = 'constant stiffness' # Modifying the analysis object based on supplied parameters if analysis_nr == 'A10' or analysis_nr == 'A13': for item in mod_param: for cal_block in analysis.calculation_blocks: if cal_block.name == item[0]: if 'execute' in item[1].lower(): for ex_block in cal_block.execute_blocks: if ex_block.name == item[1]: if item[2].lower() in ['start steps', 'load steps']: ex_block.steps = item[3] elif 'equilibrium iteration' == item[2].lower(): if 'maximum number of iterations' == item[3].lower(): ex_block.maximum_number_iterations = item[4] elif 'method' == item[3].lower(): ex_block.iteration_method = item[4] elif 'type' == item[3].lower(): ex_block.iteration_method_type = item[4] elif 'first tangent' == item[3].lower(): ex_block.iteration_method_first_tangent = item[4] elif 'line search' == item[3].lower(): ex_block.line_search = item[4] elif 'energy' == item[3].lower(): ex_block.convergence_energy = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_energy_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_energy_abort = item[6] elif 'displacement' == item[3].lower(): ex_block.convergence_displacement = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_displacement_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_displacement_abort = item[6] elif 'force' == item[3].lower(): ex_block.convergence_force = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_force_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_force_abort = item[6] elif 'satisfy all criteria' == item[3].lower(): ex_block.satisfy_all_criteria = item[4] elif 'physic nonlinear options' == item[2].lower(): if 'overrule use of physical phenomena' == item[3].lower(): if 'liquefaction' == item[4].lower(): ex_block.physical_nonlinear_options.liquefaction = item[5] elif 'drained behaviour' == item[4].lower(): ex_block.physical_nonlinear_options.drained_behavior = item[5] elif 'clear displacement and rotation field' == item[4].lower(): ex_block.physical_nonlinear_options.clear_displacement_and_rotations = \ item[5] elif 'suppress superposition' == item[4].lower(): if isinstance(item[5], str): ex_block.physical_nonlinear_options.suppress_superposition = item[6] elif 'output' in item[1].lower(): for out_block in cal_block.output_blocks: if 'OUTPUT_STATIC-NL' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] if analysis_nr == 'A12' or analysis_nr == 'A15': for item in mod_param: for cal_block in analysis.calculation_blocks: if cal_block.name == item[0]: if 'execute' in item[1].lower(): for ex_block in cal_block.execute_blocks: if ex_block.name == item[1]: if 'start steps' == item[2].lower(): ex_block.steps[0] = item[3] elif 'time steps' == item[2].lower(): ex_block.steps[0] = item[3] elif 'equilibrium iteration' == item[2].lower(): if 'maximum number of iterations' == item[3].lower(): ex_block.maximum_number_iterations = item[4] elif 'method' == item[3].lower(): ex_block.iteration_method = item[4] elif 'type' == item[3].lower(): ex_block.iteration_method_type = item[4] elif 'first tangent' == item[3].lower(): ex_block.iteration_method_first_tangent = item[4] elif 'line search' == item[3].lower(): ex_block.line_search = item[4] elif 'energy' == item[3].lower(): ex_block.convergence_energy = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_energy_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_energy_abort = item[6] elif 'displacement' == item[3].lower(): ex_block.convergence_displacement = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_displacement_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_displacement_abort = item[6] elif 'force' == item[3].lower(): ex_block.convergence_force = item[4] if len(item) > 5: if 'convergence tolerance' == item[5].lower(): ex_block.convergence_force_tolerance = item[6] elif 'abort criterion' == item[5].lower(): ex_block.convergence_force_abort = item[6] elif 'satisfy all criteria' == item[3].lower(): ex_block.satisfy_all_criteria = item[4] elif 'physic nonlinear options' == item[2].lower(): if 'overrule use of physical phenomena' == item[3].lower(): if 'liquefaction' == item[4].lower(): ex_block.physical_nonlinear_options.liquefaction = item[5] elif 'drained behaviour' == item[4].lower(): ex_block.physical_nonlinear_options.drained_behavior = item[5] elif 'clear displacement and rotation field' == item[4].lower(): ex_block.physical_nonlinear_options.clear_displacement_and_rotations = \ item[5] elif 'suppress superposition' == item[4].lower(): if isinstance(item[5], str): ex_block.physical_nonlinear_options.suppress_superposition = item[6] elif 'output' in item[1].lower(): for out_block in cal_block.output_blocks: if 'OUTPUT_1A_MAX' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_1B_MIN' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_2' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_3' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_4' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_5A' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_GEO1' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_GEO2' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_GEO3' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] elif 'OUTPUT_GEO_REF' == item[1] == out_block.name: if 'steps' in item[2].lower(): out_block.steps = item[3] elif 'user selection' == item[2].lower(): if 'nodes' == item[3].lower(): out_block.manual_nodes = item[4] elif 'elements' == item[3].lower(): out_block.manual_nodes = item[4] elif 'base node for relative motion' == item[2].lower(): out_block.base_node = item[3] # Deleting extra output blocks (for either A10 or A12) for item in mod_param: if 'OUTPUT' == item[0]: for blocks in analysis.calculation_blocks[-1].output_blocks: if blocks.name == item[1]: analysis.calculation_blocks[-1].output_blocks.remove(blocks) if project.software != 'abaqus': if project.rhdhvDIANA.run_diana and create_files and project.rhdhvDIANA.model_created: # Removing existing analysis from DIANA project.rhdhvDIANA.removeAnalysis(analysis.name) # Adding modified analysis in DIANA analysis.to_diana() # Select if dcf-file should be updated for running in DIANA command box if run: combox = None # Create the analysis files viia_create_analysis_files( project=project, analysis=analysis, combox_location=combox) # Run analysis if requested if run: out_file, runtime = viia_run_analysis(project=project, analysis=analysis) # Handle results of analysis performed project.viia_results( analysis_nr=analysis_nr, out_file=out_file, runtime=runtime, save_mode_pictures=save_mode_pictures, load_model=False)
### =================================================================================================================== ### 5. Functionality to convert analysis created for DIANA to analysis for ABAQUS ### ===================================================================================================================
[docs]def viia_update_analyses_DIANA_to_ABAQUS(project: ViiaProject): """ This function updates the DIANA analysis objects to ABAQUS applicable ones. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. Output: - All present analyses in the project are updated or replaced with analysis specified for explicit analysis in ABAQUS, following VIIA workflow. """ if project.software != 'abaqus': project.write_log( "WARNING: Software is not set to abaqus. To use the functionality to update the analysis for ABAQUS, " "first switch software.") return output_item_dict = viia_get_abaqus_output(project) create_A12 = False create_A15 = False analysis_to_remove = [] for analysis in project.collections.analyses: if analysis.name == 'A1 - Lineair statische analyse': if not analysis.calculation_blocks[0].output_blocks[0].meta_data: analysis.calculation_blocks[0].output_blocks[0].meta_data = { 'diana_analysis': { 'output_items': analysis.calculation_blocks[0].output_blocks[0].output_items}} else: analysis.calculation_blocks[0].output_blocks[0].meta_data['diana_analysis'] = { 'output_items': analysis.calculation_blocks[0].output_blocks[0].output_items} field_output_items = [] for output_item in output_item_dict['A1']['field']: 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'])) analysis.calculation_blocks[0].output_blocks[0].output_items = field_output_items field_connector_output_items = [] for output_item in output_item_dict['A1']['field-connectors']: field_connector_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'])) output_block = project.create_output_block_static( name='OUTPUT_STATIC_CONNECTORS', output_items=field_connector_output_items, components='OUTPUT-CONNECTORS') analysis.calculation_blocks[0].output_blocks.append(output_block) history_output_items = [] for output_item in output_item_dict['A1']['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'])) output_block = project.create_output_block_static( name='OUTPUT_STATIC_HISTORY', output_items=history_output_items, output_device='history') analysis.calculation_blocks[0].output_blocks.append(output_block) project.write_log(f'Analysis {analysis.name} is ready for ABAQUS') elif analysis.name == 'A7 - Eigenwaarde analyse met flex base': if not analysis.calculation_blocks[0].output_blocks[0].meta_data: analysis.calculation_blocks[0].output_blocks[0].meta_data = { 'diana_analysis': { 'output_items': analysis.calculation_blocks[0].output_blocks[0].output_items}} else: analysis.calculation_blocks[0].output_blocks[0].meta_data['diana_analysis'] = { 'output_items': analysis.calculation_blocks[0].output_blocks[0].output_items} field_output_items = [] for output_item in output_item_dict['A7']['field']: 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'])) analysis.calculation_blocks[0].output_blocks[0].output_items = field_output_items field_connector_output_items = [] for output_item in output_item_dict['A7']['field-connectors']: field_connector_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'])) output_block = project.create_output_block_eigenvalue( name='OUTPUT_EIGENVALUE_CONNECTORS', output_items=field_connector_output_items, components='OUTPUT-CONNECTORS') analysis.calculation_blocks[0].output_blocks.append(output_block) project.write_log(f'Analysis {analysis.name} is ready for ABAQUS') elif analysis.name == 'A10 - Niet-lineair statische analyse met flexbase': # Move old objects to meta data if analysis.meta_data is not None: analysis.meta_data['diana_analysis'] = {'calculation_blocks': analysis.calculation_blocks} else: analysis.meta_data = {'diana_analysis': {'calculation_blocks': analysis.calculation_blocks}} mass_scaling = project.create_specified_mass_scaling(mass_scaling_definitions=[ project.create_semi_automatic_mass_scaling_definition()]) 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=mass_scaling, linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2, adiabatic_heat_effects=False) field_output_items = [] for output_item in output_item_dict['A10']['field']: 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='OUTPUT_NONLINEAR', output_items=field_output_items, output_device='field', steps=0.02) field_connector_output_items = [] for output_item in output_item_dict['A10']['field-connectors']: field_connector_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_connector = project.create_output_block_nonlinear( name='OUTPUT_NONLINEAR_CONNECTORS', output_items=field_connector_output_items, output_device='field', components='OUTPUT-CONNECTORS', steps=0.02) history_output_items = [] for output_item in output_item_dict['A10']['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') live_loads = \ 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=mass_scaling, linear_bulk_viscosity=0.06, quadratic_bulk_viscosity=1.2, adiabatic_heat_effects=False) analysis.calculation_blocks = \ [project.create_nonlinear_analysis_block( name='Structural nonlinear 1', execute_blocks=[self_weight], output_blocks=[field, field_connector, history]), project.create_nonlinear_analysis_block( name='Structural nonlinear 2', execute_blocks=[live_loads])] project.write_log(f"Analysis {analysis.name} is ready for ABAQUS.") elif analysis.name == 'A12 - Niet-lineair seismische analyse met flexbase': analysis_to_remove.append(analysis) create_A12 = True elif analysis.name == 'A15 - Niet-lineair seismische analyse met flexbase met versterkingen': analysis_to_remove.append(analysis) create_A15 = True else: project.write_log(f"WARNING: Analysis {analysis.name} is not yet available for ABAQUS.") while len(analysis_to_remove) != 0: analysis_to_remove[-1].remove_analysis() analysis_to_remove.remove(analysis_to_remove[-1]) if create_A12: viia_create_analysis_a12(project=project) if create_A15: viia_create_analysis_a15(project=project)
### =================================================================================================================== ### 6. Run analysis in DIANA command-box ### ===================================================================================================================
[docs]def viia_run_diana_command_box( analysis_folder: Union[str, Path], dat_file_name: Union[str, Path] = None, dcf_file_name: str = None, filos_file_name: Optional[str] = None, out_file_name: Optional[str] = None, version: str = '10.9'): """ Runs an analysis in the command box. If not given the dat-file or dcf-file name, it will try to find them in the analysis folder. Input: - analysis_folder (path): Folder where the analysis should be executed. - dat_file_name (path): Name of the dat file. - dcf_file_name (path): Name of the dcf file. - filos_file_name (str): Name of the filos file. Default value is None. - out_file_name (str): Name of the out file. Default value is None. - version (str): Version of DIANA, default value is version 10.9. Output: - Analysis is executed in the DIANA Command Box. """ # If the file names are not given, looking for the files in the analysis folder # Convert str to Path instance if isinstance(analysis_folder, str): analysis_folder = Path(analysis_folder) # Check dat-file if not dat_file_name: dat_file_name = [f for f in analysis_folder.iterdir() if f.suffix == '.dat'] if not dat_file_name: raise FileNotFoundError( f"ERROR: The dat-file is missing, please put the dat-file in the folder {analysis_folder.as_posix()}.") elif len(dat_file_name) != 1: raise Exception( f"ERROR: There should only be one dat-file in the {analysis_folder.as_posix()}, multiple dat-files are " f"found.") else: dat_file_name = str(dat_file_name[0]) # Check dcf-file if not dcf_file_name: dcf_file_name = [f for f in analysis_folder.iterdir() if f.suffix == '.dcf'] if not dcf_file_name: raise FileNotFoundError( f"ERROR: The dcf-file is missing, please put the dcf-file in the folder {analysis_folder.as_posix()}.") else: dcf_file_name = str(dcf_file_name[0]) # Execute the commands in the com-box fem_run_diana_command_box( analysis_folder=analysis_folder, dat_file_name=dat_file_name, dcf_file_name=dcf_file_name, filos_file_name=filos_file_name, out_file_name=out_file_name, version=version)
### =================================================================================================================== ### 7. End of script ### ===================================================================================================================