Source code for pyNastran.bdf.cards.methods

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

 * EIGB
 * EIGC
 * EIGR
 * EIGP
 * EIGRL

All cards are Method objects.
"""
from __future__ import (nested_scopes, generators, division, absolute_import,
                        print_function, unicode_literals)
#import sys
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, string_or_blank, components,
    components_or_blank, integer_double_string_or_blank, blank, interpret_value)
from pyNastran.bdf.field_writer_8 import print_card_8
from pyNastran.bdf.field_writer_16 import print_card_16


[docs]class Method(BaseCard): """ Generic class for all methods. Part of self.methods """ def __init__(self, card, data): pass
[docs]class EIGB(Method): """ Defines data needed to perform buckling analysis """ type = 'EIGB' def __init__(self, card=None, data=None, comment=''): Method.__init__(self, card, data) if comment: self._comment = comment if card: #: Set identification number. (Unique Integer > 0) self.sid = integer(card, 1, 'sid') #: Method of eigenvalue extraction. (Character: 'INV' for inverse #: power method or 'SINV' for enhanced inverse power method.) #: apparently it can also be blank... self.method = string_or_blank(card, 2, 'method') if self.method not in ['INV', 'SINV', None]: msg = 'method must be INV or SINV. method=|%s|' % self.method raise RuntimeError(msg) #: Eigenvalue range of interest. (Real, L1 < L2) self.L1 = double(card, 3, 'L1') self.L2 = double(card, 4, 'L2') if not self.L1 < self.L2: msg = 'L1=%s L2=%s; L1<L2 is requried' % (self.L1, self.L2) raise RuntimeError(msg) #: Estimate of number of roots in positive range not used for #: METHOD = 'SINV'. (Integer > 0) self.nep = integer_or_blank(card, 5, 'nep', 0) #: Desired number of positive and negative roots. #: (Integer>0; Default = 3*NEP) self.ndp = integer_or_blank(card, 6, 'ndp', 3 * self.nep) self.ndn = integer_or_blank(card, 7, 'ndn', 3 * self.nep) #: Method for normalizing eigenvectors. #: ('MAX' or 'POINT';Default='MAX') self.norm = string_or_blank(card, 9, 'norm', 'MAX') if self.norm == 'POINT': self.G = integer(card, 10, 'G') self.C = components(card, 11, 'C') else: self.G = integer_or_blank(card, 10, 'G') self.C = components_or_blank(card, 11, 'C') assert len(card) <= 12, 'len(EIGB card) = %i' % len(card) else: raise NotImplementedError('EIGB')
[docs] def cross_reference(self, model): pass
[docs] def raw_fields(self): list_fields = ['EIGB', self.sid, self.method, self.L1, self.L2, self.nep, self.ndp, self.ndn, None, self.norm, self.G, self.C] return list_fields
[docs] def repr_fields(self): #method = set_blank_if_default(self.method,'INV') nep = set_blank_if_default(self.nep, 0) ndp = set_blank_if_default(self.ndp, 3 * self.nep) ndn = set_blank_if_default(self.ndn, 3 * self.nep) norm = set_blank_if_default(self.norm, 'MAX') list_fields = ['EIGB', self.sid, self.method, self.L1, self.L2, nep, ndp, ndn, None, norm, self.G, self.C] 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 EIGC(Method): """ Defines data needed to perform complex eigenvalue analysis .. todo: not done """ type = 'EIGC' def __init__(self, card=None, data=None, comment=''): Method.__init__(self, card, data) if comment: self._comment = comment # CLAN self.mblkszs = [] self.iblkszs = [] self.ksteps = [] self.NJIs = [] # HESS self.alphaBjs = [] self.omegaBjs = [] self.LJs = [] self.NEJs = [] self.NDJs = [] if card: #: Set identification number. (Unique Integer > 0) self.sid = integer(card, 1, 'sid') #: Method of complex eigenvalue extraction self.method = string(card, 2, 'method') assert self.method in ['INV', 'HESS', 'CLAN'], ( 'method=%s is not INV, HESS, CLAN' % (self.method)) #: Method for normalizing eigenvectors self.norm = string_or_blank(card, 3, 'norm') if self.norm == 'POINT': #: Grid or scalar point identification number. Required only if #: NORM='POINT'. (Integer>0) self.G = integer(card, 4, 'G') #: Component number. Required only if NORM='POINT' and G is a #: geometric grid point. (1<Integer<6) self.C = components(card, 5, 'C') else: self.G = blank(card, 4, 'G') self.C = blank(card, 5, 'C') #: Convergence criterion. (Real > 0.0. Default values are: #: 10^-4 for METHOD = "INV", #: 10^-15 for METHOD = "HESS", #: E is machine dependent for METHOD = "CLAN".) self.E = double_or_blank(card, 6, 'E') self.ndo = integer_double_string_or_blank(card, 7, 'ND0') # ALPHAAJ OMEGAAJ ALPHABJ OMEGABJ LJ NEJ NDJ fields = [interpret_value(field) for field in card[9:]] self.alphaAjs = [] self.omegaAjs = [] nfields = len(fields) nrows = nfields // 8 if nfields % 8 > 0: nrows += 1 #if nrows == 0: #raise RuntimeError('invalid row count=0; nfields=%s \ncard=%s\nfields=%s' % (nfields, card, fields)) if self.method == 'CLAN': self.loadCLAN(nrows, card) elif self.method in ['HESS', 'INV']: # HESS, INV self.loadHESS_INV(nrows, card) else: msg = 'invalid EIGC method...method=%r' % self.method raise RuntimeError(msg) #assert card.nFields() < 8, 'card = %s' % card else: raise NotImplementedError('EIGC')
[docs] def loadCLAN(self, nRows, card): for irow in range(nRows): #NDJ_default = None i = 9 + 8 * irow self.alphaAjs.append( double_or_blank(card, i, 'alpha' + str(irow), 0.0)) self.omegaAjs.append( double_or_blank(card, i + 1, 'omega' + str(irow), 0.0)) self.mblkszs.append( double_or_blank(card, i + 2, 'mblock' + str(irow), 7)) self.iblkszs.append( integer_or_blank(card, i + 3, 'iblksz' + str(irow), 2)) self.ksteps.append( integer_or_blank(card, i + 4, 'kstep' + str(irow), 5)) self.NJIs.append( integer(card, i + 6, 'NJI' + str(irow)))
[docs] def loadHESS_INV(self, nRows, card): alphaOmega_default = None LJ_default = None if self.method == 'INV': alphaOmega_default = 0.0 LJ_default = 1.0 for iRow in range(nRows): NEj = integer(card, 9 + 7 * iRow + 5, 'NE%s' % str(iRow)) NDJ_default = None if self.method == 'INV': NDJ_default = 3 * NEj i = 9 + 8 * iRow self.alphaAjs.append( double_or_blank(card, i, 'alphaA' + str(iRow), alphaOmega_default)) self.omegaAjs.append( double_or_blank(card, i + 1, 'omegaA' + str(iRow), alphaOmega_default)) self.alphaBjs.append( double_or_blank(card, i + 2, 'alphaB' + str(iRow), alphaOmega_default)) self.omegaBjs.append( double_or_blank(card, i + 3, 'omegaB' + str(iRow), alphaOmega_default)) self.LJs.append( double_or_blank(card, i + 4, 'LJ' + str(iRow), LJ_default)) self.NEJs.append( integer(card, i + 5, 'NEJ' + str(iRow))) self.NDJs.append( integer_or_blank(card, i + 6, 'NDJ' + str(iRow), NDJ_default))
[docs] def cross_reference(self, model): pass
[docs] def rawMethod(self): list_fields = [] if self.method in ['HESS', 'INV']: for (alphaA, omegaA, alphaB, omegaB, Lj, NEj, NDj) in zip( self.alphaAjs, self.omegaAjs, self.alphaBjs, self.omegaBjs, self.LJs, self.NEJs, self.NDJs): alphaA = set_blank_if_default(alphaA, 0.0) omegaA = set_blank_if_default(omegaA, 0.0) alphaB = set_blank_if_default(alphaB, 0.0) omegaB = set_blank_if_default(omegaB, 0.0) list_fields += [alphaA, omegaA, alphaB, omegaB, Lj, NEj, NDj, None] elif self.method == 'CLAN': assert len(self.alphaAjs) == len(self.omegaAjs) assert len(self.alphaAjs) == len(self.mblkszs) assert len(self.alphaAjs) == len(self.iblkszs) assert len(self.alphaAjs) == len(self.ksteps) assert len(self.alphaAjs) == len(self.NJIs) for (alphaA, omegaA, mblksz, iblksz, kstep, Nj) in zip( self.alphaAjs, self.omegaAjs, self.mblkszs, self.iblkszs, self.ksteps, self.NJIs): alphaA = set_blank_if_default(alphaA, 0.0) omegaA = set_blank_if_default(omegaA, 0.0) mblksz = set_blank_if_default(mblksz, 7) iblksz = set_blank_if_default(iblksz, 2) kstep = set_blank_if_default(kstep, 5) list_fields += [alphaA, omegaA, mblksz, iblksz, kstep, None, Nj, None] else: msg = 'invalid EIGC method...method=%r' % self.method raise RuntimeError(msg) return list_fields
[docs] def reprMethod(self): return self.rawMethod()
[docs] def raw_fields(self): list_fields = ['EIGC', self.sid, self.method, self.norm, self.G, self.C, self.E, self.ndo, None] list_fields += self.rawMethod() return list_fields
[docs] def repr_fields(self): if self.E is None: E = None else: E = str(self.E) list_fields = ['EIGC', self.sid, self.method, self.norm, self.G, self.C, E, self.ndo, None] list_fields += self.reprMethod() 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 EIGP(Method): """ Defines poles that are used in complex eigenvalue extraction by the Determinant method. """ type = 'EIGP' def __init__(self, card=None, data=None, comment=''): Method.__init__(self, card, data) if comment: self._comment = comment if card: #: Set identification number. (Unique Integer > 0) self.sid = integer(card, 1, 'sid') #: Coordinates of point in complex plane. (Real) self.alpha1 = double(card, 2, 'alpha1') #: Coordinates of point in complex plane. (Real) self.omega1 = double(card, 3, 'omega1') #: Multiplicity of complex root at pole defined by point at ALPHAi #: and OMEGAi self.m1 = integer(card, 4, 'm1') #: Coordinates of point in complex plane. (Real) self.alpha2 = double(card, 5, 'alpha2') #: Coordinates of point in complex plane. (Real) self.omega2 = double(card, 6, 'omega2') #: Multiplicity of complex root at pole defined by point at ALPHAi #: and OMEGAi self.m2 = integer(card, 7, 'm2') assert len(card) == 8, 'len(EIGP card) = %i' % len(card) else: raise NotImplementedError('EIGP')
[docs] def cross_reference(self, model): pass
[docs] def raw_fields(self): list_fields = ['EIGP', self.alpha1, self.omega1, self.m1, self.alpha2, self.omega2, self.m2] 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 EIGR(Method): """ Defines data needed to perform real eigenvalue analysis """ type = 'EIGR' def __init__(self, card=None, data=None, comment=''): Method.__init__(self, card, data) if comment: self._comment = comment if card: #: Set identification number. (Unique Integer > 0) self.sid = integer(card, 1, 'sid') #: Method of eigenvalue extraction. (Character: 'INV' for inverse #: power method or 'SINV' for enhanced inverse power method.) self.method = string_or_blank(card, 2, 'method', 'LAN') assert self.method in ['LAN', 'AHOU', 'INV', 'SINV', 'GIV', 'MGIV', 'HOU', 'MHOU', 'AGIV'], 'method=%s' % self.method #: Frequency range of interest self.f1 = double_or_blank(card, 3, 'f1') self.f2 = double_or_blank(card, 4, 'f2') #: Estimate of number of roots in range (Required for #: METHOD = 'INV'). Not used by 'SINV' method. self.ne = integer_or_blank(card, 5, 'ne') #: Desired number of roots (default=600 for SINV 3*ne for INV) if self.method in ['SINV']: self.nd = integer_or_blank(card, 6, 'nd', 600) if self.method in ['INV']: self.nd = integer_or_blank(card, 6, 'nd', 3 * self.ne) elif self.method in ['GIV', 'MGIV', 'HOU', 'MHOU']: self.nd = integer_or_blank(card, 6, 'nd', 0) else: self.nd = integer(card, 6, 'nd') #: Method for normalizing eigenvectors. ('MAX' or 'POINT'; #: Default='MAX') self.norm = string_or_blank(card, 9, 'norm', 'MASS') assert self.norm in ['POINT', 'MASS', 'MAX'] if self.method == 'POINT': #: Grid or scalar point identification number. Required only if #: NORM='POINT'. (Integer>0) self.G = integer(card, 10, 'G') #: Component number. Required only if NORM='POINT' and G is a #: geometric grid point. (1<Integer<6) self.C = components(card, 11, 'C') else: self.G = blank(card, 10, 'G') self.C = blank(card, 11, 'C') assert len(card) <= 12, 'len(EIGR card) = %i' % len(card) else: raise NotImplementedError('EIGR')
[docs] def cross_reference(self, model): pass
[docs] def raw_fields(self): list_fields = ['EIGR', self.sid, self.method, self.f1, self.f2, self.ne, self.nd, None, None, self.norm, self.G, self.C] return list_fields
[docs] def repr_fields(self): method = set_blank_if_default(self.method, 'LAN') norm = set_blank_if_default(self.norm, 'MASS') list_fields = ['EIGR', self.sid, method, self.f1, self.f2, self.ne, self.nd, None, None, norm, self.G, self.C] 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 EIGRL(Method): """ Defines data needed to perform real eigenvalue (vibration or buckling) analysis with the Lanczos method """ type = 'EIGRL' def __init__(self, card=None, data=None, sol=None, comment=''): Method.__init__(self, card, data) if comment: self._comment = comment if card: #: Set identification number. (Unique Integer > 0) self.sid = integer(card, 1, 'sid') #: For vibration analysis: frequency range of interest. For #: buckling analysis: eigenvalue range of interest. See Remark 4. #: (Real or blank, -5 10e16 <= V1 < V2 <= 5.10e16) self.v1 = double_or_blank(card, 2, 'v1') self.v2 = double_or_blank(card, 3, 'v2') #: Number of roots desired self.nd = integer_or_blank(card, 4, 'nd') #: Diagnostic level. (0 < Integer < 4; Default = 0) self.msglvl = integer_or_blank(card, 5, 'msglvl', 0) #: Number of vectors in block or set. Default is machine dependent self.maxset = integer_or_blank(card, 6, 'maxset') #: Estimate of the first flexible mode natural frequency #: (Real or blank) self.shfscl = double_or_blank(card, 7, 'shfscl') #: Method for normalizing eigenvectors (Character: 'MASS' or 'MAX') self.norm = string_or_blank(card, 8, 'norm') optionValues = [interpret_value(field) for field in card[9:]] self.options = [] self.values = [] #print "optionValues = ",optionValues for optionValue in optionValues: #print "optionValue = ",optionValue (option, value) = optionValue.split('=') self.options.append(option) self.values.append(value) #: Method for normalizing eigenvectors if sol in [103, 115, 146]: # normal modes,cyclic normal modes, flutter self.norm = string_or_blank(card, 8, 'norm', 'MASS') elif sol in [105, 110, 111, 116]: # buckling, modal complex eigenvalues, # modal frequency response,cyclic buckling self.norm = string_or_blank(card, 8, 'norm', 'MAX') else: self.norm = string_or_blank(card, 8, 'norm') #assert len(card) <= 9, 'len(EIGRL card) = %i' % len(card) assert len(card) <= 10, 'len(EIGRL card) = %i' % len(card) #msg = 'norm=%s sol=%s' % (self.norm, sol) #assert self.norm in ['MASS', 'MAX'],msg #assert card.nFields()<9,'card = %s' %(card.fields(0)) else: raise NotImplementedError('EIGRL')
[docs] def cross_reference(self, model): pass
#if self.norm is None: #if model.is_modal_solution(): #self.norm = 'MASS' #elif mdoel.is_buckling_solution(): #self.norm = 'MAX'
[docs] def raw_fields(self): list_fields = ['EIGRL', self.sid, self.v1, self.v2, self.nd, self.msglvl, self.maxset, self.shfscl, self.norm] for (option, value) in zip(self.options, self.values): list_fields += [option + '=' + str(value)] return list_fields
[docs] def repr_fields(self): msglvl = set_blank_if_default(self.msglvl, 0) list_fields = ['EIGRL', self.sid, self.v1, self.v2, self.nd, msglvl, self.maxset, self.shfscl, self.norm] for (option, value) in zip(self.options, self.values): list_fields += [option + '=' + str(value)] 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)