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 # pylint: disable=C0103,R0902,R0904,R0914 00026 00027 from __future__ import division, print_function 00028 from math import log, exp 00029 from itertools import izip 00030 00031 from pyNastran.bdf.fieldWriter import set_blank_if_default 00032 from pyNastran.bdf.cards.baseCard import BaseCard 00033 00034 00035 class FREQ(BaseCard): 00036 """ 00037 Defines a set of frequencies to be used in the solution of frequency 00038 response problems. 00039 FREQ SID F1 F2 F3 F4 F5 F6 F7 00040 F8 F9 F10 00041 """ 00042 type = 'FREQ' 00043 def __init__(self, card=None, data=None): 00044 self.sid = card.field(1) 00045 self.freqs = card.fields(2) 00046 self.cleanFreqs() 00047 00048 def cleanFreqs(self): 00049 self.freqs = list(set(self.freqs)) 00050 self.freqs.sort() 00051 00052 def getFreqs(self): 00053 return self.freqs 00054 00055 def addFrequencies(self, freqs): 00056 """ 00057 Combines the frequencies from 1 FREQx object with another. 00058 All FREQi entries with the same frequency set identification numbers 00059 will be used. Duplicate frequencies will be ignored. 00060 @param self the object pointer 00061 @param freqs the frequencies for a FREQx object 00062 """ 00063 #print "self.freqs = ",self.freqs 00064 #print "freqs = ",freqs 00065 self.freqs += freqs 00066 self.cleanFreqs() 00067 00068 def addFrequencyObject(self, freq): 00069 """ 00070 @see addFrequencies 00071 @param self the object pointer 00072 @param freq a FREQx object 00073 """ 00074 self.addFrequencies(freq.freqs) 00075 00076 def rawFields(self): 00077 fields = ['FREQ', self.sid]+self.freqs 00078 return fields 00079 00080 class FREQ1(FREQ): 00081 """ 00082 Defines a set of frequencies to be used in the solution of frequency 00083 response problems by specification of a starting frequency, frequency 00084 increment, and the number of increments desired. 00085 FREQ1 SID F1 DF NDF 00086 @note this card rewrites as a FREQ card 00087 """ 00088 type = 'FREQ1' 00089 def __init__(self, card=None, data=None): 00090 self.sid = card.field(1) 00091 f1 = card.field(2, 0.0) 00092 df = card.field(3) 00093 ndf = card.field(4, 1) 00094 00095 self.freqs = [] 00096 for i in xrange(ndf): 00097 self.freqs.append(f1+i*df) 00098 ### 00099 self.cleanFreqs() 00100 00101 class FREQ2(FREQ): 00102 """ 00103 Defines a set of frequencies to be used in the solution of frequency 00104 response problems by specification of a starting frequency, final 00105 frequency, and the number of logarithmic increments desired. 00106 FREQ2 SID F1 F2 NDF 00107 @note this card rewrites as a FREQ card 00108 """ 00109 type = 'FREQ2' 00110 def __init__(self,card=None,data=None): 00111 self.sid = card.field(1) 00112 f1 = card.field(2,0.0) 00113 f2 = card.field(3) 00114 nf = card.field(4,1) 00115 00116 d = 1./nf*log(f2/f1) 00117 self.freqs = [] 00118 for i in xrange(nf): 00119 self.freqs.append(f1*exp(i*d)) # 0 based index 00120 self.cleanFreqs() 00121 00122 #class FREQ3(FREQ): 00123 00124 class FREQ4(FREQ): 00125 """ 00126 Defines a set of frequencies used in the solution of modal frequency 00127 response problems by specifying the amount of 'spread' around each natural 00128 frequency and the number of equally spaced excitation frequencies within 00129 the spread. 00130 FREQ4 SID F1 F2 FSPD NFM 00131 @note this card rewrites as a FREQ card 00132 @todo not done... 00133 """ 00134 type = 'FREQ4' 00135 def __init__(self,card=None,data=None): 00136 self.sid = card.field(1) 00137 self.f1 = card.field(2,0.0) 00138 self.f2 = card.field(3,1.e20) 00139 self.fspd = card.field(4,0.1) 00140 self.nfm = card.field(5,3) 00141 00142 def rawFields(self): 00143 fields = ['FREQ4',self.sid,self.f1,self.f2,self.fspd,self.nfm] 00144 return fields 00145 00146 def reprFields(self): 00147 return self.rawFields() 00148 00149 00150 #class FREQ5(FREQ): 00151 00152 class TSTEP(BaseCard): 00153 """ 00154 Transient Time Step 00155 Defines time step intervals at which a solution will be generated and 00156 output in transient analysis. 00157 """ 00158 type = 'TSTEP' 00159 def __init__(self, card=None, data=None): 00160 self.sid = card.field(1) 00161 self.N=[]; self.DT=[]; self.NO=[] 00162 fields = card.fields(1) 00163 00164 i = 1 00165 nFields = len(fields) 00166 while i < nFields: 00167 self.N.append(card.field(i+1,1)) 00168 self.DT.append(card.field(i+2,0.)) 00169 self.NO.append(card.field(i+3,1)) 00170 i+= 8 00171 00172 def rawFields(self): 00173 fields = ['TSTEP',self.sid] 00174 for (n, dt, no) in izip(self.N, self.DT, self.NO): 00175 fields += [n,dt,no,None,None,None,None,None] 00176 return fields 00177 00178 def reprFields(self): 00179 return self.rawFields() 00180 00181 class TSTEPNL(BaseCard): 00182 """ 00183 Defines parametric controls and data for nonlinear transient structural or 00184 heat transfer analysis. TSTEPNL is intended for SOLs 129, 159, and 600. 00185 Parameters for Nonlinear Transient Analysis 00186 """ 00187 type = 'TSTEPNL' 00188 def __init__(self, card=None, data=None): 00189 if card: 00190 self.sid = card.field(1) 00191 self.ndt = card.field(2) 00192 self.dt = card.field(3) 00193 self.no = card.field(4, 1) 00194 ## @note not listed in all QRGs 00195 self.method = card.field(5, 'ADAPT') 00196 if self.method == 'ADAPT': 00197 self.kStep = card.field(6, 2) 00198 elif self.method == 'ITER': 00199 self.kStep = card.field(6, 10) 00200 elif self.method in ['AUTO','TSTEP']: 00201 self.kStep = card.field(6) 00202 else: 00203 msg = 'invalid TSTEPNL Method. method=|%s|' %(self.method) 00204 raise RuntimeError(msg) 00205 self.maxIter = card.field(7, 10) 00206 self.conv = card.field(8, 'PW') 00207 00208 # line 2 00209 self.epsU = card.field(9, 1.E-2) 00210 self.epsP = card.field(10, 1.E-3) 00211 self.epsW = card.field(11, 1.E-6) 00212 self.maxDiv = card.field(12, 2) 00213 self.maxQn = card.field(13, 10) 00214 self.MaxLs = card.field(14, 2) 00215 self.fStress = card.field(15, 0.2) 00216 00217 # line 3 00218 self.maxBisect = card.field(17, 5) 00219 self.adjust = card.field(18, 5) 00220 self.mStep = card.field(19) 00221 self.rb = card.field(20, 0.6) 00222 self.maxR = card.field(21, 32.) 00223 self.uTol = card.field(22, 0.1) 00224 self.rTolB = card.field(23, 20.) 00225 self.minIter = card.field(24) # not listed in all QRGs 00226 else: 00227 (sid, ndt, dt, no, method, kStep, maxIter, conv, epsU, epsP, epsW, 00228 maxDiv, maxQn, maxLs, fStress, maxBisect, 00229 adjust, mStep, rb, maxR, uTol, rTolB) = data 00230 self.sid = sid 00231 self.ndt = ndt 00232 self.dt = dt 00233 self.no = no 00234 self.method = method 00235 self.kStep = kStep 00236 self.maxIter = maxIter 00237 self.conv = conv 00238 00239 # line 2 00240 self.epsU = epsU 00241 self.epsP = epsP 00242 self.epsW = epsW 00243 self.maxDiv = maxDiv 00244 self.maxQn = maxQn 00245 self.MaxLs = maxLs 00246 self.fStress = fStress 00247 00248 # line 3 00249 self.maxBisect = maxBisect 00250 self.adjust = adjust 00251 self.mStep = mStep 00252 self.rb = rb 00253 self.maxR = maxR 00254 self.uTol = uTol 00255 self.rTolB = rTolB 00256 self.minIter = None # not listed in DMAP 2005 00257 ### 00258 00259 def rawFields(self): 00260 fields = ['TSTEPNL',self.sid,self.ndt,self.dt,self.no,self.method,self.kStep,self.maxIter,self.conv, 00261 self.epsU,self.epsP,self.epsW,self.maxDiv,self.maxQn,self.MaxLs,self.fStress,None, 00262 self.maxBisect,self.adjust,self.mStep,self.rb,self.maxR,self.uTol,self.rTolB,self.minIter] 00263 return fields 00264 00265 def reprFields(self): 00266 #no = set_blank_if_default(self.no,1) 00267 no = self.no 00268 method = set_blank_if_default(self.method, 'ADAPT') 00269 00270 kStep = self.kStep 00271 #if self.method=='ADAPT': 00272 #kStep = set_blank_if_default(self.kStep, 2) 00273 #elif self.method=='ITER': 00274 #kStep = set_blank_if_default(self.kStep, 10) 00275 #else: 00276 #msg = 'invalid TSTEPNL Method. method=|%s|' %(self.method) 00277 #raise RuntimeError(msg) 00278 00279 #maxIter = set_blank_if_default(self.maxIter, 10) 00280 conv = set_blank_if_default(self.conv, 'PW') 00281 00282 epsU = set_blank_if_default(self.epsU, 1e-2) 00283 epsP = set_blank_if_default(self.epsP, 1e-3) 00284 epsW = set_blank_if_default(self.epsW, 1e-6) 00285 maxDiv = set_blank_if_default(self.maxDiv, 2) 00286 maxQn = set_blank_if_default(self.maxQn, 10) 00287 MaxLs = set_blank_if_default(self.MaxLs, 2) 00288 fStress = set_blank_if_default(self.fStress,0.2) 00289 00290 maxBisect = set_blank_if_default(self.maxBisect ,5) 00291 adjust = set_blank_if_default(self.adjust ,5) 00292 rb = set_blank_if_default(self.rb ,0.6) 00293 maxR = set_blank_if_default(self.maxR ,32.) 00294 uTol = set_blank_if_default(self.uTol ,0.1) 00295 rTolB = set_blank_if_default(self.rTolB ,20.) 00296 00297 fields = ['TSTEPNL', self.sid, self.ndt, self.dt, no, method, kStep, self.maxIter, conv, 00298 epsU, epsP, epsW, maxDiv, maxQn, MaxLs, fStress, None, 00299 maxBisect, adjust, self.mStep, rb, maxR, uTol, rTolB, self.minIter] 00300 return fields 00301 00302 class NLPARM(BaseCard): 00303 """ 00304 Defines a set of parameters for nonlinear static analysis iteration 00305 strategy. 00306 NLPARM ID NINC DT KMETHOD KSTEP MAXITER CONV INTOUT 00307 EPSU EPSP EPSW MAXDIV MAXQN MAXLS FSTRESS LSTOL 00308 MAXBIS MAXR RTOLB 00309 """ 00310 type = 'NLPARM' 00311 def __init__(self,card=None,data=None): 00312 if card: 00313 self.nid = card.field(1) 00314 self.ninc = card.field(2, 10) 00315 self.dt = card.field(3, 0.0) 00316 self.kMethod = card.field(4, 'AUTO') 00317 self.kStep = card.field(5, 5) 00318 self.maxIter = card.field(6, 25) 00319 self.conv = card.field(7, 'PW') 00320 self.intOut = card.field(8, 'NO') 00321 00322 # line 2 00323 self.epsU = card.field(9, 0.01) 00324 self.epsP = card.field(10, 0.01) 00325 self.epsW = card.field(11, 0.01) 00326 self.maxDiv = card.field(12, 3) 00327 self.maxQn = card.field(13, self.maxIter) 00328 self.maxLs = card.field(14, 4) 00329 self.fStress = card.field(15, 0.2) 00330 self.lsTol = card.field(16, 0.5) 00331 00332 # line 3 00333 self.maxBisect = card.field(17, 5) 00334 self.maxR = card.field(21, 20.) 00335 self.rTolB = card.field(23, 20.) 00336 else: 00337 (sid, ninc, dt, kMethod, kStep, maxIter, conv, intOut, epsU, epsP, epsW, 00338 maxDiv, maxQn, maxLs, fStress, lsTol, maxBisect, maxR, rTolB) = data 00339 self.nid = sid 00340 self.ninc = ninc 00341 self.dt = dt 00342 self.kMethod = kMethod 00343 self.kStep = kStep 00344 self.maxIter = maxIter 00345 self.conv = conv 00346 self.intOut = intOut 00347 00348 # line 2 00349 self.epsU = epsU 00350 self.epsP = epsP 00351 self.epsW = epsW 00352 self.maxDiv = maxDiv 00353 self.maxQn = maxQn 00354 self.maxLs = maxLs 00355 self.fStress = fStress 00356 self.lsTol = lsTol 00357 00358 # line 3 00359 self.maxBisect = maxBisect 00360 self.maxR = maxR 00361 self.rTolB = rTolB 00362 ### 00363 00364 def rawFields(self): 00365 fields = ['NLPARM',self.nid,self.ninc,self.dt,self.kMethod,self.kStep,self.maxIter,self.conv,self.intOut, 00366 self.epsU,self.epsP,self.epsW,self.maxDiv,self.maxQn,self.maxLs,self.fStress,self.lsTol, 00367 self.maxBisect ,None, None, None, self.maxR, None, self.rTolB] 00368 return fields 00369 00370 def reprFields(self): 00371 ninc = set_blank_if_default(self.ninc, 10) 00372 dt = set_blank_if_default(self.dt, 0.0) 00373 kMethod = set_blank_if_default(self.kMethod, 'AUTO') 00374 kStep = set_blank_if_default(self.kStep, 5) 00375 maxIter = set_blank_if_default(self.maxIter, 25) 00376 conv = set_blank_if_default(self.conv, 'PW') 00377 intOut = set_blank_if_default(self.intOut, 'NO') 00378 epsU = set_blank_if_default(self.epsU, 0.01) 00379 epsP = set_blank_if_default(self.epsP, 0.01) 00380 epsW = set_blank_if_default(self.epsW, 0.01) 00381 maxDiv = set_blank_if_default(self.maxDiv, 3) 00382 maxQn = set_blank_if_default(self.maxQn, self.maxIter) 00383 maxLs = set_blank_if_default(self.maxLs, 4) 00384 fStress = set_blank_if_default(self.fStress, 0.2) 00385 lsTol = set_blank_if_default(self.lsTol, 0.5) 00386 maxBisect = set_blank_if_default(self.maxBisect, 5) 00387 maxR = set_blank_if_default(self.maxR, 20.) 00388 rTolB = set_blank_if_default(self.rTolB, 20.) 00389 00390 fields = ['NLPARM', self.nid, ninc, dt, kMethod, kStep, maxIter, conv, intOut, 00391 epsU, epsP, epsW, maxDiv, maxQn, maxLs, fStress, lsTol, 00392 maxBisect, None, None, None, maxR, None, rTolB] 00393 return fields