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 #import sys 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 OptConstraint(BaseCard): 00036 def __init__(self): 00037 pass 00038 00039 class DCONSTR(OptConstraint): 00040 type = 'DCONSTR' 00041 def __init__(self, card=None, data=None): 00042 if card: 00043 self.oid = card.field(1) 00044 self.rid = card.field(2) 00045 self.lid = card.field(3, -1e20) 00046 self.uid = card.field(4, 1e20) 00047 self.lowfq = card.field(5, 0.0) 00048 self.highfq = card.field(6, 1e20) 00049 else: 00050 self.oid = data[0] 00051 self.rid = data[1] 00052 self.lid = data[2] 00053 self.uid = data[3] 00054 self.lowfq = data[4] 00055 self.highfq = data[5] 00056 ### 00057 00058 def rawFields(self): 00059 fields = ['DCONSTR', self.oid, self.rid, self.lid, self.uid, self.lowfq, self.highfq] 00060 return fields 00061 00062 def reprFields(self): 00063 lid = set_blank_if_default(self.lid, -1e20) 00064 uid = set_blank_if_default(self.uid, 1e20) 00065 lowfq = set_blank_if_default(self.lowfq, 0.0) 00066 highfq = set_blank_if_default(self.highfq, 1e20) 00067 fields = ['DCONSTR', self.oid, self.rid, lid, uid, lowfq, highfq] 00068 return fields 00069 00070 class DESVAR(OptConstraint): 00071 type = 'DESVAR' 00072 def __init__(self,card=None,data=None): 00073 self.oid = card.field(1) 00074 self.label = card.field(2) 00075 self.xinit = card.field(3) 00076 self.xlb = card.field(4, -1e20) 00077 self.xub = card.field(5, 1e20) 00078 self.delx = card.field(6, 1e20) 00079 self.ddval = card.field(7) 00080 00081 def rawFields(self): 00082 fields = ['DESVAR', self.oid, self.label, self.xinit, self.xlb, self.xub, 00083 self.delx, self.ddval] 00084 return fields 00085 00086 def reprFields(self): 00087 xlb = set_blank_if_default(self.xlb, -1e20) 00088 xub = set_blank_if_default(self.xub, 1e20) 00089 delx = set_blank_if_default(self.delx, 1e20) 00090 fields = ['DESVAR', self.oid, self.label, self.xinit, xlb, xub, delx, self.ddval] 00091 return fields 00092 00093 class DDVAL(OptConstraint): 00094 type = 'DDVAL' 00095 def __init__(self,card=None,data=None): 00096 self.oid = card.field(1) 00097 self.dval1 = card.field(2) 00098 self.dval2 = card.field(3) 00099 self.dval3 = card.field(4) 00100 self.dval4 = card.field(5) 00101 self.dval5 = card.field(6) 00102 self.dval6 = card.field(7) 00103 self.dval7 = card.field(8) 00104 00105 def rawFields(self): 00106 fields = ['DDVAL', self.oid, self.dval1, self.dval2, self.dval3, 00107 self.dval4, self.dval5, self.dval6, self.dval7] 00108 return self.printCard(fields) 00109 00110 class DOPTPRM(OptConstraint): 00111 type = 'DOPTPRM' 00112 def __init__(self,card=None,data=None): 00113 """ 00114 Design Optimization Parameters 00115 Overrides default values of parameters used in design optimization 00116 DOPTPRM PARAM1 VAL1 PARAM2 VAL2 PARAM3 VAL3 PARAM4 VAL4 00117 PARAM5 VAL5 -etc.- 00118 """ 00119 fields = card.fields(1) 00120 nFields = len(fields) 00121 00122 self.params = {} 00123 for i in xrange(0,nFields, 2): 00124 param = fields[i] 00125 val = fields[i+1] 00126 self.params[param] = val 00127 ### 00128 00129 def rawFields(self): 00130 fields = ['DOPTPRM'] 00131 for param,val in sorted(self.params.iteritems()): 00132 fields += [param, val] 00133 return fields 00134 00135 class DLINK(OptConstraint): 00136 type = 'DLINK' 00137 def __init__(self, card=None, data=None): 00138 """ 00139 Multiple Design Variable Linking 00140 Relates one design variable to one or more other design variables 00141 DLINK ID DDVID C0 CMULT IDV1 C1 IDV2 C2 00142 IDV3 C3 -etc.- 00143 """ 00144 self.oid = card.field(1) 00145 self.ddvid = card.field(2) 00146 self.c0 = card.field(3, 0.) 00147 self.cmult = card.field(4, 1.) 00148 00149 fields = card.fields(5) 00150 nFields = len(fields) 00151 self.IDv = [] 00152 self.Ci = [] 00153 00154 for i in xrange(0, nFields, 2): 00155 self.IDv.append(fields[i]) 00156 self.Ci.append(fields[i+1]) 00157 ### 00158 00159 def rawFields(self): 00160 fields = ['DLINK',self.oid, self.ddvid, self.c0, self.cmult] 00161 for (idv, ci) in izip(self.IDv, self.Ci): 00162 fields += [idv, ci] 00163 return fields 00164 00165 def reprFields(self): 00166 c0 = set_blank_if_default(self.c0, 0.) 00167 cmult = set_blank_if_default(self.cmult, 1.) 00168 fields = ['DLINK', self.oid, self.ddvid, c0, cmult] 00169 for (idv, ci) in izip(self.IDv, self.Ci): 00170 fields += [idv, ci] 00171 return fields 00172 00173 00174 class DSCREEN(OptConstraint): 00175 type = 'DSCREEN' 00176 def __init__(self,card=None,data=None): 00177 ## Response type for which the screening criteria apply. (Character) 00178 self.rType = card.field(1) 00179 ## Truncation threshold. (Real; Default = -0.5) 00180 self.trs = card.field(2, -0.5) 00181 ## Maximum number of constraints to be retained per region per load 00182 ## case. (Integer > 0; Default = 20) 00183 self.nstr = card.field(3, 20) 00184 00185 def rawFields(self): 00186 fields = ['DSCREEN', self.rType, self.trs, self.nstr] 00187 return fields 00188 00189 def reprFields(self): 00190 trs = set_blank_if_default(self.trs, -0.5) 00191 nstr = set_blank_if_default(self.nstr, 20) 00192 fields = ['DSCREEN', self.rType, trs, nstr] 00193 return fields 00194 00195 class DRESP1(OptConstraint): 00196 type = 'DRESP1' 00197 def __init__(self, card=None, data=None): 00198 """ 00199 DRESP1 1S1 CSTRAIN PCOMP 1 1 10000 00200 """ 00201 self.oid = card.field(1) 00202 self.label = card.field(2) 00203 self.rtype = card.field(3) 00204 self.ptype = card.field(4) 00205 self.region = card.field(5) 00206 self.atta = card.field(6) 00207 self.attb = card.field(7) 00208 self.atti = card.field(8) 00209 self.others = card.fields(9) 00210 #if self.others: 00211 # print("self.others = %s" %(self.others)) 00212 # print(str(self)) 00213 #assert len(self.others)==0 00214 00215 def rawFields(self): 00216 fields = ['DRESP1',self.oid, self.label, self.rtype, self.ptype, self.region,self.atta, self.attb, self.atti 00217 ]+self.others 00218 return fields 00219 00220 class DRESP2(OptConstraint): 00221 type = 'DRESP2' 00222 def __init__(self, card=None, data=None): 00223 """ 00224 Design Sensitivity Equation Response Quantities 00225 Defines equation responses that are used in the design, either as 00226 constraints or as an objective. 00227 """ 00228 self.oid = card.field(1) 00229 self.label = card.field(2) 00230 self.eqidFunc = card.field(3) 00231 self.region = card.field(4) 00232 self.method = card.field(5, 'MIN') 00233 self.c1 = card.field(6, 100.) 00234 self.c2 = card.field(7, 0.005) 00235 self.c3 = card.field(8) 00236 00237 i=0 00238 fields = card.fields(9) 00239 key = '$NULL$' # dummy key 00240 self.params = { key:[] } 00241 valueList = [] 00242 for (i, field) in enumerate(fields): 00243 if i%8==0 and field is not None: 00244 self.params[key] = valueList 00245 key = field 00246 valueList = [] 00247 elif field is not None: 00248 valueList.append(field) 00249 #else: 00250 # pass 00251 ### 00252 self.params[key] = valueList 00253 del self.params['$NULL$'] 00254 00255 #print "--Params--" 00256 #for (key, valueList) in sorted(self.params.iteritems()): 00257 # print(" key=%s params=%s" %(key, valueList)) 00258 00259 #print self 00260 00261 def packParams(self): 00262 packLength = { # the amount of padding at the [beginning,end] of the 2nd line 00263 'DESVAR' : [1,0], 00264 'DTABLE' : [1,0], 00265 'DRESP1' : [1,0], 00266 'DNODE' : [1,1], # unique entry 00267 'DVPREL1': [1,0], 00268 'DVCREL1': [1,0], 00269 'DVMREL1': [1,0], 00270 'DVPREL2': [1,0], 00271 'DVCREL2': [1,0], 00272 'DVMREL2': [1,0], 00273 'DRESP2' : [1,0], 00274 'DESVAR' : [1,0], 00275 'DESVAR' : [1,0], 00276 'DESVAR' : [1,0], 00277 'DESVAR' : [1,0], 00278 } 00279 fields = [] 00280 for (key, valueList) in sorted(self.params.iteritems()): 00281 fields2 = [key]+valueList 00282 try: 00283 (i, j) = packLength[key] 00284 except KeyError: 00285 msg = 'INVALID DRESP2 key=|%s| fields=%s ID=%s' %(key, valueList, self.oid) 00286 raise KeyError(msg) 00287 fields += self.buildTableLines(fields2,nStart=i,nEnd=j) 00288 ### 00289 return fields 00290 00291 def rawFields(self): 00292 fields = ['DRESP2', self.oid, self.label, self.eqidFunc, self.region, self.method, self.c1, self.c2, self.c3] 00293 fields += self.packParams() 00294 return fields 00295 00296 def reprFields(self): 00297 method = set_blank_if_default(self.method, 'MIN') 00298 c1 = set_blank_if_default(self.c1, 100.) 00299 c2 = set_blank_if_default(self.c2, 0.005) 00300 00301 fields = ['DRESP2', self.oid, self.label, self.eqidFunc, self.region, method, c1, c2, self.c3] 00302 fields += self.packParams() 00303 return fields 00304 00305 class DVMREL1(OptConstraint): # similar to DVPREL1 00306 type = 'DVMREL1' 00307 def __init__(self, card=None, data=None): 00308 """ 00309 Design Variable to Material Relation 00310 Defines the relation between a material property and design variables 00311 DVMREL1 ID TYPE MID MPNAME MPMIN MPMAX C0 00312 DVID1 COEF1 DVID2 COEF2 DVID3 COEF3 -etc.- 00313 """ 00314 self.oid = card.field(1) 00315 self.Type = card.field(2) 00316 self.mid = card.field(3) 00317 self.mpName = card.field(4) 00318 self.mpMin = card.field(5) ## @todo bad default 00319 self.mpMax = card.field(6, 1e20) 00320 self.c0 = card.field(7, 0.0) 00321 00322 self.dvids = [] 00323 self.coeffs = [] 00324 endFields = card.fields(9) 00325 #print "endFields = ",endFields 00326 nFields = len(endFields)-1 00327 if nFields%2==1: 00328 endFields.append(None) 00329 nFields += 1 00330 i = 0 00331 for i in xrange(0,nFields,2): 00332 self.dvids.append(endFields[i]) 00333 self.coeffs.append(endFields[i+1]) 00334 if nFields%2==1: 00335 print(card) 00336 print("dvids = %s" %(self.dvids)) 00337 print("coeffs = %s" %(self.coeffs)) 00338 print(str(self)) 00339 raise RuntimeError('invalid DVMREL1...') 00340 00341 def crossReference(self, model): 00342 self.mid = model.Material(self.mid) 00343 00344 def Mid(self): 00345 if isinstance(self.mid, int): 00346 return self.mid 00347 return self.mid.mid 00348 00349 def rawFields(self): 00350 fields = ['DVMREL1', self.oid, self.Type, self.Mid(), self.mpName, self.mpMin, self.mpMax, self.c0, None] 00351 for (dvid, coeff) in izip(self.dvids, self.coeffs): 00352 fields.append(dvid) 00353 fields.append(coeff) 00354 return fields 00355 00356 def reprFields(self): 00357 mpMax = set_blank_if_default(self.mpMax, 1e20) 00358 c0 = set_blank_if_default(self.c0, 0.) 00359 fields = ['DVMREL1', self.oid, self.Type, self.Mid(), self.mpName, self.mpMin, mpMax, c0, None] 00360 for (dvid, coeff) in izip(self.dvids, self.coeffs): 00361 fields.append(dvid) 00362 fields.append(coeff) 00363 return fields 00364 00365 class DVPREL1(OptConstraint): # similar to DVMREL1 00366 type = 'DVPREL1' 00367 def __init__(self, card=None, data=None): 00368 """ 00369 DVPREL1 200000 PCOMP 2000 T2 00370 200000 1.0 00371 """ 00372 self.oid = card.field(1) 00373 self.Type = card.field(2) 00374 self.pid = card.field(3) 00375 self.pNameFid = card.field(4) 00376 self.pMin = card.field(5) ## @todo bad default 00377 self.pMax = card.field(6, 1e20) 00378 self.c0 = card.field(7, 0.0) 00379 00380 self.dvids = [] 00381 self.coeffs = [] 00382 endFields = card.fields(9) 00383 #print "endFields = ",endFields 00384 nFields = len(endFields)-1 00385 if nFields%2==1: 00386 endFields.append(None) 00387 nFields+=1 00388 i = 0 00389 for i in xrange(0, nFields, 2): 00390 self.dvids.append(endFields[i]) 00391 self.coeffs.append(endFields[i+1]) 00392 if nFields%2==1: 00393 print(card) 00394 print("dvids = %s" %(self.dvids)) 00395 print("coeffs = %s" %(self.coeffs)) 00396 print(str(self)) 00397 raise RuntimeError('invalid DVPREL1...') 00398 00399 def crossReference(self, model): 00400 self.pid = model.Property(self.pid) 00401 00402 def Pid(self): 00403 if isinstance(self.pid, int): 00404 return self.pid 00405 return self.pid.pid 00406 00407 def rawFields(self): 00408 fields = ['DVPREL1',self.oid,self.Type,self.Pid(),self.pNameFid,self.pMin,self.pMax,self.c0,None] 00409 for (dvid, coeff) in izip(self.dvids, self.coeffs): 00410 fields.append(dvid) 00411 fields.append(coeff) 00412 return fields 00413 00414 def reprFields(self): 00415 pMax = set_blank_if_default(self.pMax, 1e20) 00416 c0 = set_blank_if_default(self.c0, 0.) 00417 fields = ['DVPREL1',self.oid,self.Type,self.Pid(),self.pNameFid,self.pMin,pMax,c0,None] 00418 for (dvid, coeff) in izip(self.dvids, self.coeffs): 00419 fields.append(dvid) 00420 fields.append(coeff) 00421 return fields 00422 00423 class DVPREL2(OptConstraint): 00424 type = 'DVPREL2' 00425 def __init__(self, card=None, data=None): 00426 """ 00427 DVPREL2 ID TYPE PID PNAME/FID PMIN PMAX EQID 00428 'DESVAR' DVID1 DVID2 DVID3 DVID4 DVID5 DVID6 DVID7 00429 DVID8 -etc.- 00430 'DTABLE' LABL1 LABL2 LABL3 LABL4 LABL5 LABL6 LABL7 00431 LABL8 -etc.- 00432 """ 00433 ## Unique identification number 00434 self.oid = card.field(1) 00435 ## Name of a property entry, such as PBAR, PBEAM, etc 00436 self.Type = card.field(2) 00437 ## Property entry identification number 00438 self.pid = card.field(3) 00439 ## Property name, such as 'T', 'A', or field position of the property 00440 ## entry, or word position in the element property table of the analysis 00441 ## model. Property names that begin with an integer such as 12I/T**3 00442 ## may only be referred to by field position. (Character or Integer 0) 00443 self.pnameFid = card.field(4) 00444 ## Minimum value allowed for this property. If FID references a stress 00445 ## recovery location field, then the default value for PMIN is -1.0+35. 00446 ## PMIN must be explicitly set to a negative number for properties that 00447 ## may be less than zero (for example, field ZO on the PCOMP entry). 00448 ## (Real; Default = 1.E-15) 00449 self.pmin = card.field(5, 1e-15) 00450 ## Maximum value allowed for this property. (Real; Default = 1.0E20) 00451 self.pmax = card.field(6, 1e20) 00452 ## DEQATN entry identification number. (Integer > 0) 00453 self.eqID = card.field(7) 00454 00455 fields = card.fields(9) 00456 #print "fields = ",fields 00457 iOffset = 9 00458 iEnd = len(fields)+iOffset 00459 00460 try: 00461 iDesvar = fields.index('DESVAR')+iOffset 00462 except ValueError: 00463 iDesvar = None 00464 00465 try: 00466 iDTable = fields.index('DTABLE')+iOffset 00467 #iDesMax = iDTable # the index to start parsing DESVAR 00468 iDesStop = iDTable # the index to stop parsing DESVAR 00469 except ValueError: 00470 iDTable = None 00471 iDesStop = iEnd 00472 00473 self.dvids = [] 00474 self.dtables = [] 00475 if iDesvar: 00476 for i in xrange(10, iDesStop): 00477 dvid = card.field(i) 00478 if dvid: 00479 self.dvids.append(dvid) 00480 ### 00481 ### 00482 ### 00483 if iDTable: 00484 for i in xrange(iDTable+1, iEnd): 00485 dtable = card.field(i) 00486 if dtable: 00487 assert dtable is not 'DTABLE' 00488 self.dtables.append(dtable) 00489 ### 00490 ### 00491 ### 00492 00493 def Pid(self): 00494 if isinstance(self.pid, int): 00495 return self.pid 00496 return self.pid.pid 00497 00498 #def EqID(self): 00499 00500 def crossReference(self, model): 00501 """@todo add support for DEQATN cards to finish DVPREL2 xref""" 00502 self.pid = model.Property(self.pid) 00503 #self.eqID = model.DEquation(self.eqID) 00504 00505 def OptValue(self): ## @todo not implemented 00506 self.pid.OptValue(self.pnameFid) 00507 00508 def rawFields(self): 00509 fields = ['DVPREL2',self.oid,self.Type,self.Pid(),self.pnameFid,self.pmin,self.pmax,self.eqID,None] 00510 00511 if self.dvids: 00512 fields2 = ['DESVAR']+self.dvids 00513 fields += self.buildTableLines(fields2, nStart=1, nEnd=0) 00514 00515 if self.dtables: 00516 fields2 = ['DTABLE']+self.dtables 00517 fields += self.buildTableLines(fields2, nStart=1, nEnd=0) 00518 return fields 00519 00520 def reprFields(self): 00521 """@todo finish reprFields for DVPREL2""" 00522 return self.rawFields() 00523