diff --git a/lib/damask/__init__.py b/lib/damask/__init__.py new file mode 100644 index 000000000..75c7f6caa --- /dev/null +++ b/lib/damask/__init__.py @@ -0,0 +1,5 @@ +from .environment import Environment # only one class +from .asciitable import ASCIItable # only one class +from . import config # multiple classes +from . import result # multiple subclasses +from . import geometry # multiple subclasses diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py new file mode 100644 index 000000000..ea0d965de --- /dev/null +++ b/lib/damask/asciitable.py @@ -0,0 +1,95 @@ +class ASCIItable(): + ''' + There should be a doc string here :) + ''' + import sys + __slots__ = ['__IO__', + 'info', + 'labels', + 'data', + ] + + def __init__(self, + fileIn = sys.stdin, + fileOut = sys.stdout, + buffered = True): + self.__IO__ = {'in': fileIn, + 'out':fileOut, + 'output':[], + 'buffered':buffered, + 'validReadSize': 0, + } + self.info = [] + self.labels = [] + self.data = [] + + def output_write(self, + what): + if isinstance(what,list): + for item in what: self.output_write(item) + else: + self.__IO__['output'] += [str(what)] + self.__IO__['buffered'] or self.output_flush() + + def output_flush(self, + clear = True): + self.__IO__['output'] == [] or self.__IO__['out'].write('\n'.join(self.__IO__['output']) + '\n') + if clear: self.output_clear() + + def output_clear(self): + self.__IO__['output'] = [] + + def head_read(self): + ''' + get column labels by either read the first row, or + --if keyword "head[*]" is present-- the last line of the header + ''' + try: + self.__IO__['in'].seek(0) + except: + pass + firstline = self.__IO__['in'].readline() + m = re.search('(\d+)\s*head', firstline.lower()) + if m: + self.info = [self.__IO__['in'].readline().strip() for i in xrange(1,int(m.group(1)))] + self.labels = self.__IO__['in'].readline().split() + else: + self.info = [] + self.labels = firstline.split() + self.__IO__['validReadSize'] = len(self.labels) + + def head_write(self): + self.output_write (['%i\theader'%(len(self.info)+1), + self.info, + '\t'.join(self.labels)]) + + def labels_append(self, + what): + if isinstance(what,list): + for item in what: self.labels_append(item) + else: self.labels += [str(what)] + + def info_append(self, + what): + if isinstance(what,list): + for item in what: self.info_append(item) + else: self.info += [str(what)] + + def data_read(self): + line = self.__IO__['in'].readline() + items = line.split()[:self.__IO__['validReadSize']] # get next data row + self.data = {False: [], + True: items}[len(items) == self.__IO__['validReadSize']] # take if correct number of entries + return line != '' + + def data_write(self): + if isinstance(self.data[0],list): + self.output_write (['\t'.join(map(str,items)) for items in self.data]) + else: + self.output_write ('\t'.join(map(str,self.data))) + + def data_append(self, + what): + if isinstance(what,list): + for item in what: self.data_append(item) + else: self.data += [str(what)] diff --git a/lib/damask/config.py b/lib/damask/config.py new file mode 100644 index 000000000..02c53f563 --- /dev/null +++ b/lib/damask/config.py @@ -0,0 +1,185 @@ +class Material(): + ''' + Reads, manipulates and writes material.config files + ''' + __slots__ = ['data'] + + def __init__(self): + self.parts = [ + 'homogenization', + 'microstructure', + 'crystallite', + 'phase', + 'texture', + ] # ordered (!) list of parts + self.data = {\ + 'homogenization': {'__order__': []}, + 'microstructure': {'__order__': []}, + 'crystallite': {'__order__': []}, + 'phase': {'__order__': []}, + 'texture': {'__order__': []}, + } + + def __repr__(self): + me = [] + for part in self.parts: + print 'doing',part + me += ['','#-----------------------------#','<%s>'%part,'#-----------------------------#',] + for section in self.data[part]['__order__']: + me += ['','[%s] %s'%(section,'-'*max(0,27-len(section))),'',] + for key in self.data[part][section]['__order__']: + if key.startswith('(') and key.endswith(')'): # multiple (key) + me += ['%s\t%s'%(key,' '.join(values)) for values in self.data[part][section][key]] + else: # plain key + me += ['%s\t%s'%(key,' '.join(map(str,self.data[part][section][key])))] + + return '\n'.join(me) + + def parse_data(self, part=None, sections=[], content=None): + + re_part = re.compile(r'^<(.+)>$') # pattern for part + re_sec = re.compile(r'^\[(.+)\]$') # pattern for section + + name_section = '' + idx_section = 0 + active = False + + for line in content: + line = line.split('#')[0].strip() # kill comments and extra whitespace + if line: # content survives... + match_part = re_part.match(line) + if match_part: # found separator + active = (match_part.group(1) == part) # only active in + continue + if active: + match_sec = re_sec.match(line) + if match_sec: # found [section] + name_section = match_sec.group(1) # remember name ... + if '__order__' not in self.data[part]: self.data[part]['__order__'] = [] + self.data[part]['__order__'].append(name_section) # ... and position + self.data[part][name_section] = {'__order__':[]} + continue + + if sections == [] or name_section in sections: # respect subset + items = line.split() + if items[0] not in self.data[part][name_section]: # first encounter of key? + self.data[part][name_section][items[0]] = [] # create item + self.data[part][name_section]['__order__'].append(items[0]) + if items[0].startswith('(') and items[0].endswith(')'): # multiple "(key)" + self.data[part][name_section][items[0]].append(items[1:]) + else: # plain key + self.data[part][name_section][items[0]] = items[1:] + + def read(self,file=None): + f=open(file,'r') + c=f.readlines() + f.close() + for p in self.parts: + self.parse_data(part=p, content=c) + + def write(self,file='material.config', overwrite=False): + if overwrite is False: + if os.path.exists(file): + i=1 + while os.path.exists(file+'_%i'%i):i+=1 + file+='_%i'%i + print('Writing material data to file %s'%file) + f=open(file,'w') + f.write(str(self)) + f.close() + return file + + def add_data(self, part=None, section=None, data={}): + '''Generic data adding/updating''' + if part not in self.parts: raise Exception('invalid part %s'%part) + if section not in self.data[part]: self.data[part]['__order__'] += [section] + self.data[part][section] = data + + def add_homogenization(self, label='', type='', Ngrains=None): + if type.lower() == 'isostrain': + self.add_data(part='homogenization', + section=label, + data={'type':[type], + 'Ngrains':[Ngrains], + '__order__':['type','Ngrains'] + } + ) + elif type.lower() == 'rgc': + raise Exception('Please implement me') + + def add_crystallite(self, label='', output=[]): + self.add_data(part='crystallite', + section=label, + data={'(output)':[[o] for o in output], + '__order__':'(output)'}) + + def add_texture(self, label='',type='', eulers=[], scatter=0., fraction=1.): + ''' Experimental! Needs expansion to multi-component textures...''' + if type == '(gauss)': + texture={type:[['phi1','%f'%float(eulers[0]),'Phi','%f'%float(eulers[1]), 'phi2','%f'%float(eulers[2]),'scatter','%f'%float(scatter), 'fraction','%f'%fraction]],'__order__':label} + #self.data['texture'][label]=texture + #if len(self.data['texture'])>old_len: # added new label + # self.data['texture']['__order__'].append(label) + else: + raise Exception('Please implement me.') + self.add_data(part='texture',section=label, data=texture) + + def add_phase(self, file='', label='', newlabel=None, phase=None): + ''' USAGE: + - read phase "label" from file + OR + - phase is dict with one key + ''' + if file and label and (phase is None): + other=MATERIAL_CONFIG() + other.read(file=file) + phase={label:other.data['phase'][label]} + label=None + print phase + if len(phase)==1 and label is None: + if newlabel: + label=newlabel + else: + label=phase.keys()[0] + print('Adding phase %s'%label) + self.add_data(part='phase', section=label, data=phase) + else: + raise Exception('Wrong arguments') + + def add_microstructure(self, label=None, + crystallite=None, # label + phases=None, # list of labels + textures=None, # list of labels + fractions=None): # list of floats + ''' Experimental! Needs expansion to multi-constituent microstructures...''' + c=self.data['crystallite']['__order__'].index(crystallite)+1 + constituent=phases[:] + if fractions is None: + fractions=[1./len(phases)]*len(phases) + for i in range(len(phases)): + p=self.data['phase']['__order__'].index(phases[i])+1 + t=self.data['texture']['__order__'].index(textures[i])+1 + f=fractions[i] + constituent[i]=['phase','%i'%p,'texture','%i'%t,'fraction','%f'%f] + data={'crystallite':['%i'%c], + '(constituent)':constituent, + '__order__':['crystallite','(constituent)']} + self.add_data(part='microstructure',section=label,data=data) + + def change_value(self, part=None, + section=None, + key=None, + value=None): + if type(value) is not type([]): + if type(value) is not type('s'): + value = '%s'%value + value = [value] + newlen = len(value) + oldval = self.data[part][section][key] + oldlen = len(oldval) + print('changing %s:%s:%s:%s'%(part,section,key,oldval)) + self.data[part][section][key] = value + print('new: %s'%self.data[part][section][key]) + if newlen is not oldlen: + print('Length of value was changed from %i to %i!'%(oldlen,newlen)) + diff --git a/lib/damask/environment.py b/lib/damask/environment.py new file mode 100644 index 000000000..ef7217069 --- /dev/null +++ b/lib/damask/environment.py @@ -0,0 +1,39 @@ +import os,sys,string,re + +class Environment(): + __slots__ = ['pathInfo', + ] + + def __init__(self,rootRelation = '.'): + self.pathInfo = {\ + 'acml': '/opt/acml4.4.0', + 'fftw': '.', + 'msc': '/msc', + } + self.get_pathInfo(rootRelation) + + def relPath(self,relative = '.'): + return os.path.join(self.rootDir(),relative) + + def rootDir(self,rootRelation = '.'): #getting pathinfo + damask_root = os.getenv('DAMASK_ROOT') + if damask_root == '' or damask_root == None: damask_root = os.path.join(os.path.dirname(sys.argv[0]),rootRelation) + return damask_root + + def binDir(self,rootRelation = '.'): #getting pathinfo + damask_bin = os.getenv('DAMASK_BIN') + if damask_bin == '' or damask_bin == None: damask_bin = self.relPath('bin/') + return damask_bin + + def get_pathInfo(self,rootRelation = '.'): #getting pathinfo + damask_root = self.rootDir(rootRelation) + + try: # check for user-defined pathinfo + file = open(self.relPath('lib/pathinfo')) + content = file.readlines() + file.close() + for line in content: + self.pathInfo[line.split()[0].lower()] = os.path.normpath(os.path.join(self.relPath('lib/'),line.split()[1])) + except: + pass + diff --git a/lib/damask/geometry/__init__.py b/lib/damask/geometry/__init__.py new file mode 100644 index 000000000..effd44cae --- /dev/null +++ b/lib/damask/geometry/__init__.py @@ -0,0 +1,3 @@ +from .geometry import Geometry # only one class +from .spectral import Spectral # only one class +from .marc import Marc # only one class diff --git a/lib/damask/geometry/geometry.py b/lib/damask/geometry/geometry.py new file mode 100644 index 000000000..8ad0fe891 --- /dev/null +++ b/lib/damask/geometry/geometry.py @@ -0,0 +1,17 @@ +import damask.geometry + +class Geometry(): + ''' + General class for geometry parsing. + Sub-classed by the individual solvers. + ''' + + def __init__(self,solver=''): + solverClass = { + 'spectral': damask.geometry.Spectral, + 'marc': damask.geometry.Marc, + } + if solver.lower() in solverClass.keys(): + self.__class__=solverClass[solver.lower()] + self.__init__() + diff --git a/lib/damask/geometry/marc.py b/lib/damask/geometry/marc.py new file mode 100644 index 000000000..8cfecfc9f --- /dev/null +++ b/lib/damask/geometry/marc.py @@ -0,0 +1,6 @@ +from .geometry import Geometry + +class Marc(Geometry): + + def __init__(self): + self.solver='Marc' diff --git a/lib/damask/geometry/spectral.py b/lib/damask/geometry/spectral.py new file mode 100644 index 000000000..626c50f45 --- /dev/null +++ b/lib/damask/geometry/spectral.py @@ -0,0 +1,6 @@ +from .geometry import Geometry + +class Spectral(Geometry): + + def __init__(self): + self.solver='Spectral' diff --git a/lib/damask/result/__init__.py b/lib/damask/result/__init__.py new file mode 100644 index 000000000..b04817869 --- /dev/null +++ b/lib/damask/result/__init__.py @@ -0,0 +1,3 @@ +from .result import Result # only one class +from .spectral import Spectral # only one class +from .marc import Marc # only one class diff --git a/lib/damask/result/marc.py b/lib/damask/result/marc.py new file mode 100644 index 000000000..062747326 --- /dev/null +++ b/lib/damask/result/marc.py @@ -0,0 +1,6 @@ +from .result import Result + +class Marc(Result): + + def __init__(self): + self.solver='Marc' diff --git a/lib/damask/result/result.py b/lib/damask/result/result.py new file mode 100644 index 000000000..295cd8b21 --- /dev/null +++ b/lib/damask/result/result.py @@ -0,0 +1,17 @@ +import damask.result + +class Result(): + ''' + General class for result parsing. + Sub-classed by the individual solvers. + ''' + + def __init__(self,solver=''): + solverClass = { + 'spectral': damask.result.Spectral, + 'marc': damask.result.Marc, + } + if solver.lower() in solverClass.keys(): + self.__class__=solverClass[solver.lower()] + self.__init__() + diff --git a/lib/damask/result/spectral.py b/lib/damask/result/spectral.py new file mode 100644 index 000000000..9fa4f0c13 --- /dev/null +++ b/lib/damask/result/spectral.py @@ -0,0 +1,6 @@ +from .result import Result + +class Spectral(Result): + + def __init__(self): + self.solver='Spectral'