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