# pylint: disable=R0904,R0902,E1101,E1103,C0111,C0302,C0103,W0101
from __future__ import (nested_scopes, generators, division, absolute_import,
print_function, unicode_literals)
from six import string_types
from numpy import array
from numpy.linalg import norm
from pyNastran.bdf.field_writer_8 import set_blank_if_default
from pyNastran.bdf.cards.baseCard import Element
from pyNastran.bdf.bdfInterface.assign_type import (integer, integer_or_blank,
integer_double_or_blank, double_or_blank, string_or_blank)
from pyNastran.bdf.field_writer_8 import print_card_8
from pyNastran.bdf.field_writer_16 import print_card_16
[docs]class LineElement(Element): # CBAR, CBEAM, CBEAM3, CBEND
def __init__(self, card, data):
Element.__init__(self, card, data)
[docs] def C(self):
"""torsional constant"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.C()
[docs] def Area(self):
"""returns the area of the element face"""
raise NotImplementedError('implement self.Area() for %s' % self.type)
[docs] def E(self):
"""returns the Young's Modulus, :math:`E`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.mid.E()
[docs] def G(self):
"""returns the Shear Modulus, :math:`G`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.mid.G()
[docs] def J(self):
"""returns the Polar Moment of Inertia, :math:`J`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.J()
[docs] def I11(self):
"""returns the Moment of Inertia, :math:`I_{11}`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.I11()
[docs] def I22(self):
"""returns the Moment of Inertia, :math:`I_{22}`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.I22()
[docs] def I12(self):
"""returns the Moment of Inertia, :math:`I_{12}`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.I12()
[docs] def Nu(self):
"""Get Poisson's Ratio, :math:`\nu`"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.mid.nu
[docs] def Rho(self):
"""Get the material density, :math:`\rho`"""
#print(str(self.pid), type(self.pid))
#raise NotImplementedError('implement self.Rho() for %s' % self.type)
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.mid.rho
[docs] def Nsm(self):
"""Placeholder method for the non-structural mass, :math:`nsm`"""
raise NotImplementedError('implement self.Area() for %s' % self.type)
[docs] def MassPerLength(self):
"""
Get the mass per unit length, :math:`\frac{m}{L}`
"""
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been '
'cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.MassPerLength()
[docs] def Mass(self):
r"""
Get the mass of the element.
.. math:: m = \left( \rho A + nsm \right) L
"""
L = self.Length()
mass = L * self.MassPerLength()
#try:
#mass = (self.Rho() * self.Area() + self.Nsm()) * L
#except TypeError:
#msg = 'TypeError on eid=%s pid=%s:\n' % (self.eid, self.Pid())
#msg += 'rho = %s\narea = %s\nnsm = %s\nL = %s' % (self.Rho(),
# self.Area(),
# self.Nsm(), L)
#raise TypeError(msg)
return mass
[docs] def cross_reference(self, model):
msg = ' which is required by %s eid=%s' % (self.type, self.eid)
self.nodes = model.Nodes(self.nodes, msg=msg)
self.pid = model.Property(self.pid, msg=msg)
#self.g0 = model.nodes[self.g0]
[docs] def Length(self):
r"""
Gets the length, :math:`L`, of the element.
.. math:: L = \sqrt{ (n_{x2}-n_{x1})^2+(n_{y2}-n_{y1})^2+(n_{z2}-n_{z1})^2 }
:param self: the object pointer
"""
L = norm(self.nodes[1].Position() - self.nodes[0].Position())
return L
[docs]class CBAROR(object):
type = 'CBAROR'
def __init__(self):
self.n = 0
[docs] def add(self, card=None, data=None, comment=''):
if self.n == 1:
raise RuntimeError('only one CBAROR is allowed')
self.n = 1
if comment:
self._comment = comment
self.property_id = integer_or_blank(card, 2, 'pid')
# x / g0
field5 = integer_double_or_blank(card, 5, 'g0_x1', 0.0)
if isinstance(field5, int):
self.is_g0 = True
self.g0 = field5
self.x = [0., 0., 0.]
elif isinstance(field5, float):
self.is_g0 = False
self.g0 = None
self.x = array([field5,
double_or_blank(card, 6, 'x2', 0.0),
double_or_blank(card, 7, 'x3', 0.0)], dtype='float64')
self.offt = string_or_blank(card, 8, 'offt', 'GGG')
assert len(card) <= 9, 'len(CBAROR card) = %i' % len(card)
[docs]class CBAR(LineElement):
"""
+-------+-----+-----+-----+-----+-----+-----+-----+------+
| CBAR | EID | PID | GA | GB | X1 | X2 | X3 | OFFT |
+-------+-----+-----+-----+-----+-----+-----+-----+------+
| | PA | PB | W1A | W2A | W3A | W1B | W2B | W3B |
+-------+-----+-----+-----+-----+-----+-----+-----+------+
or
+-------+-----+-----+-----+-----+-----+-----+-----+------+
| CBAR | EID | PID | GA | GB | G0 | | | OFFT |
+-------+-----+-----+-----+-----+-----+-----+-----+------+
| | PA | PB | W1A | W2A | W3A | W1B | W2B | W3B |
+-------+-----+-----+-----+-----+-----+-----+-----+------+
+-------+-------+-----+-------+-------+--------+-------+-------+-------+
| CBAR | 2 | 39 | 7 | 6 | 105 | | | GGG |
+-------+-------+-----+-------+-------+--------+-------+-------+-------+
| | | 513 | 0.0+0 | 0.0+0 | -9. | 0.0+0 | 0.0+0 | -9. |
+-------+-------+-----+-------+-------+--------+-------+-------+-------+
"""
type = 'CBAR'
asterType = 'CBAR'
_field_map = {
1: 'eid', 2:'pid', 3:'ga', 4:'gb',
8:'offt', 9:'pa', 10:'pb',
}
[docs] def _update_field_helper(self, n, value):
if n == 11:
self.wa[0] = value
elif n == 12:
self.wa[1] = value
elif n == 13:
self.wa[2] = value
elif n == 14:
self.wb[0] = value
elif n == 15:
self.wb[1] = value
elif n == 16:
self.wb[2] = value
else:
if self.g0 is not None:
if n == 5:
self.g0 = value
else:
raise KeyError('Field %r=%r is an invalid %s entry.' % (n, value, self.type))
else:
if n == 5:
self.x[0] = value
elif n == 6:
self.x[1] = value
elif n == 7:
self.x[2] = value
else:
raise KeyError('Field %r=%r is an invalid %s entry.' % (n, value, self.type))
def __init__(self, card=None, data=None, comment=''):
LineElement.__init__(self, card, data)
if comment:
self._comment = comment
if card:
self.eid = integer(card, 1, 'eid')
self.pid = integer_or_blank(card, 2, 'pid', self.eid)
self.ga = integer(card, 3, 'ga')
self.gb = integer(card, 4, 'gb')
self.initX_G0(card)
self.offt = string_or_blank(card, 8, 'offt', 'GGG')
#print('self.offt = |%s|' % (self.offt))
self.pa = integer_or_blank(card, 9, 'pa', 0)
self.pb = integer_or_blank(card, 10, 'pb', 0)
self.wa = array([double_or_blank(card, 11, 'w1a', 0.0),
double_or_blank(card, 12, 'w2a', 0.0),
double_or_blank(card, 13, 'w3a', 0.0)], dtype='float64')
self.wb = array([double_or_blank(card, 14, 'w1b', 0.0),
double_or_blank(card, 15, 'w2b', 0.0),
double_or_blank(card, 16, 'w3b', 0.0)], dtype='float64')
assert len(card) <= 17, 'len(CBAR card) = %i' % len(card)
else: #: .. todo:: verify
#data = [[eid,pid,ga,gb,pa,pb,w1a,w2a,w3a,w1b,w2b,w3b],[f,g0]]
#data = [[eid,pid,ga,gb,pa,pb,w1a,w2a,w3a,w1b,w2b,w3b],[f,x1,x2,x3]]
main = data[0]
flag = data[1][0]
if flag in [0, 1]:
self.g0 = None
self.x = array([data[1][1],
data[1][2],
data[1][3]], dtype='float64')
else:
self.g0 = data[1][1]
self.x = None
self.eid = main[0]
self.pid = main[1]
self.ga = main[2]
self.gb = main[3]
#self.offt = str(data[4]) # GGG
self.offt = 'GGG' #: .. todo:: offt can be an integer; translate to char
self.pa = main[4]
self.pb = main[5]
self.wa = array([main[6], main[7], main[8]], dtype='float64')
self.wb = array([main[9], main[10], main[11]], dtype='float64')
if not isinstance(self.offt, string_types):
raise SyntaxError('invalid offt expected a string of length 3 '
'offt=|%r|; Type=%s' % (self.offt, type(self.offt)))
if self.g0 in [self.ga, self.gb]:
msg = 'G0=%s cannot be GA=%s or GB=%s' % (self.g0, self.ga, self.gb)
raise RuntimeError(msg)
msg = 'invalid offt parameter of %s...offt=%s' % (self.type, self.offt)
# B,G,O
assert self.offt[0] in ['G', 'B'], msg
assert self.offt[1] in ['G', 'O', 'E'], msg
assert self.offt[2] in ['G', 'O', 'E'], msg
[docs] def _verify(self, xref=False):
pid = self.Pid()
if xref: # True
mid = self.Mid()
A = self.Area()
nsm = self.Nsm()
mpl = self.MassPerLength()
L = self.Length()
mass = self.Mass()
assert isinstance(mid, int), 'mid=%r' % mid
assert isinstance(A, float), 'A=%r' % A
assert isinstance(L, float), 'L=%r' % L
assert isinstance(nsm, float), 'nsm=%r' % nsm
assert isinstance(mpl, float), 'mass_per_length=%r' % mpl
assert isinstance(mass, float), 'nass=%r' % mass
[docs] def Mid(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.Mid()
[docs] def Area(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
A = self.pid.Area()
assert isinstance(A, float)
return A
[docs] def J(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
j = self.pid.J()
assert isinstance(j, float), 'J=%r for CBAR eid=%s pid=%s pidType=%s' % (j, self.eid, self.pid.pid, self.pid.type)
return j
[docs] def Length(self):
L = norm(self.gb.Position() - self.ga.Position())
assert isinstance(L, float)
return L
[docs] def Nsm(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
nsm = self.pid.Nsm()
assert isinstance(nsm, float)
return nsm
[docs] def I1(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.I1()
[docs] def I2(self):
return self.pid.I2()
[docs] def Centroid(self):
return (self.ga.Position() + self.gb.Position()) / 2.
[docs] def initX_G0(self, card):
field5 = integer_double_or_blank(card, 5, 'g0_x1', 0.0)
if isinstance(field5, int):
self.g0 = field5
self.x = None
elif isinstance(field5, float):
self.g0 = None
self.x = array([field5,
double_or_blank(card, 6, 'x2', 0.0),
double_or_blank(card, 7, 'x3', 0.0)], dtype='float64')
if norm(self.x) == 0.0:
msg = 'G0 vector defining plane 1 is not defined.\n'
msg += 'G0 = %s\n' % self.g0
msg += 'X = %s\n' % self.x
raise RuntimeError(msg)
else:
msg = ('field5 on %s (G0/X1) is the wrong type...id=%s field5=%s '
'type=%s' % (self.type, self.eid, field5, type(field5)))
raise RuntimeError(msg)
[docs] def cross_reference(self, model):
#if self.g0:
# self.x = nodes[self.g0].Position() - nodes[self.ga].Position()
msg = ' which is required by %s eid=%s' % (self.type, self.eid)
self.ga = model.Node(self.ga, msg=msg)
self.gb = model.Node(self.gb, msg=msg)
self.pid = model.Property(self.pid, msg=msg)
[docs] def Ga(self):
if isinstance(self.ga, int):
return self.ga
else:
return self.ga.nid
[docs] def Gb(self):
if isinstance(self.gb, int):
return self.gb
else:
return self.gb.nid
[docs] def getX_G0_defaults(self):
if self.g0:
return (self.g0, None, None)
else:
#x1 = set_blank_if_default(self.x[0], 0.0)
#x2 = set_blank_if_default(self.x[1], 0.0)
#x3 = set_blank_if_default(self.x[2], 0.0)
return list(self.x)
[docs] def get_orientation_vector(self, xyz):
if self.g0:
v = xyz[self.g0] - xyz[self.Ga()]
else:
v = self.x
assert self.offt == 'GGG', self.offt
return v
[docs] def nodeIDs(self):
return self.node_ids
@property
def node_ids(self):
return [self.Ga(), self.Gb()]
@node_ids.setter
def node_ids(self, value):
raise ValueError("You cannot set node IDs like this...modify the node objects")
[docs] def raw_fields(self):
"""
.. todo:: not perfectly accurate b/c ???
"""
(x1, x2, x3) = self.getX_G0_defaults()
offt = set_blank_if_default(self.offt, 'GGG')
list_fields = ['CBAR', self.eid, self.Pid(), self.Ga(), self.Gb(), x1, x2,
x3, offt, self.pa, self.pb] + list(self.wa) + list(self.wb)
return list_fields
[docs] def repr_fields(self):
pa = set_blank_if_default(self.pa, 0)
pb = set_blank_if_default(self.pb, 0)
w1a = set_blank_if_default(self.wa[0], 0.0)
w2a = set_blank_if_default(self.wa[1], 0.0)
w3a = set_blank_if_default(self.wa[2], 0.0)
w1b = set_blank_if_default(self.wb[0], 0.0)
w2b = set_blank_if_default(self.wb[1], 0.0)
w3b = set_blank_if_default(self.wb[2], 0.0)
(x1, x2, x3) = self.getX_G0_defaults()
offt = set_blank_if_default(self.offt, 'GGG')
list_fields = ['CBAR', self.eid, self.Pid(), self.Ga(), self.Gb(), x1, x2,
x3, offt, pa, pb, w1a, w2a, w3a, w1b, w2b, w3b]
return list_fields
[docs] def write_card(self, size=8, is_double=False):
card = self.repr_fields()
if size == 8:
return self.comment() + print_card_8(card)
return self.comment() + print_card_16(card)
[docs]class CBEAM3(CBAR):
"""
Defines a three-node beam element
"""
type = 'CBEAM3'
def __init__(self, card=None, data=None, comment=''):
LineElement.__init__(self, card, data)
if comment:
self._comment = comment
if card:
self.eid = integer(card, 1, 'eid')
self.pid = integer_or_blank(card, 2, 'pid', self.eid)
self.ga = integer(card, 3, 'ga')
self.gb = integer(card, 4, 'gb')
self.gc = integer(card, 5, 'gc')
self.initX_G0(card)
self.wa = array([double_or_blank(card, 9, 'w1a', 0.0),
double_or_blank(card, 10, 'w2a', 0.0),
double_or_blank(card, 11, 'w3a', 0.0)], dtype='float64')
self.wb = array([double_or_blank(card, 12, 'w1b', 0.0),
double_or_blank(card, 13, 'w2b', 0.0),
double_or_blank(card, 14, 'w3b', 0.0)], dtype='float64')
self.wc = array([double_or_blank(card, 15, 'w1c', 0.0),
double_or_blank(card, 16, 'w2c', 0.0),
double_or_blank(card, 17, 'w3c', 0.0)], dtype='float64')
self.tw = array([double_or_blank(card, 18, 0., 'twa'),
double_or_blank(card, 19, 0., 'twb'),
double_or_blank(card, 20, 0., 'twc')], dtype='float64')
self.s = array([integer_or_blank(card, 21, 'sa'),
integer_or_blank(card, 22, 'sb'),
integer_or_blank(card, 23, 'sc')], dtype='float64')
assert len(card) <= 24, 'len(CBEAM3 card) = %i' % len(card)
else:
raise NotImplementedError(data)
[docs] def cross_reference(self, model):
msg = ' which is required by %s eid=%s' % (self.type, self.eid)
self.ga = model.Node(self.ga, msg=msg)
self.gb = model.Node(self.gb, msg=msg)
self.gc = model.Node(self.gc, msg=msg)
self.pid = model.Property(self.pid, msg=msg)
[docs] def Length(self):
"""
.. math:: L = g_b - g_a
"""
L = norm(self.gb.Position() - self.ga.Position())
return L
[docs] def raw_fields(self):
(x1, x2, x3) = self.getX_G0_defaults()
(ga, gb, gc) = self.node_ids
list_fields = ['CBEAM3', self.eid, self.Pid(), ga, gb, gc, x1, x2, x3] + \
list(self.wa) + list(self.wb) + list(self.wc) + list(self.tw) + list(self.s)
return list_fields
[docs] def repr_fields(self):
w1a = set_blank_if_default(self.wa[0], 0.0)
w2a = set_blank_if_default(self.wa[1], 0.0)
w3a = set_blank_if_default(self.wa[2], 0.0)
w1b = set_blank_if_default(self.wb[0], 0.0)
w2b = set_blank_if_default(self.wb[1], 0.0)
w3b = set_blank_if_default(self.wb[2], 0.0)
w1c = set_blank_if_default(self.wc[0], 0.0)
w2c = set_blank_if_default(self.wc[1], 0.0)
w3c = set_blank_if_default(self.wc[2], 0.0)
twa = set_blank_if_default(self.tw[0], 0.0)
twb = set_blank_if_default(self.tw[1], 0.0)
twc = set_blank_if_default(self.tw[2], 0.0)
(x1, x2, x3) = self.getX_G0_defaults()
(ga, gb, gc) = self.node_ids
list_fields = ['CBEAM3', self.eid, self.Pid(), ga, gb, gc, x1, x2, x3,
w1a, w2a, w3a, w1b, w2b, w3b, w1c, w2c, w3c,
twa, twb, twc, self.s[0], self.s[1], self.s[2]]
return list_fields
[docs] def write_card(self, size=8, is_double=False):
card = self.repr_fields()
if size == 8:
return self.comment() + print_card_8(card)
return self.comment() + print_card_16(card)
[docs]class CBEND(LineElement):
type = 'CBEND'
_field_map = {
1: 'eid', 2:'pid', 3:'ga', 4:'gb', 8:'geom',
}
[docs] def _update_field_helper(self, n, value):
if self.g0 is not None:
if n == 5:
self.g0 = value
else:
raise KeyError('Field %r=%r is an invalid %s entry.' % (n, value, self.type))
else:
if n == 5:
self.x[0] = value
elif n == 6:
self.x[1] = value
elif n == 7:
self.x[2] = value
else:
raise KeyError('Field %r=%r is an invalid %s entry.' % (n, value, self.type))
def __init__(self, card=None, data=None, comment=''):
LineElement.__init__(self, card, data)
if comment:
self._comment = comment
if card:
self.eid = integer(card, 1, 'eid')
self.pid = integer_or_blank(card, 2, 'pid', self.eid)
self.ga = integer(card, 3, 'ga')
self.gb = integer(card, 4, 'gb')
x1Go = integer_double_or_blank(card, 5, 'x1_g0', 0.0)
if isinstance(x1Go, int):
self.g0 = x1Go
self.x = None
elif isinstance(x1Go, float):
self.g0 = None
self.x = array([double_or_blank(card, 5, 'x1', 0.0),
double_or_blank(card, 6, 'x2', 0.0),
double_or_blank(card, 7, 'x3', 0.0)], dtype='float64')
if norm(self.x) == 0.0:
msg = 'G0 vector defining plane 1 is not defined.\n'
msg += 'G0 = %s\n' % self.g0
msg += 'X = %s\n' % self.x
raise RuntimeError(msg)
else:
raise ValueError('invalid x1Go=|%s| on CBEND' % x1Go)
self.geom = integer(card, 8, 'geom')
assert len(card) == 9, 'len(CBEND card) = %i' % len(card)
assert self.geom in [1, 2, 3, 4], 'geom is invalid geom=|%s|' % self.geom
else:
raise NotImplementedError(data)
if self.g0 in [self.ga, self.gb]:
msg = 'G0=%s cannot be GA=%s or GB=%s' % (self.g0, self.ga, self.gb)
raise RuntimeError(msg)
[docs] def Area(self):
if isinstance(self.pid, int):
raise RuntimeError('Element eid=%i has not been cross referenced.\n%s' % (self.eid, str(self)))
return self.pid.Area()
[docs] def raw_fields(self):
(x1, x2, x3) = self.getX_G0_defaults()
list_fields = ['CBEND', self.eid, self.Pid(), self.Ga(), self.Gb(),
x1, x2, x3, self.geom]
return list_fields
[docs] def repr_fields(self):
return self.raw_fields()
[docs] def write_card(self, size, is_double):
card = self.repr_fields()
if size == 8:
return self.comment() + print_card_8(card)
else:
return self.comment() + print_card_16(card)