diff --git a/python/damask/lattice.py b/python/damask/lattice.py index 1887bae7c..ee4cbff3c 100644 --- a/python/damask/lattice.py +++ b/python/damask/lattice.py @@ -312,330 +312,330 @@ class Symmetry: # ****************************************************************************************** class Lattice: - """ - Lattice system. - - Currently, this contains only a mapping from Bravais lattice to symmetry - and orientation relationships. It could include twin and slip systems. - - References - ---------- - https://en.wikipedia.org/wiki/Bravais_lattice - - """ - - lattices = { - 'triclinic':{'symmetry':None}, - 'bct':{'symmetry':'tetragonal'}, - 'hex':{'symmetry':'hexagonal'}, - 'fcc':{'symmetry':'cubic','c/a':1.0}, - 'bcc':{'symmetry':'cubic','c/a':1.0}, - } - - - def __init__(self, lattice): """ - New lattice of given type. + Lattice system. - Parameters - ---------- - lattice : str - Bravais lattice. - - """ - self.lattice = lattice - self.symmetry = Symmetry(self.lattices[lattice]['symmetry']) - - - def __repr__(self): - """Report basic lattice information.""" - return 'Bravais lattice {} ({} symmetry)'.format(self.lattice,self.symmetry) - - - # Kurdjomov--Sachs orientation relationship for fcc <-> bcc transformation - # from S. Morito et al., Journal of Alloys and Compounds 577:s587-s592, 2013 - # also see K. Kitahara et al., Acta Materialia 54:1279-1288, 2006 - KS = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]], - [[ 1, 1, -1],[ 0, 1, 1]]],dtype='float'), - 'directions': np.array([ - [[ -1, 0, 1],[ -1, -1, 1]], - [[ -1, 0, 1],[ -1, 1, -1]], - [[ 0, 1, -1],[ -1, -1, 1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ 1, -1, 0],[ -1, -1, 1]], - [[ 1, -1, 0],[ -1, 1, -1]], - [[ 1, 0, -1],[ -1, -1, 1]], - [[ 1, 0, -1],[ -1, 1, -1]], - [[ -1, -1, 0],[ -1, -1, 1]], - [[ -1, -1, 0],[ -1, 1, -1]], - [[ 0, 1, 1],[ -1, -1, 1]], - [[ 0, 1, 1],[ -1, 1, -1]], - [[ 0, -1, 1],[ -1, -1, 1]], - [[ 0, -1, 1],[ -1, 1, -1]], - [[ -1, 0, -1],[ -1, -1, 1]], - [[ -1, 0, -1],[ -1, 1, -1]], - [[ 1, 1, 0],[ -1, -1, 1]], - [[ 1, 1, 0],[ -1, 1, -1]], - [[ -1, 1, 0],[ -1, -1, 1]], - [[ -1, 1, 0],[ -1, 1, -1]], - [[ 0, -1, -1],[ -1, -1, 1]], - [[ 0, -1, -1],[ -1, 1, -1]], - [[ 1, 0, 1],[ -1, -1, 1]], - [[ 1, 0, 1],[ -1, 1, -1]]],dtype='float')} - - # Greninger--Troiano orientation relationship for fcc <-> bcc transformation - # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 - GT = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 1, 1, 1],[ 1, 0, 1]], - [[ 1, 1, 1],[ 1, 1, 0]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ -1, 0, 1]], - [[ -1, -1, 1],[ -1, -1, 0]], - [[ -1, -1, 1],[ 0, -1, 1]], - [[ -1, 1, 1],[ -1, 0, 1]], - [[ -1, 1, 1],[ -1, 1, 0]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 1, 0, 1]], - [[ 1, -1, 1],[ 1, -1, 0]], - [[ 1, -1, 1],[ 0, -1, 1]], - [[ 1, 1, 1],[ 1, 1, 0]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 1, 0, 1]], - [[ -1, -1, 1],[ -1, -1, 0]], - [[ -1, -1, 1],[ 0, -1, 1]], - [[ -1, -1, 1],[ -1, 0, 1]], - [[ -1, 1, 1],[ -1, 1, 0]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ -1, 0, 1]], - [[ 1, -1, 1],[ 1, -1, 0]], - [[ 1, -1, 1],[ 0, -1, 1]], - [[ 1, -1, 1],[ 1, 0, 1]]],dtype='float'), - 'directions': np.array([ - [[ -5,-12, 17],[-17, -7, 17]], - [[ 17, -5,-12],[ 17,-17, -7]], - [[-12, 17, -5],[ -7, 17,-17]], - [[ 5, 12, 17],[ 17, 7, 17]], - [[-17, 5,-12],[-17, 17, -7]], - [[ 12,-17, -5],[ 7,-17,-17]], - [[ -5, 12,-17],[-17, 7,-17]], - [[ 17, 5, 12],[ 17, 17, 7]], - [[-12,-17, 5],[ -7,-17, 17]], - [[ 5,-12,-17],[ 17, -7,-17]], - [[-17, -5, 12],[-17,-17, 7]], - [[ 12, 17, 5],[ 7, 17, 17]], - [[ -5, 17,-12],[-17, 17, -7]], - [[-12, -5, 17],[ -7,-17, 17]], - [[ 17,-12, -5],[ 17, -7,-17]], - [[ 5,-17,-12],[ 17,-17, -7]], - [[ 12, 5, 17],[ 7, 17, 17]], - [[-17, 12, -5],[-17, 7,-17]], - [[ -5,-17, 12],[-17,-17, 7]], - [[-12, 5,-17],[ -7, 17,-17]], - [[ 17, 12, 5],[ 17, 7, 17]], - [[ 5, 17, 12],[ 17, 17, 7]], - [[ 12, -5,-17],[ 7,-17,-17]], - [[-17,-12, 5],[-17,-7, 17]]],dtype='float')} - - # Greninger--Troiano' orientation relationship for fcc <-> bcc transformation - # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 - GTprime = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 7, 17, 17],[ 12, 5, 17]], - [[ 17, 7, 17],[ 17, 12, 5]], - [[ 17, 17, 7],[ 5, 17, 12]], - [[ -7,-17, 17],[-12, -5, 17]], - [[-17, -7, 17],[-17,-12, 5]], - [[-17,-17, 7],[ -5,-17, 12]], - [[ 7,-17,-17],[ 12, -5,-17]], - [[ 17, -7,-17],[ 17,-12, -5]], - [[ 17,-17, -7],[ 5,-17,-12]], - [[ -7, 17,-17],[-12, 5,-17]], - [[-17, 7,-17],[-17, 12, -5]], - [[-17, 17, -7],[ -5, 17,-12]], - [[ 7, 17, 17],[ 12, 17, 5]], - [[ 17, 7, 17],[ 5, 12, 17]], - [[ 17, 17, 7],[ 17, 5, 12]], - [[ -7,-17, 17],[-12,-17, 5]], - [[-17, -7, 17],[ -5,-12, 17]], - [[-17,-17, 7],[-17, -5, 12]], - [[ 7,-17,-17],[ 12,-17, -5]], - [[ 17, -7,-17],[ 5, -12,-17]], - [[ 17,-17, -7],[ 17, -5,-12]], - [[ -7, 17,-17],[-12, 17, -5]], - [[-17, 7,-17],[ -5, 12,-17]], - [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), - 'directions': np.array([ - [[ 0, 1, -1],[ 1, 1, -1]], - [[ -1, 0, 1],[ -1, 1, 1]], - [[ 1, -1, 0],[ 1, -1, 1]], - [[ 0, -1, -1],[ -1, -1, -1]], - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, -1, 0],[ 1, -1, -1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ 1, 0, 1],[ 1, 1, 1]], - [[ -1, -1, 0],[ -1, -1, 1]], - [[ 0, -1, -1],[ 1, -1, -1]], - [[ -1, 0, 1],[ -1, -1, 1]], - [[ -1, -1, 0],[ -1, -1, -1]], - [[ 0, -1, 1],[ 1, -1, 1]], - [[ 1, 0, -1],[ 1, 1, -1]], - [[ -1, 1, 0],[ -1, 1, 1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ -1, 0, -1],[ -1, -1, -1]], - [[ -1, 1, 0],[ -1, 1, -1]], - [[ 0, -1, 1],[ -1, -1, 1]], - [[ -1, 0, -1],[ -1, 1, -1]], - [[ 1, 1, 0],[ 1, 1, 1]], - [[ 0, 1, 1],[ 1, 1, 1]], - [[ 1, 0, -1],[ 1, -1, -1]], - [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} - - # Nishiyama--Wassermann orientation relationship for fcc <-> bcc transformation - # from H. Kitahara et al., Materials Characterization 54:378-386, 2005 - NW = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ 1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ -1, 1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ 1, -1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]]],dtype='float'), - 'directions': np.array([ - [[ 2, -1, -1],[ 0, -1, 1]], - [[ -1, 2, -1],[ 0, -1, 1]], - [[ -1, -1, 2],[ 0, -1, 1]], - [[ -2, -1, -1],[ 0, -1, 1]], - [[ 1, 2, -1],[ 0, -1, 1]], - [[ 1, -1, 2],[ 0, -1, 1]], - [[ 2, 1, -1],[ 0, -1, 1]], - [[ -1, -2, -1],[ 0, -1, 1]], - [[ -1, 1, 2],[ 0, -1, 1]], - [[ 2, -1, 1],[ 0, -1, 1]], #It is wrong in the paper, but matrix is correct - [[ -1, 2, 1],[ 0, -1, 1]], - [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} - - # Pitsch orientation relationship for fcc <-> bcc transformation - # from Y. He et al., Acta Materialia 53:1179-1190, 2005 - Pitsch = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 0, 1, 0],[ -1, 0, 1]], - [[ 0, 0, 1],[ 1, -1, 0]], - [[ 1, 0, 0],[ 0, 1, -1]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 1, 0, 0],[ 0, -1, 1]], - [[ 0, 1, 0],[ 1, 0, -1]], - [[ 0, 0, 1],[ -1, 1, 0]]],dtype='float'), - 'directions': np.array([ - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ -1, 0, 1],[ -1, -1, 1]], - [[ 1, -1, 0],[ 1, -1, -1]], - [[ 1, 0, -1],[ 1, -1, -1]], - [[ -1, 1, 0],[ -1, 1, -1]], - [[ 0, -1, 1],[ -1, -1, 1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} - - # Bain orientation relationship for fcc <-> bcc transformation - # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 - Bain = {'mapping':{'fcc':0,'bcc':1}, - 'planes': np.array([ - [[ 1, 0, 0],[ 1, 0, 0]], - [[ 0, 1, 0],[ 0, 1, 0]], - [[ 0, 0, 1],[ 0, 0, 1]]],dtype='float'), - 'directions': np.array([ - [[ 0, 1, 0],[ 0, 1, 1]], - [[ 0, 0, 1],[ 1, 0, 1]], - [[ 1, 0, 0],[ 1, 1, 0]]],dtype='float')} - - def relationOperations(self,model): - """ - Crystallographic orientation relationships for phase transformations. + Currently, this contains only a mapping from Bravais lattice to symmetry + and orientation relationships. It could include twin and slip systems. References ---------- - S. Morito et al., Journal of Alloys and Compounds 577:s587-s592, 2013 - https://doi.org/10.1016/j.jallcom.2012.02.004 - - K. Kitahara et al., Acta Materialia 54(5):1279-1288, 2006 - https://doi.org/10.1016/j.actamat.2005.11.001 - - Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 - https://doi.org/10.1107/S0021889805038276 - - H. Kitahara et al., Materials Characterization 54(4-5):378-386, 2005 - https://doi.org/10.1016/j.matchar.2004.12.015 - - Y. He et al., Acta Materialia 53(4):1179-1190, 2005 - https://doi.org/10.1016/j.actamat.2004.11.021 + https://en.wikipedia.org/wiki/Bravais_lattice """ - models={'KS':self.KS, 'GT':self.GT, 'GT_prime':self.GTprime, - 'NW':self.NW, 'Pitsch': self.Pitsch, 'Bain':self.Bain} - try: - relationship = models[model] - except KeyError : - raise KeyError('Orientation relationship "{}" is unknown'.format(model)) - if self.lattice not in relationship['mapping']: - raise ValueError('Relationship "{}" not supported for lattice "{}"'.format(model,self.lattice)) + lattices = { + 'triclinic':{'symmetry':None}, + 'bct':{'symmetry':'tetragonal'}, + 'hex':{'symmetry':'hexagonal'}, + 'fcc':{'symmetry':'cubic','c/a':1.0}, + 'bcc':{'symmetry':'cubic','c/a':1.0}, + } - r = {'lattice':Lattice((set(relationship['mapping'])-{self.lattice}).pop()), # target lattice - 'rotations':[] } - myPlane_id = relationship['mapping'][self.lattice] - otherPlane_id = (myPlane_id+1)%2 - myDir_id = myPlane_id +2 - otherDir_id = otherPlane_id +2 + def __init__(self, lattice): + """ + New lattice of given type. - for miller in np.hstack((relationship['planes'],relationship['directions'])): - myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) - myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) - myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]) + Parameters + ---------- + lattice : str + Bravais lattice. - otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) - otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) - otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]) + """ + self.lattice = lattice + self.symmetry = Symmetry(self.lattices[lattice]['symmetry']) - r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix.T,myMatrix))) - return r + def __repr__(self): + """Report basic lattice information.""" + return 'Bravais lattice {} ({} symmetry)'.format(self.lattice,self.symmetry) + + + # Kurdjomov--Sachs orientation relationship for fcc <-> bcc transformation + # from S. Morito et al., Journal of Alloys and Compounds 577:s587-s592, 2013 + # also see K. Kitahara et al., Acta Materialia 54:1279-1288, 2006 + KS = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]], + [[ 1, 1, -1],[ 0, 1, 1]]],dtype='float'), + 'directions': np.array([ + [[ -1, 0, 1],[ -1, -1, 1]], + [[ -1, 0, 1],[ -1, 1, -1]], + [[ 0, 1, -1],[ -1, -1, 1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ 1, -1, 0],[ -1, -1, 1]], + [[ 1, -1, 0],[ -1, 1, -1]], + [[ 1, 0, -1],[ -1, -1, 1]], + [[ 1, 0, -1],[ -1, 1, -1]], + [[ -1, -1, 0],[ -1, -1, 1]], + [[ -1, -1, 0],[ -1, 1, -1]], + [[ 0, 1, 1],[ -1, -1, 1]], + [[ 0, 1, 1],[ -1, 1, -1]], + [[ 0, -1, 1],[ -1, -1, 1]], + [[ 0, -1, 1],[ -1, 1, -1]], + [[ -1, 0, -1],[ -1, -1, 1]], + [[ -1, 0, -1],[ -1, 1, -1]], + [[ 1, 1, 0],[ -1, -1, 1]], + [[ 1, 1, 0],[ -1, 1, -1]], + [[ -1, 1, 0],[ -1, -1, 1]], + [[ -1, 1, 0],[ -1, 1, -1]], + [[ 0, -1, -1],[ -1, -1, 1]], + [[ 0, -1, -1],[ -1, 1, -1]], + [[ 1, 0, 1],[ -1, -1, 1]], + [[ 1, 0, 1],[ -1, 1, -1]]],dtype='float')} + + # Greninger--Troiano orientation relationship for fcc <-> bcc transformation + # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 + GT = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 1, 1, 1],[ 1, 0, 1]], + [[ 1, 1, 1],[ 1, 1, 0]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ -1, 0, 1]], + [[ -1, -1, 1],[ -1, -1, 0]], + [[ -1, -1, 1],[ 0, -1, 1]], + [[ -1, 1, 1],[ -1, 0, 1]], + [[ -1, 1, 1],[ -1, 1, 0]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 1, 0, 1]], + [[ 1, -1, 1],[ 1, -1, 0]], + [[ 1, -1, 1],[ 0, -1, 1]], + [[ 1, 1, 1],[ 1, 1, 0]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 1, 0, 1]], + [[ -1, -1, 1],[ -1, -1, 0]], + [[ -1, -1, 1],[ 0, -1, 1]], + [[ -1, -1, 1],[ -1, 0, 1]], + [[ -1, 1, 1],[ -1, 1, 0]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ -1, 0, 1]], + [[ 1, -1, 1],[ 1, -1, 0]], + [[ 1, -1, 1],[ 0, -1, 1]], + [[ 1, -1, 1],[ 1, 0, 1]]],dtype='float'), + 'directions': np.array([ + [[ -5,-12, 17],[-17, -7, 17]], + [[ 17, -5,-12],[ 17,-17, -7]], + [[-12, 17, -5],[ -7, 17,-17]], + [[ 5, 12, 17],[ 17, 7, 17]], + [[-17, 5,-12],[-17, 17, -7]], + [[ 12,-17, -5],[ 7,-17,-17]], + [[ -5, 12,-17],[-17, 7,-17]], + [[ 17, 5, 12],[ 17, 17, 7]], + [[-12,-17, 5],[ -7,-17, 17]], + [[ 5,-12,-17],[ 17, -7,-17]], + [[-17, -5, 12],[-17,-17, 7]], + [[ 12, 17, 5],[ 7, 17, 17]], + [[ -5, 17,-12],[-17, 17, -7]], + [[-12, -5, 17],[ -7,-17, 17]], + [[ 17,-12, -5],[ 17, -7,-17]], + [[ 5,-17,-12],[ 17,-17, -7]], + [[ 12, 5, 17],[ 7, 17, 17]], + [[-17, 12, -5],[-17, 7,-17]], + [[ -5,-17, 12],[-17,-17, 7]], + [[-12, 5,-17],[ -7, 17,-17]], + [[ 17, 12, 5],[ 17, 7, 17]], + [[ 5, 17, 12],[ 17, 17, 7]], + [[ 12, -5,-17],[ 7,-17,-17]], + [[-17,-12, 5],[-17,-7, 17]]],dtype='float')} + + # Greninger--Troiano' orientation relationship for fcc <-> bcc transformation + # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 + GTprime = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 7, 17, 17],[ 12, 5, 17]], + [[ 17, 7, 17],[ 17, 12, 5]], + [[ 17, 17, 7],[ 5, 17, 12]], + [[ -7,-17, 17],[-12, -5, 17]], + [[-17, -7, 17],[-17,-12, 5]], + [[-17,-17, 7],[ -5,-17, 12]], + [[ 7,-17,-17],[ 12, -5,-17]], + [[ 17, -7,-17],[ 17,-12, -5]], + [[ 17,-17, -7],[ 5,-17,-12]], + [[ -7, 17,-17],[-12, 5,-17]], + [[-17, 7,-17],[-17, 12, -5]], + [[-17, 17, -7],[ -5, 17,-12]], + [[ 7, 17, 17],[ 12, 17, 5]], + [[ 17, 7, 17],[ 5, 12, 17]], + [[ 17, 17, 7],[ 17, 5, 12]], + [[ -7,-17, 17],[-12,-17, 5]], + [[-17, -7, 17],[ -5,-12, 17]], + [[-17,-17, 7],[-17, -5, 12]], + [[ 7,-17,-17],[ 12,-17, -5]], + [[ 17, -7,-17],[ 5, -12,-17]], + [[ 17,-17, -7],[ 17, -5,-12]], + [[ -7, 17,-17],[-12, 17, -5]], + [[-17, 7,-17],[ -5, 12,-17]], + [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), + 'directions': np.array([ + [[ 0, 1, -1],[ 1, 1, -1]], + [[ -1, 0, 1],[ -1, 1, 1]], + [[ 1, -1, 0],[ 1, -1, 1]], + [[ 0, -1, -1],[ -1, -1, -1]], + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, -1, 0],[ 1, -1, -1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ 1, 0, 1],[ 1, 1, 1]], + [[ -1, -1, 0],[ -1, -1, 1]], + [[ 0, -1, -1],[ 1, -1, -1]], + [[ -1, 0, 1],[ -1, -1, 1]], + [[ -1, -1, 0],[ -1, -1, -1]], + [[ 0, -1, 1],[ 1, -1, 1]], + [[ 1, 0, -1],[ 1, 1, -1]], + [[ -1, 1, 0],[ -1, 1, 1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ -1, 0, -1],[ -1, -1, -1]], + [[ -1, 1, 0],[ -1, 1, -1]], + [[ 0, -1, 1],[ -1, -1, 1]], + [[ -1, 0, -1],[ -1, 1, -1]], + [[ 1, 1, 0],[ 1, 1, 1]], + [[ 0, 1, 1],[ 1, 1, 1]], + [[ 1, 0, -1],[ 1, -1, -1]], + [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} + + # Nishiyama--Wassermann orientation relationship for fcc <-> bcc transformation + # from H. Kitahara et al., Materials Characterization 54:378-386, 2005 + NW = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ 1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ -1, 1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ 1, -1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]]],dtype='float'), + 'directions': np.array([ + [[ 2, -1, -1],[ 0, -1, 1]], + [[ -1, 2, -1],[ 0, -1, 1]], + [[ -1, -1, 2],[ 0, -1, 1]], + [[ -2, -1, -1],[ 0, -1, 1]], + [[ 1, 2, -1],[ 0, -1, 1]], + [[ 1, -1, 2],[ 0, -1, 1]], + [[ 2, 1, -1],[ 0, -1, 1]], + [[ -1, -2, -1],[ 0, -1, 1]], + [[ -1, 1, 2],[ 0, -1, 1]], + [[ 2, -1, 1],[ 0, -1, 1]], #It is wrong in the paper, but matrix is correct + [[ -1, 2, 1],[ 0, -1, 1]], + [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} + + # Pitsch orientation relationship for fcc <-> bcc transformation + # from Y. He et al., Acta Materialia 53:1179-1190, 2005 + Pitsch = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 0, 1, 0],[ -1, 0, 1]], + [[ 0, 0, 1],[ 1, -1, 0]], + [[ 1, 0, 0],[ 0, 1, -1]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 1, 0, 0],[ 0, -1, 1]], + [[ 0, 1, 0],[ 1, 0, -1]], + [[ 0, 0, 1],[ -1, 1, 0]]],dtype='float'), + 'directions': np.array([ + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ -1, 0, 1],[ -1, -1, 1]], + [[ 1, -1, 0],[ 1, -1, -1]], + [[ 1, 0, -1],[ 1, -1, -1]], + [[ -1, 1, 0],[ -1, 1, -1]], + [[ 0, -1, 1],[ -1, -1, 1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} + + # Bain orientation relationship for fcc <-> bcc transformation + # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 + Bain = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 1, 0, 0],[ 1, 0, 0]], + [[ 0, 1, 0],[ 0, 1, 0]], + [[ 0, 0, 1],[ 0, 0, 1]]],dtype='float'), + 'directions': np.array([ + [[ 0, 1, 0],[ 0, 1, 1]], + [[ 0, 0, 1],[ 1, 0, 1]], + [[ 1, 0, 0],[ 1, 1, 0]]],dtype='float')} + + def relationOperations(self,model): + """ + Crystallographic orientation relationships for phase transformations. + + References + ---------- + S. Morito et al., Journal of Alloys and Compounds 577:s587-s592, 2013 + https://doi.org/10.1016/j.jallcom.2012.02.004 + + K. Kitahara et al., Acta Materialia 54(5):1279-1288, 2006 + https://doi.org/10.1016/j.actamat.2005.11.001 + + Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 + https://doi.org/10.1107/S0021889805038276 + + H. Kitahara et al., Materials Characterization 54(4-5):378-386, 2005 + https://doi.org/10.1016/j.matchar.2004.12.015 + + Y. He et al., Acta Materialia 53(4):1179-1190, 2005 + https://doi.org/10.1016/j.actamat.2004.11.021 + + """ + models={'KS':self.KS, 'GT':self.GT, 'GT_prime':self.GTprime, + 'NW':self.NW, 'Pitsch': self.Pitsch, 'Bain':self.Bain} + try: + relationship = models[model] + except KeyError : + raise KeyError('Orientation relationship "{}" is unknown'.format(model)) + + if self.lattice not in relationship['mapping']: + raise ValueError('Relationship "{}" not supported for lattice "{}"'.format(model,self.lattice)) + + r = {'lattice':Lattice((set(relationship['mapping'])-{self.lattice}).pop()), # target lattice + 'rotations':[] } + + myPlane_id = relationship['mapping'][self.lattice] + otherPlane_id = (myPlane_id+1)%2 + myDir_id = myPlane_id +2 + otherDir_id = otherPlane_id +2 + + for miller in np.hstack((relationship['planes'],relationship['directions'])): + myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) + myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) + myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]) + + otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) + otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) + otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]) + + r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix.T,myMatrix))) + + return r diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 55a58959c..4916c1679 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -13,137 +13,137 @@ class Orientation: __slots__ = ['rotation','lattice'] def __repr__(self): - """Report lattice type and orientation.""" - return self.lattice.__repr__()+'\n'+self.rotation.__repr__() + """Report lattice type and orientation.""" + return self.lattice.__repr__()+'\n'+self.rotation.__repr__() def __init__(self, rotation, lattice): - """ - New orientation from rotation and lattice. + """ + New orientation from rotation and lattice. - Parameters - ---------- - rotation : Rotation - Rotation specifying the lattice orientation. - lattice : Lattice - Lattice type of the crystal. + Parameters + ---------- + rotation : Rotation + Rotation specifying the lattice orientation. + lattice : Lattice + Lattice type of the crystal. - """ - if isinstance(lattice, Lattice): - self.lattice = lattice - else: - self.lattice = Lattice(lattice) # assume string + """ + if isinstance(lattice, Lattice): + self.lattice = lattice + else: + self.lattice = Lattice(lattice) # assume string - if isinstance(rotation, Rotation): - self.rotation = rotation - else: - self.rotation = Rotation.fromQuaternion(rotation) # assume quaternion + if isinstance(rotation, Rotation): + self.rotation = rotation + else: + self.rotation = Rotation.fromQuaternion(rotation) # assume quaternion def disorientation(self, other, SST = True, symmetries = False): - """ - Disorientation between myself and given other orientation. + """ + Disorientation between myself and given other orientation. - Rotation axis falls into SST if SST == True. - (Currently requires same symmetry for both orientations. - Look into A. Heinz and P. Neumann 1991 for cases with differing sym.) - """ - if self.lattice.symmetry != other.lattice.symmetry: - raise NotImplementedError('disorientation between different symmetry classes not supported yet.') + Rotation axis falls into SST if SST == True. + (Currently requires same symmetry for both orientations. + Look into A. Heinz and P. Neumann 1991 for cases with differing sym.) + """ + if self.lattice.symmetry != other.lattice.symmetry: + raise NotImplementedError('disorientation between different symmetry classes not supported yet.') - mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations([0]) # take all or only first sym operation - otherSymEqs = other.equivalentOrientations() + mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations([0]) # take all or only first sym operation + otherSymEqs = other.equivalentOrientations() - for i,sA in enumerate(mySymEqs): - aInv = sA.rotation.inversed() - for j,sB in enumerate(otherSymEqs): - b = sB.rotation - r = b*aInv - for k in range(2): - r.inverse() - breaker = self.lattice.symmetry.inFZ(r.asRodrigues(vector=True)) \ - and (not SST or other.lattice.symmetry.inDisorientationSST(r.asRodrigues(vector=True))) + for i,sA in enumerate(mySymEqs): + aInv = sA.rotation.inversed() + for j,sB in enumerate(otherSymEqs): + b = sB.rotation + r = b*aInv + for k in range(2): + r.inverse() + breaker = self.lattice.symmetry.inFZ(r.asRodrigues(vector=True)) \ + and (not SST or other.lattice.symmetry.inDisorientationSST(r.asRodrigues(vector=True))) + if breaker: break if breaker: break if breaker: break - if breaker: break - return (Orientation(r,self.lattice), i,j, k == 1) if symmetries else r # disorientation ... + return (Orientation(r,self.lattice), i,j, k == 1) if symmetries else r # disorientation ... # ... own sym, other sym, # self-->other: True, self<--other: False def inFZ(self): - return self.lattice.symmetry.inFZ(self.rotation.asRodrigues(vector=True)) + return self.lattice.symmetry.inFZ(self.rotation.asRodrigues(vector=True)) def equivalentOrientations(self,members=[]): - """List of orientations which are symmetrically equivalent.""" - try: - iter(members) # asking for (even empty) list of members? - except TypeError: - return self.__class__(self.lattice.symmetry.symmetryOperations(members)*self.rotation,self.lattice) # no, return rotation object - else: - return [self.__class__(q*self.rotation,self.lattice) \ - for q in self.lattice.symmetry.symmetryOperations(members)] # yes, return list of rotations + """List of orientations which are symmetrically equivalent.""" + try: + iter(members) # asking for (even empty) list of members? + except TypeError: + return self.__class__(self.lattice.symmetry.symmetryOperations(members)*self.rotation,self.lattice) # no, return rotation object + else: + return [self.__class__(q*self.rotation,self.lattice) \ + for q in self.lattice.symmetry.symmetryOperations(members)] # yes, return list of rotations def relatedOrientations(self,model): - """List of orientations related by the given orientation relationship.""" - r = self.lattice.relationOperations(model) - return [self.__class__(o*self.rotation,r['lattice']) for o in r['rotations']] + """List of orientations related by the given orientation relationship.""" + r = self.lattice.relationOperations(model) + return [self.__class__(o*self.rotation,r['lattice']) for o in r['rotations']] def reduced(self): - """Transform orientation to fall into fundamental zone according to symmetry.""" - for me in self.equivalentOrientations(): - if self.lattice.symmetry.inFZ(me.rotation.asRodrigues(vector=True)): break + """Transform orientation to fall into fundamental zone according to symmetry.""" + for me in self.equivalentOrientations(): + if self.lattice.symmetry.inFZ(me.rotation.asRodrigues(vector=True)): break - return self.__class__(me.rotation,self.lattice) + return self.__class__(me.rotation,self.lattice) def inversePole(self, axis, proper = False, SST = True): - """Axis rotated according to orientation (using crystal symmetry to ensure location falls into SST).""" - if SST: # pole requested to be within SST - for i,o in enumerate(self.equivalentOrientations()): # test all symmetric equivalent quaternions - pole = o.rotation*axis # align crystal direction to axis - if self.lattice.symmetry.inSST(pole,proper): break # found SST version - else: - pole = self.rotation*axis # align crystal direction to axis + """Axis rotated according to orientation (using crystal symmetry to ensure location falls into SST).""" + if SST: # pole requested to be within SST + for i,o in enumerate(self.equivalentOrientations()): # test all symmetric equivalent quaternions + pole = o.rotation*axis # align crystal direction to axis + if self.lattice.symmetry.inSST(pole,proper): break # found SST version + else: + pole = self.rotation*axis # align crystal direction to axis - return (pole,i if SST else 0) + return (pole,i if SST else 0) def IPFcolor(self,axis): - """TSL color of inverse pole figure for given axis.""" - color = np.zeros(3,'d') + """TSL color of inverse pole figure for given axis.""" + color = np.zeros(3,'d') - for o in self.equivalentOrientations(): - pole = o.rotation*axis # align crystal direction to axis - inSST,color = self.lattice.symmetry.inSST(pole,color=True) - if inSST: break + for o in self.equivalentOrientations(): + pole = o.rotation*axis # align crystal direction to axis + inSST,color = self.lattice.symmetry.inSST(pole,color=True) + if inSST: break - return color + return color @staticmethod def fromAverage(orientations, weights = []): - """Create orientation from average of list of orientations.""" - if not all(isinstance(item, Orientation) for item in orientations): - raise TypeError("Only instances of Orientation can be averaged.") + """Create orientation from average of list of orientations.""" + if not all(isinstance(item, Orientation) for item in orientations): + raise TypeError("Only instances of Orientation can be averaged.") - closest = [] - ref = orientations[0] - for o in orientations: - closest.append(o.equivalentOrientations( - ref.disorientation(o, - SST = False, # select (o[ther]'s) sym orientation - symmetries = True)[2]).rotation) # with lowest misorientation + closest = [] + ref = orientations[0] + for o in orientations: + closest.append(o.equivalentOrientations( + ref.disorientation(o, + SST = False, # select (o[ther]'s) sym orientation + symmetries = True)[2]).rotation) # with lowest misorientation - return Orientation(Rotation.fromAverage(closest,weights),ref.lattice) + return Orientation(Rotation.fromAverage(closest,weights),ref.lattice) def average(self,other): - """Calculate the average rotation.""" - return Orientation.fromAverage([self,other]) + """Calculate the average rotation.""" + return Orientation.fromAverage([self,other]) diff --git a/python/damask/rotation.py b/python/damask/rotation.py index 084e4bf38..78686ab1f 100644 --- a/python/damask/rotation.py +++ b/python/damask/rotation.py @@ -4,14 +4,10 @@ from . import Lambert P = -1 -def isone(a): - return np.isclose(a,1.0,atol=1.0e-7,rtol=0.0) - def iszero(a): - return np.isclose(a,0.0,atol=1.0e-12,rtol=0.0) + return np.isclose(a,0.0,atol=1.0e-12,rtol=0.0) -#################################################################################################### class Rotation: u""" Orientation stored with functionality for conversion to different representations.