From 302da1f76a43caa09c273db125d4a4fd93b5c27f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Jun 2021 09:28:27 +0200 Subject: [PATCH] separating functionality --- python/damask/__init__.py | 2 +- python/damask/_lattice.py | 651 +++++++++++++++++++++++++++++++ python/damask/_lattice_family.py | 29 +- python/damask/_orientation.py | 169 ++------ python/damask/lattice.py | 444 --------------------- python/tests/test_Lattice.py | 64 +++ python/tests/test_Orientation.py | 70 ---- 7 files changed, 755 insertions(+), 674 deletions(-) create mode 100644 python/damask/_lattice.py delete mode 100644 python/damask/lattice.py create mode 100644 python/tests/test_Lattice.py diff --git a/python/damask/__init__.py b/python/damask/__init__.py index 5cdfbe899..eb333487d 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -14,11 +14,11 @@ from . import tensor # noqa from . import mechanics # noqa from . import solver # noqa from . import grid_filters # noqa -from . import lattice # noqa #Modules that contain only one class (of the same name), are prefixed by a '_'. #For example, '_colormap' containsa class called 'Colormap' which is imported as 'damask.Colormap'. from ._rotation import Rotation # noqa from ._lattice_family import LatticeFamily # noqa +from ._lattice import Lattice # noqa from ._orientation import Orientation # noqa from ._table import Table # noqa from ._vtk import VTK # noqa diff --git a/python/damask/_lattice.py b/python/damask/_lattice.py new file mode 100644 index 000000000..c9303968c --- /dev/null +++ b/python/damask/_lattice.py @@ -0,0 +1,651 @@ +import numpy as np + +from . import util +from . import LatticeFamily + +lattice_symmetries = { + 'aP': 'triclinic', + + 'mP': 'monoclinic', + 'mS': 'monoclinic', + + 'oP': 'orthorhombic', + 'oS': 'orthorhombic', + 'oI': 'orthorhombic', + 'oF': 'orthorhombic', + + 'tP': 'tetragonal', + 'tI': 'tetragonal', + + 'hP': 'hexagonal', + + 'cP': 'cubic', + 'cI': 'cubic', + 'cF': 'cubic', + } + + +class Lattice(LatticeFamily): + """Lattice.""" + + def __init__(self, + lattice = None, + a = None,b = None,c = None, + alpha = None,beta = None,gamma = None, + degrees = False): + """ + Lattice. + + Parameters + ---------- + lattice : {'aP', 'mP', 'mS', 'oP', 'oS', 'oI', 'oF', 'tP', 'tI', 'hP', 'cP', 'cI', 'cF'}. + Name of the Bravais lattice in Pearson notation. + a : float, optional + Length of lattice parameter 'a'. + b : float, optional + Length of lattice parameter 'b'. + c : float, optional + Length of lattice parameter 'c'. + alpha : float, optional + Angle between b and c lattice basis. + beta : float, optional + Angle between c and a lattice basis. + gamma : float, optional + Angle between a and b lattice basis. + degrees : bool, optional + Angles are given in degrees. Defaults to False. + + """ + super().__init__(lattice_symmetries[lattice]) + self.lattice = lattice + + + self.a = 1 if a is None else a + self.b = b + self.c = c + self.a = float(self.a) if self.a is not None else \ + (self.b / self.ratio['b'] if self.b is not None and self.ratio['b'] is not None else + self.c / self.ratio['c'] if self.c is not None and self.ratio['c'] is not None else None) + self.b = float(self.b) if self.b is not None else \ + (self.a * self.ratio['b'] if self.a is not None and self.ratio['b'] is not None else + self.c / self.ratio['c'] * self.ratio['b'] + if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None) + self.c = float(self.c) if self.c is not None else \ + (self.a * self.ratio['c'] if self.a is not None and self.ratio['c'] is not None else + self.b / self.ratio['b'] * self.ratio['c'] + if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None) + + self.alpha = np.radians(alpha) if degrees and alpha is not None else alpha + self.beta = np.radians(beta) if degrees and beta is not None else beta + self.gamma = np.radians(gamma) if degrees and gamma is not None else gamma + if self.alpha is None and 'alpha' in self.immutable: self.alpha = self.immutable['alpha'] + if self.beta is None and 'beta' in self.immutable: self.beta = self.immutable['beta'] + if self.gamma is None and 'gamma' in self.immutable: self.gamma = self.immutable['gamma'] + + if \ + (self.a is None) \ + or (self.b is None or ('b' in self.immutable and self.b != self.immutable['b'] * self.a)) \ + or (self.c is None or ('c' in self.immutable and self.c != self.immutable['c'] * self.b)) \ + or (self.alpha is None or ('alpha' in self.immutable and self.alpha != self.immutable['alpha'])) \ + or (self.beta is None or ( 'beta' in self.immutable and self.beta != self.immutable['beta'])) \ + or (self.gamma is None or ('gamma' in self.immutable and self.gamma != self.immutable['gamma'])): + raise ValueError (f'Incompatible parameters {self.parameters} for crystal family {self.family}') + + if np.any(np.array([self.alpha,self.beta,self.gamma]) <= 0): + raise ValueError ('Lattice angles must be positive') + if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0] + > np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]): + raise ValueError ('Each lattice angle must be less than sum of others') + + + @property + def parameters(self): + """Return lattice parameters a, b, c, alpha, beta, gamma.""" + return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) + + + @property + def ratio(self): + """Return axes ratios of own lattice.""" + _ratio = { 'hexagonal': {'c': np.sqrt(8./3.)}} + + return dict(b = self.immutable['b'] + if 'b' in self.immutable else + _ratio[self.family]['b'] if self.family in _ratio and 'b' in _ratio[self.family] else None, + c = self.immutable['c'] + if 'c' in self.immutable else + _ratio[self.family]['c'] if self.family in _ratio and 'c' in _ratio[self.family] else None, + ) + + + @property + def basis_real(self): + """ + Calculate orthogonal real space crystal basis. + + References + ---------- + C.T. Young and J.L. Lytton, Journal of Applied Physics 43:1408–1417, 1972 + https://doi.org/10.1063/1.1661333 + + """ + if None in self.parameters: + raise KeyError('missing crystal lattice parameters') + return np.array([ + [1,0,0], + [np.cos(self.gamma),np.sin(self.gamma),0], + [np.cos(self.beta), + (np.cos(self.alpha)-np.cos(self.beta)*np.cos(self.gamma)) /np.sin(self.gamma), + np.sqrt(1 - np.cos(self.alpha)**2 - np.cos(self.beta)**2 - np.cos(self.gamma)**2 + + 2 * np.cos(self.alpha) * np.cos(self.beta) * np.cos(self.gamma))/np.sin(self.gamma)], + ],dtype=float).T \ + * np.array([self.a,self.b,self.c]) + + + @property + def basis_reciprocal(self): + """Calculate reciprocal (dual) crystal basis.""" + return np.linalg.inv(self.basis_real.T) + + + def to_lattice(self,*,direction=None,plane=None): + """ + Calculate lattice vector corresponding to crystal frame direction or plane normal. + + Parameters + ---------- + direction|normal : numpy.ndarray of shape (...,3) + Vector along direction or plane normal. + + Returns + ------- + Miller : numpy.ndarray of shape (...,3) + lattice vector of direction or plane. + Use util.scale_to_coprime to convert to (integer) Miller indices. + + """ + if (direction is not None) ^ (plane is None): + raise KeyError('Specify either "direction" or "plane"') + axis,basis = (np.array(direction),self.basis_reciprocal.T) \ + if plane is None else \ + (np.array(plane),self.basis_real.T) + return np.einsum('il,...l',basis,axis) + + + def to_frame(self,*,uvw=None,hkl=None): + """ + Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl). + + Parameters + ---------- + uvw|hkl : numpy.ndarray of shape (...,3) + Miller indices of crystallographic direction or plane normal. + + Returns + ------- + vector : numpy.ndarray of shape (...,3) or (N,...,3) + Crystal frame vector (or vectors if with_symmetry) along [uvw] direction or (hkl) plane normal. + + """ + if (uvw is not None) ^ (hkl is None): + raise KeyError('Specify either "uvw" or "hkl"') + axis,basis = (np.array(uvw),self.basis_real) \ + if hkl is None else \ + (np.array(hkl),self.basis_reciprocal) + return np.einsum('il,...l',basis,axis) + + + def kinematics(self,mode): + master = self._kinematics[self.lattice][mode] + if self.lattice == 'hP': + return {'direction':util.Bravais_to_Miller(uvtw=master[:,0:4]), + 'plane': util.Bravais_to_Miller(hkil=master[:,4:8])} + else: + return {'direction':master[:,0:3], + 'plane': master[:,3:6]} + + + @property + def orientation_relationships(self): + return {k:v for k,v in self._orientation_relationships.items() if self.lattice in v} + + + _kinematics = { + 'cF': { + 'slip' : 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], + [+1,+1,+0, +1,-1,+0], + [+1,-1,+0, +1,+1,+0], + [+1,+0,+1, +1,+0,-1], + [+1,+0,-1, +1,+0,+1], + [+0,+1,+1, +0,+1,-1], + [+0,+1,-1, +0,+1,+1], + ],'d'), + 'twin' : np.array([ + [-2, 1, 1, 1, 1, 1], + [ 1,-2, 1, 1, 1, 1], + [ 1, 1,-2, 1, 1, 1], + [ 2,-1, 1, -1,-1, 1], + [-1, 2, 1, -1,-1, 1], + [-1,-1,-2, -1,-1, 1], + [-2,-1,-1, 1,-1,-1], + [ 1, 2,-1, 1,-1,-1], + [ 1,-1, 2, 1,-1,-1], + [ 2, 1,-1, -1, 1,-1], + [-1,-2,-1, -1, 1,-1], + [-1, 1, 2, -1, 1,-1], + ],dtype=float), + }, + 'cI': { + 'slip' : 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, +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,+0], + [+1,+1,-1, -1,+1,+0], + [-1,+1,+1, +2,+1,+1], + [+1,+1,+1, -2,+1,+1], + [+1,+1,-1, +2,-1,+1], + [+1,-1,+1, +2,+1,-1], + [+1,-1,+1, +1,+2,+1], + [+1,+1,-1, -1,+2,+1], + [+1,+1,+1, +1,-2,+1], + [-1,+1,+1, +1,+2,-1], + [+1,+1,-1, +1,+1,+2], + [+1,-1,+1, -1,+1,+2], + [-1,+1,+1, +1,-1,+2], + [+1,+1,+1, +1,+1,-2], + [+1,+1,-1, +1,+2,+3], + [+1,-1,+1, -1,+2,+3], + [-1,+1,+1, +1,-2,+3], + [+1,+1,+1, +1,+2,-3], + [+1,-1,+1, +1,+3,+2], + [+1,+1,-1, -1,+3,+2], + [+1,+1,+1, +1,-3,+2], + [-1,+1,+1, +1,+3,-2], + [+1,+1,-1, +2,+1,+3], + [+1,-1,+1, -2,+1,+3], + [-1,+1,+1, +2,-1,+3], + [+1,+1,+1, +2,+1,-3], + [+1,-1,+1, +2,+3,+1], + [+1,+1,-1, -2,+3,+1], + [+1,+1,+1, +2,-3,+1], + [-1,+1,+1, +2,+3,-1], + [-1,+1,+1, +3,+1,+2], + [+1,+1,+1, -3,+1,+2], + [+1,+1,-1, +3,-1,+2], + [+1,-1,+1, +3,+1,-2], + [-1,+1,+1, +3,+2,+1], + [+1,+1,+1, -3,+2,+1], + [+1,+1,-1, +3,-2,+1], + [+1,-1,+1, +3,+2,-1], + ],'d'), + 'twin' : np.array([ + [-1, 1, 1, 2, 1, 1], + [ 1, 1, 1, -2, 1, 1], + [ 1, 1,-1, 2,-1, 1], + [ 1,-1, 1, 2, 1,-1], + [ 1,-1, 1, 1, 2, 1], + [ 1, 1,-1, -1, 2, 1], + [ 1, 1, 1, 1,-2, 1], + [-1, 1, 1, 1, 2,-1], + [ 1, 1,-1, 1, 1, 2], + [ 1,-1, 1, -1, 1, 2], + [-1, 1, 1, 1,-1, 2], + [ 1, 1, 1, 1, 1,-2], + ],dtype=float), + }, + 'hP': { + 'slip' : np.array([ + [+2,-1,-1,+0, +0,+0,+0,+1], + [-1,+2,-1,+0, +0,+0,+0,+1], + [-1,-1,+2,+0, +0,+0,+0,+1], + [+2,-1,-1,+0, +0,+1,-1,+0], + [-1,+2,-1,+0, -1,+0,+1,+0], + [-1,-1,+2,+0, +1,-1,+0,+0], + [-1,+1,+0,+0, +1,+1,-2,+0], + [+0,-1,+1,+0, -2,+1,+1,+0], + [+1,+0,-1,+0, +1,-2,+1,+0], + [-1,+2,-1,+0, +1,+0,-1,+1], + [-2,+1,+1,+0, +0,+1,-1,+1], + [-1,-1,+2,+0, -1,+1,+0,+1], + [+1,-2,+1,+0, -1,+0,+1,+1], + [+2,-1,-1,+0, +0,-1,+1,+1], + [+1,+1,-2,+0, +1,-1,+0,+1], + [-2,+1,+1,+3, +1,+0,-1,+1], + [-1,-1,+2,+3, +1,+0,-1,+1], + [-1,-1,+2,+3, +0,+1,-1,+1], + [+1,-2,+1,+3, +0,+1,-1,+1], + [+1,-2,+1,+3, -1,+1,+0,+1], + [+2,-1,-1,+3, -1,+1,+0,+1], + [+2,-1,-1,+3, -1,+0,+1,+1], + [+1,+1,-2,+3, -1,+0,+1,+1], + [+1,+1,-2,+3, +0,-1,+1,+1], + [-1,+2,-1,+3, +0,-1,+1,+1], + [-1,+2,-1,+3, +1,-1,+0,+1], + [-2,+1,+1,+3, +1,-1,+0,+1], + [-1,-1,+2,+3, +1,+1,-2,+2], + [+1,-2,+1,+3, -1,+2,-1,+2], + [+2,-1,-1,+3, -2,+1,+1,+2], + [+1,+1,-2,+3, -1,-1,+2,+2], + [-1,+2,-1,+3, +1,-2,+1,+2], + [-2,+1,+1,+3, +2,-1,-1,+2], + ],'d'), + 'twin' : np.array([ + [-1, 0, 1, 1, 1, 0,-1, 2], # shear = (3-(c/a)^2)/(sqrt(3) c/a) <-10.1>{10.2} + [ 0,-1, 1, 1, 0, 1,-1, 2], + [ 1,-1, 0, 1, -1, 1, 0, 2], + [ 1, 0,-1, 1, -1, 0, 1, 2], + [ 0, 1,-1, 1, 0,-1, 1, 2], + [-1, 1, 0, 1, 1,-1, 0, 2], + [-1,-1, 2, 6, 1, 1,-2, 1], # shear = 1/(c/a) <11.6>{-1-1.1} + [ 1,-2, 1, 6, -1, 2,-1, 1], + [ 2,-1,-1, 6, -2, 1, 1, 1], + [ 1, 1,-2, 6, -1,-1, 2, 1], + [-1, 2,-1, 6, 1,-2, 1, 1], + [-2, 1, 1, 6, 2,-1,-1, 1], + [ 1, 0,-1,-2, 1, 0,-1, 1], # shear = (4(c/a)^2-9)/(4 sqrt(3) c/a) <10.-2>{10.1} + [ 0, 1,-1,-2, 0, 1,-1, 1], + [-1, 1, 0,-2, -1, 1, 0, 1], + [-1, 0, 1,-2, -1, 0, 1, 1], + [ 0,-1, 1,-2, 0,-1, 1, 1], + [ 1,-1, 0,-2, 1,-1, 0, 1], + [ 1, 1,-2,-3, 1, 1,-2, 2], # shear = 2((c/a)^2-2)/(3 c/a) <11.-3>{11.2} + [-1, 2,-1,-3, -1, 2,-1, 2], + [-2, 1, 1,-3, -2, 1, 1, 2], + [-1,-1, 2,-3, -1,-1, 2, 2], + [ 1,-2, 1,-3, 1,-2, 1, 2], + [ 2,-1,-1,-3, 2,-1,-1, 2], + ],dtype=float), + }, + } + + + _orientation_relationships = { + 'KS': { + 'cF' : 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), + 'cI' : 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), + }, + 'GT': { + 'cF' : np.array([ + [[ -5,-12, 17],[ 1, 1, 1]], + [[ 17, -5,-12],[ 1, 1, 1]], + [[-12, 17, -5],[ 1, 1, 1]], + [[ 5, 12, 17],[ -1, -1, 1]], + [[-17, 5,-12],[ -1, -1, 1]], + [[ 12,-17, -5],[ -1, -1, 1]], + [[ -5, 12,-17],[ -1, 1, 1]], + [[ 17, 5, 12],[ -1, 1, 1]], + [[-12,-17, 5],[ -1, 1, 1]], + [[ 5,-12,-17],[ 1, -1, 1]], + [[-17, -5, 12],[ 1, -1, 1]], + [[ 12, 17, 5],[ 1, -1, 1]], + [[ -5, 17,-12],[ 1, 1, 1]], + [[-12, -5, 17],[ 1, 1, 1]], + [[ 17,-12, -5],[ 1, 1, 1]], + [[ 5,-17,-12],[ -1, -1, 1]], + [[ 12, 5, 17],[ -1, -1, 1]], + [[-17, 12, -5],[ -1, -1, 1]], + [[ -5,-17, 12],[ -1, 1, 1]], + [[-12, 5,-17],[ -1, 1, 1]], + [[ 17, 12, 5],[ -1, 1, 1]], + [[ 5, 17, 12],[ 1, -1, 1]], + [[ 12, -5,-17],[ 1, -1, 1]], + [[-17,-12, 5],[ 1, -1, 1]], + ],dtype=float), + 'cI' : np.array([ + [[-17, -7, 17],[ 1, 0, 1]], + [[ 17,-17, -7],[ 1, 1, 0]], + [[ -7, 17,-17],[ 0, 1, 1]], + [[ 17, 7, 17],[ -1, 0, 1]], + [[-17, 17, -7],[ -1, -1, 0]], + [[ 7,-17,-17],[ 0, -1, 1]], + [[-17, 7,-17],[ -1, 0, 1]], + [[ 17, 17, 7],[ -1, 1, 0]], + [[ -7,-17, 17],[ 0, 1, 1]], + [[ 17, -7,-17],[ 1, 0, 1]], + [[-17,-17, 7],[ 1, -1, 0]], + [[ 7, 17, 17],[ 0, -1, 1]], + [[-17, 17, -7],[ 1, 1, 0]], + [[ -7,-17, 17],[ 0, 1, 1]], + [[ 17, -7,-17],[ 1, 0, 1]], + [[ 17,-17, -7],[ -1, -1, 0]], + [[ 7, 17, 17],[ 0, -1, 1]], + [[-17, 7,-17],[ -1, 0, 1]], + [[-17,-17, 7],[ -1, 1, 0]], + [[ -7, 17,-17],[ 0, 1, 1]], + [[ 17, 7, 17],[ -1, 0, 1]], + [[ 17, 17, 7],[ 1, -1, 0]], + [[ 7,-17,-17],[ 0, -1, 1]], + [[-17, -7, 17],[ 1, 0, 1]], + ],dtype=float), + }, + 'GT_prime': { + 'cF' : np.array([ + [[ 0, 1, -1],[ 7, 17, 17]], + [[ -1, 0, 1],[ 17, 7, 17]], + [[ 1, -1, 0],[ 17, 17, 7]], + [[ 0, -1, -1],[ -7,-17, 17]], + [[ 1, 0, 1],[-17, -7, 17]], + [[ 1, -1, 0],[-17,-17, 7]], + [[ 0, 1, -1],[ 7,-17,-17]], + [[ 1, 0, 1],[ 17, -7,-17]], + [[ -1, -1, 0],[ 17,-17, -7]], + [[ 0, -1, -1],[ -7, 17,-17]], + [[ -1, 0, 1],[-17, 7,-17]], + [[ -1, -1, 0],[-17, 17, -7]], + [[ 0, -1, 1],[ 7, 17, 17]], + [[ 1, 0, -1],[ 17, 7, 17]], + [[ -1, 1, 0],[ 17, 17, 7]], + [[ 0, 1, 1],[ -7,-17, 17]], + [[ -1, 0, -1],[-17, -7, 17]], + [[ -1, 1, 0],[-17,-17, 7]], + [[ 0, -1, 1],[ 7,-17,-17]], + [[ -1, 0, -1],[ 17, -7,-17]], + [[ 1, 1, 0],[ 17,-17, -7]], + [[ 0, 1, 1],[ -7, 17,-17]], + [[ 1, 0, -1],[-17, 7,-17]], + [[ 1, 1, 0],[-17, 17, -7]], + ],dtype=float), + 'cI' : np.array([ + [[ 1, 1, -1],[ 12, 5, 17]], + [[ -1, 1, 1],[ 17, 12, 5]], + [[ 1, -1, 1],[ 5, 17, 12]], + [[ -1, -1, -1],[-12, -5, 17]], + [[ 1, -1, 1],[-17,-12, 5]], + [[ 1, -1, -1],[ -5,-17, 12]], + [[ -1, 1, -1],[ 12, -5,-17]], + [[ 1, 1, 1],[ 17,-12, -5]], + [[ -1, -1, 1],[ 5,-17,-12]], + [[ 1, -1, -1],[-12, 5,-17]], + [[ -1, -1, 1],[-17, 12, -5]], + [[ -1, -1, -1],[ -5, 17,-12]], + [[ 1, -1, 1],[ 12, 17, 5]], + [[ 1, 1, -1],[ 5, 12, 17]], + [[ -1, 1, 1],[ 17, 5, 12]], + [[ -1, 1, 1],[-12,-17, 5]], + [[ -1, -1, -1],[ -5,-12, 17]], + [[ -1, 1, -1],[-17, -5, 12]], + [[ -1, -1, 1],[ 12,-17, -5]], + [[ -1, 1, -1],[ 5,-12,-17]], + [[ 1, 1, 1],[ 17, -5,-12]], + [[ 1, 1, 1],[-12, 17, -5]], + [[ 1, -1, -1],[ -5, 12,-17]], + [[ 1, 1, -1],[-17, 5,-12]], + ],dtype=float), + }, + 'NW': { + 'cF' : np.array([ + [[ 2, -1, -1],[ 1, 1, 1]], + [[ -1, 2, -1],[ 1, 1, 1]], + [[ -1, -1, 2],[ 1, 1, 1]], + [[ -2, -1, -1],[ -1, 1, 1]], + [[ 1, 2, -1],[ -1, 1, 1]], + [[ 1, -1, 2],[ -1, 1, 1]], + [[ 2, 1, -1],[ 1, -1, 1]], + [[ -1, -2, -1],[ 1, -1, 1]], + [[ -1, 1, 2],[ 1, -1, 1]], + [[ 2, -1, 1],[ -1, -1, 1]], + [[ -1, 2, 1],[ -1, -1, 1]], + [[ -1, -1, -2],[ -1, -1, 1]], + ],dtype=float), + 'cI' : np.array([ + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + [[ 0, -1, 1],[ 0, 1, 1]], + ],dtype=float), + }, + 'Pitsch': { + 'cF' : np.array([ + [[ 1, 0, 1],[ 0, 1, 0]], + [[ 1, 1, 0],[ 0, 0, 1]], + [[ 0, 1, 1],[ 1, 0, 0]], + [[ 0, 1, -1],[ 1, 0, 0]], + [[ -1, 0, 1],[ 0, 1, 0]], + [[ 1, -1, 0],[ 0, 0, 1]], + [[ 1, 0, -1],[ 0, 1, 0]], + [[ -1, 1, 0],[ 0, 0, 1]], + [[ 0, -1, 1],[ 1, 0, 0]], + [[ 0, 1, 1],[ 1, 0, 0]], + [[ 1, 0, 1],[ 0, 1, 0]], + [[ 1, 1, 0],[ 0, 0, 1]], + ],dtype=float), + 'cI' : np.array([ + [[ 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],[ -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]], + ],dtype=float), + }, + 'Bain': { + 'cF' : np.array([ + [[ 0, 1, 0],[ 1, 0, 0]], + [[ 0, 0, 1],[ 0, 1, 0]], + [[ 1, 0, 0],[ 0, 0, 1]], + ],dtype=float), + 'cI' : np.array([ + [[ 0, 1, 1],[ 1, 0, 0]], + [[ 1, 0, 1],[ 0, 1, 0]], + [[ 1, 1, 0],[ 0, 0, 1]], + ],dtype=float), + }, + 'Burgers' : { + 'cI' : np.array([ + [[ -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, 0, 1]], + [[ -1, 1, 1],[ 1, 0, 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],[ 0, -1, 1]], + [[ 1, 1, 1],[ 0, -1, 1]], + ],dtype=float), + 'hP' : np.array([ + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], + [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], + ],dtype=float), + }, + } diff --git a/python/damask/_lattice_family.py b/python/damask/_lattice_family.py index 8f352e8df..d6288cff0 100644 --- a/python/damask/_lattice_family.py +++ b/python/damask/_lattice_family.py @@ -5,7 +5,15 @@ from . import Rotation class LatticeFamily(): def __init__(self,family): - """Symmetry-related operations for crystal families.""" + """ + Symmetry-related operations for crystal families. + + Parameters + ---------- + family : {'triclinic', 'monoclinic', 'orthorhombic', 'tetragonal', 'hexagonal', 'cubic'} + Name of the crystal family. + + """ if family not in self._immutable.keys(): raise KeyError(f'invalid lattice family "{family}"') self.family = family @@ -121,41 +129,36 @@ class LatticeFamily(): _immutable = { - 'cubic': - { + 'cubic': { 'b': 1.0, 'c': 1.0, 'alpha': np.pi/2., 'beta': np.pi/2., 'gamma': np.pi/2., }, - 'hexagonal': - { + 'hexagonal': { 'b': 1.0, 'alpha': np.pi/2., 'beta': np.pi/2., 'gamma': 2.*np.pi/3., }, - 'tetragonal': - { + 'tetragonal': { 'b': 1.0, 'alpha': np.pi/2., 'beta': np.pi/2., 'gamma': np.pi/2., }, - 'orthorhombic': - { + 'orthorhombic': { 'alpha': np.pi/2., 'beta': np.pi/2., 'gamma': np.pi/2., }, - 'monoclinic': - { + 'monoclinic': { 'alpha': np.pi/2., 'gamma': np.pi/2., }, - 'triclinic': {} - } + 'triclinic': {} + } _basis = { diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index 8a3f9fe24..b2ee9628b 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -4,9 +4,9 @@ import numpy as np from . import Rotation from . import LatticeFamily +from . import Lattice from . import util from . import tensor -from . import lattice as lattice_ lattice_symmetries = { @@ -130,13 +130,13 @@ class Orientation(Rotation): Defaults to no rotation. """ - Rotation.__init__(self,rotation=rotation) + super().__init__(rotation) if family in set(lattice_symmetries.values()) and lattice is None: self.family = family self.lattice = None - l = LatticeFamily(self.family) + l = LatticeFamily(self.family) # noqa self.immutable = l.immutable self.basis = l.basis self.symmetry_operations = l.symmetry_operations @@ -149,48 +149,25 @@ class Orientation(Rotation): self.family = lattice_symmetries[lattice] self.lattice = lattice - l = LatticeFamily(self.family) + l = Lattice(self.lattice, a,b,c, alpha,beta,gamma, degrees) # noqa self.immutable = l.immutable self.basis = l.basis self.symmetry_operations = l.symmetry_operations - self.a = 1 if a is None else a - self.b = b - self.c = c - self.a = float(self.a) if self.a is not None else \ - (self.b / self.ratio['b'] if self.b is not None and self.ratio['b'] is not None else - self.c / self.ratio['c'] if self.c is not None and self.ratio['c'] is not None else None) - self.b = float(self.b) if self.b is not None else \ - (self.a * self.ratio['b'] if self.a is not None and self.ratio['b'] is not None else - self.c / self.ratio['c'] * self.ratio['b'] - if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None) - self.c = float(self.c) if self.c is not None else \ - (self.a * self.ratio['c'] if self.a is not None and self.ratio['c'] is not None else - self.b / self.ratio['b'] * self.ratio['c'] - if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None) + self.a = l.a + self.b = l.b + self.c = l.c - self.alpha = np.radians(alpha) if degrees and alpha is not None else alpha - self.beta = np.radians(beta) if degrees and beta is not None else beta - self.gamma = np.radians(gamma) if degrees and gamma is not None else gamma - if self.alpha is None and 'alpha' in self.immutable: self.alpha = self.immutable['alpha'] - if self.beta is None and 'beta' in self.immutable: self.beta = self.immutable['beta'] - if self.gamma is None and 'gamma' in self.immutable: self.gamma = self.immutable['gamma'] + self.alpha = l.alpha + self.beta = l.beta + self.gamma = l.gamma - if \ - (self.a is None) \ - or (self.b is None or ('b' in self.immutable and self.b != self.immutable['b'] * self.a)) \ - or (self.c is None or ('c' in self.immutable and self.c != self.immutable['c'] * self.b)) \ - or (self.alpha is None or ('alpha' in self.immutable and self.alpha != self.immutable['alpha'])) \ - or (self.beta is None or ( 'beta' in self.immutable and self.beta != self.immutable['beta'])) \ - or (self.gamma is None or ('gamma' in self.immutable and self.gamma != self.immutable['gamma'])): - raise ValueError (f'Incompatible parameters {self.parameters} for crystal family {self.family}') + self.ratio = l.ratio - if np.any(np.array([self.alpha,self.beta,self.gamma]) <= 0): - raise ValueError ('Lattice angles must be positive') - if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0] - > np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]): - raise ValueError ('Each lattice angle must be less than sum of others') + self.to_frame = l.to_frame + self.kinematics = l.kinematics + self.orientation_relationships = l.orientation_relationships else: raise KeyError(f'no valid family or lattice') @@ -590,12 +567,9 @@ class Orientation(Rotation): https://doi.org/10.1016/j.actamat.2004.11.021 """ - if model not in lattice_.relations: + if model not in self.orientation_relationships: raise KeyError(f'unknown orientation relationship "{model}"') - r = lattice_.relations[model] - - if self.lattice not in r: - raise KeyError(f'relationship "{model}" not supported for lattice "{self.lattice}"') + r = self.orientation_relationships[model] sl = self.lattice ol = (set(r)-{sl}).pop() @@ -640,50 +614,6 @@ class Orientation(Rotation): return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) - @property - def ratio(self): - """Return axes ratios of own lattice.""" - _ratio = { 'hexagonal': {'c': np.sqrt(8./3.)}} - - return dict(b = self.immutable['b'] - if 'b' in self.immutable else - _ratio[self.family]['b'] if self.family in _ratio and 'b' in _ratio[self.family] else None, - c = self.immutable['c'] - if 'c' in self.immutable else - _ratio[self.family]['c'] if self.family in _ratio and 'c' in _ratio[self.family] else None, - ) - - - @property - def basis_real(self): - """ - Calculate orthogonal real space crystal basis. - - References - ---------- - C.T. Young and J.L. Lytton, Journal of Applied Physics 43:1408–1417, 1972 - https://doi.org/10.1063/1.1661333 - - """ - if None in self.parameters: - raise KeyError('missing crystal lattice parameters') - return np.array([ - [1,0,0], - [np.cos(self.gamma),np.sin(self.gamma),0], - [np.cos(self.beta), - (np.cos(self.alpha)-np.cos(self.beta)*np.cos(self.gamma)) /np.sin(self.gamma), - np.sqrt(1 - np.cos(self.alpha)**2 - np.cos(self.beta)**2 - np.cos(self.gamma)**2 - + 2 * np.cos(self.alpha) * np.cos(self.beta) * np.cos(self.gamma))/np.sin(self.gamma)], - ],dtype=float).T \ - * np.array([self.a,self.b,self.c]) - - - @property - def basis_reciprocal(self): - """Calculate reciprocal (dual) crystal basis.""" - return np.linalg.inv(self.basis_real.T) - - def in_SST(self,vector,proper=False): """ Check whether given crystal frame vector falls into standard stereographic triangle of own symmetry. @@ -944,58 +874,6 @@ class Orientation(Rotation): ) - def to_lattice(self,*,direction=None,plane=None): - """ - Calculate lattice vector corresponding to crystal frame direction or plane normal. - - Parameters - ---------- - direction|normal : numpy.ndarray of shape (...,3) - Vector along direction or plane normal. - - Returns - ------- - Miller : numpy.ndarray of shape (...,3) - lattice vector of direction or plane. - Use util.scale_to_coprime to convert to (integer) Miller indices. - - """ - if (direction is not None) ^ (plane is None): - raise KeyError('specify either "direction" or "plane"') - axis,basis = (np.array(direction),self.basis_reciprocal.T) \ - if plane is None else \ - (np.array(plane),self.basis_real.T) - return np.einsum('il,...l',basis,axis) - - - def to_frame(self,*,uvw=None,hkl=None,with_symmetry=False): - """ - Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl). - - Parameters - ---------- - uvw|hkl : numpy.ndarray of shape (...,3) - Miller indices of crystallographic direction or plane normal. - with_symmetry : bool, optional - Calculate all N symmetrically equivalent vectors. - - Returns - ------- - vector : numpy.ndarray of shape (...,3) or (N,...,3) - Crystal frame vector (or vectors if with_symmetry) along [uvw] direction or (hkl) plane normal. - - """ - if (uvw is not None) ^ (hkl is None): - raise KeyError('specify either "uvw" or "hkl"') - axis,basis = (np.array(uvw),self.basis_real) \ - if hkl is None else \ - (np.array(hkl),self.basis_reciprocal) - return (self.symmetry_operations.broadcast_to(self.symmetry_operations.shape+axis.shape[:-1],mode='right') - @ np.broadcast_to(np.einsum('il,...l',basis,axis),self.symmetry_operations.shape+axis.shape) - if with_symmetry else - np.einsum('il,...l',basis,axis)) - - def to_pole(self,*,uvw=None,hkl=None,with_symmetry=False): """ Calculate lab frame vector along lattice direction [uvw] or plane normal (hkl). @@ -1013,7 +891,11 @@ class Orientation(Rotation): Lab frame vector (or vectors if with_symmetry) along [uvw] direction or (hkl) plane normal. """ - v = self.to_frame(uvw=uvw,hkl=hkl,with_symmetry=with_symmetry) + # ToDo: simplify 'with_symmetry' + v = self.to_frame(uvw=uvw,hkl=hkl) + if with_symmetry: + v = self.symmetry_operations.broadcast_to(self.symmetry_operations.shape+v.shape[:-1],mode='right') \ + @ np.broadcast_to(v,self.symmetry_operations.shape+v.shape) return ~(self if self.shape+v.shape[:-1] == () else self.broadcast_to(self.shape+v.shape[:-1],mode='right')) \ @ np.broadcast_to(v,self.shape+v.shape) @@ -1047,15 +929,10 @@ class Orientation(Rotation): """ try: - master = lattice_.kinematics[self.lattice][mode] - kinematics = {'direction':master[:,0:3],'plane':master[:,3:6]} \ - if master.shape[-1] == 6 else \ - {'direction':util.Bravais_to_Miller(uvtw=master[:,0:4]), - 'plane': util.Bravais_to_Miller(hkil=master[:,4:8])} + d = self.to_frame(uvw=self.kinematics(mode)['direction']) + p = self.to_frame(hkl=self.kinematics(mode)['plane']) except KeyError: raise (f'"{mode}" not defined for lattice "{self.lattice}"') - d = self.to_frame(uvw=kinematics['direction'],with_symmetry=False) - p = self.to_frame(hkl=kinematics['plane'] ,with_symmetry=False) P = np.einsum('...i,...j',d/np.linalg.norm(d,axis=-1,keepdims=True), p/np.linalg.norm(p,axis=-1,keepdims=True)) diff --git a/python/damask/lattice.py b/python/damask/lattice.py deleted file mode 100644 index 5b4621f3d..000000000 --- a/python/damask/lattice.py +++ /dev/null @@ -1,444 +0,0 @@ -import numpy as _np - -kinematics = { - 'cF': { - 'slip' : _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], - [+1,+1,+0 , +1,-1,+0], - [+1,-1,+0 , +1,+1,+0], - [+1,+0,+1 , +1,+0,-1], - [+1,+0,-1 , +1,+0,+1], - [+0,+1,+1 , +0,+1,-1], - [+0,+1,-1 , +0,+1,+1], - ],'d'), - 'twin' : _np.array([ - [-2, 1, 1, 1, 1, 1], - [ 1,-2, 1, 1, 1, 1], - [ 1, 1,-2, 1, 1, 1], - [ 2,-1, 1, -1,-1, 1], - [-1, 2, 1, -1,-1, 1], - [-1,-1,-2, -1,-1, 1], - [-2,-1,-1, 1,-1,-1], - [ 1, 2,-1, 1,-1,-1], - [ 1,-1, 2, 1,-1,-1], - [ 2, 1,-1, -1, 1,-1], - [-1,-2,-1, -1, 1,-1], - [-1, 1, 2, -1, 1,-1], - ],dtype=float), - }, - 'cI': { - 'slip' : _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 , +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,+0], - [+1,+1,-1 , -1,+1,+0], - [-1,+1,+1 , +2,+1,+1], - [+1,+1,+1 , -2,+1,+1], - [+1,+1,-1 , +2,-1,+1], - [+1,-1,+1 , +2,+1,-1], - [+1,-1,+1 , +1,+2,+1], - [+1,+1,-1 , -1,+2,+1], - [+1,+1,+1 , +1,-2,+1], - [-1,+1,+1 , +1,+2,-1], - [+1,+1,-1 , +1,+1,+2], - [+1,-1,+1 , -1,+1,+2], - [-1,+1,+1 , +1,-1,+2], - [+1,+1,+1 , +1,+1,-2], - [+1,+1,-1 , +1,+2,+3], - [+1,-1,+1 , -1,+2,+3], - [-1,+1,+1 , +1,-2,+3], - [+1,+1,+1 , +1,+2,-3], - [+1,-1,+1 , +1,+3,+2], - [+1,+1,-1 , -1,+3,+2], - [+1,+1,+1 , +1,-3,+2], - [-1,+1,+1 , +1,+3,-2], - [+1,+1,-1 , +2,+1,+3], - [+1,-1,+1 , -2,+1,+3], - [-1,+1,+1 , +2,-1,+3], - [+1,+1,+1 , +2,+1,-3], - [+1,-1,+1 , +2,+3,+1], - [+1,+1,-1 , -2,+3,+1], - [+1,+1,+1 , +2,-3,+1], - [-1,+1,+1 , +2,+3,-1], - [-1,+1,+1 , +3,+1,+2], - [+1,+1,+1 , -3,+1,+2], - [+1,+1,-1 , +3,-1,+2], - [+1,-1,+1 , +3,+1,-2], - [-1,+1,+1 , +3,+2,+1], - [+1,+1,+1 , -3,+2,+1], - [+1,+1,-1 , +3,-2,+1], - [+1,-1,+1 , +3,+2,-1], - ],'d'), - 'twin' : _np.array([ - [-1, 1, 1, 2, 1, 1], - [ 1, 1, 1, -2, 1, 1], - [ 1, 1,-1, 2,-1, 1], - [ 1,-1, 1, 2, 1,-1], - [ 1,-1, 1, 1, 2, 1], - [ 1, 1,-1, -1, 2, 1], - [ 1, 1, 1, 1,-2, 1], - [-1, 1, 1, 1, 2,-1], - [ 1, 1,-1, 1, 1, 2], - [ 1,-1, 1, -1, 1, 2], - [-1, 1, 1, 1,-1, 2], - [ 1, 1, 1, 1, 1,-2], - ],dtype=float), - }, - 'hP': { - 'slip' : _np.array([ - [+2,-1,-1,+0 , +0,+0,+0,+1], - [-1,+2,-1,+0 , +0,+0,+0,+1], - [-1,-1,+2,+0 , +0,+0,+0,+1], - [+2,-1,-1,+0 , +0,+1,-1,+0], - [-1,+2,-1,+0 , -1,+0,+1,+0], - [-1,-1,+2,+0 , +1,-1,+0,+0], - [-1,+1,+0,+0 , +1,+1,-2,+0], - [+0,-1,+1,+0 , -2,+1,+1,+0], - [+1,+0,-1,+0 , +1,-2,+1,+0], - [-1,+2,-1,+0 , +1,+0,-1,+1], - [-2,+1,+1,+0 , +0,+1,-1,+1], - [-1,-1,+2,+0 , -1,+1,+0,+1], - [+1,-2,+1,+0 , -1,+0,+1,+1], - [+2,-1,-1,+0 , +0,-1,+1,+1], - [+1,+1,-2,+0 , +1,-1,+0,+1], - [-2,+1,+1,+3 , +1,+0,-1,+1], - [-1,-1,+2,+3 , +1,+0,-1,+1], - [-1,-1,+2,+3 , +0,+1,-1,+1], - [+1,-2,+1,+3 , +0,+1,-1,+1], - [+1,-2,+1,+3 , -1,+1,+0,+1], - [+2,-1,-1,+3 , -1,+1,+0,+1], - [+2,-1,-1,+3 , -1,+0,+1,+1], - [+1,+1,-2,+3 , -1,+0,+1,+1], - [+1,+1,-2,+3 , +0,-1,+1,+1], - [-1,+2,-1,+3 , +0,-1,+1,+1], - [-1,+2,-1,+3 , +1,-1,+0,+1], - [-2,+1,+1,+3 , +1,-1,+0,+1], - [-1,-1,+2,+3 , +1,+1,-2,+2], - [+1,-2,+1,+3 , -1,+2,-1,+2], - [+2,-1,-1,+3 , -2,+1,+1,+2], - [+1,+1,-2,+3 , -1,-1,+2,+2], - [-1,+2,-1,+3 , +1,-2,+1,+2], - [-2,+1,+1,+3 , +2,-1,-1,+2], - ],'d'), - 'twin' : _np.array([ - [-1, 0, 1, 1, 1, 0, -1, 2], # shear = (3-(c/a)^2)/(sqrt(3) c/a) <-10.1>{10.2} - [ 0, -1, 1, 1, 0, 1, -1, 2], - [ 1, -1, 0, 1, -1, 1, 0, 2], - [ 1, 0, -1, 1, -1, 0, 1, 2], - [ 0, 1, -1, 1, 0, -1, 1, 2], - [-1, 1, 0, 1, 1, -1, 0, 2], - [-1, -1, 2, 6, 1, 1, -2, 1], # shear = 1/(c/a) <11.6>{-1-1.1} - [ 1, -2, 1, 6, -1, 2, -1, 1], - [ 2, -1, -1, 6, -2, 1, 1, 1], - [ 1, 1, -2, 6, -1, -1, 2, 1], - [-1, 2, -1, 6, 1, -2, 1, 1], - [-2, 1, 1, 6, 2, -1, -1, 1], - [ 1, 0, -1, -2, 1, 0, -1, 1], # shear = (4(c/a)^2-9)/(4 sqrt(3) c/a) <10.-2>{10.1} - [ 0, 1, -1, -2, 0, 1, -1, 1], - [-1, 1, 0, -2, -1, 1, 0, 1], - [-1, 0, 1, -2, -1, 0, 1, 1], - [ 0, -1, 1, -2, 0, -1, 1, 1], - [ 1, -1, 0, -2, 1, -1, 0, 1], - [ 1, 1, -2, -3, 1, 1, -2, 2], # shear = 2((c/a)^2-2)/(3 c/a) <11.-3>{11.2} - [-1, 2, -1, -3, -1, 2, -1, 2], - [-2, 1, 1, -3, -2, 1, 1, 2], - [-1, -1, 2, -3, -1, -1, 2, 2], - [ 1, -2, 1, -3, 1, -2, 1, 2], - [ 2, -1, -1, -3, 2, -1, -1, 2], - ],dtype=float), - }, -} - -# 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 - -relations = { - 'KS': { - 'cF' : _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), - 'cI' : _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), - }, - 'GT': { - 'cF' : _np.array([ - [[ -5,-12, 17],[ 1, 1, 1]], - [[ 17, -5,-12],[ 1, 1, 1]], - [[-12, 17, -5],[ 1, 1, 1]], - [[ 5, 12, 17],[ -1, -1, 1]], - [[-17, 5,-12],[ -1, -1, 1]], - [[ 12,-17, -5],[ -1, -1, 1]], - [[ -5, 12,-17],[ -1, 1, 1]], - [[ 17, 5, 12],[ -1, 1, 1]], - [[-12,-17, 5],[ -1, 1, 1]], - [[ 5,-12,-17],[ 1, -1, 1]], - [[-17, -5, 12],[ 1, -1, 1]], - [[ 12, 17, 5],[ 1, -1, 1]], - [[ -5, 17,-12],[ 1, 1, 1]], - [[-12, -5, 17],[ 1, 1, 1]], - [[ 17,-12, -5],[ 1, 1, 1]], - [[ 5,-17,-12],[ -1, -1, 1]], - [[ 12, 5, 17],[ -1, -1, 1]], - [[-17, 12, -5],[ -1, -1, 1]], - [[ -5,-17, 12],[ -1, 1, 1]], - [[-12, 5,-17],[ -1, 1, 1]], - [[ 17, 12, 5],[ -1, 1, 1]], - [[ 5, 17, 12],[ 1, -1, 1]], - [[ 12, -5,-17],[ 1, -1, 1]], - [[-17,-12, 5],[ 1, -1, 1]], - ],dtype=float), - 'cI' : _np.array([ - [[-17, -7, 17],[ 1, 0, 1]], - [[ 17,-17, -7],[ 1, 1, 0]], - [[ -7, 17,-17],[ 0, 1, 1]], - [[ 17, 7, 17],[ -1, 0, 1]], - [[-17, 17, -7],[ -1, -1, 0]], - [[ 7,-17,-17],[ 0, -1, 1]], - [[-17, 7,-17],[ -1, 0, 1]], - [[ 17, 17, 7],[ -1, 1, 0]], - [[ -7,-17, 17],[ 0, 1, 1]], - [[ 17, -7,-17],[ 1, 0, 1]], - [[-17,-17, 7],[ 1, -1, 0]], - [[ 7, 17, 17],[ 0, -1, 1]], - [[-17, 17, -7],[ 1, 1, 0]], - [[ -7,-17, 17],[ 0, 1, 1]], - [[ 17, -7,-17],[ 1, 0, 1]], - [[ 17,-17, -7],[ -1, -1, 0]], - [[ 7, 17, 17],[ 0, -1, 1]], - [[-17, 7,-17],[ -1, 0, 1]], - [[-17,-17, 7],[ -1, 1, 0]], - [[ -7, 17,-17],[ 0, 1, 1]], - [[ 17, 7, 17],[ -1, 0, 1]], - [[ 17, 17, 7],[ 1, -1, 0]], - [[ 7,-17,-17],[ 0, -1, 1]], - [[-17, -7, 17],[ 1, 0, 1]], - ],dtype=float), - }, - 'GT_prime': { - 'cF' : _np.array([ - [[ 0, 1, -1],[ 7, 17, 17]], - [[ -1, 0, 1],[ 17, 7, 17]], - [[ 1, -1, 0],[ 17, 17, 7]], - [[ 0, -1, -1],[ -7,-17, 17]], - [[ 1, 0, 1],[-17, -7, 17]], - [[ 1, -1, 0],[-17,-17, 7]], - [[ 0, 1, -1],[ 7,-17,-17]], - [[ 1, 0, 1],[ 17, -7,-17]], - [[ -1, -1, 0],[ 17,-17, -7]], - [[ 0, -1, -1],[ -7, 17,-17]], - [[ -1, 0, 1],[-17, 7,-17]], - [[ -1, -1, 0],[-17, 17, -7]], - [[ 0, -1, 1],[ 7, 17, 17]], - [[ 1, 0, -1],[ 17, 7, 17]], - [[ -1, 1, 0],[ 17, 17, 7]], - [[ 0, 1, 1],[ -7,-17, 17]], - [[ -1, 0, -1],[-17, -7, 17]], - [[ -1, 1, 0],[-17,-17, 7]], - [[ 0, -1, 1],[ 7,-17,-17]], - [[ -1, 0, -1],[ 17, -7,-17]], - [[ 1, 1, 0],[ 17,-17, -7]], - [[ 0, 1, 1],[ -7, 17,-17]], - [[ 1, 0, -1],[-17, 7,-17]], - [[ 1, 1, 0],[-17, 17, -7]], - ],dtype=float), - 'cI' : _np.array([ - [[ 1, 1, -1],[ 12, 5, 17]], - [[ -1, 1, 1],[ 17, 12, 5]], - [[ 1, -1, 1],[ 5, 17, 12]], - [[ -1, -1, -1],[-12, -5, 17]], - [[ 1, -1, 1],[-17,-12, 5]], - [[ 1, -1, -1],[ -5,-17, 12]], - [[ -1, 1, -1],[ 12, -5,-17]], - [[ 1, 1, 1],[ 17,-12, -5]], - [[ -1, -1, 1],[ 5,-17,-12]], - [[ 1, -1, -1],[-12, 5,-17]], - [[ -1, -1, 1],[-17, 12, -5]], - [[ -1, -1, -1],[ -5, 17,-12]], - [[ 1, -1, 1],[ 12, 17, 5]], - [[ 1, 1, -1],[ 5, 12, 17]], - [[ -1, 1, 1],[ 17, 5, 12]], - [[ -1, 1, 1],[-12,-17, 5]], - [[ -1, -1, -1],[ -5,-12, 17]], - [[ -1, 1, -1],[-17, -5, 12]], - [[ -1, -1, 1],[ 12,-17, -5]], - [[ -1, 1, -1],[ 5,-12,-17]], - [[ 1, 1, 1],[ 17, -5,-12]], - [[ 1, 1, 1],[-12, 17, -5]], - [[ 1, -1, -1],[ -5, 12,-17]], - [[ 1, 1, -1],[-17, 5,-12]], - ],dtype=float), - }, - 'NW': { - 'cF' : _np.array([ - [[ 2, -1, -1],[ 1, 1, 1]], - [[ -1, 2, -1],[ 1, 1, 1]], - [[ -1, -1, 2],[ 1, 1, 1]], - [[ -2, -1, -1],[ -1, 1, 1]], - [[ 1, 2, -1],[ -1, 1, 1]], - [[ 1, -1, 2],[ -1, 1, 1]], - [[ 2, 1, -1],[ 1, -1, 1]], - [[ -1, -2, -1],[ 1, -1, 1]], - [[ -1, 1, 2],[ 1, -1, 1]], - [[ 2, -1, 1],[ -1, -1, 1]], - [[ -1, 2, 1],[ -1, -1, 1]], - [[ -1, -1, -2],[ -1, -1, 1]], - ],dtype=float), - 'cI' : _np.array([ - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - [[ 0, -1, 1],[ 0, 1, 1]], - ],dtype=float), - }, - 'Pitsch': { - 'cF' : _np.array([ - [[ 1, 0, 1],[ 0, 1, 0]], - [[ 1, 1, 0],[ 0, 0, 1]], - [[ 0, 1, 1],[ 1, 0, 0]], - [[ 0, 1, -1],[ 1, 0, 0]], - [[ -1, 0, 1],[ 0, 1, 0]], - [[ 1, -1, 0],[ 0, 0, 1]], - [[ 1, 0, -1],[ 0, 1, 0]], - [[ -1, 1, 0],[ 0, 0, 1]], - [[ 0, -1, 1],[ 1, 0, 0]], - [[ 0, 1, 1],[ 1, 0, 0]], - [[ 1, 0, 1],[ 0, 1, 0]], - [[ 1, 1, 0],[ 0, 0, 1]], - ],dtype=float), - 'cI' : _np.array([ - [[ 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],[ -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]], - ],dtype=float), - }, - 'Bain': { - 'cF' : _np.array([ - [[ 0, 1, 0],[ 1, 0, 0]], - [[ 0, 0, 1],[ 0, 1, 0]], - [[ 1, 0, 0],[ 0, 0, 1]], - ],dtype=float), - 'cI' : _np.array([ - [[ 0, 1, 1],[ 1, 0, 0]], - [[ 1, 0, 1],[ 0, 1, 0]], - [[ 1, 1, 0],[ 0, 0, 1]], - ],dtype=float), - }, - 'Burgers' : { - 'cI' : _np.array([ - [[ -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, 0, 1]], - [[ -1, 1, 1],[ 1, 0, 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],[ 0, -1, 1]], - [[ 1, 1, 1],[ 0, -1, 1]], - ],dtype=float), - 'hP' : _np.array([ - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - [[ -1, 2, -1, 0],[ 0, 0, 0, 1]], - [[ -1, -1, 2, 0],[ 0, 0, 0, 1]], - ],dtype=float), - }, -} diff --git a/python/tests/test_Lattice.py b/python/tests/test_Lattice.py new file mode 100644 index 000000000..c9593301c --- /dev/null +++ b/python/tests/test_Lattice.py @@ -0,0 +1,64 @@ +import pytest +import numpy as np + +from damask import Lattice + +class TestLattice: + + def test_double_to_lattice(self): + L = Lattice('cF') + with pytest.raises(KeyError): + L.to_lattice(direction=np.ones(3),plane=np.ones(3)) + + def test_double_to_frame(self): + L = Lattice('cF') + with pytest.raises(KeyError): + L.to_frame(uvw=np.ones(3),hkl=np.ones(3)) + + @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma', + [ + ('aP',0.5,2.0,3.0,0.8,0.5,1.2), + ('mP',1.0,2.0,3.0,np.pi/2,0.5,np.pi/2), + ('oI',0.5,1.5,3.0,np.pi/2,np.pi/2,np.pi/2), + ('tP',0.5,0.5,3.0,np.pi/2,np.pi/2,np.pi/2), + ('hP',1.0,None,1.6,np.pi/2,np.pi/2,2*np.pi/3), + ('cF',1.0,1.0,None,np.pi/2,np.pi/2,np.pi/2), + ]) + def test_bases_contraction(self,lattice,a,b,c,alpha,beta,gamma): + L = Lattice(lattice=lattice, + a=a,b=b,c=c, + alpha=alpha,beta=beta,gamma=gamma) + assert np.allclose(np.eye(3),np.einsum('ik,jk',L.basis_real,L.basis_reciprocal)) + + + @pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),]) + @pytest.mark.parametrize('vector',np.array([ + [1.,1.,1.], + [-2.,3.,0.5], + [0.,0.,1.], + [1.,1.,1.], + [2.,2.,2.], + [0.,1.,1.], + ])) + @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma', + [ + ('aP',0.5,2.0,3.0,0.8,0.5,1.2), + ('mP',1.0,2.0,3.0,np.pi/2,0.5,np.pi/2), + ('oI',0.5,1.5,3.0,np.pi/2,np.pi/2,np.pi/2), + ('tP',0.5,0.5,3.0,np.pi/2,np.pi/2,np.pi/2), + ('hP',1.0,1.0,1.6,np.pi/2,np.pi/2,2*np.pi/3), + ('cF',1.0,1.0,1.0,np.pi/2,np.pi/2,np.pi/2), + ]) + def test_to_frame_to_lattice(self,lattice,a,b,c,alpha,beta,gamma,vector,keyFrame,keyLattice): + L = Lattice(lattice=lattice, + a=a,b=b,c=c, + alpha=alpha,beta=beta,gamma=gamma) + assert np.allclose(vector, + L.to_frame(**{keyFrame:L.to_lattice(**{keyLattice:vector})})) + + + @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch','Burgers']) + def test_relationship_definition(self,model): + m,o = list(Lattice._orientation_relationships[model]) + assert Lattice._orientation_relationships[model][m].shape[:-1] == \ + Lattice._orientation_relationships[model][o].shape[:-1] diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 471dada58..a1302bcb7 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -7,7 +7,6 @@ from damask import Orientation from damask import Table from damask import util from damask import grid_filters -from damask import lattice from damask import _orientation crystal_families = set(_orientation.lattice_symmetries.values()) @@ -341,29 +340,6 @@ class TestOrientation: with pytest.raises(KeyError): Orientation(family=invalid_family) - def test_invalid_rot(self): - with pytest.raises(TypeError): - Orientation.from_random(family='cubic') * np.ones(3) - - def test_missing_symmetry_immutable(self): - with pytest.raises(KeyError): - Orientation(lattice=None).immutable # noqa - - def test_missing_symmetry_basis_real(self): - with pytest.raises(KeyError): - Orientation(lattice=None).basis_real # noqa - - def test_missing_symmetry_basis_reciprocal(self): - with pytest.raises(KeyError): - Orientation(lattice=None).basis_reciprocal # noqa - - def test_double_to_lattice(self): - with pytest.raises(KeyError): - Orientation().to_lattice(direction=np.ones(3),plane=np.ones(3)) # noqa - - def test_double_to_frame(self): - with pytest.raises(KeyError): - Orientation().to_frame(uvw=np.ones(3),hkl=np.ones(3)) # noqa @pytest.mark.parametrize('relation',[None,'Peter','Paul']) def test_unknown_relation(self,relation): @@ -395,12 +371,6 @@ class TestOrientation: o = Orientation(family='cubic') # noqa with pytest.raises(ValueError): eval(f'o.{function}(np.ones(4))') - - @pytest.mark.parametrize('model',lattice.relations) - def test_relationship_definition(self,model): - m,o = list(lattice.relations[model]) - assert lattice.relations[model][m].shape[:-1] == lattice.relations[model][o].shape[:-1] - @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch']) @pytest.mark.parametrize('lattice',['cF','cI']) def test_relationship_vectorize(self,set_of_quaternions,lattice,model): @@ -441,46 +411,6 @@ class TestOrientation: ) assert np.allclose(o.to_frame(uvw=np.eye(3)),basis), 'Lattice basis disagrees with initialization' - @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma', - [ - ('aP',0.5,2.0,3.0,0.8,0.5,1.2), - ('mP',1.0,2.0,3.0,np.pi/2,0.5,np.pi/2), - ('oI',0.5,1.5,3.0,np.pi/2,np.pi/2,np.pi/2), - ('tP',0.5,0.5,3.0,np.pi/2,np.pi/2,np.pi/2), - ('hP',1.0,None,1.6,np.pi/2,np.pi/2,2*np.pi/3), - ('cF',1.0,1.0,None,np.pi/2,np.pi/2,np.pi/2), - ]) - def test_bases_contraction(self,lattice,a,b,c,alpha,beta,gamma): - L = Orientation(lattice=lattice, - a=a,b=b,c=c, - alpha=alpha,beta=beta,gamma=gamma) - assert np.allclose(np.eye(3),np.einsum('ik,jk',L.basis_real,L.basis_reciprocal)) - - @pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),]) - @pytest.mark.parametrize('vector',np.array([ - [1.,1.,1.], - [-2.,3.,0.5], - [0.,0.,1.], - [1.,1.,1.], - [2.,2.,2.], - [0.,1.,1.], - ])) - @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma', - [ - ('aP',0.5,2.0,3.0,0.8,0.5,1.2), - ('mP',1.0,2.0,3.0,np.pi/2,0.5,np.pi/2), - ('oI',0.5,1.5,3.0,np.pi/2,np.pi/2,np.pi/2), - ('tP',0.5,0.5,3.0,np.pi/2,np.pi/2,np.pi/2), - ('hP',1.0,1.0,1.6,np.pi/2,np.pi/2,2*np.pi/3), - ('cF',1.0,1.0,1.0,np.pi/2,np.pi/2,np.pi/2), - ]) - def test_to_frame_to_lattice(self,lattice,a,b,c,alpha,beta,gamma,vector,keyFrame,keyLattice): - L = Orientation(lattice=lattice, - a=a,b=b,c=c, - alpha=alpha,beta=beta,gamma=gamma) - assert np.allclose(vector, - L.to_frame(**{keyFrame:L.to_lattice(**{keyLattice:vector})})) - @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma', [