Source code for viiapackage.results.geo_output.geo_output_nls

### ===================================================================================================================
###   CLASS: GeoOutputNLS
### ===================================================================================================================
# Copyright ©VIIA 2024

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

# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Tuple, List
from collections import namedtuple
from pathlib import Path
import json

# 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.results.geo_output.geo_output import GeoOutput


### ===================================================================================================================
###   2. Class for geo-output (Non-linear static analysis, flexbase)
### ===================================================================================================================

[docs]class GeoOutputNLS(GeoOutput): """ This is a subclass of the GeoOutput class. It contains the methods and attributes specific for A10 analysis non-linear static flexbase analysis geo-output.""" def __init__( self, static_force_step: int, variable_force_step: int, foundation_type: str): """ Input: - static_force_step (int): Step number that should be used to determine the static force. For DIANA and ABAQUS other steps may apply. - variable_force_step (int): Step number that should be used to determine the variable force. For DIANA and ABAQUS other steps may apply. - foundation_type (str): Type of foundation. Should be 'strips', 'mixed' or 'piles'. """ # Initialise the base-class GeoOutput GeoOutput.__init__(self, foundation_type=foundation_type) # Container for pile and shallow foundation forces self.pile_data_lst = [] self.fstrip_data_lst = [] self.static_force_step = static_force_step self.variable_force_step = variable_force_step
[docs] def calculate_force(self, software: str = 'diana') -> Tuple[List[namedtuple], List[namedtuple]]: """ Method of 'GeoOutputNLS' class to calculate the normal forces for each foundation strip or pile.""" # Procedure for the shallow foundation if self.foundation_type in ['strips', 'mixed']: # Collect results fstrips = {strip['object']: strip for strip in self.foundation_elements['fstrips']} Fstrip_data = namedtuple('Fstrip_data', ['fstrip', 'static_force', 'variable_force']) results = {strip.fstrip.name: strip for strip in self.forces_foundation_elements['fstrips']} for fstrip in fstrips: vertical_force_per_step = results[fstrip.name].forces[-1]['z'] # In DIANA dead loads are located in second load step of the last phase and variable force in last load # step. However, in ABAQUS the dead loads is in the first load step and imposed loads is in the last. if software != 'abaqus' and len(vertical_force_per_step) != 4: raise ValueError( f"ERROR: Could not calculate static and variable force. Last phase should contain only 4 " f"load steps! Last phase has {len(vertical_force_per_step)} steps.") static_force_fstrip = vertical_force_per_step[self.static_force_step] variable_force_fstrip = vertical_force_per_step[self.variable_force_step] self.fstrip_data_lst.append(Fstrip_data( fstrip=fstrip.name, static_force=static_force_fstrip, variable_force=variable_force_fstrip)) # Retrieve pile data if self.foundation_type in ['piles', 'mixed']: # Collect results piles = {pile['object']: pile for pile in self.foundation_elements['piles']} Pile_data = namedtuple('Pile_data', ['pile', 'static_force', 'variable_force']) results = {pile.pile.name: pile for pile in self.forces_foundation_elements['piles']} for pile in piles: vertical_force_per_step = results[pile.name].forces[-1]['z'] # In DIANA dead loads are located in second load step of the last phase and variable force in last load # step. However, in ABAQUS the dead loads is in the first load step and imposed loads is in the last. if software != 'abaqus' and len(vertical_force_per_step) != 4: raise ValueError( "ERROR: Could not calculate static and variable force. Last phase should contain only 4 " "load steps!") static_force_pile = vertical_force_per_step[self.static_force_step] variable_force_pile = vertical_force_per_step[self.variable_force_step] self.pile_data_lst.append(Pile_data( pile=pile.name, static_force=static_force_pile, variable_force=variable_force_pile)) return self.pile_data_lst, self.fstrip_data_lst
[docs] def write_json(self, output_dir: Optional[Path] = None) -> Path: """ Method of 'GeoOutputNLS' to write the json-file in the A10 or A13 analysis result folder. A json-file that contains the force data will be created. Input: - output_dir (Path): Path to the A10 or A13 result folder, where the json-file should be saved. Default value is None, storing the json-file in the workfolder. Output: - Creates the json-file containing the information from the GeoOutputLS class. - The path of the generated json-file is returned. """ # At least one of the list should not be empty if not self.pile_data_lst and not self.fstrip_data_lst: raise ValueError("ERROR: There are no forces calculated for the geo-output, please check your results.") # If output directory is not given json_dir = self.project.workfolder_location if not output_dir else output_dir json_name = json_dir / 'geo_output_nls.json' # Convert namedtuple to dictionary to_dump = { 'fstrips': [i._asdict() for i in self.fstrip_data_lst], 'piles': [i._asdict() for i in self.pile_data_lst]} # Write to Json with json_name.open('w') as f: json.dump(to_dump, f, indent=4) # Notification for user self.project.write_log(f"The non-linear static flexbase geo-output has been stored to {json_name.as_posix()}.") return json_name
### =================================================================================================================== ### 3. Functions for geo-output for flexbase non-linear static analysis ### ===================================================================================================================
[docs]def viia_create_geo_output_static_analysis( project: ViiaProject, analysis: Analysis, output_5a: Optional[Path] = None, output_5b: Optional[Path] = None, abaqus_results: Optional[Path] = None, foundation_type: Optional[str] = None, output_dir: Optional[Path] = None) -> Path: """ This function handles the results to collect the geo-output. It processes the tb-file(s) for pile, shallow and mixed foundations and calculates the normal forces per foundation strip or pile for A10 or A13 analysis. All the data is stored in a json-file. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - analysis (obj): Object reference of nonlinear static analysis. - output_5a (Path): The full path of 5a tabulated file for fstrips elements and nodes. Mutually exclusive to abaqus_results. Default is None, shallow foundation is not considered (output_5b is then required). - output_5b (Path): The full path of 5b tabulated file for pile nodes. Mutually exclusive to abaqus_results. Default is None, pile foundation is not considered (output_5a is then required). - abaqus_results (Path): The full path to Abaqus post processed results file. Mutually exclusive to output_5a/output_5b. Default value is None. - foundation_type (str): The foundation type modelled in the model. The allowed values are 'mixed', 'strips' or 'piles'. Default value None, in which case it is derived from the model. - output_dir (Path): The path where the result json-file will be saved. Default value None, the json-file will be saved to the current analysis folder (this is the normal workflow in VIIA). Output: - Generates the json-file with the geo-output from the flexbase non-linear static analysis. - Saves the json-file to the requested folder. - The path of the generated json-file is returned. """ project.write_log("Starting result handling for geo-output ...") # Check the foundation type if foundation_type is None: foundation_type = GeoOutput.check_foundation_type(project) # Specify the steps static_force_step = 1 variable_force_step = 3 if project.software == 'abaqus': static_force_step = 0 variable_force_step = -1 # Initialise helper class for nonlinear static geo-output geo_output_nls = GeoOutputNLS( static_force_step=static_force_step, variable_force_step=variable_force_step, foundation_type=foundation_type) geo_output_nls.project = project # Collect the results from the tb-file(s) geo_output_nls.get_geo_input( tb_file_5a=output_5a, tb_file_5b=output_5b, abaqus_results=abaqus_results, get_displacements=False, analysis=analysis) geo_output_nls.calculate_force(software=project.software) # Write the output json-file output_dir = project.current_analysis_folder if not output_dir else output_dir return geo_output_nls.write_json(output_dir=output_dir)
### =================================================================================================================== ### 4. End of script ### ===================================================================================================================