pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
optimization.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 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     
 All Classes Namespaces Files Functions Variables