Skip to content

Commit

Permalink
feat: add contact element display
Browse files Browse the repository at this point in the history
  • Loading branch information
yexiang1992 committed Dec 15, 2024
1 parent 3ab9733 commit 921550e
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 20 deletions.
64 changes: 55 additions & 9 deletions opstool/post/_get_model_data_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self) -> None:
# --------------------------nodal info------------------------------------
# ------------------------------------------------------------------------
self.node_tags = ops.getNodeTags()
self.unused_node_tags = [] # record unused nodal tags by this pacakge
self.node_coords = [] # Nodal Coords
self.node_index = dict() # Key: nodeTag, value: index in self.node_coords
self.node_ndims, self.node_ndofs = [], [] # Nodal Dims, Nodal dofs
Expand All @@ -68,7 +69,7 @@ def __init__(self) -> None:
# ------------------------------------------------------------------------
# --------------------------Element info----------------------------------
# ------------------------------------------------------------------------
self.ele_tags = ops.getEleTags()
self.ele_tags = []
self.ele_centers, self.ele_class_tags = [], []
# -----------------------------------------------------------------------
self.truss_tags, self.truss_cells = [], []
Expand All @@ -84,6 +85,8 @@ def __init__(self) -> None:
self.link_centers, self.link_lengths = [], []
self.link_xaxis, self.link_yaxis, self.link_zaxis = [], [], []
# ------------------------------------------------------------------------
self.contact_tags, self.contact_cells = [], []
# ------------------------------------------------------------------------
self.plane_tags, self.plane_cells, self.plane_cells_type = [], [], []
self.shell_tags, self.shell_cells, self.shell_cells_type = [], [], []
self.brick_tags, self.brick_cells, self.brick_cells_type = [], [], []
Expand Down Expand Up @@ -301,6 +304,37 @@ def _make_beam_info(self, ele_tag):
self.beam_yaxis.append(yaxis)
self.beam_zaxis.append(zaxis)

def _make_contact_info(self, ele_tag, ele_class_tag):
ele_nodes = ops.eleNodes(ele_tag)
key = OPS_ELE_CLASSTAG2TYPE[ele_class_tag]
self.contact_tags.append(ele_tag)
cell = []
if ele_class_tag in [22, 23, 24, 25, 140]: # zero-length element
if len(ele_nodes) == 2:
pass
elif len(ele_nodes) > 2:
mid = len(ele_nodes) // 2
part1 = ele_nodes[:mid]
part2 = ele_nodes[mid:]
part2 = part2[::-1]
for tag1, tag2 in zip(part1, part2):
cell.extend([2, self.node_index[tag1], self.node_index[tag2]])
self.ELE_CELLS_VTK[key].append([2, self.node_index[tag1], self.node_index[tag2]])
self.ELE_CELLS_TYPE_VTK[key].append(LINE_CELL_TYPE_VTK[2])
self.ELE_CELLS_TAGS[key].append(ele_tag)
else:
ele_nodes = ops.eleNodes(ele_tag)
cNode = ele_nodes[-2]
rNodes = ele_nodes[:-2]
# record the last Lagrange multiplier node that will be not used
self.unused_node_tags.append(ele_nodes[-1])
for rntag in rNodes:
cell.extend([2, self.node_index[cNode], self.node_index[rntag]])
self.ELE_CELLS_VTK[key].append([2, self.node_index[cNode], self.node_index[rntag]])
self.ELE_CELLS_TYPE_VTK[key].append(LINE_CELL_TYPE_VTK[2])
self.ELE_CELLS_TAGS[key].append(ele_tag)
self.contact_cells.append(cell)

def _make_all_line_info(self, ele_tag, class_tag):
idxs = [self.node_index[tag_] for tag_ in ops.eleNodes(ele_tag)]
key = OPS_ELE_CLASSTAG2TYPE[class_tag]
Expand Down Expand Up @@ -365,8 +399,18 @@ def _make_joint_info(self, ele_tag, class_tag):
self.unstru_cells.append([4, idxs[4], idxs[1], idxs[5], idxs[3]])
self.unstru_cells_type.append(PLANE_CELL_TYPE_VTK[4])

def _make_ele_centers(self, ele_tag, class_tag):
# coords
ele_nodes = ops.eleNodes(ele_tag)
idxs = [self.node_index[tag_] for tag_ in ele_nodes]
coords = [self.node_coords[idx] for idx in idxs]
self.ele_centers.append(np.mean(coords, axis=0))
# ele_class_tags
self.ele_class_tags.append(class_tag)
self.ele_tags.append(ele_tag)

def _make_ele_info(self):
for ele_tag in self.ele_tags:
for ele_tag in ops.getEleTags():
class_tag = ops.getEleClassTags(ele_tag)
if not isinstance(class_tag, int):
class_tag = class_tag[0]
Expand All @@ -375,26 +419,28 @@ def _make_ele_info(self):
self._make_all_line_info(ele_tag, class_tag)
if class_tag in OPS_ELE_TAGS.Truss:
self._make_truss_info(ele_tag)
self._make_ele_centers(ele_tag, class_tag)
elif class_tag in OPS_ELE_TAGS.Beam:
self._make_beam_info(ele_tag)
self._make_ele_centers(ele_tag, class_tag)
elif class_tag in OPS_ELE_TAGS.Link:
self._make_link_info(ele_tag)
self._make_ele_centers(ele_tag, class_tag)
else:
if class_tag in OPS_ELE_TAGS.Plane:
self._make_plane_info(ele_tag, class_tag)
self._make_ele_centers(ele_tag, class_tag)
elif class_tag in OPS_ELE_TAGS.Shell:
self._make_shell_info(ele_tag, class_tag)
self._make_ele_centers(ele_tag, class_tag)
elif class_tag in OPS_ELE_TAGS.Solid:
self._make_solid_info(ele_tag, class_tag)
self._make_ele_centers(ele_tag, class_tag)
elif class_tag in OPS_ELE_TAGS.Joint:
self._make_joint_info(ele_tag, class_tag)
# coords
ele_nodes = ops.eleNodes(ele_tag)
idxs = [self.node_index[tag_] for tag_ in ele_nodes]
coords = [self.node_coords[idx] for idx in idxs]
self.ele_centers.append(np.mean(coords, axis=0))
# ele_class_tags
self.ele_class_tags.append(class_tag)
self._make_ele_centers(ele_tag, class_tag)
if class_tag in OPS_ELE_TAGS.Contact:
self._make_contact_info(ele_tag, class_tag)

# reshape, ensure array alignment, starting with the element with the most nodes
def reshape_cells(cells):
Expand Down
14 changes: 13 additions & 1 deletion opstool/post/_get_response/_get_model_info_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def add_data_one_step(self):

def _to_xarray(self):
for key, data in self.model_info_steps.items():
print(key)
new_data = xr.concat(data, dim="time", join="outer")
new_data.coords["time"] = self.times
self.model_info_steps[key] = new_data
Expand All @@ -53,7 +54,12 @@ def _to_xarray(self):

def get_current_node_tags(self):
da = self.model_info_steps["NodalData"][-1]
return da.coords["tags"].values
node_tags = list(da.coords["tags"].data)
unused_node_tags = da.attrs["unusedNodeTags"]
for tag in unused_node_tags:
if tag in node_tags:
node_tags.remove(tag)
return node_tags

def get_current_truss_tags(self):
da = self.model_info_steps["TrussData"][-1]
Expand Down Expand Up @@ -91,6 +97,12 @@ def get_current_brick_tags(self):
return da.coords["eleTags"].values
return []

def get_current_contact_tags(self):
da = self.model_info_steps["ContactData"][-1]
if len(da) > 0:
return da.coords["eleTags"].values
return []

def get_current_frame_load_data(self):
da = self.model_info_steps["EleLoadData"][-1]
if len(da) > 0:
Expand Down
37 changes: 29 additions & 8 deletions opstool/post/model_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ def get_nodal_data(self):
"tags": self.node_tags,
"coords": ["x", "y", "z"],
},
dims=["tags", "coords"],
dims=["tags", "coords"]
)
else:
node_data = xr.DataArray(
self.node_coords,
coords={
"tags": [],
"coords": [],
},
dims=["tags", "coords"],
# coords={
# "tags": [],
# "coords": [],
# },
# dims=["tags", "coords"],
)
node_data.name = "NodalData"
node_data.attrs = {
Expand Down Expand Up @@ -340,6 +340,21 @@ def get_unstru_data(self):
unstru.name = "UnstructuralData"
return unstru

def get_contact_data(self):
if len(self.contact_cells) > 0:
contact = xr.DataArray(
self.contact_cells,
coords={
"cells": ["numNodes", "nodeI", "nodeJ"] * (len(self.contact_cells[0]) // 3),
"eleTags": self.contact_tags,
},
dims=["eleTags", "cells"],
)
else:
contact = xr.DataArray(self.contact_cells)
contact.name = "ContactData"
return contact

def get_ele_centers_data(self):
if len(self.ele_centers) > 0:
return xr.DataArray(
Expand All @@ -366,6 +381,7 @@ def get_ele_data(self):
plane_data = self.get_plane_date()
brick_data = self.get_brick_data()
unstru_data = self.get_unstru_data()
contact_data = self.get_contact_data()
ele_centers = self.get_ele_centers_data()
# --------------------------------------------------------------
all_eles = dict()
Expand Down Expand Up @@ -396,6 +412,7 @@ def get_ele_data(self):
plane_data,
brick_data,
unstru_data,
contact_data,
ele_centers,
all_eles,
)
Expand All @@ -407,13 +424,17 @@ def get_model_info(self):
ele_load_data = self.get_ele_load_data()
mp_constraint_data = self.get_mp_constraint_data()

ele_data = self.get_ele_data()

# ----------------------------------------------------------------
# update and save the model info
nodal_data.attrs["unusedNodeTags"] = tuple(self.unused_node_tags)
self.MODEL_INFO[nodal_data.name] = nodal_data
self.MODEL_INFO[node_fixed_data.name] = node_fixed_data
self.MODEL_INFO[nodal_load_data.name] = nodal_load_data
self.MODEL_INFO[ele_load_data.name] = ele_load_data
self.MODEL_INFO[mp_constraint_data.name] = mp_constraint_data
# ---------------------------------------------------
ele_data = self.get_ele_data()
# -----------------------------------------------------------------
for edata in ele_data[:-1]:
self.MODEL_INFO[edata.name] = edata

Expand Down
4 changes: 2 additions & 2 deletions opstool/utils/ops_ele_class_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@
]
ELE_TAG_PFEM = [133, 141, 142, 143, 144, 164, 187, 189, 199, 200, 255]
ELE_TAG_UP = [40, 46, 47, 48, 50, 51, 120, 122]
ELE_TAG_CONTACT = [22, 23, 24, 113, 114, 115, 117, 118, 123, 124, 125]
ELE_TAG_CONTACT = [22, 23, 24, 25, 113, 114, 115, 117, 118, 123, 124, 125, 140]

OPS_ELE_TAGS = SimpleNamespace(
Types=ELE_TYPE_TAGS,
Expand All @@ -456,7 +456,7 @@
SurfaceLoad=ELE_TAG_SURFACE_LOAD,
# solid-fluid coupled elements, solid displacement (u) and fluid pressure (p)
UP=ELE_TAG_UP,
CONTACT=ELE_TAG_CONTACT,
Contact=ELE_TAG_CONTACT,
)
OPS_ELE_CLASSTAG2TYPE = ELE_TYPE_TAGS

Expand Down
6 changes: 6 additions & 0 deletions opstool/vis/plotly/plot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def set_plot_colors(
brick: Union[str, list, tuple] = "#FF4500",
tet: Union[str, list, tuple] = "#FFFF33",
joint: Union[str, list, tuple] = "#7FFF00",
contact: Union[str, list, tuple] = "#ff9408",
pfem: Union[str, list, tuple] = "#8080FF",
constraint: Union[str, list, tuple] = "#FF1493",
bc: Union[str, list, tuple] = "#15b01a",
Expand Down Expand Up @@ -156,6 +157,8 @@ def set_plot_colors(
Color for tetrahedral (solid) elements.
joint : str, list[int, int, int], optional
Color for beam-column joint elements.
contact : str, list[int, int, int], optional
Color for contact elements.
pfem : str, list[int, int, int], optional
Color for PFEM elements.
constraint : str, list[int, int, int], optional
Expand Down Expand Up @@ -199,6 +202,7 @@ def set_plot_colors(
PLOT_ARGS.color_pfem = pfem
PLOT_ARGS.color_brick = brick
PLOT_ARGS.joint = joint
PLOT_ARGS.color_contact = contact
PLOT_ARGS.color_constraint = constraint
PLOT_ARGS.color_bc = bc
PLOT_ARGS.color_map = cmap
Expand Down Expand Up @@ -235,6 +239,8 @@ def _get_ele_color(ele_types: list[str]):
colors[i] = PLOT_ARGS.color_pfem
elif ele_type in OPS_ELE_TYPES.Joint:
colors[i] = PLOT_ARGS.color_joint
elif ele_type in OPS_ELE_TYPES.Contact:
colors[i] = PLOT_ARGS.color_contact
return colors


Expand Down
6 changes: 6 additions & 0 deletions opstool/vis/pyvista/plot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ def set_plot_colors(
brick: Union[str, list, tuple] = "#FF4500",
tet: Union[str, list, tuple] = "#FFFF33",
joint: Union[str, list, tuple] = "#7FFF00",
contact: Union[str, list, tuple] = "#ff9408",
pfem: Union[str, list, tuple] = "#8080FF",
constraint: Union[str, list, tuple] = "#FF1493",
bc: Union[str, list, tuple] = "#15b01a",
Expand Down Expand Up @@ -265,6 +266,8 @@ def set_plot_colors(
Color for tetrahedral (solid) elements.
joint : str, list[int, int, int], optional
Color for beam-column joint elements.
contact : str, list[int, int, int], optional
Color for contact elements.
pfem : str, list[int, int, int], optional
Color for PFEM elements.
constraint : str, list[int, int, int], optional
Expand Down Expand Up @@ -306,6 +309,7 @@ def set_plot_colors(
PLOT_ARGS.color_pfem = pfem
PLOT_ARGS.color_brick = brick
PLOT_ARGS.joint = joint
PLOT_ARGS.color_contact = contact
PLOT_ARGS.color_constraint = constraint
PLOT_ARGS.color_bc = bc
PLOT_ARGS.cmap = cmap
Expand Down Expand Up @@ -342,6 +346,8 @@ def _get_ele_color(ele_types: list[str]):
colors[i] = PLOT_ARGS.color_pfem
elif ele_type in OPS_ELE_TYPES.Joint:
colors[i] = PLOT_ARGS.color_joint
elif ele_type in OPS_ELE_TYPES.Contact:
colors[i] = PLOT_ARGS.color_contact
return colors


Expand Down

0 comments on commit 921550e

Please sign in to comment.