pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
shell.py
Go to the documentation of this file.
00001 ## GNU Lesser General Public License
00002 ## 
00003 ## Program pyNastran - a python interface to NASTRAN files
00004 ## Copyright (C) 2011-2012  Steven Doyle, Al Danial
00005 ## 
00006 ## Authors and copyright holders of pyNastran
00007 ## Steven Doyle <mesheb82@gmail.com>
00008 ## Al Danial    <al.danial@gmail.com>
00009 ## 
00010 ## This file is part of pyNastran.
00011 ## 
00012 ## pyNastran is free software: you can redistribute it and/or modify
00013 ## it under the terms of the GNU Lesser General Public License as published by
00014 ## the Free Software Foundation, either version 3 of the License, or
00015 ## (at your option) any later version.
00016 ## 
00017 ## pyNastran is distributed in the hope that it will be useful,
00018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 ## GNU General Public License for more details.
00021 ## 
00022 ## You should have received a copy of the GNU Lesser General Public License
00023 ## along with pyNastran.  If not, see <http://www.gnu.org/licenses/>.
00024 ## 
00025 # pylint: disable=C0103,R0902,R0904,R0914
00026 
00027 from __future__ import division, print_function
00028 import sys
00029 
00030 from numpy import array,eye,cross #zeros,dot
00031 from numpy.linalg import det # inv
00032 
00033 from pyNastran.bdf.fieldWriter import (set_blank_if_default,
00034                                        set_default_if_blank)
00035 from pyNastran.bdf.cards.baseCard import Element
00036 from pyNastran.general.generalMath import (Area, Triangle_AreaCentroidNormal,
00037                                            Normal)
00038 
00039 class ShellElement(Element):
00040     type = 'ShellElement'
00041     def __init__(self, card, data):
00042         Element.__init__(self, card, data)
00043 
00044     def Area(self):
00045         raise NotImplementedError('Area undefined for %s' %(self.type))
00046 
00047     def Thickness(self):
00048         return self.pid.Thickness()
00049 
00050     def mid(self):
00051         return self.pid.mid()
00052 
00053     def Mid(self):
00054         return self.pid.Mid()
00055 
00056     def Rho(self):
00057         return self.pid.mid().rho
00058 
00059     def Nsm(self):
00060         return self.pid.Nsm()
00061 
00062     def MassPerArea(self):
00063         return self.pid.MassPerArea()
00064 
00065     def Mass(self):
00066         """
00067         \f[ \large  mass = \frac{mass}{area} area  \f]
00068         """
00069         return self.pid.MassPerArea()*self.Area()
00070 
00071     def flipNormal(self):
00072         raise NotImplementedError('flipNormal undefined for %s' %(self.type))
00073 
00074     def crossReference(self,mesh):
00075         self.nodes = mesh.Nodes(self.nodes)
00076         self.pid   = mesh.Property(self.pid)
00077 
00078 class TriShell(ShellElement):
00079     def __init__(self, card, data):
00080         ShellElement.__init__(self, card, data)
00081 
00082     def Thickness(self):
00083         return self.pid.Thickness()
00084 
00085     def AreaCentroidNormal(self):
00086         """
00087         returns area,centroid, normal as it's more efficient to do them together
00088         """
00089         (n0,n1,n2) = self.nodePositions()
00090         return Triangle_AreaCentroidNormal([n0,n1,n2])
00091 
00092     def Area(self):
00093         """
00094         returns the normal vector
00095         \f[ \large A = \frac{1}{2} (n_0-n_1) \cross (n_0-n_2)  \f]
00096         """
00097         (n0,n1,n2) = self.nodePositions()
00098         a = n0-n1
00099         b = n0-n2
00100         area = Area(a,b)
00101         return area
00102 
00103     def Normal(self):
00104         """
00105         returns the normal vector
00106         \f[ \large a = (n_0-n_1) \cross (n_0-n_2)  \f]
00107         \f[ \large n = \frac{n}{norm(N)}           \f]
00108         """
00109         (n0,n1,n2) = self.nodePositions()
00110         a = n0-n1
00111         b = n0-n2
00112         return Normal(a,b)
00113 
00114     def Centroid(self,debug=False):
00115         """
00116         returns the centroid
00117         \f[ \large CG = \frac{1}{3} (n_0+n_1+n_2)  \f]
00118         """
00119         (n0,n1,n2) = self.nodePositions()
00120         centroid = self.CentroidTriangle(n0,n1,n2,debug)
00121         return centroid
00122 
00123     def MassMatrix(self, isLumped=True):
00124         """
00125         6x6 mass matrix triangle
00126         http://www.colorado.edu/engineering/cas/courses.d/IFEM.d/IFEM.Ch32.d/IFEM.Ch32.pdf
00127         """
00128         mass = self.Mass() # rho*A*t
00129         if isLumped:  # lumped mass matrix
00130             Mass = mass/3*eye(6)
00131         else: # consistent mass
00132             M = eye(6)*2.
00133             M[2,0] = M[4,0] = M[0,2] = M[0,4] = 1.
00134             M[3,1] = M[5,1] = M[1,3] = M[1,5] = 1.
00135             M[4,2] = M[2,4] = 1.
00136             M[5,3] = M[5,3] = 1.
00137             Mass = mass/12*M
00138         return Mass
00139 
00140 class CTRIA3(TriShell):
00141     type = 'CTRIA3'
00142     asterType = 'TRIA3'
00143     calculixType = 'S3'
00144     def __init__(self,card=None,data=None):
00145         TriShell.__init__(self, card, data)
00146         if card:
00147             ## element ID number
00148             self.eid = int(card.field(1))
00149             self.pid = card.field(2)
00150 
00151             nids = card.fields(3,6)
00152 
00153             self.thetaMcid = card.field(6,0.0)
00154             self.zOffset   = card.field(7,0.0)
00155 
00156             self.TFlag = card.field(10,0)
00157             self.T1 = card.field(11,1.0)
00158             self.T2 = card.field(12,1.0)
00159             self.T3 = card.field(13,1.0)
00160         else:
00161             self.eid = data[0]
00162             self.pid = data[1]
00163             nids = data[2:5]
00164 
00165             self.thetaMcid = data[5]
00166             self.zOffset   = data[6]
00167             self.TFlag     = data[7]
00168             self.T1 = data[8]
00169             self.T2 = data[9]
00170             self.T3 = data[10]
00171             if self.T1==-1.0: self.T1=1.0
00172             if self.T2==-1.0: self.T2=1.0
00173             if self.T3==-1.0: self.T3=1.0
00174         ###
00175         self.prepareNodeIDs(nids)
00176         assert len(self.nodes)==3
00177 
00178     def flipNormal(self):
00179         """
00180              1           1
00181             * *   -->   * *
00182            *   *       *   *
00183           2-----3     3-----2
00184         """
00185         (n1,n2,n3) = self.nodes
00186         self.nodes = [n1,n3,n2]
00187 
00188     def Interp(self,un):
00189         """
00190         Interpolation based on the area coordinates
00191         """
00192         (n0,n1,n2) = self.nodePositions()
00193         nc = (n0+n1+n2)/3.
00194 
00195         a = n0-nc
00196         b = n1-nc
00197         c = n2-nc
00198 
00199         tA1 = det(cross(b,c))   # 2*A1
00200         tA2 = det(cross(c,a))   # 2*A2
00201         tA3 = det(cross(a,b))   # 2*A3
00202         otA = 1./(tA1+tA2+tA3)  # 1/2A
00203 
00204         S = array([tA1,tA2,tA3])*otA  # Ai/A
00205         u = S*un
00206         return u
00207 
00208     def Jacob(self):
00209         (n0, n1, n2) = self.nodePositions()
00210         (nx0, ny0, nz0) = n0
00211         (nx1, ny1, nz1) = n1
00212         (nx2, ny2, nz2) = n2
00213         #J = matrix([n0,n1-n0,n2-n0])
00214         
00215         J = array([ [nx0, nx1-nx0, nx2-nx0],
00216                     [ny0, ny1-ny0, ny2-ny0],
00217                     [nz0, nz1-nz0, nz2-nz0], ])
00218         detJ = J.det()
00219         return J
00220 
00221     def getReprDefaults(self):
00222         zOffset   = set_blank_if_default(self.zOffset, 0.0)
00223         TFlag     = set_blank_if_default(self.TFlag, 0)
00224         thetaMcid = set_blank_if_default(self.thetaMcid, 0.0)
00225 
00226         T1 = set_blank_if_default(self.T1, 1.0)
00227         T2 = set_blank_if_default(self.T2, 1.0)
00228         T3 = set_blank_if_default(self.T3, 1.0)
00229         return (thetaMcid, zOffset, TFlag, T1, T2, T3)
00230 
00231     def rawFields(self):
00232         fields = ['CTRIA3', self.eid, self.Pid()]+self.nodeIDs()+[self.thetaMcid, self.zOffset, None]+[
00233             None, self.TFlag, self.T1, self.T2, self.T3]
00234         return fields
00235 
00236     def reprFields(self):
00237         (thetaMcid,zOffset,TFlag,T1,T2,T3) = self.getReprDefaults()
00238         fields = [self.type,self.eid,self.Pid()]+self.nodeIDs()+[thetaMcid,zOffset,None]+[
00239         None,TFlag,T1,T2,T3]
00240         return fields
00241 
00242 class CTRIA6(TriShell):
00243     type = 'CTRIA6'
00244     asterType = 'TRIA6'
00245     calculixType = 'S6'
00246     def __init__(self,card=None,data=None):
00247         TriShell.__init__(self, card, data)
00248         if card:
00249             ## element ID number
00250             self.eid = int(card.field(1))
00251             self.pid = card.field(2)
00252 
00253             nids = card.fields(3,9)
00254             self.thetaMcid = card.field(9 ,0.0)
00255             self.zOffset   = card.field(10,0.0)
00256 
00257             self.T1 = card.field(11,1.0)
00258             self.T2 = card.field(12,1.0)
00259             self.T3 = card.field(13,1.0)
00260             self.TFlag = card.field(14,0)
00261         else:
00262             self.eid = data[0]
00263             self.pid = data[1]
00264             nids     = data[2:8]
00265             self.thetaMcid = data[8]
00266             self.zOffset   = data[8]
00267             self.T1    = data[9]
00268             self.T2    = data[10]
00269             self.T3    = data[11]
00270             self.TFlag = data[12]
00271         self.prepareNodeIDs(nids,allowEmptyNodes=True)
00272         assert len(nids)==6,'error on CTRIA6'
00273 
00274         #print self.thetaMcid
00275         #print card
00276 
00277         #print "self.xi = ",self.xi
00278         #raise
00279 
00280     def Thickness(self):
00281         return self.pid.Thickness()
00282 
00283     def AreaCentroidNormal(self):
00284         """
00285         returns area,centroid, normal as it's more efficient to do them together
00286         """
00287         (n1, n2, n3, n4, n5, n6) = self.nodePositions()
00288         return Triangle_AreaCentroidNormal([n1, n2, n3])
00289 
00290     def Area(self):
00291         """
00292         returns the normal vector
00293         \f[ \large A = \frac{1}{2} (n_0-n_1) \cross (n_0-n_2)  \f]
00294         """
00295         (n1, n2, n3, n4, n5, n6) = self.nodePositions()
00296         a = n1-n2
00297         b = n1-n3
00298         area = Area(a, b)
00299         return area
00300 
00301     def Normal(self):
00302         """
00303         returns the normal vector
00304         \f[ \large a = (n_0-n_1) \cross (n_0-n_2)  \f]
00305         \f[ \large n = \frac{n}{norm(N)}           \f]
00306         """
00307         (n1,n2,n3,n4,n5,n6) = self.nodePositions()
00308         a = n1-n2
00309         b = n1-n3
00310         return Normal(a,b)
00311 
00312     def Centroid(self,debug=False):
00313         """
00314         returns the centroid
00315         \f[ \large CG = \frac{1}{3} (n_1+n_2+n_3)  \f]
00316         """
00317         (n1,n2,n3,n4,n5,n6) = self.nodePositions()
00318         centroid = self.CentroidTriangle(n1,n2,n3,debug)
00319         return centroid
00320 
00321     def flipNormal(self):
00322         """
00323              1                1
00324              **               **
00325             *  *             *  *
00326            4    6   -->     6    4
00327           *      *         *      *
00328          2----5---3       3----5---2
00329         """
00330         (n1,n2,n3,n4,n5,n6) = self.nodes
00331         self.nodes = [n1,n3,n2,n6,n5,n4]
00332         
00333     def getReprDefaults(self):
00334         zOffset   = set_blank_if_default(self.zOffset,0.0)
00335         TFlag     = set_blank_if_default(self.TFlag,0)
00336         thetaMcid = set_blank_if_default(self.thetaMcid,0.0)
00337 
00338         T1 = set_blank_if_default(self.T1,1.0)
00339         T2 = set_blank_if_default(self.T2,1.0)
00340         T3 = set_blank_if_default(self.T3,1.0)
00341         return (thetaMcid,zOffset,TFlag,T1,T2,T3)
00342 
00343     def rawFields(self):
00344         fields = ['CTRIA6',self.eid,self.Pid()]+self.nodeIDs()+[self.thetaMcid,self.zOffset,None]+[
00345         None,self.TFlag,self.T1,self.T2,self.T3]
00346         return fields
00347 
00348     def reprFields(self):
00349         (thetaMcid,zOffset,TFlag,T1,T2,T3) = self.getReprDefaults()
00350         fields = ['CTRIA6',self.eid,self.Pid()]+self.nodeIDs()+[thetaMcid,zOffset,None]+[
00351         None,TFlag,T1,T2,T3]
00352         return fields
00353 
00354 class CTRIAR(TriShell):
00355     type = 'CTRIAR'
00356     def __init__(self,card=None,data=None):
00357         TriShell.__init__(self, card, data)
00358         ## element ID number
00359         self.eid = int(card.field(1))
00360         self.pid = card.field(2)
00361 
00362         nids = card.fields(3,6)
00363         self.prepareNodeIDs(nids)
00364         assert len(self.nodes)==3
00365 
00366         self.thetaMcid = card.field(6,0.0)
00367         self.zOffset   = card.field(7,0.0)
00368 
00369         self.TFlag = card.field(10,0)
00370         self.T1 = card.field(11,1.0)
00371         self.T2 = card.field(12,1.0)
00372         self.T3 = card.field(13,1.0)
00373 
00374     def Thickness(self):
00375         return self.pid.Thickness()
00376 
00377     def flipNormal(self):
00378         """
00379              1           1
00380             * *   -->   * *
00381            *   *       *   *
00382           2-----3     3-----2
00383         """
00384         (n1,n2,n3) = self.nodes
00385         self.nodes = [n1,n3,n2]
00386 
00387     def getReprDefaults(self):
00388         zOffset   = set_blank_if_default(self.zOffset,0.0)
00389         TFlag     = set_blank_if_default(self.TFlag,0)
00390         thetaMcid = set_blank_if_default(self.thetaMcid,0.0)
00391 
00392         T1 = set_blank_if_default(self.T1,1.0)
00393         T2 = set_blank_if_default(self.T2,1.0)
00394         T3 = set_blank_if_default(self.T3,1.0)
00395         return (thetaMcid,zOffset,TFlag,T1,T2,T3)
00396 
00397     def rawFields(self):
00398         fields = [self.eid,self.Pid()]+self.nodeIDs()+[self.thetaMcid,self.zOffset,self.TFlag,self.T1,self.T2,self.T3]
00399         return fields
00400 
00401     def reprFields(self):
00402         (thetaMcid,zOffset,TFlag,T1,T2,T3) = self.getReprDefaults()
00403         fields = ['CTRIAR',self.eid,self.Pid()]+self.nodeIDs()+[thetaMcid,zOffset,None,
00404                   None,TFlag,T1,T2,T3]
00405         return fields
00406 
00407 class CTRIAX(TriShell):
00408     type = 'CTRIAX'
00409     calculixType = 'CAX6'
00410     def __init__(self,card=None,data=None):
00411         TriShell.__init__(self, card, data)
00412         ## element ID number
00413         self.eid = int(card.field(1))
00414 
00415         nids = card.fields(3,9)
00416         self.prepareNodeIDs(nids,allowEmptyNodes=True)
00417         assert len(nids)==6,'error on CTRIAX'
00418 
00419     def rawFields(self):
00420         fields = ['CTRIAX',self.eid,self.Pid()]+self.nodeIDs()
00421         return fields
00422 
00423     def reprFields(self):
00424         return self.rawFields()
00425 
00426 class CTRIAX6(TriShell):
00427     """
00428     Nodes defined in a non-standard way
00429          5
00430         / \
00431        6   4
00432      /       \
00433     1----2----3
00434     """
00435     type = 'CTRIAX6'
00436     #calculixType = 'CAX6'
00437     def __init__(self,card=None,data=None):
00438         TriShell.__init__(self, card, data)
00439         ## element ID number
00440         self.eid = int(card.field(1))
00441         self.mid = int(card.field(2))
00442 
00443         nids = card.fields(3,9)
00444         self.prepareNodeIDs(nids,allowEmptyNodes=True)
00445         assert len(nids)==6,'error on CTRIAX6'
00446 
00447         ## theta
00448         self.th = card.field(10,0.0)
00449 
00450     def Area(self):
00451         """
00452         returns the normal vector
00453         \f[ \large A = \frac{1}{2} (n_0-n_1) \cross (n_0-n_2)  \f]
00454         """
00455         (n1,n2,n3,n4,n5,n6) = self.nodePositions()
00456         a = n1-n3
00457         b = n1-n5
00458         area = Area(a,b)
00459         return area
00460 
00461     def Thickness(self):
00462         raise AttributeError('CTRIAX6 does not have a thickness')
00463 
00464     def Nsm(self):
00465         raise AttributeError('CTRIAX6 does not have a non-structural mass')
00466 
00467     def crossReference(self,model):
00468         self.nodes = model.Nodes(self.nodes)
00469         self.mid   = model.Material(self.mid)
00470     
00471     def Mid(self):
00472         if isinstance(self.mid,int):
00473             return self.mid
00474         return self.mid.mid
00475 
00476     def flipNormal(self):
00477         """
00478              5               5
00479             / \             / \
00480            6   4   -->     6   4
00481          /       \       /       \
00482         1----2----3     1----2----3
00483         """
00484         (n1,n2,n3,n4,n5,n6) = self.nodes
00485         self.nodes = [n1,n6,n5,n4,n3,n2]
00486 
00487     def rawFields(self):
00488         fields = ['CTRIAX6',self.eid,self.Mid(),self.Pid()]+self.nodeIDs()+[
00489                   self.th]
00490         return fields
00491 
00492     def reprFields(self):
00493         th = set_default_if_blank(self.th, 0.0)
00494         fields = ['CTRIAX6', self.eid, self.Mid()]+self.nodeIDs()+[th]
00495         return fields
00496 
00497 class QuadShell(ShellElement):
00498     def __init__(self,card=None,data=None):
00499         ShellElement.__init__(self, card, data)
00500 
00501     def Thickness(self):
00502         return self.pid.Thickness()
00503 
00504     def Normal(self):
00505         (n1,n2,n3,n4) = self.nodePositions()
00506         a = n1-n3
00507         b = n2-n4
00508         return Normal(a,b)
00509 
00510     def AreaCentroidNormal(self):
00511         (area,centroid) = self.AreaCentroid()
00512         normal = self.Normal()
00513         return (area,centroid,normal)
00514 
00515     def AreaCentroid(self,debug=False):
00516         """
00517         1-----2
00518         |    /|
00519         | A1/ |
00520         |  /  |
00521         |/ A2 |
00522         4-----3
00523         
00524         centroid
00525            c = sum(ci*Ai)/sum(A)
00526            where:
00527              c=centroid
00528              A=area
00529         """
00530         #if debug:
00531         #    print("nodes = %s" %(self.nodes))
00532         (n1,n2,n3,n4) = self.nodePositions()
00533         a = n1-n2
00534         b = n2-n4
00535         area1 = Area(a,b)
00536         c1 = self.CentroidTriangle(n1,n2,n4)
00537 
00538         a = n2-n4
00539         b = n2-n3
00540         area2 = Area(a,b)
00541         c2 = self.CentroidTriangle(n2,n3,n4)
00542         
00543         area = area1+area2
00544         centroid = (c1*area1+c2*area2)/area
00545         if debug:
00546             print("c1=%s \n c2=%s \n a1=%s a2=%s" %(c1,c2,area1,area2))
00547             print("type(centroid=%s centroid=%s \n" %(type(centroid),centroid))
00548         return(area,centroid)
00549     ###
00550 
00551     def Centroid(self,debug=False):
00552         #nodes = self.nodePositions()
00553         (area,centroid) = self.AreaCentroid(debug)
00554         return centroid
00555 
00556     def Area(self):
00557         """
00558         \f[ A = \frac{1}{2} \lvert (n_1-n_3) \times (n_2-n_4) \rvert \f]
00559         where a and b are the quad's cross node point vectors
00560         """
00561         (n1,n2,n3,n4) = self.nodePositions()
00562         a = n1-n3
00563         b = n2-n4
00564         area = Area(a,b)
00565         return area
00566     ###
00567 
00568     def MassMatrix(self, isLumped=True, gauss=1):
00569         """
00570         6x6 mass matrix triangle
00571         http://www.colorado.edu/engineering/cas/courses.d/IFEM.d/IFEM.Ch32.d/IFEM.Ch32.pdf
00572         """
00573         mass = self.Mass() # rho*A*t
00574         if isLumped:  # lumped mass matrix
00575             Mass = mass/3*eye(6)
00576         else: # consistent mass
00577             if gauss==1:
00578                 M = eye(8)*1. # 1x1 Gauss Rule
00579                 M[2,0] = M[3,1] = M[4,2] = M[5,3] = M[6,4] = M[7,5] = 1.
00580                 M[4,0] = M[5,1] = M[6,2] = M[7,3] = 1.
00581                 M[6,0] = M[7,1] = 1.
00582 
00583                 M[0,2] = M[1,3] = M[2,4] = M[3,5] = M[4,6] = M[5,7] = 1.
00584                 M[0,4] = M[1,5] = M[2,6] = M[3,7] = 1.
00585                 M[0,6] = M[1,7] = 1.
00586                 Mass = mass/32*M
00587             if gauss==2:
00588                 M = eye(8)*4. # 2x2 Gauss Rule
00589                 M[2,0] = M[3,1] = M[4,2] = M[5,3] = M[6,4] = M[7,5] = 2.
00590                 M[4,0] = M[5,1] = M[6,2] = M[7,3] = 1.
00591                 M[6,0] = M[7,1] = 2.
00592 
00593                 M[0,2] = M[1,3] = M[2,4] = M[3,5] = M[4,6] = M[5,7] = 2.
00594                 M[0,4] = M[1,5] = M[2,6] = M[3,7] = 1.
00595                 M[0,6] = M[1,7] = 2.
00596                 Mass = mass/72*M
00597         return Mass
00598 
00599     def flipNormal(self):
00600         """
00601         1---2        1---4
00602         |   |  -->   |   |
00603         |   |        |   |
00604         4---3        2---3
00605         """
00606         (n1,n2,n3,n4) = self.nodes
00607         self.nodes = [n1,n4,n3,n2]
00608 
00609     def getReprDefaults(self,debug=False):
00610         zOffset   = set_blank_if_default(self.zOffset,0.0)
00611         TFlag     = set_blank_if_default(self.TFlag,0)
00612         thetaMcid = set_blank_if_default(self.thetaMcid,0.0)
00613 
00614         T1 = set_blank_if_default(self.T1,1.0)
00615         T2 = set_blank_if_default(self.T2,1.0)
00616         T3 = set_blank_if_default(self.T3,1.0)
00617         T4 = set_blank_if_default(self.T4,1.0)
00618         if debug:
00619         #if 1:
00620             print("eid       = %s" %(self.eid))
00621             print("nodes     = %s" %(self.nodes))
00622 
00623             print("self.zOffset   = %s" %(self.zOffset))
00624             print("self.TFlag     = %s" %(self.TFlag))
00625             print("self.thetaMcid = %s" %(self.thetaMcid))
00626 
00627             print("zOffset   = %s" %(zOffset))
00628             print("TFlag     = %s" %(TFlag))
00629             print("thetaMcid = %s" %(thetaMcid))
00630 
00631             print("T1 = %s" %(T1))
00632             print("T2 = %s" %(T2))
00633             print("T3 = %s" %(T3))
00634             print("T4 = %s\n" %(T4))
00635         return (thetaMcid,zOffset,TFlag,T1,T2,T3,T4)
00636 
00637 class CSHEAR(QuadShell):
00638     type = 'CSHEAR'
00639     calculixType = 'S4'
00640     def __init__(self,card=None,data=None):
00641         QuadShell.__init__(self, card, data)
00642         if card:
00643             self.eid = card.field(1)
00644             self.pid = card.field(2)
00645             nids = card.fields(3,7)
00646         else:
00647             self.eid = data[0]
00648             self.pid = data[1]
00649             nids = data[2:]
00650         ###
00651         self.prepareNodeIDs(nids)
00652         assert len(self.nodes)==4
00653 
00654     def Normal(self):
00655         (n1,n2,n3,n4) = self.nodePositions()
00656         a = n1-n3
00657         b = n2-n4
00658         return Normal(a,b)
00659 
00660     def AreaCentroidNormal(self):
00661         (area,centroid) = self.AreaCentroid()
00662         normal = self.Normal()
00663         return (area,centroid,normal)
00664 
00665     def AreaCentroid(self,debug=False):
00666         """
00667         1-----2
00668         |    /|
00669         | A1/ |
00670         |  /  |
00671         |/ A2 |
00672         4-----3
00673         
00674         centroid
00675            c = sum(ci*Ai)/sum(A)
00676            where:
00677              c=centroid
00678              A=area
00679         """
00680         #if debug:
00681         #    print("nodes = %s" %(self.nodes))
00682         (n1,n2,n3,n4) = self.nodePositions()
00683         a = n1-n2
00684         b = n2-n4
00685         area1 = Area(a,b)
00686         c1 = self.CentroidTriangle(n1,n2,n4)
00687 
00688         a = n2-n4
00689         b = n2-n3
00690         area2 = Area(a,b)
00691         c2 = self.CentroidTriangle(n2,n3,n4)
00692         
00693         area = area1+area2
00694         centroid = (c1*area1+c2*area2)/area
00695         if debug:
00696             print("c1=%s \n c2=%s \n a1=%s a2=%s" %(c1,c2,area1,area2))
00697             print("type(centroid=%s centroid=%s \n" %(type(centroid),centroid))
00698         return(area,centroid)
00699     ###
00700 
00701     def Centroid(self,debug=False):
00702         (area,centroid) = self.AreaCentroid(debug)
00703         return centroid
00704 
00705     def Area(self):
00706         """
00707         \f[ A = \frac{1}{2} \lvert (n_1-n_3) \times (n_2-n_4) \rvert \f]
00708         where a and b are the quad's cross node point vectors
00709         """
00710         (n1,n2,n3,n4) = self.nodePositions()
00711         a = n1-n3
00712         b = n2-n4
00713         area = Area(a,b)
00714         return area
00715     ###
00716 
00717     def flipNormal(self):
00718         """
00719         1---2        1---4
00720         |   |  -->   |   |
00721         |   |        |   |
00722         4---3        2---3
00723         """
00724         (n1,n2,n3,n4) = self.nodes
00725         self.nodes = [n1,n4,n3,n2]
00726 
00727     def rawFields(self):
00728         fields = ['CSHEAR',self.eid,self.Pid()]+self.nodeIDs()
00729         return fields
00730     
00731     def reprFields(self):
00732         return self.rawFields()
00733 
00734 
00735 class CQUAD4(QuadShell):
00736     type = 'CQUAD4'
00737     asterType = 'QUAD4 # CQUAD4'
00738     calculixType = 'S4'
00739     def __init__(self,card=None,data=None):
00740         QuadShell.__init__(self, card, data)
00741         if card:
00742             ## element ID number
00743             self.eid = int(card.field(1))
00744             self.pid = card.field(2)
00745 
00746             nids = card.fields(3,7)
00747 
00748             self.thetaMcid = card.field(7,0.0)
00749             self.zOffset   = card.field(8,0.0)
00750 
00751             self.TFlag = card.field(10,0)
00752             self.T1 = card.field(11,1.0)
00753             self.T2 = card.field(12,1.0)
00754             self.T3 = card.field(13,1.0)
00755             self.T4 = card.field(14,1.0)
00756         else:
00757             self.eid = data[0]
00758             self.pid = data[1]
00759             nids = data[2:6]
00760 
00761             self.thetaMcid = data[6]
00762             self.zOffset   = data[7]
00763             self.TFlag     = data[8]
00764             self.T1 = data[9]
00765             self.T2 = data[10]
00766             self.T3 = data[11]
00767             self.T4 = data[12]
00768             if self.T1==-1.0: self.T1=1.0
00769             if self.T2==-1.0: self.T2=1.0
00770             if self.T3==-1.0: self.T3=1.0
00771             if self.T4==-1.0: self.T4=1.0
00772         ###            
00773         self.prepareNodeIDs(nids)
00774         assert len(self.nodes)==4,'CQUAD4'
00775 
00776         #print "self.xi = ",self.xi
00777         #print "nodes = ",self.nodes
00778         #for nid in nids:
00779         #    self.nodes.append(int(nid))
00780 
00781         #print 'self.T1 = ',self.T1
00782         #if self.id==20020:
00783             #print "thetaMcid = ",card.field(7)
00784             #print "actual = ",self.thetaMcid
00785             #print str(self)
00786         
00787     def flipNormal(self):
00788         """
00789         1---2        1---4
00790         |   |  -->   |   |
00791         |   |        |   |
00792         4---3        2---3
00793         """
00794         (n1,n2,n3,n4) = self.nodes
00795         self.nodes = [n1,n4,n3,n2]
00796 
00797     def writeAsCTRIA3(self, newID):
00798         """
00799         triangle - 012
00800         triangle - 023
00801         """
00802         zOffset = set_blank_if_default(self.zOffset, 0.0)
00803         nodes1 = [self.nodes[0], self.nodes[1], self.nodes[2]]
00804         nodes2 = [self.nodes[0], self.nodes[2], self.nodes[3]]
00805         fields1 = ['CTRIA3', self.eid, self.Pid()]+nodes1+[self.thetaMcid, zOffset]
00806         fields2 = ['CTRIA3', newID,    self.Pid()]+nodes2+[self.thetaMcid, zOffset]
00807         return self.printCard(fields1)+self.printCard(fields2)
00808 
00809     def rawFields(self):
00810         fields = [self.type,self.eid,self.Pid()]+self.nodeIDs()+[self.thetaMcid,self.zOffset,self.TFlag,self.T1,self.T2,self.T3,self.T4]
00811         return fields
00812 
00813     def reprFields(self):
00814         debug = False
00815         (thetaMcid,zOffset,TFlag,T1,T2,T3,T4) = self.getReprDefaults(debug=debug)
00816 
00817         fields = ['CQUAD4',self.eid,self.Pid()]+self.nodeIDs()+[thetaMcid,zOffset,
00818                   None,TFlag,T1,T2,T3,T4]
00819         return fields
00820 
00821 class CQUADR(QuadShell):
00822     type = 'CQUADR'
00823     #calculixType = 'CAX8'
00824     def __init__(self,card=None,data=None):
00825         QuadShell.__init__(self, card, data)
00826         if card:
00827             ## element ID number
00828             self.eid = int(card.field(1))
00829             self.pid = card.field(2)
00830 
00831             nids = card.fields(3,7)
00832 
00833             self.thetaMcid = card.field(7,0.0)
00834             self.zOffset   = card.field(8,0.0)
00835 
00836             self.TFlag = card.field(10,0)
00837             self.T1 = card.field(11,1.0)
00838             self.T2 = card.field(12,1.0)
00839             self.T3 = card.field(13,1.0)
00840             self.T4 = card.field(14,1.0)
00841         else:
00842             self.eid = data[0]
00843             self.pid = data[1]
00844             nids = data[2:6]
00845 
00846             self.thetaMcid = data[6]
00847             self.zOffset   = data[7]
00848             self.TFlag     = data[8]
00849             self.T1 = data[9]
00850             self.T2 = data[10]
00851             self.T3 = data[11]
00852             self.T4 = data[12]
00853             if self.T1==-1.0: self.T1=1.0
00854             if self.T2==-1.0: self.T2=1.0
00855             if self.T3==-1.0: self.T3=1.0
00856             if self.T4==-1.0: self.T4=1.0
00857         ###            
00858         self.prepareNodeIDs(nids)
00859         assert len(self.nodes)==4,'CQUADR'
00860 
00861     def Thickness(self):
00862         return self.pid.Thickness()
00863 
00864     def flipNormal(self):
00865         """
00866         1---2        1---4
00867         |   |  -->   |   |
00868         |   |        |   |
00869         4---3        2---3
00870         """
00871         (n1,n2,n3,n4) = self.nodes
00872         self.nodes = [n1,n4,n3,n2]
00873 
00874     def rawFields(self):
00875         fields = ['CQUADR',self.eid,self.Pid()]+self.nodeIDs()+[self.thetaMcid,self.zOffset,
00876                   None,self.TFlag,self.T1,self.T2,self.T3,self.T4,]
00877         return fields
00878 
00879     def reprFields(self):
00880         (thetaMcid,zOffset,TFlag,T1,T2,T3,T4) = self.getReprDefaults()
00881         fields = ['CQUADR',self.eid,self.Pid()]+self.nodeIDs()+[thetaMcid,zOffset,
00882                   None,TFlag,T1,T2,T3,T4]
00883         return fields
00884 
00885 class CQUAD(QuadShell):
00886     type = 'CQUAD'
00887     def __init__(self,card=None,data=None):
00888         QuadShell.__init__(self, card, data)
00889         ## element ID number
00890         self.eid = int(card.field(1))
00891         self.pid = card.field(2)
00892 
00893         nids = card.fields(3,12)
00894         self.prepareNodeIDs(nids)
00895         assert len(self.nodes)==9
00896 
00897         self.thetaMcid = card.field(7,0.0)
00898         self.zOffset   = card.field(8,0.0)
00899 
00900         self.TFlag = card.field(10,0)
00901         self.T1 = card.field(11,1.0)
00902         self.T2 = card.field(12,1.0)
00903         self.T3 = card.field(13,1.0)
00904         self.T4 = card.field(14,1.0)
00905 
00906     def Thickness(self):
00907         return self.pid.Thickness()
00908 
00909     def flipNormal(self):
00910         """
00911         1--5--2        1--8--4
00912         |     |  -->   |     |
00913         8  9  6        5  9  7
00914         |     |        |     |
00915         4--7--3        2--6--3
00916         """
00917         (n1,n2,n3,n4,n5,n6,n7,n8,n9) = self.nodes
00918         self.nodes = [n1,n4,n3,n2,  n8,n7,n6,n5,  n9]
00919 
00920     def rawFields(self):
00921         fields = ['CQUAD',self.eid,self.Pid()]+self.nodeIDs()
00922         return fields
00923 
00924     def reprFields(self):
00925         (thetaMcid,zOffset,TFlag,T1,T2,T3,T4) = self.getReprDefaults()
00926         fields = ['CQUAD',self.eid,self.Pid()]+self.nodeIDs()
00927         return fields
00928 
00929 class CQUAD8(QuadShell):
00930     type = 'CQUAD8'
00931     asterType = 'QUAD8'
00932     def __init__(self,card=None,data=None):
00933         QuadShell.__init__(self, card, data)
00934         if card:
00935             ## element ID number
00936             self.eid = int(card.field(1))
00937             self.pid = card.field(2)
00938             nids     = card.fields(3,11)
00939             self.T1  = card.field(11,1.0)
00940             self.T2  = card.field(12,1.0)
00941             self.T3  = card.field(13,1.0)
00942             self.T4  = card.field(14,1.0)
00943             self.thetaMcid = card.field(15,0.0)
00944             self.zOffset   = card.field(16,0.0)
00945             self.TFlag     = card.field(17,0)
00946         else:
00947             #print "CQUAD8 = ",data
00948             #(6401, 
00949             #6400, 
00950             #6401, 6402, 6405, 6403, 0, 0, 6404, 0, 
00951             #-1.0, -1.0, -1.0, -1.0, 
00952             #0.0, 0)
00953             self.eid = data[0]
00954             self.pid = data[1]
00955             nids     = data[2:10]
00956             self.T1  = data[10]
00957             self.T2  = data[11]
00958             self.T3  = data[12]
00959             self.T4  = data[13]
00960             self.thetaMcid = data[14]
00961             self.zOffset   = data[14]
00962             self.TFlag     = data[15]
00963         ###
00964         self.prepareNodeIDs(nids,allowEmptyNodes=True)
00965         assert len(self.nodes)==8
00966 
00967     def Thickness(self):
00968         return self.pid.Thickness()
00969 
00970     def flipNormal(self):
00971         """
00972         1--5--2        1--8--4
00973         |     |  -->   |     |
00974         8     6        5     7
00975         |     |        |     |
00976         4--7--3        2--6--3
00977         """
00978         (n1,n2,n3,n4,n5,n6,n7,n8) = self.nodes
00979         self.nodes = [n1,n4,n3,n2,  n8,n7,n6,n5]
00980 
00981     def Normal(self):
00982         (n1,n2,n3,n4,n5,n6,n7,n8) = self.nodePositions()
00983         a = n1-n3
00984         b = n2-n4
00985         return Normal(a,b)
00986 
00987     def AreaCentroid(self,debug=False):
00988         """
00989         1-----2
00990         |    /|
00991         | A1/ |
00992         |  /  |
00993         |/ A2 |
00994         4-----3
00995         
00996         centroid
00997            c = sum(ci*Ai)/sum(A)
00998            where:
00999              c=centroid
01000              A=area
01001         """
01002         #if debug:
01003         #    print("nodes = %s" %(self.nodes))
01004         (n1,n2,n3,n4,n5,n6,n7,n8) = self.nodePositions()
01005         a = n1-n2
01006         b = n2-n4
01007         area1 = Area(a,b)
01008         c1 = self.CentroidTriangle(n1,n2,n4)
01009 
01010         a = n2-n4
01011         b = n2-n3
01012         area2 = Area(a,b)
01013         c2 = self.CentroidTriangle(n2,n3,n4)
01014         
01015         area = area1+area2
01016         centroid = (c1*area1+c2*area2)/area
01017         if debug:
01018             print("c1=%s \n c2=%s \n a1=%s a2=%s" %(c1,c2,area1,area2))
01019             print("type(centroid=%s centroid=%s \n" %(type(centroid),centroid))
01020         return(area,centroid)
01021     ###
01022 
01023     def Area(self):
01024         """
01025         \f[ A = \frac{1}{2} \lvert (n_1-n_3) \times (n_2-n_4) \rvert \f]
01026         where a and b are the quad's cross node point vectors
01027         """
01028         (n1,n2,n3,n4,n5,n6,n7,n8) = self.nodePositions()
01029         a = n1-n3
01030         b = n2-n4
01031         area = Area(a,b)
01032         return area
01033     ###
01034 
01035     def rawFields(self):
01036         fields = ['CQUAD8',self.eid,self.Pid()]+self.nodeIDs()+[
01037                   self.T1,self.T2,self.T3,self.T4,self.thetaMcid,self.zOffset,
01038                   self.TFlag]
01039         return fields
01040 
01041     def reprFields(self):
01042         (thetaMcid,zOffset,TFlag,T1,T2,T3,T4) = self.getReprDefaults()
01043         fields = ['CQUAD8',self.eid,self.Pid()]+self.nodeIDs()+[
01044                   T1,T2,T3,T4,thetaMcid,zOffset,
01045                   TFlag]
01046         return fields
01047 
01048 class CQUADX(QuadShell):
01049     type = 'CQUADX'
01050     calculixType = 'CAX8'
01051     def __init__(self,card=None,data=None):
01052         QuadShell.__init__(self, card, data)
01053         ## element ID number
01054         self.eid = int(card.field(1))
01055         self.pid = card.field(2)
01056 
01057         nids = card.fields(3,12)
01058         self.prepareNodeIDs(nids,allowEmptyNodes=True)
01059         assert len(self.nodes)==9
01060 
01061     def Thickness(self):
01062         return self.pid.Thickness()
01063 
01064     def flipNormal(self):
01065         """
01066         1--5--2        1--8--4
01067         |     |  -->   |     |
01068         8  9  6        5  9  7
01069         |     |        |     |
01070         4--7--3        2--6--3
01071         """
01072         (n1,n2,n3,n4,n5,n6,n7,n8,n9) = self.nodes
01073         self.nodes = [n1,n4,n3,n2,  n8,n7,n6,n5,  n9]
01074 
01075     def rawFields(self):
01076         fields = ['CQUADX',self.eid,self.Pid()]+self.nodeIDs()
01077         return fields
01078     
01079     def reprFields(self):
01080         return self.rawFields()
 All Classes Namespaces Files Functions Variables