Source code for o3seespy.command.node

from o3seespy.base_model import OpenSeesObject


[docs]class Node(OpenSeesObject): op_base_type = "node" op_type = "node" def __init__(self, osi, x: float, y=None, z=None, vel=None, acc=None, mass: list=None, x_mass=None, y_mass=None, z_mass=None, x_rot_mass=None, y_rot_mass=None, z_rot_mass=None, tag=None, build=1): """ An OpenSees node Parameters ---------- osi : o3seespy.opensees_instance.OpenSeesInstance object An instance of OpenSees x : float x-coordinate y : float, optional y-coordinate z : float, optional z-coordinate vel : iterable object, optional nodal velocities (x, y, z) acc : iterable object, optional mass: iterable object, option nodal masses """ self.x = float(x) if y is not None: self.y = float(y) if z is not None: self.z = float(z) self.vel = vel self.acc = acc if tag is None: osi.n_node += 1 self._tag = osi.n_node else: self._tag = int(tag) if osi.ndm == 1: self._parameters = [self._tag, self.x] poss_mass = [x_mass] elif osi.ndm == 2: self._parameters = [self._tag, self.x, self.y] poss_mass = [x_mass, y_mass, z_rot_mass] elif osi.ndm == 3: self._parameters = [self._tag, self.x, self.y, self.z] poss_mass = [x_mass, y_mass, z_mass, x_rot_mass, y_rot_mass, z_rot_mass] else: raise NotImplementedError(f"Currently only supports 1-3D analyses, ndm={osi.ndm}") if mass is None: mass = [] if poss_mass[0] is not None: none_found = False for mval in poss_mass: if mval is None: none_found = True else: if not none_found: mass.append(float(mval)) else: mstr = ','.join([str(x) for x in poss_mass]) raise ValueError(f'Cannot set mass, since None in mass=[{mstr}]') else: mass = [float(x) for x in mass] if len(mass): self.mass = mass self._parameters += ["-mass", *mass] if self.vel is not None: self._parameters += ["-vel", self.vel] if self.acc is not None: self._parameters += ["-accel", self.acc] if build: self.to_process(osi)
[docs]def build_regular_node_mesh(osi, xs, ys, zs=None, active=None, tags=None): """ Creates an array of nodes that are in a regular mesh The mesh has len(xs) nodes in the x-direction and len(ys) in the y-direction. If zs is not None then has len(zs) in the z-direction. Parameters ---------- osi xs ys zs active tags: array_like array of node tags Returns ------- np.array axis-0 = x-direction axis-1 = y-direction axis-2 = z # not included if len(zs)=1 or zs=None """ # axis-0 = x # unless x or y are singular # axis-1 = y # axis-2 = z # not included if len(zs)=1 or tag = None from numpy import array if not hasattr(zs, '__len__'): zs = [zs] sn = [] for xx in range(len(xs)): sn.append([]) for yy in range(len(ys)): if len(zs) == 1: if tags is not None: tag = tags[xx][yy] if active is None or active[xx][yy]: if osi.ndm == 2: pms = [osi, xs[xx], ys[yy]] else: pms = [osi, xs[xx], ys[yy], zs[0]] sn[xx].append(Node(*pms, tag=tag)) else: sn[xx].append(None) else: sn[xx].append([]) for zz in range(len(zs)): if tags is not None: tag = tags[xx][yy][zz] # Establish left and right nodes if active is None or active[xx][yy][zz]: sn[xx][yy].append(Node(osi, xs[xx], ys[yy], zs[zz], tag=tag)) else: sn[xx][yy].append(None) # if len(zs) == 1: # return sn[0] return array(sn)
[docs]def build_varied_y_node_mesh(osi, xs, ys, zs=None, active=None): """ Creates an array of nodes that in vertical lines, but vary in height The mesh has len(xs)=ln(ys) nodes in the x-direction and len(ys[0]) in the y-direction. If zs is not None then has len(zs) in the z-direction. Parameters ---------- osi xs ys zs active Returns ------- np.array axis-0 = x-direction axis-1 = y-direction axis-2 = z # not included if len(zs)=1 or zs=None """ # axis-0 = x # unless x or y are singular # axis-1 = y # axis-2 = z # not included if len(zs)=1 or from numpy import array if not hasattr(zs, '__len__'): zs = [zs] sn = [] for xx in range(len(xs)): sn.append([]) for yy in range(len(ys[xx])): if len(zs) == 1: if active is None or active[xx][yy]: if osi.ndm == 2: pms = [osi, xs[xx], ys[xx][yy]] else: pms = [osi, xs[xx], ys[xx][yy], zs[0]] sn[xx].append(Node(*pms)) else: sn[xx].append(None) else: sn[xx].append([]) for zz in range(len(zs)): # Establish left and right nodes if active is None or active[xx][yy][zz]: sn[xx][yy].append(Node(osi, xs[xx], ys[xx][yy], zs[zz])) else: sn[xx][yy].append(None) # if len(zs) == 1: # return sn[0] return array(sn)
[docs]def build_varied_xy_node_mesh(osi, xs, ys, zs=None, active=None, tags=None): """ Creates an array of nodes that vary in both x and y but are still in a grid. The mesh has len(xs)=ln(ys) nodes in the x-direction and len(ys[0]) in the y-direction. If zs is not None then has len(zs) in the z-direction. Parameters ---------- osi xs ys zs active Returns ------- np.array axis-0 = x-direction axis-1 = y-direction axis-2 = z # not included if len(zs)=1 or zs=None """ # axis-0 = x # unless x or y are singular # axis-1 = y # axis-2 = z # not included if len(zs)=1 or tag = None from numpy import array if not hasattr(zs, '__len__'): zs = [zs] sn = [] for xx in range(len(xs)): sn.append([]) for yy in range(len(ys[xx])): if len(zs) == 1: if tags is not None: tag = tags[xx][yy] if active is None or active[xx][yy]: if osi.ndm == 2: pms = [osi, xs[xx][yy], ys[xx][yy]] else: pms = [osi, xs[xx][yy], ys[xx][yy], zs[0]] sn[xx].append(Node(*pms, tag=tag)) else: sn[xx].append(None) else: sn[xx].append([]) for zz in range(len(zs)): if tags is not None: tag = tags[xx][yy][zz] # Establish left and right nodes if active is None or active[xx][yy][zz]: sn[xx][yy].append(Node(osi, xs[xx][yy], ys[xx][yy], zs[zz], tag=tag)) else: sn[xx][yy].append(None) # if len(zs) == 1: # return sn[0] return array(sn)
# UNUSED?
[docs]def duplicate_node(osi, node): """ Copy a node to initialise in another processor in parallel mode Note: It has the same node number """ if osi.ndm == 1: _parameters = [node.tag, *[node.x]] pms = ['mass'] elif osi.ndm == 2: _parameters = [node.tag, *[node.x, node.y]] pms = ['mass'] elif osi.ndm == 3: _parameters = [node.tag, *[node.x, node.y, node.z]] pms = ['mass'] else: raise NotImplementedError("Currently only supports 1-3D analyses") masses = [] none_found = 0 if hasattr(node, 'mass') and node.mass is not None: _parameters += ["-mass", *node.mass] if node.vel is not None: _parameters += ["-vel", node.vel] if node.acc is not None: _parameters += ["-accel", node.acc] osi.to_process('node', _parameters)
[docs]def repeat_node(osi, node, tag=None): """ Copy a node to initialise in another processor in parallel mode Note: It has the same node number """ if osi.ndm == 1: return Node(osi, node.x, tag=tag) elif osi.ndm == 2: return Node(osi, node.x, node.y, tag=tag) elif osi.ndm == 3: return Node(osi, node.x, node.y, node.z, tag=tag) else: raise NotImplementedError("Currently only supports 1-3D analyses")
# def build_node_if_within_segment(osi, coords, segment): # """ # # Parameters # ---------- # coords # segment: array_like # if osi.ndm = 1, segment is [[min_x], [max_x]] # if osi.num = 2, segment is [[ # # Returns # ------- # # """ # pass
[docs]def hash_coords(coords, nsf=8): return '_'.join(['{n:.{nsf}}'.format(n=float(x), nsf=nsf) for x in coords])
[docs]def build_node_tag_hash_dict_from_mesh(ndm, xs, ys, zs=None, active=None, init_tag=0, nsf=8): """ Creates an array of nodes that in vertical lines, but vary in height The mesh has len(xs) nodes in the x-direction and len(ys[0]) in the y-direction. If zs is not None then has len(zs) in the z-direction. Parameters ---------- osi xs ys zs active Returns ------- np.array axis-0 = x-direction axis-1 = y-direction axis-2 = z # not included if len(zs)=1 or zs=None """ # axis-0 = x # unless x or y are singular # axis-1 = y # axis-2 = z # not included if len(zs)=1 or import numpy as np ys = np.array(ys) nx = xs.shape[0] ny = ys.shape[min(len(ys.shape), 1)] if not hasattr(zs, '__len__'): zs = [zs] if len(active.shape) == 3: azi = np.arange(len(zs)) else: azi = [None] * len(xs) if len(xs.shape) >= 2: yind4x = np.arange(ny) else: yind4x = [None] * ny if len(ys.shape) >= 2: xind4y = np.arange(nx) else: xind4y = [None] * nx nz = zs.shape[-1] sd = {} tag = init_tag for xx in range(nx): for yy in range(ny): for zz in range(nz): if active is None or active[xx, yy, azi[zz]]: if ndm == 2: pms = [xs[xx, yind4x[yy]], ys[xind4y[xx], yy]] else: pms = [xs[xx, yind4x[yy]], ys[xind4y[xx], yy], zs[zz]] fstr = hash_coords(pms, nsf) if fstr not in sd: sd[fstr] = [] sd[fstr].append((tag, *pms)) tag += 1 return sd, tag