Source code for pyNastran.bdf.cards.dynamic

# pylint: disable=C0103,R0902,R0904,R0914
"""
All dynamic control cards are defined in this file.  This includes:

 * FREQ
 * FREQ1
 * FREQ2 (not implemented)
 * FREQ3
 * FREQ4
 * FREQ5 (not implemented)
 * NLPCI
 * NLPARM
 * TSTEP
 * TSTEPNL

All cards are BaseCard objects.
"""
from __future__ import (nested_scopes, generators, division, absolute_import,
                        print_function, unicode_literals)
from math import log, exp, ceil
from six.moves import zip, range

from pyNastran.bdf.field_writer_8 import set_blank_if_default
from pyNastran.bdf.cards.baseCard import BaseCard
from pyNastran.bdf.bdfInterface.assign_type import (integer, integer_or_blank,
    double, double_or_blank, string_or_blank, blank, fields)
from pyNastran.bdf.field_writer_8 import print_card_8
from pyNastran.bdf.field_writer_16 import print_card_16


[docs]class FREQ(BaseCard): """ Defines a set of frequencies to be used in the solution of frequency response problems. +-----+-----+-----+-----+------+-----+-----+-----+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +=====+=====+=====+=====+======+=====+=====+=====+=====+ |FREQ | SID | F1 | F2 | etc. | | | | | +-----+-----+-----+-----+------+-----+-----+-----+-----+ """ type = 'FREQ' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.sid = integer(card, 1, 'sid') self.freqs = fields(double, card, 'freq', i=2, j=len(card)) self.cleanFreqs()
[docs] def cleanFreqs(self): self.freqs = list(set(self.freqs)) self.freqs.sort()
[docs] def getFreqs(self): return self.freqs
[docs] def add_frequencies(self, freqs): """ Combines the frequencies from 1 FREQx object with another. All FREQi entries with the same frequency set identification numbers will be used. Duplicate frequencies will be ignored. :param self: the object pointer :param freqs: the frequencies for a FREQx object """ #print("self.freqs = ",self.freqs) #print("freqs = ",freqs) self.freqs += freqs self.cleanFreqs()
[docs] def add_frequency_object(self, freq): """ :param self: the object pointer :param freq: a FREQx object .. seealso:: :func:`addFrequencies` """ self.add_frequencies(freq.freqs)
[docs] def raw_fields(self): list_fields = ['FREQ', self.sid] + self.freqs return list_fields
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class FREQ1(FREQ): """ Defines a set of frequencies to be used in the solution of frequency response problems by specification of a starting frequency, frequency increment, and the number of increments desired. +------+-----+-----+-----+-----+-----+-----+-----+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +======+=====+=====+=====+=====+=====+=====+=====+=====+ |FREQ1 | SID | F1 | DF | NDF | | | | | +------+-----+-----+-----+-----+-----+-----+-----+-----+ .. note:: this card rewrites as a FREQ card """ type = 'FREQ1' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.sid = integer(card, 1, 'sid') f1 = double_or_blank(card, 2, 'f1', 0.0) df = double(card, 3, 'df') ndf = integer_or_blank(card, 4, 'ndf', 1) assert len(card) <= 5, 'len(FREQ card) = %i' % len(card) self.freqs = [] for i in range(ndf): self.freqs.append(f1 + i * df) self.cleanFreqs()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class FREQ2(FREQ): """ Defines a set of frequencies to be used in the solution of frequency response problems by specification of a starting frequency, final frequency, and the number of logarithmic increments desired. +-------+-----+-----+-----+-----+-----+-----+-----+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +=======+=====+=====+=====+=====+=====+=====+=====+=====+ | FREQ2 | SID | F1 | F2 | NDF | | | | | +-------+-----+-----+-----+-----+-----+-----+-----+-----+ .. note:: this card rewrites as a FREQ card """ type = 'FREQ2' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.sid = integer(card, 1, 'sid') f1 = double(card, 2, 'f1') # default=0.0 ? f2 = double(card, 3, 'f2') nf = integer_or_blank(card, 4, 'nf', 1) assert len(card) <= 5, 'len(FREQ2 card) = %i' % len(card) d = 1. / nf * log(f2 / f1) self.freqs = [] for i in range(nf): self.freqs.append(f1 * exp(i * d)) # 0 based index self.cleanFreqs()
[docs]class FREQ3(FREQ): type = 'FREQ3' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment raise NotImplementedError()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class FREQ4(FREQ): """ Defines a set of frequencies used in the solution of modal frequency response problems by specifying the amount of 'spread' around each natural frequency and the number of equally spaced excitation frequencies within the spread. +------+-----+-----+-----+------+-----+-----+-----+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +======+=====+=====+=====+======+=====+=====+=====+=====+ |FREQ4 | SID | F1 | F2 | FSPD | NFM | | | | +------+-----+-----+-----+------+-----+-----+-----+-----+ .. note:: this card rewrites as a FREQ card .. todo:: not done... """ type = 'FREQ4' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.sid = integer(card, 1, 'sid') self.f1 = double_or_blank(card, 2, 'f1', 0.0) self.f2 = double_or_blank(card, 3, 'f2', 1.e20) self.fspd = double_or_blank(card, 4, 'fspd', 0.1) self.nfm = integer_or_blank(card, 5, 'nfm', 3) assert len(card) <= 6, 'len(FREQ card) = %i' % len(card)
[docs] def raw_fields(self): list_fields = ['FREQ4', self.sid, self.f1, self.f2, self.fspd, self.nfm] return list_fields
[docs] def repr_fields(self): return self.raw_fields()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class FREQ5(FREQ): type = 'FREQ5' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment raise NotImplementedError()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class NLPARM(BaseCard): """ Defines a set of parameters for nonlinear static analysis iteration strategy. +--------+--------+------+------+---------+-------+---------+---------+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+========+======+======+=========+=======+=========+=========+========+ | NLPARM | ID | NINC | DT | KMETHOD | KSTEP | MAXITER | CONV | INTOUT | +--------+--------+------+------+---------+-------+---------+---------+--------+ | | ESPU | EPSP | EPSW | MAXDIV | MAXQN | MAXLS | FSTRESS | LSTOL | +--------+--------+------+------+---------+-------+---------+---------+--------+ | | MAXBIS | | | | MAXR | | RTOLB | CONV | +--------+--------+------+------+---------+-------+---------+---------+--------+ """ type = 'NLPARM' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment if card: self.nid = integer(card, 1, 'nid') self.ninc = integer_or_blank(card, 2, 'ninc', 10) self.dt = double_or_blank(card, 3, 'dt', 0.0) self.kMethod = string_or_blank(card, 4, 'kMethod', 'AUTO') self.kStep = integer_or_blank(card, 5, 'kStep', 5) self.maxIter = integer_or_blank(card, 6, 'maxIter', 25) self.conv = string_or_blank(card, 7, 'conv', 'PW') self.intOut = string_or_blank(card, 8, 'intOut', 'NO') # line 2 self.epsU = double_or_blank(card, 9, 'epsU', 0.01) self.epsP = double_or_blank(card, 10, 'epsP', 0.01) self.epsW = double_or_blank(card, 11, 'epsW', 0.01) self.maxDiv = integer_or_blank(card, 12, 'maxDiv', 3) if self.kMethod == 'PFNT': self.maxQn = integer_or_blank(card, 13, 'maxQn', 0) else: self.maxQn = integer_or_blank(card, 13, 'maxQn', self.maxIter) self.maxLs = integer_or_blank(card, 14, 'maxLs', 4) self.fStress = double_or_blank(card, 15, 'fStress', 0.2) self.lsTol = double_or_blank(card, 16, 'lsTol', 0.5) # line 3 self.maxBisect = integer_or_blank(card, 17, '', 5) self.maxR = double_or_blank(card, 21, 'maxR', 20.) self.rTolB = double_or_blank(card, 23, 'rTolB', 20.) assert len(card) <= 24, 'len(NLPARM card) = %i' % len(card) else: (sid, ninc, dt, kMethod, kStep, maxIter, conv, intOut, epsU, epsP, epsW, maxDiv, maxQn, maxLs, fStress, lsTol, maxBisect, maxR, rTolB) = data self.nid = sid self.ninc = ninc self.dt = dt self.kMethod = kMethod self.kStep = kStep self.maxIter = maxIter self.conv = conv self.intOut = intOut # line 2 self.epsU = epsU self.epsP = epsP self.epsW = epsW self.maxDiv = maxDiv self.maxQn = maxQn self.maxLs = maxLs self.fStress = fStress self.lsTol = lsTol # line 3 self.maxBisect = maxBisect self.maxR = maxR self.rTolB = rTolB
[docs] def raw_fields(self): list_fields = ['NLPARM', self.nid, self.ninc, self.dt, self.kMethod, self.kStep, self.maxIter, self.conv, self.intOut, self.epsU, self.epsP, self.epsW, self.maxDiv, self.maxQn, self.maxLs, self.fStress, self.lsTol, self.maxBisect, None, None, None, self.maxR, None, self.rTolB] return list_fields
[docs] def repr_fields(self): ninc = set_blank_if_default(self.ninc, 10) dt = set_blank_if_default(self.dt, 0.0) kMethod = set_blank_if_default(self.kMethod, 'AUTO') kStep = set_blank_if_default(self.kStep, 5) maxIter = set_blank_if_default(self.maxIter, 25) conv = set_blank_if_default(self.conv, 'PW') intOut = set_blank_if_default(self.intOut, 'NO') epsU = set_blank_if_default(self.epsU, 0.01) epsP = set_blank_if_default(self.epsP, 0.01) epsW = set_blank_if_default(self.epsW, 0.01) maxDiv = set_blank_if_default(self.maxDiv, 3) maxQn = set_blank_if_default(self.maxQn, self.maxIter) maxLs = set_blank_if_default(self.maxLs, 4) fStress = set_blank_if_default(self.fStress, 0.2) lsTol = set_blank_if_default(self.lsTol, 0.5) maxBisect = set_blank_if_default(self.maxBisect, 5) maxR = set_blank_if_default(self.maxR, 20.) rTolB = set_blank_if_default(self.rTolB, 20.) list_fields = ['NLPARM', self.nid, ninc, dt, kMethod, kStep, maxIter, conv, intOut, epsU, epsP, epsW, maxDiv, maxQn, maxLs, fStress, lsTol, maxBisect, None, None, None, maxR, None, rTolB] return list_fields
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) # having trouble with double precision... return self.comment() + print_card_16(card)
[docs]class NLPCI(BaseCard): type = 'NLPCI' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.nlparm_id = integer(card, 1, 'nlparm_id') self.Type = string_or_blank(card, 2, 'Type', 'CRIS') self.minalr = double_or_blank(card, 3, 'minalr', 0.25) self.maxalr = double_or_blank(card, 4, 'maxalr', 4.0) self.scale = double_or_blank(card, 5, 'scale', 0.0) blank(card, 6, 'blank') self.desiter = integer_or_blank(card, 7, 'desiter', 12) self.mxinc = integer_or_blank(card, 8, 'mxinc', 20)
[docs] def raw_fields(self): list_fields = ['NLPCI', self.nlparm_id, self.Type, self.minalr, self.maxalr, self.scale, None, self.desiter, self.mxinc] return list_fields
[docs] def repr_fields(self): #minalr = set_blank_if_default(self.minalr, 0.25) return self.raw_fields()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class TSTEP(BaseCard): """ Transient Time Step Defines time step intervals at which a solution will be generated and output in transient analysis. +-------+------+-----+-----+-----+-----+-----+-----+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +-------+------+-----+-----+-----+-----+-----+-----+-----+ | TSTEP | N1 | DT1 | NO1 | | | | | | +-------+------+-----+-----+-----+-----+-----+-----+-----+ | | N2 | DT2 | NO2 | | | | | | +-------+------+-----+-----+-----+-----+-----+-----+-----+ | | etc. | | | | | | | | +-------+------+-----+-----+-----+-----+-----+-----+-----+ """ type = 'TSTEP' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment self.sid = integer(card, 1, 'sid') self.N = [] self.DT = [] self.NO = [] nrows = int(ceil((len(card) - 1.) / 8.)) for i in range(nrows): n = 8 * i + 1 N = integer_or_blank(card, n + 1, 'N' + str(i), 1) dt = double_or_blank(card, n + 2, 'dt' + str(i), 0.) no = integer_or_blank(card, n + 3, 'NO' + str(i), 1) self.N.append(N) self.DT.append(dt) self.NO.append(no)
[docs] def raw_fields(self): list_fields = ['TSTEP', self.sid] for (N, dt, no) in zip(self.N, self.DT, self.NO): list_fields += [N, dt, no, None, None, None, None, None] return list_fields
[docs] def repr_fields(self): return self.raw_fields()
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)
[docs]class TSTEPNL(BaseCard): """ Defines parametric controls and data for nonlinear transient structural or heat transfer analysis. TSTEPNL is intended for SOLs 129, 159, and 600. Parameters for Nonlinear Transient Analysis. +---------+--------+--------+-------+--------+--------+-------+---------+------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +---------+--------+--------+-------+--------+--------+-------+---------+------+ | TSTEPNL | ID | NDT | DT | NO | METHOD | KSTEP | MAXITER | CONV | +---------+--------+--------+-------+--------+--------+-------+---------+------+ | | ESPU | EPSP | EPSW | MAXDIV | MAXQN | MAXLS | FSTRESS | | +---------+--------+--------+-------+--------+--------+-------+---------+------+ | | MAXBIS | ADJUST | MSTEP | RB | MAXR | UTOL | RTOLB | | +---------+--------+--------+-------+--------+--------+-------+---------+------+ """ type = 'TSTEPNL' def __init__(self, card=None, data=None, comment=''): if comment: self._comment = comment if card: self.sid = integer(card, 1, 'sid') self.ndt = integer(card, 2, 'ndt') assert self.ndt >= 3 self.dt = double(card, 3, 'dt') assert self.dt > 0. self.no = integer_or_blank(card, 4, 'no', 1) #: .. note:: not listed in all QRGs self.method = string_or_blank(card, 5, 'method', 'ADAPT') if self.method == 'ADAPT': self.kStep = integer_or_blank(card, 6, 'kStep', 2) elif self.method == 'ITER': self.kStep = integer_or_blank(card, 6, 'kStep', 10) elif self.method in ['AUTO', 'TSTEP']: self.kStep = None #self.kStep = blank(card, 6, 'kStep') #: .. todo:: not blank else: msg = 'invalid TSTEPNL Method. method=|%s|' % (self.method) raise RuntimeError(msg) self.maxIter = integer_or_blank(card, 7, 'maxIter', 10) self.conv = string_or_blank(card, 8, 'conv', 'PW') # line 2 self.epsU = double_or_blank(card, 9, 'epsU', 1.E-2) self.epsP = double_or_blank(card, 10, 'epsP', 1.E-3) self.epsW = double_or_blank(card, 11, 'epsW', 1.E-6) self.maxDiv = integer_or_blank(card, 12, 'maxDiv', 2) self.maxQn = integer_or_blank(card, 13, 'maxQn', 10) self.MaxLs = integer_or_blank(card, 14, 'MaxLs', 2) self.fStress = double_or_blank(card, 15, 'fStress', 0.2) # line 3 self.maxBisect = integer_or_blank(card, 17, 'maxBisect', 5) self.adjust = integer_or_blank(card, 18, 'adjust', 5) self.mStep = integer_or_blank(card, 19, 'mStep') self.rb = double_or_blank(card, 20, 'rb', 0.6) self.maxR = double_or_blank(card, 21, 'maxR', 32.) self.uTol = double_or_blank(card, 22, 'uTol', 0.1) self.rTolB = double_or_blank(card, 23, 'rTolB', 20.) # not listed in all QRGs self.minIter = integer_or_blank(card, 24, 'minIter') assert len(card) <= 25, 'len(TSTEPNL card) = %i' % len(card) else: (sid, ndt, dt, no, method, kStep, maxIter, conv, epsU, epsP, epsW, maxDiv, maxQn, maxLs, fStress, maxBisect, adjust, mStep, rb, maxR, uTol, rTolB) = data self.sid = sid self.ndt = ndt self.dt = dt self.no = no self.method = method self.kStep = kStep self.maxIter = maxIter self.conv = conv # line 2 self.epsU = epsU self.epsP = epsP self.epsW = epsW self.maxDiv = maxDiv self.maxQn = maxQn self.MaxLs = maxLs self.fStress = fStress # line 3 self.maxBisect = maxBisect self.adjust = adjust self.mStep = mStep self.rb = rb self.maxR = maxR self.uTol = uTol self.rTolB = rTolB self.minIter = None # not listed in DMAP 2005
[docs] def raw_fields(self): list_fields = ['TSTEPNL', self.sid, self.ndt, self.dt, self.no, self.method, self.kStep, self.maxIter, self.conv, self.epsU, self.epsP, self.epsW, self.maxDiv, self.maxQn, self.MaxLs, self.fStress, None, self.maxBisect, self.adjust, self.mStep, self.rb, self.maxR, self.uTol, self.rTolB, self.minIter] return list_fields
[docs] def repr_fields(self): #no = set_blank_if_default(self.no,1) no = self.no method = set_blank_if_default(self.method, 'ADAPT') kStep = self.kStep #if self.method=='ADAPT': #kStep = set_blank_if_default(self.kStep, 2) #elif self.method=='ITER': #kStep = set_blank_if_default(self.kStep, 10) #else: #msg = 'invalid TSTEPNL Method. method=|%s|' %(self.method) #raise RuntimeError(msg) #maxIter = set_blank_if_default(self.maxIter, 10) conv = set_blank_if_default(self.conv, 'PW') epsU = set_blank_if_default(self.epsU, 1e-2) epsP = set_blank_if_default(self.epsP, 1e-3) epsW = set_blank_if_default(self.epsW, 1e-6) maxDiv = set_blank_if_default(self.maxDiv, 2) maxQn = set_blank_if_default(self.maxQn, 10) MaxLs = set_blank_if_default(self.MaxLs, 2) fStress = set_blank_if_default(self.fStress, 0.2) maxBisect = set_blank_if_default(self.maxBisect, 5) adjust = set_blank_if_default(self.adjust, 5) rb = set_blank_if_default(self.rb, 0.6) maxR = set_blank_if_default(self.maxR, 32.) uTol = set_blank_if_default(self.uTol, 0.1) rTolB = set_blank_if_default(self.rTolB, 20.) list_fields = ['TSTEPNL', self.sid, self.ndt, self.dt, no, method, kStep, self.maxIter, conv, epsU, epsP, epsW, maxDiv, maxQn, MaxLs, fStress, None, maxBisect, adjust, self.mStep, rb, maxR, uTol, rTolB, self.minIter] return list_fields
[docs] def write_card(self, size=8, is_double=False): card = self.repr_fields() if size == 8: return self.comment() + print_card_8(card) return self.comment() + print_card_16(card)