diff --git a/processing/post/postResults b/processing/post/postResults index 7714a118b..6ae2460dd 100755 --- a/processing/post/postResults +++ b/processing/post/postResults @@ -3,7 +3,13 @@ import pdb, os, sys, gc, math, re, threading, time, struct, string from optparse import OptionParser, OptionGroup, Option, SUPPRESS_HELP -releases = {'2010':['linux64',''], +fileExtensions = { \ + 'marc': ['.t16',], + 'spectral': ['.spectralOut',], + } + +releases = { \ + '2010':['linux64',''], '2008r1':[''], '2007r1':[''], '2005r3':[''], @@ -75,16 +81,16 @@ class MPIEspectral_result: # mimic py_post result object self.theTitle = self._keyedString('load') self.wd = self._keyedString('workingdir') self.geometry = self._keyedString('geometry') - self.N_loadcases = self._keyedInt('loadcases',default=1) - self._frequencies = self._keyedInts('frequencies',self.N_loadcases,1) - self._increments = self._keyedInts('increments',self.N_loadcases) + self.N_loadcases = self._keyedPackedArray('loadcases',count=1,type='i',default=1)[0] + self._frequencies = self._keyedPackedArray('frequencies',count=self.N_loadcases,type='i',default=1) + self._increments = self._keyedPackedArray('increments',count=self.N_loadcases,type='i') self._increments[0] -= 1 # delete zero'th entry - self._times = self._keyedFloats('times',self.N_loadcases,0.0) - self.dimension = self._keyedPackedArray('dimension',3,'d') - self.resolution = self._keyedPackedArray('resolution',3,'i') + self._times = self._keyedPackedArray('times',count=self.N_loadcases,type='d',default=0.0) + self.dimension = self._keyedPackedArray('dimension',count=3,type='d') + self.resolution = self._keyedPackedArray('resolution',count=3,type='i') self.N_nodes = (self.resolution[0]+1)*(self.resolution[1]+1)*(self.resolution[2]+1) self.N_elements = self.resolution[0] * self.resolution[1] * self.resolution[2] - self.N_element_scalars = self._keyedInt('materialpoint_sizeResults') + self.N_element_scalars = self._keyedPackedArray('materialpoint_sizeResults',count=1,type='i',default=0)[0] self.file.seek(0) self.dataOffset = self.file.read(2048).find('eoh')+7 @@ -97,60 +103,43 @@ class MPIEspectral_result: # mimic py_post result object def __str__(self): return '\n'.join([ - 'title: %s'%self.theTitle, 'workdir: %s'%self.wd, 'geometry: %s'%self.geometry, - 'extrapolation: %s'%self.extrapolate, 'loadcases: %i'%self.N_loadcases, - 'increments: %i'%self.N_increments, - 'increment: %i'%self.increment, - 'position: %i'%self.position, - 'time: %i'%self.time, - 'nodes: %i'%self.N_nodes, 'resolution: %s'%(','.join(map(str,self.resolution))), 'dimension: %s'%(','.join(map(str,self.dimension))), - 'elements: %i'%self.N_elements, - 'nodal_scalars: %i'%self.N_node_scalars, - 'elemental scalars: %i'%self.N_element_scalars, - 'elemental tensors: %i'%self.N_element_tensors, + 'header size: %i'%self.dataOffset, + 'file size: %i'%(self.dataOffset+self.N_increments*(8+self.N_elements*self.N_element_scalars*8)), ] ) - def _keyedPackedArray(self,identifier,length = 3,type = 'd'): - match = {'d': 8,'i': 4} - self.file.seek(0) - m = re.search('%s%s'%(identifier,'(.{%i})'%(match[type])*length),self.file.read(2048),re.DOTALL) - values = [] - if m: - for i in m.groups(): - values.append(struct.unpack(type,i)[0]) + + def locateKeyValue(self,identifier): + + key = {'name':'','pos':0} + filepos = 0 + while key['name'] != identifier and key['name'] != 'eoh' and filepos < 2048: + self.file.seek(filepos) + tag = self.file.read(4) # read the starting/ending tag + key['name'] = self.file.read(len(identifier)) # anticipate identifier + key['pos'] = self.file.tell() # remember position right after identifier + self.file.seek(filepos+4) # start looking after opening tag + filepos += 4 + self.file.read(2048).find(tag) + 4 # locate end of closing tag + + return key + + + def _keyedPackedArray(self,identifier,count = 3,type = 'd',default = None): + bytecount = {'d': 8,'i': 4} + values = [default]*count + key = self.locateKeyValue(identifier) + if key['name'] == identifier: + self.file.seek(key['pos']) + for i in range(count): + values[i] = struct.unpack(type,self.file.read(bytecount[type]))[0] + return values - def _keyedInt(self,identifier,default=None): - value = default - self.file.seek(0) - m = re.search('%s%s'%(identifier,'(.{4})'),self.file.read(2048),re.DOTALL) - if m: - value = struct.unpack('i',m.group(1))[0] - return value - - def _keyedInts(self,identifier,number=1,default=None): - values = [default]*number - self.file.seek(0) - m = re.search('%s%s'%(identifier,'(.{4})'*number),self.file.read(2048),re.DOTALL) - if m: - for i in range(number): - values[i] = struct.unpack('i',m.group(1+i))[0] - return values - - def _keyedFloats(self,identifier,number=1,default=None): - values = [default]*number - self.file.seek(0) - m = re.search('%s%s'%(identifier,'(.{8})'*number),self.file.read(2048),re.DOTALL) - if m: - for i in range(number): - values[i] = struct.unpack('d',m.group(1+i))[0] - return values def _keyedString(self,identifier,default=None): value = default @@ -229,7 +218,12 @@ class MPIEspectral_result: # mimic py_post result object def element_scalar(self,e,idx): self.file.seek(self.dataOffset+(self.position*(4+self.N_elements*self.N_element_scalars*8+4) + 4+(e*self.N_element_scalars + idx)*8)) - value = struct.unpack('d',self.file.read(8))[0] + try: + value = struct.unpack('d',self.file.read(8))[0] + except: + print 'seeking',self.dataOffset+(self.position*(4+self.N_elements*self.N_element_scalars*8+4) + 4+(e*self.N_element_scalars + idx)*8) + print 'e',e,'idx',idx + sys.exit(1) return [elemental_scalar(node,value) for node in self.element(e).items] def element_scalar_label(elem,idx): @@ -434,13 +428,7 @@ def OpenPostfile(name,type): p = {\ 'spectral': MPIEspectral_result,\ 'marc': post_open,\ - }[type]\ - (name+ - {\ - 'marc': '.t16',\ - 'spectral': '.spectralOut',\ - }[type] - ) + }[type](name) p.extrapolation('translate') p.moveto(1) @@ -554,33 +542,34 @@ def ParsePostfile(p,filename, outputFormat): else: stat['IndexOfLabel']['%s'%(var[0])] = startIndex + offset + 1 offset += var[1] - - for grain in range(outputFormat['Homogenization']['specials']['(ngrains)']): - stat['IndexOfLabel']['%i_CrystalliteCount'%(grain+1)] = startIndex + offset + 1 - offset += 1 - for var in outputFormat['Crystallite']['outputs']: - if var[1] > 1: - for i in range(var[1]): - stat['IndexOfLabel']['%i_%i_%s'%(grain+1,i+1,var[0])] = startIndex + offset + (i+1) - else: - stat['IndexOfLabel']['%i_%s'%(grain+1,var[0])] = startIndex + offset + 1 - offset += var[1] + + if '(ngrains)' in outputFormat['Homogenization']['specials']: + for grain in range(outputFormat['Homogenization']['specials']['(ngrains)']): + stat['IndexOfLabel']['%i_CrystalliteCount'%(grain+1)] = startIndex + offset + 1 + offset += 1 + for var in outputFormat['Crystallite']['outputs']: + if var[1] > 1: + for i in range(var[1]): + stat['IndexOfLabel']['%i_%i_%s'%(grain+1,i+1,var[0])] = startIndex + offset + (i+1) + else: + stat['IndexOfLabel']['%i_%s'%(grain+1,var[0])] = startIndex + offset + 1 + offset += var[1] - stat['IndexOfLabel']['%i_ConstitutiveCount'%(grain+1)] = startIndex + offset + 1 - offset += 1 - for var in outputFormat['Constitutive']['outputs']: - if var[1] > 1: - for i in range(var[1]): - stat['IndexOfLabel']['%i_%i_%s'%(grain+1,i+1,var[0])] = startIndex + offset + (i+1) - else: - stat['IndexOfLabel']['%i_%s'%(grain+1,var[0])] = startIndex + offset + 1 - offset += var[1] + stat['IndexOfLabel']['%i_ConstitutiveCount'%(grain+1)] = startIndex + offset + 1 + offset += 1 + for var in outputFormat['Constitutive']['outputs']: + if var[1] > 1: + for i in range(var[1]): + stat['IndexOfLabel']['%i_%i_%s'%(grain+1,i+1,var[0])] = startIndex + offset + (i+1) + else: + stat['IndexOfLabel']['%i_%s'%(grain+1,var[0])] = startIndex + offset + 1 + offset += var[1] return stat # ----------------------------- -def SummarizePostfile(stat,where=sys.stdout): +def SummarizePostfile(stat,where=sys.stdout,format='marc'): # ----------------------------- where.write('\n\n') @@ -638,9 +627,8 @@ parser.add_option('-m','--map', dest='func', type='string', \ help='data reduction mapping ["%default"] out of min, max, avg, sum, abssum or user-lambda') parser.add_option('-p','--type', dest='filetype', type='string', \ help = 'type of result file [%default]') + group_material = OptionGroup(parser,'Material identifier') -group_special = OptionGroup(parser,'Special outputs') -group_general = OptionGroup(parser,'General outputs') group_material.add_option('--homogenization', dest='homog', type='string', \ help='homogenization identifier (as string or integer [%default])') @@ -649,6 +637,8 @@ group_material.add_option('--crystallite', dest='cryst', type='string', \ group_material.add_option('--phase', dest='phase', type='string', \ help='phase identifier (as string or integer [%default])') +group_special = OptionGroup(parser,'Special outputs') + group_special.add_option('-t','--time', action='store_true', dest='time', \ help='output time of increment [%default]') group_special.add_option('-f','--filter', dest='filter', type='string', \ @@ -658,6 +648,8 @@ group_special.add_option('--separation', action='extend', dest='separation', typ group_special.add_option('--sort', action='extend', dest='sort', type='string', \ help='properties to sort results [%default]') +group_general = OptionGroup(parser,'General outputs') + group_general.add_option('--ns', action='extend', dest='nodalScalar', type='string', \ help='list of nodal scalars to extract') group_general.add_option('--es', action='extend', dest='elementalScalar', type='string', \ @@ -679,7 +671,7 @@ parser.set_defaults(info = False) parser.set_defaults(sloppy = False) parser.set_defaults(prefix = '') parser.set_defaults(directory = 'postProc') -parser.set_defaults(filetype = 'marc') +parser.set_defaults(filetype = None) parser.set_defaults(func = 'avg') parser.set_defaults(homog = '1') parser.set_defaults(cryst = '1') @@ -693,8 +685,33 @@ parser.set_defaults(separateFiles = False) (options, files) = parser.parse_args() +# --- basic sanity checks + +if files == []: + parser.print_help() + parser.error('no file specified...') + +if not os.path.exists(files[0]): + parser.print_help() + parser.error('invalid file "%s" specified...'%files[0]) + +# --- figure out filetype + +if options.filetype == None: + ext = os.path.splitext(files[0])[1] + for theType in fileExtensions.keys(): + if ext in fileExtensions[theType]: + options.filetype = theType + break + options.filetype = options.filetype.lower() +# --- more sanity checks + +if options.filetype not in ['marc','spectral']: + parser.print_help() + parser.error('file type "%s" not supported...'%options.filetype) + if options.filetype == 'marc': try: file = open('%s/../MSCpath'%os.path.dirname(os.path.realpath(sys.argv[0]))) @@ -722,22 +739,6 @@ else: def post_open(): return - - -# --- sanity checks - -if files == []: - parser.print_help() - parser.error('no file specified...') - -if not os.path.exists(files[0]): - parser.print_help() - parser.error('invalid file "%s" specified...'%files[0]) - -if options.filetype not in ['marc','spectral']: - parser.print_help() - parser.error('file type "%s" not supported...'%options.filetype) - if options.constitutiveResult and not options.phase: parser.print_help() parser.error('constitutive results require phase...') @@ -764,7 +765,12 @@ bg.start() # --- parse .output and .t16 files -filename = os.path.splitext(files[0])[0] +if os.path.splitext(files[0])[1] == '': + filename = files[0] + extension = fileExtensions[options.filetype] +else: + filename = os.path.splitext(files[0])[0] + extension = os.path.splitext(files[0])[1] outputFormat = {} me = { @@ -782,7 +788,7 @@ for what in me: print '\n'.join(map(lambda x:' '+x, outputFormat[what]['specials']['brothers'])) bg.set_message('opening result file...') -p = OpenPostfile(filename,options.filetype) +p = OpenPostfile(filename+extension,options.filetype) bg.set_message('parsing result file...') stat = ParsePostfile(p, filename, outputFormat) if options.filetype == 'marc': @@ -806,6 +812,8 @@ for opt in ['nodalScalar','elementalScalar','elementalTensor','homogenizationRes if options.info: if options.filetype == 'marc': print '\n\nMentat release %s'%release + if options.filetype == 'spectral': + print '\n\n',p SummarizePostfile(stat,sys.stderr) @@ -837,24 +845,24 @@ for l in elementsOfNode.values(): # --- get output data from .t16 file -increments = range(stat['NumberOfIncrements']) +positions = range(stat['NumberOfIncrements']) if options.filetype == 'marc': - offset_inc = 1 + offset_pos = 1 else: - offset_inc = 0 + offset_pos = 0 if options.range: options.range = list(options.range) if options.sloppy: - increments = range(options.range[0],options.range[1]+1,options.range[2]) + positions = range(options.range[0],options.range[1]+1,options.range[2]) else: - increments = range( max(0,options.range[0]), + positions = range( max(0,options.range[0]), min(stat['NumberOfIncrements'],options.range[1]+1), options.range[2]) # --------------------------- build group membership -------------------------------- -p.moveto(increments[0]+offset_inc) +p.moveto(positions[0]+offset_pos) index = {} groups = [] groupCount = 0 @@ -982,19 +990,26 @@ standard = ['inc'] + \ {True: ['node.x','node.y','node.z'], False:['ip.x','ip.y','ip.z']}[options.nodalScalar != []] -# --------------------------- loop over increments -------------------------------- +# --------------------------- loop over positions -------------------------------- + +bg.set_message('getting increments...') +increments = [None]*len(positions) + +for incCount,position in enumerate(positions): + p.moveto(position+offset_pos) + increments[incCount] = p.increment # remember "real" increment at this position time_start = time.time() -for incCount,increment in enumerate(increments): - p.moveto(increment+offset_inc) +for incCount,position in enumerate(positions): + p.moveto(position+offset_pos) # --------------------------- file management -------------------------------- if options.separateFiles: if fileOpen: file.close() fileOpen = False - outFilename = eval('"'+eval("'%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increment)') + outFilename = eval('"'+eval("'%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increments[incCount])') else: outFilename = '%s.txt'%(dirname + os.sep + options.prefix + os.path.split(filename)[1]) @@ -1017,8 +1032,8 @@ for incCount,increment in enumerate(increments): for (e,n,i,g,n_local) in group[1:]: # loop over group members member += 1 if member%1000 == 0: - time_delta = ((len(increments)*memberCount)/float(member+incCount*memberCount)-1.0)*(time.time()-time_start) - bg.set_message('(%02i:%02i:%02i) processing point %i of %i from increment %i...'%(time_delta//3600,time_delta%3600//60,time_delta%60,member,memberCount,increment)) + time_delta = ((len(positions)*memberCount)/float(member+incCount*memberCount)-1.0)*(time.time()-time_start) + bg.set_message('(%02i:%02i:%02i) processing point %i of %i from position %i...'%(time_delta//3600,time_delta%3600//60,time_delta%60,member,memberCount,position)) newby = [] # current member's data