Source code for opstool.post.responses_data

from typing import Union

import openseespy.opensees as ops
import xarray as xr

from ._get_response import (
    ModelInfoStepData,
    NodalRespStepData,
    TrussRespStepData,
    FrameRespStepData,
    LinkRespStepData,
    FiberSecRespStepData,
    ShellRespStepData,
    PlaneRespStepData,
    BrickRespStepData,
)
from .eigen_data import save_eigen_data
from .model_data import save_model_data
from ..utils import RESULTS_DIR, get_random_color, CONSOLE, PKG_PREFIX


[docs] class CreateODB: """Create an output database (ODB) to save response data. Parameters ------------ odb_tag: Union[int, str], default: 1 Tag of output databases (ODB) to be saved. model_update: bool, default: False Whether to update the model data. .. Note:: If True, the model data will be updated at each step. If no nodes and elements are added or removed during the analysis of your model, keep this parameter set to **`False`**. Enabling model updates unnecessarily can increase memory usage and slow down performance. save_nodal_resp: bool, default: True Whether to save nodal responses. save_frame_resp: bool, default: True Whether to save frame element responses. save_truss_resp: bool, default: True Whether to save truss element responses. save_link_resp: bool, default: True Whether to save link element responses. save_shell_resp: bool, default: True Whether to save shell element responses. save_fiber_sec_resp: bool, default: True Whether to save fiber section responses. save_plane_resp: bool, default: True Whether to save plane element responses. save_brick_resp: bool, default: True Whether to save brick element responses. """ def __init__( self, odb_tag: Union[int, str] = 1, model_update: bool = False, save_nodal_resp: bool = True, save_frame_resp: bool = True, save_truss_resp: bool = True, save_link_resp: bool = True, save_shell_resp: bool = True, save_fiber_sec_resp: bool = True, save_plane_resp: bool = True, save_brick_resp: bool = True, ): self.odb_tag = odb_tag self.model_update = model_update self.save_nodal_resp = save_nodal_resp self.save_frame_resp = save_frame_resp self.save_truss_resp = save_truss_resp self.save_link_resp = save_link_resp self.save_shell_resp = save_shell_resp self.save_fiber_sec_resp = save_fiber_sec_resp self.save_plane_resp = save_plane_resp self.save_brick_resp = save_brick_resp self.ModelInfo = None self.NodalResp = None self.FrameResp = None self.TrussResp = None self.LinkResp = None self.ShellResp = None self.FiberSecResp = None self.PlaneResp = None self.BrickResp = None self.initialize() def initialize(self): self.ModelInfo = ModelInfoStepData(model_update=self.model_update) node_tags = self.ModelInfo.get_current_node_tags() if len(node_tags) > 0 and self.save_nodal_resp: self.NodalResp = NodalRespStepData(node_tags) frame_tags = self.ModelInfo.get_current_frame_tags() frame_load_data = self.ModelInfo.get_current_frame_load_data() if len(frame_tags) > 0 and self.save_frame_resp: self.FrameResp = FrameRespStepData(frame_tags, frame_load_data) truss_tags = self.ModelInfo.get_current_truss_tags() if len(truss_tags) > 0 and self.save_truss_resp: self.TrussResp = TrussRespStepData(truss_tags) link_tags = self.ModelInfo.get_current_link_tags() if len(link_tags) > 0 and self.save_link_resp: self.LinkResp = LinkRespStepData(link_tags) shell_tags = self.ModelInfo.get_current_shell_tags() if len(shell_tags) > 0 and self.save_shell_resp: self.ShellResp = ShellRespStepData(shell_tags) if self.save_fiber_sec_resp: self.FiberSecResp = FiberSecRespStepData() plane_tags = self.ModelInfo.get_current_plane_tags() if len(plane_tags) > 0 and self.save_plane_resp: self.PlaneResp = PlaneRespStepData(plane_tags) brick_tags = self.ModelInfo.get_current_brick_tags() if len(brick_tags) > 0 and self.save_brick_resp: self.BrickResp = BrickRespStepData(brick_tags) def reset(self): if self.ModelInfo is not None: self.ModelInfo.reset() if self.NodalResp is not None: self.NodalResp.reset() if self.FrameResp is not None: self.FrameResp.reset() if self.TrussResp is not None: self.TrussResp.reset() if self.LinkResp is not None: self.LinkResp.reset() if self.ShellResp is not None: self.ShellResp.reset() if self.FiberSecResp is not None: self.FiberSecResp.reset() if self.PlaneResp is not None: self.PlaneResp.reset() if self.BrickResp is not None: self.BrickResp.reset()
[docs] def fetch_response_step(self, print_info: bool = False): """Extract response data for the current moment. Parameters ------------ print_info: bool, optional print information, by default, False """ self.ModelInfo.add_data_one_step() node_tags = self.ModelInfo.get_current_node_tags() if len(node_tags) > 0 and self.save_nodal_resp: self.NodalResp.add_data_one_step(node_tags) frame_tags = self.ModelInfo.get_current_frame_tags() frame_load_data = self.ModelInfo.get_current_frame_load_data() if len(frame_tags) > 0 and self.save_frame_resp: self.FrameResp.add_data_one_step(frame_tags, frame_load_data) truss_tags = self.ModelInfo.get_current_truss_tags() if len(truss_tags) > 0 and self.save_truss_resp: self.TrussResp.add_data_one_step(truss_tags) link_tags = self.ModelInfo.get_current_link_tags() if len(link_tags) > 0 and self.save_link_resp: self.LinkResp.add_data_one_step(link_tags) shell_tags = self.ModelInfo.get_current_shell_tags() if len(shell_tags) > 0 and self.save_shell_resp: self.ShellResp.add_data_one_step(shell_tags) if self.save_fiber_sec_resp: self.FiberSecResp.add_data_one_step() plane_tags = self.ModelInfo.get_current_plane_tags() if len(plane_tags) > 0 and self.save_plane_resp: self.PlaneResp.add_data_one_step(plane_tags) brick_tags = self.ModelInfo.get_current_brick_tags() if len(brick_tags) > 0 and self.save_brick_resp: self.BrickResp.add_data_one_step(brick_tags) time = ops.getTime() if print_info: color = get_random_color() CONSOLE.print( f"{PKG_PREFIX} The responses data at time [bold {color}]{time:.4f}[/] has been fetched!" )
[docs] def save_response(self): """ Save all response data to a file name ``RespStepData-{odb_tag}.nc``. """ filename = f"{RESULTS_DIR}/" + f"RespStepData-{self.odb_tag}.nc" dt = xr.DataTree(name="RespStepData") if self.ModelInfo is not None: self.ModelInfo.save_file(dt) if self.NodalResp is not None: self.NodalResp.save_file(dt) if self.FrameResp is not None: self.FrameResp.save_file(dt) if self.TrussResp is not None: self.TrussResp.save_file(dt) if self.LinkResp is not None: self.LinkResp.save_file(dt) if self.ShellResp is not None: self.ShellResp.save_file(dt) if self.FiberSecResp is not None: self.FiberSecResp.save_file(dt) if self.PlaneResp is not None: self.PlaneResp.save_file(dt) if self.BrickResp is not None: self.BrickResp.save_file(dt) dt.to_netcdf(filename, mode="w", engine="netcdf4") color = get_random_color() CONSOLE.print( f"{PKG_PREFIX} All responses data with odb_tag = {self.odb_tag} " f"saved in [bold {color}]{filename}[/]!" )
[docs] def save_eigen_data( self, mode_tag: int = 1, solver: str = "-genBandArpack", ): """Save modal analysis data. Parameters ---------- mode_tag : int, optional, Modal tag, all modal data smaller than this modal tag will be saved, by default 1 solver : str, optional, OpenSees' eigenvalue analysis solver, by default "-genBandArpack". """ save_eigen_data(odb_tag=self.odb_tag, mode_tag=mode_tag, solver=solver)
[docs] def save_model_data( self, ): """Save the model data from the current domain.""" save_model_data(odb_tag=self.odb_tag)
def loadODB(obd_tag, resp_type: str = "Nodal"): """Load saved response data. Parameters ---------- Returns -------- Relevant to a response type. """ filename = f"{RESULTS_DIR}/" + f"RespStepData-{obd_tag}.nc" dt = xr.open_datatree(filename, engine="netcdf4").load() color = get_random_color() CONSOLE.print( f"{PKG_PREFIX} Loading response data from [bold {color}]{filename}[/] ..." ) model_info_steps, model_update = ModelInfoStepData.read_file(dt) if resp_type.lower() == "nodal": resp_step = NodalRespStepData.read_file(dt) elif resp_type.lower() == "frame": resp_step = FrameRespStepData.read_file(dt) elif resp_type.lower() == "fibersec": resp_step = FiberSecRespStepData.read_file(dt) elif resp_type.lower() == "truss": resp_step = TrussRespStepData.read_file(dt) elif resp_type.lower() == "link": resp_step = LinkRespStepData.read_file(dt) elif resp_type.lower() == "shell": resp_step = ShellRespStepData.read_file(dt) elif resp_type.lower() == "plane": resp_step = PlaneRespStepData.read_file(dt) elif resp_type.lower() == "brick": resp_step = BrickRespStepData.read_file(dt) else: raise ValueError(f"Unsupported response type {resp_type}!") return model_info_steps, model_update, resp_step
[docs] def get_nodal_responses( odb_tag: int, resp_type: str = None, node_tags: Union[list, tuple, int] = None ) -> xr.Dataset: """Read nodal responses data from a file. Parameters ---------- odb_tag: Union[int, str], default: one Tag of output databases (ODB) to be read. resp_type: str, default: disp Type of response to be read. Optional: * "disp" - Displacement at the node. * "vel" - Velocity at the node. * "accel" - Acceleration at the node. * "reaction" - Reaction forces at the node. * "reactionIncInertia" - Reaction forces including inertial effects. * "rayleighForces" - Forces resulting from Rayleigh damping. * "pressure" - Pressure applied to the node. * If None, return all responses. node_tags: Union[list, tuple, int], default: None Node tags to be read. Such as [1, 2, 3] or numpy.array([1, 2, 3]) or 1. If None, return all nodal responses. .. Note:: If some nodes are deleted during the analysis, their response data will be filled with `numpy.nan`. Returns --------- NodalResp: xarray.Dataset Nodal responses' data. .. Note:: The returned data can be viewed using `.dims` and `.coords` to view the dimension names and coordinates. You can further index or process the data. """ filename = f"{RESULTS_DIR}/" + f"RespStepData-{odb_tag}.nc" dt = xr.open_datatree(filename, engine="netcdf4") color = get_random_color() CONSOLE.print( f"{PKG_PREFIX} Loading response data from [bold {color}]{filename}[/] ..." ) nodal_resp = NodalRespStepData.read_response(dt, resp_type=resp_type, node_tags=node_tags) return nodal_resp
[docs] def get_element_responses( odb_tag: int, ele_type: str, resp_type: str = None, ele_tags: Union[list, tuple, int] = None ) -> xr.Dataset: """Read nodal responses data from a file. Parameters ------------ odb_tag: Union[int, str], default: one Tag of output databases (ODB) to be read. ele_type: str, default: Frame Type of element to be read. Optional: "Frame", "Truss", "Link", "Shell", "Plane", "Brick". resp_type: str, default: disp The response type, which depends on the parameter `ele_type`. If None, return all responses to that `ele_type`. #. For `Frame`: * "localForces": Local forces in the element local coordinate system. * "basicForces": Basic forces in the element basic coordinate system. * "basicDeformations": Basic deformations in the element basic coordinate system. * "plasticDeformation": Plastic deformations in the element basic coordinate system. * "sectionForces": Section forces in the element coordinate system. * "sectionDeformations": Section deformations in the element coordinate system. * "sectionLocs": Section locations, 0.0 to 1.0. #. For `Truss`: * "axialForce": Axial force. * "axialDefo": Axial deformation. * "Stress": Stress of material. * "Strain": Strain of material. #. For `Link`: * "basicDeformation": Basic deformation, i.e., pure deformation. * "basicForce": Basic force. #. For `Shell`: * "sectionForces": Sectional forces at Gauss points (per unit length). * "sectionDeformations": Sectional deformation at Gauss points (per unit length). #. For `Plane`: * "stresses": Stresses at Gauss points. * "strains": Strains at Gauss points. #. For `Brick`: * "stresses": Stresses at Gauss points. * "strains": Strains at Gauss points. ele_tags: Union[list, tuple, int], default: None Element tags to be read. Such as [1, 2, 3] or numpy.array([1, 2, 3]) or 1. If None, return all nodal responses. .. note:: If some nodes are deleted during the analysis, their response data will be filled with `numpy.nan`. Returns --------- EleResp: xarray.Dataset Element responses' data. .. note:: The returned data can be viewed using `.dims`、`.coords` and `.attrs` to view the dimension names and coordinates. You can further index or process the data. """ filename = f"{RESULTS_DIR}/" + f"RespStepData-{odb_tag}.nc" dt = xr.open_datatree(filename, engine="netcdf4") color = get_random_color() CONSOLE.print( f"{PKG_PREFIX} Loading response data from [bold {color}]{filename}[/] ..." ) if ele_type.lower() == "frame": ele_resp = FrameRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) elif ele_type.lower() == "truss": ele_resp = TrussRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) elif ele_type.lower() == "link": ele_resp = LinkRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) elif ele_type.lower() == "shell": ele_resp = ShellRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) elif ele_type.lower() == "plane": ele_resp = PlaneRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) elif ele_type.lower() == "brick": ele_resp = BrickRespStepData.read_response(dt, resp_type=resp_type, ele_tags=ele_tags) else: raise ValueError( f"Unsupported element type {ele_type}, " "must in [Frame, Truss, Link, Shell, Plane, Brick]!" ) return ele_resp