pyNastran
0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
|
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 00026 from __future__ import division, print_function 00027 #import sys 00028 from itertools import izip 00029 00030 from pyNastran.bdf.fieldWriter import set_blank_if_default 00031 from pyNastran.bdf.cards.baseCard import BaseCard 00032 00033 class Method(BaseCard): 00034 """ 00035 Generic class for all methods. 00036 Part of self.methods 00037 """ 00038 def __init__(self, card=None, data=None): 00039 pass 00040 00041 class EIGB(Method): 00042 """ 00043 Defines data needed to perform buckling analysis 00044 """ 00045 type = 'EIGB' 00046 def __init__(self, card=None, data=None): 00047 Method.__init__(self, card, data) 00048 if card: 00049 ## Set identification number. (Unique Integer > 0) 00050 self.sid = card.field(1) 00051 ## Method of eigenvalue extraction. (Character: 'INV' for inverse 00052 ## power method or 'SINV' for enhanced inverse power method.) 00053 self.method = card.field(2) 00054 assert self.method in ['INV', 'SINV'], 'method must be INV or SINV. method=|%s|' %(self.method) 00055 ## Eigenvalue range of interest. (Real, L1 < L2) 00056 self.L1 = card.field(3) 00057 self.L2 = card.field(4) 00058 assert self.L1 < self.L2, 'L1=%s L2=%s; L1<L2 is requried' %(self.L1, self.L2) 00059 ## Estimate of number of roots in positive range not used for 00060 ## METHOD = 'SINV'. (Integer > 0) 00061 self.nep = card.field(5, 0) 00062 ## Desired number of positive and negative roots. 00063 ## (Integer>0; Default = 3*NEP) 00064 self.ndp = card.field(6, 3*self.nep) 00065 self.ndn = card.field(7, 3*self.nep) 00066 ## Method for normalizing eigenvectors. 00067 ## ('MAX' or 'POINT';Default='MAX') 00068 self.norm = card.field(9, 'MAX') 00069 self.G = card.field(10) 00070 self.C = card.field(11) 00071 else: 00072 raise NotImplementedError('EIGB') 00073 ### 00074 #print self.rawFields() 00075 #print self.reprFields() 00076 #print self 00077 00078 def crossReference(self, model): 00079 pass 00080 00081 def rawFields(self): 00082 fields = ['EIGB', self.sid, self.method, self.L1, self.L2, self.nep, self.ndp, self.ndn, None, 00083 self.norm, self.G, self.C] 00084 return fields 00085 00086 def reprFields(self): 00087 #method = set_blank_if_default(self.method,'INV') 00088 nep = set_blank_if_default(self.nep, 0) 00089 ndp = set_blank_if_default(self.ndp, 3*self.nep) 00090 ndn = set_blank_if_default(self.ndn, 3*self.nep) 00091 #print "nep = ",self.nep,ndn 00092 norm = set_blank_if_default(self.norm, 'MAX') 00093 fields = ['EIGB', self.sid, self.method, self.L1, self.L2, nep, ndp, ndn, None, 00094 norm, self.G, self.C] 00095 return fields 00096 00097 class EIGC(Method): ## not done 00098 """ 00099 Defines data needed to perform complex eigenvalue analysis 00100 """ 00101 type = 'EIGC' 00102 def __init__(self, card=None, data=None): 00103 Method.__init__(self, card, data) 00104 if card: 00105 ## Set identification number. (Unique Integer > 0) 00106 self.sid = card.field(1) 00107 ## Method of complex eigenvalue extraction 00108 self.method = card.field(2) 00109 assert self.method in ['INV', 'HESS', 'CLAN'], 'method=%s is not INV, HESS, CLAN' %(self.method) 00110 ## Method for normalizing eigenvectors 00111 self.norm = card.field(3) 00112 00113 ## Grid or scalar point identification number. Required only if 00114 ## NORM='POINT'. (Integer>0) 00115 self.G = card.field(4) 00116 ## Component number. Required only if NORM='POINT' and G is a 00117 ## geometric grid point. (1<Integer<6) 00118 self.C = card.field(5) 00119 ## Convergence criterion. (Real > 0.0. Default values are: 10-4 for 00120 ## METHOD = "INV", 10-15 for METHOD = "HESS", E is machine 00121 ## dependent for METHOD = "CLAN".) 00122 self.E = card.field(6) 00123 self.ndo = card.field(7) 00124 00125 # ALPHAAJ OMEGAAJ ALPHABJ OMEGABJ LJ NEJ NDJ 00126 fields = card.fields(9) 00127 self.alphaAjs = [] 00128 self.omegaAjs = [] 00129 nFields = len(fields) 00130 nRows = nFields//8 00131 if nFields%7 > 0: 00132 nRows += 1 00133 00134 if self.method=='CLAN': 00135 self.loadCLAN(nRows, card) 00136 elif self.method in ['HESS', 'INV']: # HESS, INV 00137 self.loadHESS_INV(nRows, card) 00138 else: 00139 msg = 'invalid EIGC method...method=|%r|' %(self.method) 00140 raise RuntimeError(msg) 00141 ### 00142 #assert card.nFields()<8,'card = %s' %(card.fields(0)) 00143 else: 00144 raise NotImplementedError('EIGC') 00145 ### 00146 00147 def loadCLAN(self, nRows, card): 00148 self.mblkszs = [] 00149 self.iblkszs = [] 00150 self.ksteps = [] 00151 self.NJIs = [] 00152 for iRow in xrange(nRows): 00153 #NDJ_default = None 00154 00155 self.alphaAjs.append(card.field(9+8*iRow , 0.0)) 00156 self.omegaAjs.append(card.field(9+8*iRow+1, 0.0)) 00157 self.mblkszs.append( card.field(9+8*iRow+2, 7)) 00158 00159 #self.alphaAjs.append(card.field(9+8*iRow ,'ALPHA%s'%(iRow))) 00160 #self.omegaAjs.append(card.field(9+8*iRow+1,'OMEGA%s'%(iRow))) 00161 #self.mblkszs.append( card.field(9+8*iRow+2,'MBLOCK%s'%(iRow))) 00162 00163 self.iblkszs.append( card.field(9+8*iRow+3, 2)) 00164 self.ksteps.append( card.field(9+8*iRow+4, 5)) 00165 self.NJIs.append( card.field(9+8*iRow+6)) 00166 ### 00167 00168 def loadHESS_INV(self, nRows, card): 00169 self.alphaBjs = [] 00170 self.omegaBjs = [] 00171 self.LJs = [] 00172 self.NEJs = [] 00173 self.NDJs = [] 00174 00175 alphaOmega_default = None 00176 LJ_default = None 00177 if self.method=='INV': 00178 alphaOmega_default = 0.0 00179 LJ_default = 1.0 00180 00181 for iRow in xrange(nRows): 00182 NEj = card.field(9+7*iRow+5) 00183 NDJ_default = None 00184 if self.method=='INV': 00185 NDJ_default = 3*NEj 00186 00187 self.alphaAjs.append(card.field(9+8*iRow , alphaOmega_default)) 00188 self.omegaAjs.append(card.field(9+8*iRow+1, alphaOmega_default)) 00189 self.alphaBjs.append(card.field(9+8*iRow+2, alphaOmega_default)) 00190 self.omegaBjs.append(card.field(9+8*iRow+3, alphaOmega_default)) 00191 self.LJs.append( card.field(9+8*iRow+4, LJ_default)) 00192 self.NEJs.append( card.field(9+8*iRow+5)) 00193 self.NDJs.append( card.field(9+8*iRow+6, NDJ_default)) 00194 ### 00195 00196 def crossReference(self, model): 00197 pass 00198 00199 def rawMethod(self): 00200 fields = [] 00201 if self.method in ['HESS', 'INV']: 00202 for (alphaA, omegaA, alphaB, omegaB, Lj, NEj, NDj) in izip( 00203 self.alphaAjs, self.omegaAjs, self.alphaBjs, self.omegaBjs, 00204 self.LJs, self.NEJs, self.NDJs): 00205 alphaA = set_blank_if_default(alphaA, 0.0) 00206 omegaA = set_blank_if_default(omegaA, 0.0) 00207 alphaB = set_blank_if_default(alphaB, 0.0) 00208 omegaB = set_blank_if_default(omegaB, 0.0) 00209 fields += [alphaA, omegaA, alphaB, omegaB, Lj, NEj, NDj, None] 00210 ### 00211 elif self.method=='CLAN': 00212 for (alphaA, omegaA, mblksz, iblksz, kstep, Nj) in izip( 00213 self.alphaAjs, self.omegaAjs, self.mblkszs, self.iblkszs, 00214 self.ksteps, self.NJIs): 00215 alphaA = set_blank_if_default(alphaA, 0.0) 00216 omegaA = set_blank_if_default(omegaA, 0.0) 00217 mblksz = set_blank_if_default(mblksz, 7) 00218 iblksz = set_blank_if_default(iblksz, 2) 00219 kstep = set_blank_if_default(kstep, 5) 00220 00221 fields += [alphaA, omegaA, mblksz, iblksz, kstep, None, Nj, None] 00222 else: 00223 msg = 'invalid EIGC method...method=|%r|' %(self.method) 00224 raise RuntimeError(msg) 00225 return fields 00226 00227 def reprMethod(self): 00228 return self.rawMethod() 00229 00230 def rawFields(self): 00231 fields = ['EIGC', self.sid, self.method, self.norm, self.G, self.C, self.E, self.ndo, None] 00232 fields += self.rawMethod() 00233 return fields 00234 00235 def reprFields(self): 00236 if self.E is None: 00237 E = None 00238 else: 00239 E = str(self.E) 00240 fields = ['EIGC', self.sid, self.method, self.norm, self.G, self.C, E, self.ndo, None] 00241 fields += self.reprMethod() 00242 return fields 00243 00244 class EIGR(Method): 00245 """ 00246 Defines data needed to perform real eigenvalue analysis 00247 """ 00248 type = 'EIGR' 00249 def __init__(self, card=None, data=None): 00250 Method.__init__(self, card, data) 00251 if card: 00252 ## Set identification number. (Unique Integer > 0) 00253 self.sid = card.field(1) 00254 ## Method of eigenvalue extraction. (Character: 'INV' for inverse power 00255 ## method or 'SINV' for enhanced inverse power method.) 00256 self.method = card.field(2, 'LAN') 00257 ## Frequency range of interest 00258 self.f1 = card.field(3) 00259 self.f2 = card.field(4) 00260 ## Estimate of number of roots in range (Required for 00261 ## METHOD = 'INV'). Not used by 'SINV' method. 00262 self.ne = card.field(5) 00263 ## Desired number of roots (default=600 for SINV 3*ne for INV) 00264 self.nd = card.field(6) 00265 ## Method for normalizing eigenvectors. ('MAX' or 'POINT';Default='MAX') 00266 self.norm = card.field(9, 'MASS') 00267 assert self.norm in ['POINT', 'MASS', 'MAX'] 00268 ## Grid or scalar point identification number. Required only if NORM='POINT'. (Integer>0) 00269 self.G = card.field(10) 00270 ## Component number. Required only if NORM='POINT' and G is a geometric grid point. (1<Integer<6) 00271 self.C = card.field(11) 00272 else: 00273 raise NotImplementedError('EIGR') 00274 ### 00275 00276 def crossReference(self,model): 00277 pass 00278 00279 def rawFields(self): 00280 fields = ['EIGR',self.sid, self.method, self.f1, self.f2, self.ne, self.nd, None, None, 00281 self.norm, self.G, self.C] 00282 return fields 00283 00284 def reprFields(self): 00285 method = set_blank_if_default(self.method, 'LAN') 00286 norm = set_blank_if_default(self.norm, 'MASS') 00287 fields = ['EIGR',self.sid, method, self.f1, self.f2, self.ne, self.nd, None, None, 00288 norm, self.G, self.C] 00289 return fields 00290 00291 class EIGP(Method): 00292 """ 00293 Defines poles that are used in complex eigenvalue extraction by the Determinant method. 00294 """ 00295 type = 'EIGP' 00296 def __init__(self, card=None, data=None): 00297 Method.__init__(self, card, data) 00298 if card: 00299 ## Set identification number. (Unique Integer > 0) 00300 self.sid = card.field(1) 00301 00302 ## Coordinates of point in complex plane. (Real) 00303 self.alpha1 = card.field(2) 00304 ## Coordinates of point in complex plane. (Real) 00305 self.omega1 = card.field(3) 00306 ## Multiplicity of complex root at pole defined by point at ALPHAi 00307 ## and OMEGAi 00308 self.m1 = card.field(4) 00309 00310 ## Coordinates of point in complex plane. (Real) 00311 self.alpha2 = card.field(5) 00312 ## Coordinates of point in complex plane. (Real) 00313 self.omega2 = card.field(6) 00314 ## Multiplicity of complex root at pole defined by point at ALPHAi 00315 ## and OMEGAi 00316 self.m2 = card.field(7) 00317 else: 00318 raise NotImplementedError('EIGP') 00319 ### 00320 00321 def crossReference(self, model): 00322 pass 00323 00324 def rawFields(self): 00325 fields = ['EIGP', self.alpha1, self.omega1, self.m1, self.alpha2, self.omega2, self.m2] 00326 return fields 00327 00328 def reprFields(self): 00329 return self.rawFields() 00330 00331 class EIGRL(Method): 00332 """ 00333 Defines data needed to perform real eigenvalue (vibration or buckling) 00334 analysis with the Lanczos method 00335 """ 00336 type = 'EIGRL' 00337 def __init__(self, card=None, data=None, sol=None): 00338 Method.__init__(self, card, data) 00339 if card: 00340 ## Set identification number. (Unique Integer > 0) 00341 self.sid = card.field(1) 00342 ## For vibration analysis: frequency range of interest. For buckling 00343 ## analysis: eigenvalue range of interest. See Remark 4. 00344 ## (Real or blank, -5 10e16 <= V1 < V2 <= 5.10e16) 00345 self.v1 = card.field(2) 00346 self.v2 = card.field(3) 00347 ## Number of roots desired 00348 self.nd = card.field(4) 00349 ## Diagnostic level. (0 < Integer < 4; Default = 0) 00350 self.msglvl = card.field(5, 0) 00351 ## Number of vectors in block or set. Default is machine dependent 00352 self.maxset = card.field(6) 00353 ## Estimate of the first flexible mode natural frequency 00354 ## (Real or blank) 00355 self.shfscl = card.field(7) 00356 ## Method for normalizing eigenvectors (Character: 'MASS' or 'MAX') 00357 self.norm = card.field(8) 00358 00359 optionValues = card.fields(9) 00360 self.options = [] 00361 self.values = [] 00362 #print "optionValues = ",optionValues 00363 for optionValue in optionValues: 00364 #print "optionValue = ",optionValue 00365 (option,value) = optionValue.split('=') 00366 self.options.append(option) 00367 self.values.append(value) 00368 00369 ## Method for normalizing eigenvectors 00370 if sol in [103, 115, 146]: # normal modes,cyclic normal modes, flutter 00371 self.norm = card.field(8, 'MASS') 00372 elif sol in [105, 110, 111, 116]: # buckling, modal complex eigenvalues,modal frequency response,cyclic buckling 00373 self.norm = card.field(8, 'MAX') 00374 else: 00375 self.norm = card.field(8) 00376 #assert self.norm in ['MASS', 'MAX'],'norm=%s sol=%s' %(self.norm,sol) 00377 #assert card.nFields()<9,'card = %s' %(card.fields(0)) 00378 else: 00379 raise NotImplementedError('EIGRL') 00380 ### 00381 00382 def crossReference(self,model): 00383 pass 00384 00385 def rawFields(self): 00386 fields = ['EIGRL',self.sid,self.v1,self.v2,self.nd,self.msglvl,self.maxset,self.shfscl,self.norm] 00387 for (option, value) in izip(self.options, self.values): 00388 fields += [option+'='+str(value)] 00389 return fields 00390 00391 def reprFields(self): 00392 msglvl = set_blank_if_default(self.msglvl, 0) 00393 fields = ['EIGRL',self.sid,self.v1,self.v2,self.nd,msglvl,self.maxset,self.shfscl,self.norm] 00394 for (option, value) in izip(self.options, self.values): 00395 fields += [option+'='+str(value)] 00396 return fields