Source code for pyNastran.bdf.caseControlDeck

# pylint: disable=R0904,R0902,C0103
"""
CaseControlDeck parsing and extraction class
"""
from __future__ import (nested_scopes, generators, division, absolute_import,
                        print_function, unicode_literals)
from six import iteritems, itervalues
import sys
import copy

from pyNastran.bdf import subcase
from pyNastran.bdf.subcase import Subcase, update_param_name
from pyNastran.utils.log import get_logger


[docs]class CaseControlDeckDeprecated(object): def __init__(self): pass #def hasParameter(self, isubcase, param_name): #self.has_parameter(isubcase, param_name) #def get_subcase_parameter(self, isubcase, param_name): #def has_subcase(self, isubcase): #def create_new_subcase(self, isubcase): #def delete_subcase(self, isubcase): #def copy_subcase(self, i_from_subcase, i_to_subcase, overwrite_subcase=True): #def get_subcase_list(self): #def get_local_subcase_list(self): #def update_solution(self, isubcase, sol): #def add_parameter_to_global_subcase(self, param): #def add_parameter_to_local_subcase(self, isubcase, param): #def finish_subcases(self): #def convert_to_sol_200(self, model):
[docs]class CaseControlDeck(object): """ CaseControlDeck parsing and extraction class """ def __init__(self, lines, log=None): """ :param self: the CaseControlDeck object :param lines: list of lines that represent the case control deck ending with BEGIN BULK :param log: a :mod: `logging` object """ # pulls the logger from the BDF object self.log = get_logger(log, "debug") self.debug = False #self.debug = True #: stores a single copy of 'BEGIN BULK' or 'BEGIN SUPER' self.begin_bulk = ['BEGIN', 'BULK'] # allows BEGIN BULK to be turned off self.write_begin_bulk = True self._begin_count = 0 self.lines = lines self.subcases = {0: Subcase(id=0)} self._read(self.lines)
[docs] def has_parameter(self, isubcase, param_name): """ Checks to see if a parameter (e.g. STRESS) is defined in a certain subcase ID. :param self: the CaseControlDeck object :param isubcase: the subcase ID to check :param param_name: the parameter name to look for """ if self.has_subcase(isubcase): return self.subcases[isubcase].has_parameter(param_name.upper())
[docs] def get_subcase_parameter(self, isubcase, param_name): """ Get the [value, options] of a subcase's parameter. For example, for STRESS(PLOT,POST)=ALL, param_name=STRESS, value=ALL, options=['PLOT', 'POST'] :param self: the CaseControlDeck object :param isubcase: the subcase ID to check :param param_name: the parameter name to get the [value, options] for """ if self.has_subcase(isubcase): return self.subcases[isubcase].get_parameter(param_name.upper()) msg = 'isubcase=%r does not exist...subcases=%s' % (isubcase, str(sorted(self.subcases.keys()))) raise RuntimeError(msg)
[docs] def has_subcase(self, isubcase): """ Checks to see if a subcase exists. :param self: the CaseControlDeck object :param isubcase: the subcase ID :type isubcase: int :returns val: does_subcase_exist (type = bool) """ if isubcase in self.subcases: return True return False
[docs] def create_new_subcase(self, isubcase): """ Method create_new_subcase: :param isubcase: the subcase ID :type isubcase: int .. warning:: be careful you dont add data to the global subcase after running this...is this True??? """ #print("creating subcase=%s" % isubcase) if self.has_subcase(isubcase): sys.stderr.write('subcase=%s already exists...skipping\n' % isubcase) self.copy_subcase(i_from_subcase=0, i_to_subcase=isubcase, overwrite_subcase=True) #self.subcases[isubcase] = Subcase(id=isubcase)
[docs] def delete_subcase(self, isubcase): """ Deletes a subcase. :param self: the CaseControlDeck object :param isubcase: the Subcase to delete :type isubcase: int """ if not self.has_subcase(isubcase): sys.stderr.write('subcase %s doesnt exist...skipping\n' % isubcase) del self.subcases[isubcase]
[docs] def copy_subcase(self, i_from_subcase, i_to_subcase, overwrite_subcase=True): """ Overwrites the parameters from one subcase to another. :param self: the CaseControlDeck object :param i_from_subcase: the Subcase to pull the data from :param i_to_subcase: the Subcase to map the data to :param overwrite_subcase: NULLs i_to_subcase before copying i_from_subcase """ #print("copying subcase from=%s to=%s overwrite=%s" % (i_from_subcase, i_to_subcase, overwrite_subcase)) if not self.has_subcase(i_from_subcase): msg = 'i_from_subcase=%r does not exist...subcases=%s' % (i_from_subcase, str(sorted(self.subcases.keys()))) raise RuntimeError(msg) if overwrite_subcase: subcase_from = self.subcases[i_from_subcase] subcase_to = copy.deepcopy(subcase_from) subcase_to.id = i_to_subcase #for key, param in sorted(iteritems(subcase_from.params)): #print("going to copy key=%s param=%s" % (key, param)) self.subcases[i_to_subcase] = subcase_to else: if not self.has_subcase(i_to_subcase): msg = 'i_from_subcase=%r does not exist...subcases=%s' % (i_to_subcase, str(sorted(self.subcases.keys()))) raise RuntimeError(msg) subcase_to = self.subcases[i_to_subcase] for key, param in sorted(iteritems(subcase_to)): #print('copying key=%s param=%s' % (key, param)) if key == 'BEGIN': pass subcase_to[key] = copy.deepcopy(param)
[docs] def get_subcase_list(self): """ Gets the list of subcases including the global subcase ID (0) :param self: the CaseControlDeck object """ return sorted(self.subcases.keys())
[docs] def get_local_subcase_list(self): """ Gets the list of subcases that aren't the global subcase ID :param self: the CaseControlDeck object """ id_list = [id for id in self.subcases if id != 0] # skip the global return sorted(id_list)
[docs] def update_solution(self, isubcase, sol): """ sol = STATICS, FLUTTER, MODAL, etc. :param self: the CaseControlDeck object :param isubcase: the subcase ID to update :param sol: the solution type to change the solution to >>> print(bdf.case_control) SUBCASE 1 DISP = ALL >>> bdf.case_control.update_solution(1, 'FLUTTER') >>> print(bdf.case_control) SUBCASE 1 ANALYSIS FLUTTER DISP = ALL >>> """ self.add_parameter_to_local_subcase(isubcase, 'ANALYSIS %s' % sol)
[docs] def add_parameter_to_global_subcase(self, param): """ Takes in a single-lined string and adds it to the global Subcase. :param self: the CaseControlDeck object :param param: the variable to add .. note:: dont worry about overbounding the line >>> bdf = BDF() >>> bdf.read_bdf(bdf_filename) >>> bdf.case_control.add_parameter_to_global_subcase('DISP=ALL') >>> print(bdf.case_control) TITLE = DUMMY LINE DISP = ALL """ (j, key, value, options, paramType) = self._parse_data_from_user(param) subcase_list = self.get_subcase_list() for isubcase in subcase_list: self._add_parameter_to_subcase(key, value, options, paramType, isubcase)
[docs] def add_parameter_to_local_subcase(self, isubcase, param): """ Takes in a single-lined string and adds it to a single Subcase. :param self: the CaseControlDeck object :param isubcase: the subcase ID to add :param param: the variable to add .. note:: dont worry about overbounding the line >>> bdf = BDF() >>> bdf.read_bdf(bdf_filename) >>> bdf.case_control.add_parameter_to_local_subcase(1, 'DISP=ALL') >>> print(bdf.case_control) TITLE = DUMMY LINE SUBCASE 1 DISP = ALL >>> """ (j, key, value, options, param_type) = self._parse_data_from_user(param) self._add_parameter_to_subcase(key, value, options, param_type, isubcase)
[docs] def _parse_data_from_user(self, param): """ Parses a case control line :param self: the CaseControlDeck object :param param: the variable to add """ if '\n' in param or '\r' in param or '\t' in param: msg = 'doesnt support embedded endline/tab characters\n' msg += ' param = %r' % param raise SyntaxError(msg) #self.read([param]) lines = _clean_lines(self, [param]) (j, key, value, options, param_type) = self._parse_entry(lines) return (j, key, value, options, param_type)
[docs] def _read(self, lines): """ Reads the case control deck .. note:: supports comment lines .. warning:: doesnt check for 72 character width lines, but will follow that when it's written out """ isubcase = 0 lines = _clean_lines(self, lines) self.output_lines = [] i = 0 is_output_lines = False while i < len(lines): line = lines[i] lines2 = [line] while ',' in lines[i][-1]: i += 1 lines2.append(lines[i]) (j, key, value, options, paramType) = self._parse_entry(lines2) i += 1 if key == 'BEGIN': if 'BULK' not in line and 'SUPER' not in line: raise NotImplementedError('line=%r' % line) if self._begin_count == 1: raise NotImplementedError('multiple BEGIN lines are defined...') self.begin_bulk = [key, value] self._begin_count += 1 continue elif line.startswith('OUTPUT'): is_output_lines = True #output_line = '%s(%s) = %s\n' % (key, options, value) key = 'OUTPUT' # OUTPUT(POST) -> POST post = line.split('OUTPUT')[1].strip('( )') options = [post] value = None paramType = 'STRESS-type' isubcase = self._add_parameter_to_subcase(key, value, options, paramType, isubcase) self.output_lines.append(line) continue #print("key=%-12r icase=%i value=%r options=%r paramType=%r" %(key, # isubcase, value, options, paramType)) isubcase = self._add_parameter_to_subcase(key, value, options, paramType, isubcase) #print(str(self)) self.finish_subcases()
[docs] def _parse_entry(self, lines): r""" Internal method for parsing a card of the case control deck Parses a single case control deck card into 4 sections 1. paramName - obvious 2. Value - still kind of obvious 3. options - rarely used data 4. paramType - STRESS-type, SUBCASE-type, PARAM-type, SET-type, BEGIN_BULK-type It's easier with examples: paramType = SUBCASE-type SUBCASE 1 -> paramName=SUBCASE value=1 options=[] paramType = STRESS-type STRESS = ALL -> paramName=STRESS value=ALL options=[] STRAIN(PLOT) = 5 -> paramName=STRAIN value=5 options=[PLOT] TITLE = stuff -> paramName=TITLE value=stuff options=[] paramType = SET-type SET 1 = 10,20,30 -> paramName=SET value=[10,20,30] options = 1 paramType = BEGIN_BULK-type BEGIN BULK -> paramName=BEGIN value=BULK options = [] paramType = CSV-type PARAM,FIXEDB,-1 -> paramName=PARAM value=FIXEDB options = [-1] The paramType is the "macro" form of the data (similar to integer, float, string). The value is generally whats on the RHS of the equals sign (assuming it's there). Options are modifiers on the data. Form things like the PARAM card or the SET card they arent as clear, but the paramType lets the program know how to format it when writing it out. :param self: the CaseControlDeck object :param lines: list of lines :return: paramName see brief :return: value see brief :return: options see brief :return: paramType see brief """ i = 0 options = [] value = None key = None param_type = None line = lines[i] #print(line) #print("*****lines = ", lines) equals_count = 0 for letter in line: if letter == '=': equals_count += 1 line_upper = line.upper() #print("line_upper = %r" % line) if line_upper.startswith('SUBCASE'): #print("line = %r" % line) line2 = line.replace('=', '') sline = line2.split() if len(sline) != 2: msg = "trying to parse %r..." % line raise RuntimeError(msg) (key, param_type) = sline #print("key=%r isubcase=%r" % (key, isubcase)) value = int(param_type) #self.isubcase = int(isubcase) param_type = 'SUBCASE-type' elif (line_upper.startswith('LABEL') or line_upper.startswith('SUBT') or # SUBTITLE line_upper.startswith('TITL')): # TITLE try: eIndex = line.index('=') except: msg = "cannot find an = sign in LABEL/SUBTITLE/TITLE line\n" msg += "line = %r" % line_upper.strip() raise RuntimeError(msg) key = line[0:eIndex].strip() value = line[eIndex + 1:].strip() options = [] param_type = 'STRING-type' elif equals_count == 1: # STRESS if '=' in line: (key, value) = line.strip().split('=') else: msg = 'expected item of form "name = value" line=%r' % line.strip() raise RuntimeError(msg) key = key.strip() value = value.strip() if self.debug: self.log.debug("key=%r value=%r" % (key, value)) param_type = 'STRESS-type' if '(' in key: # comma may be in line - STRESS-type #paramType = 'STRESS-type' sline = key.strip(')').split('(') key = sline[0] options = sline[1].split(',') # handle TEMPERATURE(INITIAL) and TEMPERATURE(LOAD) cards if key == 'TEMPERATURE' or key == 'TEMP': key = 'TEMPERATURE(%s)' % (options[0]) options = [] #print("key=%r options=%s" %(key,options)) elif ' ' in key and ',' in value: # SET-type (key, ID) = key.split() key = key + ' ' + ID if self.debug: self.log.debug('SET-type key=%r ID=%r' % (key, ID)) fivalues = value.rstrip(' ,').split(',') # float/int values #: .. todo:: should be more efficient multiline reader... # read more lines.... if line[-1].strip() == ',': i += 1 #print("rawSETLine = %r" % (lines[i])) while 1: if ',' == lines[i].strip()[-1]: fivalues += lines[i][:-1].split(',') else: # last case fivalues += lines[i].split(',') #print("fivalues last = i=%s %r" % (i, lines[i])) i += 1 break i += 1 #print("len(fivalues) = ",len(fivalues)) value = fivalues options = ID # needed a place to put it... param_type = 'SET-type' elif ',' in value: # STRESS-type; special TITLE = stuffA,stuffB #print('A ??? line = ',line) #raise RuntimeError(line) pass else: # STRESS-type; TITLE = stuff #print('B ??? line = ',line) pass key = update_param_name(key.strip()) verify_card(key, value, options, line) elif line_upper.startswith('BEGIN'): # begin bulk try: (key, value) = line_upper.split(' ') except: msg = 'excepted "BEGIN BULK" found=%r' % line raise RuntimeError(msg) param_type = 'BEGIN_BULK-type' elif 'PARAM' in line_upper: # param sline = line.split(',') if len(sline) != 3: raise SyntaxError("trying to parse %r..." % line) (key, value, options) = sline param_type = 'CSV-type' elif ' ' not in line: key = line.strip() value = line.strip() options = None param_type = 'KEY-type' else: msg = 'generic catch all...line=|%r|' % line key = '' value = line options = None param_type = 'KEY-type' i += 1 return (i, key, value, options, param_type)
[docs] def finish_subcases(self): """ Removes any unwanted data in the subcase...specifically the SUBCASE data member. Otherwise it will print out after a key like stress. :param self: the CaseControlDeck object """ for subcase in itervalues(self.subcases): subcase.finish_subcase()
[docs] def convert_to_sol_200(self, model): """ Takes a case control deck and changes it from a SOL xxx to a SOL 200 :param self: the CaseControlDeck object .. todo:: not done... """ analysis = model.rsolmap_toStr[model.sol] model.sol = 200 subcase.add_parameter_to_global_subcase('ANALYSIS', analysis) #subcase.add_parameter_to_global_subcase('DESSUB', dessub)
[docs] def _add_parameter_to_subcase(self, key, value, options, param_type, isubcase): """ Internal method self: the CaseControlDeck object """ if self.debug: a = 'key=%r' % key b = 'value=%r' % value c = 'options=%r' % options d = 'param_type=%r' % param_type msg = "_adding isubcase=%s %-12s %-12s %-12s %-12s" % (isubcase, a, b, c, d) self.log.debug(msg) if key == 'SUBCASE': assert value not in self.subcases assert isinstance(value, int) isubcase = value #print("value=", value) self.copy_subcase(i_from_subcase=0, i_to_subcase=isubcase, overwrite_subcase=True) if self.debug: msg = "copied subcase i_from_subcase=%r to i_to_subcase=%r" % (0, isubcase) self.log.debug(msg) elif isubcase not in self.subcases: # initialize new subcase #self.isubcase += 1 # is handled in the read code msg = 'isubcase=%r is not a valid subcase...subcases=%s' % (isubcase, str(sorted(self.subcases.keys()))) raise RuntimeError(msg) subcase = self.subcases[isubcase] subcase._add_data(key, value, options, param_type) #print("\n%s\n" % (self.subcases[isubcase])) return isubcase
[docs] def cross_reference(self, model): for (isubcase, subcase) in sorted(iteritems(self.subcases)): subcase.cross_reference(model)
[docs] def get_op2_data(self): """ Gets the relevant op2 parameters required for a given subcase :param self: the CaseControlDeck object .. todo:: not done... """ cases = {} for (isubcase, subcase) in sorted(iteritems(self.subcases)): if isubcase: cases[isubcase] = subcase.getOp2Data(self.sol, subcase.solmap_toValue) return cases
def __repr__(self): """ :param self: the CaseControlDeck object """ msg = '' subcase0 = self.subcases[0] for subcase in itervalues(self.subcases): #print('writing subcase...') msg += subcase.write_subcase(subcase0) #if len(self.subcases) == 1: #msg += 'BEGIN BULK\n' if self.output_lines: msg += '\n'.join(self.output_lines) + '\n' if self.write_begin_bulk: msg += ' '.join(self.begin_bulk) + '\n' return msg ##def parseParam(self,param): #""" #.. warning:: doesnt support comment characters #""" #param = param.substr('\n','').substr('\r','') # remove line endings #parse(param) ##param2 = [''.join(param)] ##print('param2 = ',param2)
[docs]def verify_card(key, value, options, line): if key in ['AUXMODEL', 'BC', 'BCHANGE', 'BCMOVE', 'CAMPBELL', 'CLOAD', 'CMETHOD', 'CSSCHD', 'DEACTEL', 'DEFORM', 'DESGLB', 'DESSUB', 'DIVERG', 'DLOAD', 'DRSPAN', 'FMETHOD', 'FREQUENCY', 'GUST', 'HADAPART', 'LINE', 'LOAD', 'LOADSET', 'MAXLINES', 'MCHSTAT', 'MFLUID', 'MODES', 'MODTRAK', 'MPC', 'NLHARM',]: try: value2 = int(value) except: print('line=%r is invalid; value=%r' % (line, value)) raise assert value2 > 0, 'line=%r is invalid; value=%r must be greater than 0.' % (line, value2)
[docs]def verify_card2(key, value, options, line): """ Make sure there are no obvious errors """ # this is purposely made overly strict to catch all the cases # these may only be integers #print("key =", key) if key in ['BCONTACT', 'CURVELINESYMBOL']: try: value2 = int(value) except: print('line=%r is invalid; value=%r' % (line, value)) raise # these may only be integers greater than 0 elif key in [ 'SPC', 'MPC', 'TRIM', 'FMETHOD', 'METHOD', 'LOAD', 'SUPORT', 'SUPORT1', 'TEMPERATURE(INITIAL)', 'TEMPERATURE(LOAD)', 'DLOAD', 'MFLUID', 'CLOAD', 'NLPARM', 'CMETHOD', 'FREQUENCY', 'TSTEP', 'TSTEPNL', 'SDAMPING', 'DESOBJ', 'TEMPERATURE(INIT)', 'RANDOM', 'DESSUB', 'ADAPT', 'MAXLINES', 'TFL','DESGLB', 'SMETHOD', 'DYNRED', 'GUST', 'TEMPERATURE(MATE)', 'OTIME', 'NONLINEAR', 'AUXM', 'IC', 'BC', 'OUTRCV', 'DIVERG', 'DATAREC', 'TEMPERATURE(BOTH)', 'DEFORM', 'MODES', 'CASE', 'SEDR', 'SELG', 'SEFINAL', 'SEKR', 'TEMPERATURE(ESTIMATE)', 'GPSDCON', 'AUXMODEL', 'MODTRAK', 'OFREQ', 'DRSPAN', 'OMODES', 'ADACT', 'SERESP', 'STATSUB', 'CURVESYM', 'ELSDCON', 'CSSCHD', 'NSM', 'TSTRU', 'RANDVAR', '' 'RGYRO', 'SELR', 'TEMPERATURE(ESTI)', 'RCROSS', 'SERE', 'SEMR', '', '', '', '', '', '', '', '', '', '', '']: try: value2 = int(value) except: print('line=%r is invalid; value=%r' % (line, value)) raise assert value2 > 0, 'line=%r is invalid; value=%r must be greater than 0.' % (line, value2) # these may have a value of all/none/integer, nothing else # except commas are allowed # 'DISP=ALL', 'DISP=NONE', 'DISP=1', 'DISP=1,2' elif key in ['STRESS', 'STRAIN', 'SPCFORCES', 'DISPLACEMENT', 'MPCFORCES', 'SVECTOR', 'VELOCITY', 'ACCELERATION', 'FORCE', 'ESE', 'OLOAD', 'SEALL', 'GPFORCE', 'GPSTRESS', 'GPSTRAIN', 'FLUX','AEROF', 'THERMAL', 'STRFIELD', 'NOUTPUT', 'SEDV', 'APRES', 'HTFLOW', 'NLSTRESS', 'GPKE', 'SACCELERATION', 'SDISPLACEMENT', 'SEMG', 'HARMONICS', 'PRESSURE', 'VUGRID', 'ELSUM', 'SVELOCITY', 'STRFIELD REAL', 'SENSITY', 'MONITOR', 'NLLOAD', 'GPSDCON', 'BOUTPUT', '', '', '']: if value not in ['ALL', 'NONE']: if ',' in value: sline = value.split(',') for spot in sline: try: value2 = int(spot) except: print('line=%r is invalid; value=%r' % (line, spot)) raise else: try: value2 = int(value) except: print('line=%r is invalid; value=%r' % (line, value)) raise assert value2 > 0, 'line=%r is invalid; value=%r must be greater than 0.' % (line, value2) elif key in ['ECHO']: #assert value in ['NONE','BOTH','UNSORT','SORT', 'NOSORT', 'PUNCH', ''], 'line=%r is invalid; value=%r.' % (line, value) pass elif key in ['CSCALE', 'SUBSEQ','SYMSEQ', 'DEFORMATION SCALE', '', '']: # floats pass elif 'SET' in key: pass # weird cards elif key in ['SUBTITLE', 'TITLE', 'A2GG', 'M2GG', 'K2GG', 'K2PP', 'M2PP', 'K42GG', 'XMIN', 'XMAX', 'XTITLE','XPAPE', 'XPAPER', 'XAXIS', 'XGRID', 'XGRID LINES', 'XLOG', 'YMIN', 'YMAX', 'YTITLE','YPAPE', 'YPAPER', 'YAXIS', 'YGRID', 'YGRID LINES', 'YLOG', 'XTMIN','XTMAX', 'XTGRID', 'XTTITLE', 'XTAXIS', 'XTGRID LINES', 'XTLOG', 'YTMIN','YTMAX', 'YTGRID', 'YTTITLE', 'YTAXIS', 'YTGRID LINES', 'YTLOG', 'XBMIN', 'XBMAX', 'XBGRID', 'XBAXIS', 'XBGRID LINES', 'XBTITLE', 'XBLOG', 'YBMIN', 'YBMAX', 'YBGRID', 'YBAXIS', 'YBGRID LINES', 'YBTITLE', 'YBLOG', 'RIGHT TICS','UPPER TICS', 'TRIGHT TICS', 'BRIGHT TICS', 'PLOTTER', 'XYPLOT', 'PTITLE', 'HOUTPUT', 'PLOTID', '', '', '', '', '', 'AXISYMMETRIC', 'CURVELINESYMBOL', 'CURVELINESYMB', 'AECONFIG', 'B2GG', 'B2PP', 'AESYMXZ', 'TEMP', 'DSAPRT', 'MEFFMASS', 'MAXMIN', 'RESVEC', 'MODESELECT', 'RIGID', 'TCURVE', 'SUPER', 'MAXI DEFO', 'P2G', 'EXTSEOUT', 'FLSTCNT PREFDB', 'AESYMXY', 'DSYM', '', '', '']: pass elif key == 'ANALYSIS': assert value in ['HEAT', 'ANALYSIS', 'MFREQ', 'STATICS', 'MODES', 'DFREQ', 'MTRAN', 'BUCK', 'MCEIG', 'DCEIG', 'SAERO', 'NLSTATIC', 'NLSTAT', 'STATIC', 'MTRANS', 'MODE', 'FLUTTER', 'DIVERG', 'NLTRAN', 'FLUT', '', '', '', '', ''], 'line=%r is invalid; value=%r' % (line, value) elif key == 'AUTOSPC': assert value in ['YES'], 'line=%r is invalid; value=%r' % (line, value) else: raise NotImplementedError('key=%r line=%r' % (key, line))
[docs]def _clean_lines(case_control, lines): """ Removes comment characters defined by a *$*. :param case_control: the CaseControlDeck object :param lines: the lines to clean. """ lines2 = [] for line in lines: line = line.strip(' \n\r').split('$')[0].rstrip() if line: lines2.append(line) lines3 = [] # TODO: line, comment lines_pack = [] for line in lines2: #print(line) if len(lines_pack) == 0: #print('0--', line) lines_pack.append(line) if not line.endswith(','): #print('next...') lines3.append(lines_pack) lines_pack = [] elif line.endswith(','): #print('C--', line) lines_pack.append(line) else: if lines_pack[-1][-1] == ',': # continued #print('xx--', line) lines_pack.append(line) lines3.append(lines_pack) #print('pack =', lines_pack) lines_pack = [] else: # new card #print('new--', line) lines3.append(lines_pack) lines_pack = [line] return [''.join(pack) for pack in lines3]
if __name__ == '__main__': # pragma: no cover lines = [ 'SUBCASE 1', ' ACCELERATION(PLOT,PRINT,PHASE) = ALL', ' DISPLACEMENT(PLOT,PRINT,PHASE) = ALL', ' DLOAD = 32', ' M2GG = 111', ' SET 88 = 5, 6, 7, 8, 9, 10 THRU 55 EXCEPT 15, 16, 77, 78, 79, ' '100 THRU 300', ' SET 99 = 1 THRU 10', ' SET 105 = 1.009, 10.2, 13.4, 14.0, 15.0', ' SET 111 = MAAX1,MAAX2', ' SET 1001 = 101/T1, 501/T3, 991/R3', ' SET = ALL', ' SPC = 42', ' TSTEPNL = 22', ' VELOCITY(PLOT,PRINT,PHASE) = ALL', 'BEGIN BULK', ] deck = CaseControlDeck(lines) #deck.create_new_subcase(2) #deck.add_parameter_to_local_subcase(0, 'SET 2 = 11,12,13,14,15,16,17,18,' # '19,20,21,22,23,24,25,26,' # '1000000000000000000000000000000000000000000000000000000,33') print('%s\n\n' % deck) #deck2 = CaseControlDeck(['ACCELERATION(PLOT,PRINT,PHASE) = ALL', # 'DISPLACEMENT(PLOT,PRINT,PHASE) = ALL', # 'BEGIN BULK']) #print('\n\n%s' % deck2)