Skip to content

Commit

Permalink
bdf_vectorized3:
Browse files Browse the repository at this point in the history
 - PLOAD4: single element solid load cases work now
  • Loading branch information
SteveDoyle2 committed Dec 16, 2023
1 parent b8e0386 commit 3d35f64
Show file tree
Hide file tree
Showing 9 changed files with 3,684 additions and 167 deletions.
5 changes: 4 additions & 1 deletion pyNastran/bdf/cards/elements/solid.py
Original file line number Diff line number Diff line change
Expand Up @@ -1783,14 +1783,16 @@ def cpenta_face(nid, nid_opposite, nids):
pack2 = [i - 1 for i in pack2]
return pack2

def cpenta_face_area_centroid_normal(nid, nid_opposite, nids, nodes_ref):
def cpenta_face_area_centroid_normal(nid: int, nid_opposite: int,
nids: list[int], nodes_ref):
"""
Parameters
----------
nid : int
G1 - a grid point on the corner of a face
nid_opposite : int / None
G3 - the grid point diagonally opposite of G1
"""
face = cpenta_face(nid, nid_opposite, nids)

Expand All @@ -1803,6 +1805,7 @@ def cpenta_face_area_centroid_normal(nid, nid_opposite, nids, nodes_ref):
b = p2 - p1
centroid = (p1 + p2 + p3) / 3.
else:
# uses a backwards face?
n1i, n2i, n3i, n4i = face
p1 = nodes_ref[n1i].get_position()
p2 = nodes_ref[n2i].get_position()
Expand Down
18 changes: 13 additions & 5 deletions pyNastran/dev/bdf_vectorized3/bdf_interface/bdf_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -847,24 +847,31 @@ def optimization_cards(self) -> list[Any]:
return optimization

@property
def load_cards(self) -> list[Any]:
def static_load_cards(self) -> list[Any]:
loads = [
self.load, self.lseq,
self.force, self.force1, self.force2,
self.moment, self.moment1, self.moment2,
self.pload, self.pload1, self.pload2, self.pload4,
self.grav, self.accel, self.accel1,
self.sload,
self.temp, self.tempd,
#self.dtemp, # has nodes
self.qhbdy, self.qbdy1, self.qbdy2, self.qbdy3,
self.qvol, self.qvect,
self.spcd, self.deform,
self.rforce, self.rforce1,
#self.ploadx1,
]
return loads

@property
def load_cards(self) -> list[Any]:
loads = [
self.load, self.lseq,

#self.dtemp, # has nodes
self.qhbdy, self.qbdy1, self.qbdy2, self.qbdy3,
self.qvol, self.qvect,
] + self.static_load_cards
return loads

@property
def dynamic_load_cards(self) -> list[Any]:
loads = [
Expand Down Expand Up @@ -1188,6 +1195,7 @@ def is_thermal(self) -> bool:
return is_thermal

def self_static_loads_by_subcase_id(self, subcase_ids: list[int]=None) -> dict[int, Any]:
"""intended for LOADSET in dynamic solution, not LOAD cards (so SOL 101)"""
res = get_static_loads_by_subcase_id(self, subcase_ids=subcase_ids)
return res

Expand Down
28 changes: 25 additions & 3 deletions pyNastran/dev/bdf_vectorized3/cards/elements/shell_axi.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class AxisymmetricShellElement(Element):
@Element.clear_check
def clear(self) -> None:
self.property_id = np.array([], dtype='int32')
self.nodes = np.array([], dtype='int32')
self.nodes = np.zeros((0, 0), dtype='int32')

@property
def all_properties(self) -> list[Any]:
Expand Down Expand Up @@ -189,7 +189,10 @@ class AxiShellElement(Element):
@Element.clear_check
def clear(self) -> None:
self.element_id = np.array([], dtype='int32')
self.nodes = np.array([], dtype='int32')
if not hasattr(self, 'nodes'):
self.nodes = np.zeros((0, 0), dtype='int32')
else:
self.nodes = np.zeros((0, self.nodes.shape[1]), dtype='int32')
self.property_id = np.array([], dtype='int32')
#self.tflag = np.array([], dtype='int32')
#self.T = np.array([], dtype='int32')
Expand Down Expand Up @@ -430,9 +433,15 @@ class CTRIAX(AxisymmetricShellElement):
Theta/Mcid is MSC only!
"""
@Element.clear_check
def clear(self) -> None:
self.property_id = np.array([], dtype='int32')
self.nodes = np.zeros((0, 6), dtype='int32')

def add(self, eid: int, pid: int, nids: list[int],
theta_mcid: int|float=0., comment: str='') -> int:
"""Creates a CTRIAX card"""
nids = add_empty_nodes(nids, self.nodes.shape[1])
self.cards.append((eid, pid, nids, theta_mcid, comment))
self.n += 1
return self.n - 1
Expand Down Expand Up @@ -563,12 +572,17 @@ class CTRIAX6(Element):
"""
@Element.clear_check
def clear(self) -> None:
self.nodes = np.array([], dtype='int32')
self.nodes = np.zeros((0, 6), dtype='int32')
self.material_id = np.array([], dtype='int32')

def add(self, eid: int, mid: int, nids: list[int], theta: float=0.,
comment: str='') -> int:
"""Creates a CTRIAX6 card"""
#add_empty_nodes(nids, self.nodes.shape[1])
if len(nids) == 3:
# don't do an inplace operation :)
n1, n2, n3 = nids
nids = [n1, 0, n2, 0, n3, 0]
self.cards.append((eid, mid, nids, theta, comment))
self.n += 1
return self.n - 1
Expand Down Expand Up @@ -1379,3 +1393,11 @@ def base_nodes(self) -> np.ndarray:
@property
def midside_nodes(self) -> np.ndarray:
return self.nodes[:, 3:]

def add_empty_nodes(nids: list[int], nnodes_required: int) -> list[int]:
nnodes = len(nids)
if nnodes < nnodes_required:
extra_nodes = [0] * (nnodes_required - nnodes)
# gotta do a copy vs. inplace operation
nids = nids + extra_nodes
return nids
17 changes: 13 additions & 4 deletions pyNastran/dev/bdf_vectorized3/cards/elements/solid.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,42 +287,50 @@ def quality(self) -> Quality:
(4, 0): np.array([0, 1, 4, 3]), # bottom (flipped)
(3, 1): np.array([0, 1, 4, 3]),

(0, 5): np.array([0, 2, 5, 3]), # left-reverse
(2, 3): np.array([0, 2, 5, 3]),
(5, 0): np.array([0, 2, 5, 3]), # left-reverse (flipped)
(3, 2): np.array([0, 2, 5, 3]),
(0, 5): np.array([0, 3, 5, 2]), # left-reverse
(2, 3): np.array([0, 3, 5, 2]),
(5, 0): np.array([0, 3, 5, 2]), # left-reverse (flipped)
(3, 2): np.array([0, 3, 5, 2]),

(1, 5): np.array([1, 4, 5, 2]), # right
(2, 4): np.array([1, 4, 5, 2]),
(5, 1): np.array([1, 4, 5, 2]), # right (flipped)
(4, 2): np.array([1, 4, 5, 2]),
}
CHEXA_FACE_MAPPER = {
# normals point inward

# top
(7, 5) : np.array([7, 6, 5, 4]),
(5, 7) : np.array([7, 6, 5, 4]),
(6, 4) : np.array([7, 6, 5, 4]),
(4, 6) : np.array([7, 6, 5, 4]),

# bottom
(0, 2) : np.array([0, 1, 2, 3]),
(2, 0) : np.array([0, 1, 2, 3]),
(1, 3) : np.array([0, 1, 2, 3]),
(3, 1) : np.array([0, 1, 2, 3]),

# left
(0, 7) : np.array([0, 3, 7, 4]),
(7, 0) : np.array([0, 3, 7, 4]),
(3, 4) : np.array([0, 3, 7, 4]),
(4, 3) : np.array([0, 3, 7, 4]),

# right
(5, 2) : np.array([5, 6, 2, 1]),
(2, 5) : np.array([5, 6, 2, 1]),
(6, 1) : np.array([5, 6, 2, 1]),
(1, 6) : np.array([5, 6, 2, 1]),

# front
(4, 1) : np.array([4, 5, 1, 0]),
(1, 4) : np.array([4, 5, 1, 0]),
(5, 0) : np.array([4, 5, 1, 0]),
(0, 5) : np.array([4, 5, 1, 0]),

# back
(2, 7) : np.array([2, 6, 7, 3]),
(7, 2) : np.array([2, 6, 7, 3]),
(6, 3) : np.array([2, 6, 7, 3]),
Expand Down Expand Up @@ -594,6 +602,7 @@ def quality(self) -> Quality:
out = pyram_quality(self)
return out


class SolidHex(SolidElement):
nnode_base = 8
nnode = 20
Expand Down
91 changes: 84 additions & 7 deletions pyNastran/dev/bdf_vectorized3/cards/loads/static_loads.py
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,10 @@ def set_used(self, used_dict: dict[str, np.ndarray]) -> None:
def iloc(self) -> np.ndarray:
return make_idim(self.n, self.nloc)

@property
def max_id(self) -> int:
return max(self.load_id.max(), self.coord_id.max())

@parse_load_check
def write_file(self, bdf_file: TextIOLike,
size: int=8, is_double: bool=False,
Expand Down Expand Up @@ -1579,7 +1583,6 @@ def add(self, sid: int, scale: float,
def add_card(self, card: BDFCard, comment: str='') -> int:
sid = integer(card, 1, 'sid')
scale = double(card, 2, 'scale')

scale_factors = []
load_ids = []

Expand Down Expand Up @@ -1692,11 +1695,25 @@ def write_file(self, bdf_file: TextIOLike,
#return get_loads_by_load_id(self)

def get_loads_by_load_id(load: Union[LOAD, LOADSET]) -> dict[int, Loads]:
""""""
"""
Gets all the loads by load_id.
Does NOT attach a scale factor...that's happens later
"""
model = load.model
#uload_ids = np.unique(self.load_ids)
loads_by_load_id = defaultdict(list)

if 0: # pragma: no cover
# handles singular FORCE/PLOAD cards
for load in model.static_load_cards:
if len(load) == 0:
continue
load_ids = np.unique(load.load_id)
for load_id in load_ids:
loadi = load.slice_card_by_id(load_id, assume_sorted=True, sort_ids=False)
loads_by_load_id[load_id].append(loadi)

#print('all_laods =', model.loads)
for loadi in model.load_cards:
if loadi.type in {'LOAD', 'LSEQ'}:
Expand Down Expand Up @@ -1739,7 +1756,32 @@ def get_loads_by_load_id(load: Union[LOAD, LOADSET]) -> dict[int, Loads]:
def get_reduced_loads(self,
remove_missing_loads: bool=False,
filter_zero_scale_factors: bool=False,
stop_on_failure: bool=True) -> dict[int, Loads]:
stop_on_failure: bool=True) -> dict[int, tuple[float, Loads]]:
"""
Takes a LOAD / LSEQ card and gets each referenced load.
Does NOT do summations.
Parameters
----------
resolve_load_card : bool; default=False
???
remove_missing_loads: bool; default=False
LOAD cards can reference loads (e.g., GRAV) that don't exist
Nastran sometimes ignores these loads leading to potentially incorrect results
filter_zero_scale_factors: bool; default=False
remove loads that are 0.0
Returns
-------
loads_dict: dict[load_id, tuple[float, Loads]]
load_id : int
the sub-load id
scale_factor: float
hopefully obvious :)
Loads:
FORCE, PLOAD4, etc.
"""
return get_reduced_loads(
self, remove_missing_loads=remove_missing_loads,
filter_zero_scale_factors=filter_zero_scale_factors,
Expand All @@ -1749,8 +1791,11 @@ def get_reduced_load_by_load_id(self,
load_id: int,
remove_missing_loads: bool=False,
filter_zero_scale_factors: bool=False,
stop_on_failure: bool=True) -> dict[int, Loads]:
stop_on_failure: bool=True) -> dict[int, tuple[float, Loads]]:
"""
Takes a load_id and gets each referenced load.
Does NOT do summations.
Parameters
----------
resolve_load_card : bool; default=False
Expand All @@ -1760,6 +1805,17 @@ def get_reduced_load_by_load_id(self,
Nastran sometimes ignores these loads leading to potentially incorrect results
filter_zero_scale_factors: bool; default=False
remove loads that are 0.0
Returns
-------
loads_dict: dict[load_id, tuple[float, Loads]]
load_id : int
the sub-load id
scale_factor: float
hopefully obvious :)
Loads:
FORCE, PLOAD4, etc.
"""
load = self.slice_card_by_load_id(load_id)
reduced_loads = get_reduced_loads(load)
Expand All @@ -1770,7 +1826,12 @@ def get_reduced_static_load_from_load_id(model: BDF,
load_id: int,
remove_missing_loads: bool=False,
filter_zero_scale_factors: bool=False,
stop_on_failure: bool=True) -> list[StaticLoad]:
stop_on_failure: bool=True) -> list[tuple[float, StaticLoad]]:
"""
How is this different than get_reduced_load_by_load_id?
Is it just extracting specific ids?
"""
#log = model.log

load: LOAD = model.load
Expand Down Expand Up @@ -1803,6 +1864,9 @@ def get_reduced_loads(load: Union[LOAD, LSEQ],
filter_zero_scale_factors: bool=False,
stop_on_failure: bool=True) -> dict[int, Loads]:
"""
Takes a LOAD / LSEQ card and gets each referenced load.
Does NOT do summations.
Parameters
----------
resolve_load_card : bool; default=False
Expand All @@ -1812,9 +1876,22 @@ def get_reduced_loads(load: Union[LOAD, LSEQ],
Nastran sometimes ignores these loads leading to potentially incorrect results
filter_zero_scale_factors: bool; default=False
remove loads that are 0.0
Returns
-------
loads_dict: dict[load_id, tuple[float, Loads]]
load_id : int
the sub-load id
scale_factor: float
hopefully obvious :)
Loads:
FORCE, PLOAD4, etc.
"""
reduced_loads = {}
if load.n == 0:
nbasic_cards = [card.n for card in load.model.static_load_cards]
nbasic = sum(nbasic_cards)
if load.n == 0 and nbasic == 0:
return reduced_loads

stop_on_failure = True
Expand All @@ -1824,7 +1901,7 @@ def get_reduced_loads(load: Union[LOAD, LSEQ],
reduced_loadsi = []
iload0, iload1 = iload
if global_scale == 0. and filter_zero_scale_factors:
print('continueA')
#print('continueA')
continue
scale_factors = global_scale * load.scale_factors[iload0:iload1]
load_ids = load.load_ids[iload0:iload1]
Expand Down
Loading

0 comments on commit 3d35f64

Please sign in to comment.