From 3c8d06b6f19e4e122878c2e688c2422984efd907 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Jun 2021 10:18:27 +0200 Subject: [PATCH] encapsulating all lattice(-family) related data --- python/damask/_orientation.py | 94 +++++++++++--------------------- python/tests/test_Orientation.py | 2 +- 2 files changed, 33 insertions(+), 63 deletions(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index d661dd475..9edacd790 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -1,4 +1,5 @@ import inspect +import copy import numpy as np @@ -135,37 +136,11 @@ class Orientation(Rotation): if family in set(lattice_symmetries.values()) and lattice is None: self.family = family self.lattice = None - - self.structure = l = LatticeFamily(self.family) # noqa - self.immutable = l.immutable - self.basis = l.basis - - self.a = self.b = self.c = None - self.alpha = self.beta = self.gamma = None - + self.structure = LatticeFamily(self.family) elif lattice in lattice_symmetries: - self.family = lattice_symmetries[lattice] self.lattice = lattice - - self.structure = l = Lattice(self.lattice, a,b,c, alpha,beta,gamma, degrees) # noqa - self.immutable = l.immutable - self.basis = l.basis - - self.a = l.a - self.b = l.b - self.c = l.c - - self.alpha = l.alpha - self.beta = l.beta - self.gamma = l.gamma - - self.ratio = l.ratio - - self.to_frame = l.to_frame - - self.kinematics = l.kinematics - self.relation_operations = l.relation_operations + self.structure = l = Lattice(self.lattice, a,b,c, alpha,beta,gamma, degrees) else: raise KeyError(f'no valid family or lattice') @@ -177,18 +152,12 @@ class Orientation(Rotation): + [super().__repr__()]) - def __copy__(self,**kwargs): + def __copy__(self,rotation=None): """Create deep copy.""" - return self.__class__(rotation= kwargs['rotation'] if 'rotation' in kwargs else self.quaternion, - family = kwargs['family'] if 'family' in kwargs else self.family, - lattice = kwargs['lattice'] if 'lattice' in kwargs else self.lattice, - a = kwargs['a'] if 'a' in kwargs else self.a, - b = kwargs['b'] if 'b' in kwargs else self.b, - c = kwargs['c'] if 'c' in kwargs else self.c, - alpha = kwargs['alpha'] if 'alpha' in kwargs else self.alpha, - beta = kwargs['beta'] if 'beta' in kwargs else self.beta, - gamma = kwargs['gamma'] if 'gamma' in kwargs else self.gamma, - ) + dup = copy.deepcopy(self) + if rotation is not None: + dup.quaternion = Orientation(rotation,family='cubic').quaternion + return dup copy = __copy__ @@ -415,8 +384,8 @@ class Orientation(Rotation): """ o = cls(**kwargs) - x = o.to_frame(uvw=uvw) - z = o.to_frame(hkl=hkl) + x = o.structure.to_frame(uvw=uvw) + z = o.structure.to_frame(hkl=hkl) om = np.stack([x,np.cross(z,x),z],axis=-2) return o.copy(rotation=Rotation.from_matrix(tensor.transpose(om/np.linalg.norm(om,axis=-1,keepdims=True)))) @@ -707,21 +676,21 @@ class Orientation(Rotation): if not isinstance(vector,np.ndarray) or vector.shape[-1] != 3: raise ValueError('input is not a field of three-dimensional vectors') - if self.basis is None: # direct exit for no symmetry + if self.structure.basis is None: # direct exit for no symmetry return np.ones_like(vector[...,0],bool) if proper: components_proper = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['proper'], vector.shape+(3,)), + np.broadcast_to(self.structure.basis['proper'], vector.shape+(3,)), vector), 12) components_improper = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['improper'], vector.shape+(3,)), + np.broadcast_to(self.structure.basis['improper'], vector.shape+(3,)), vector), 12) return np.all(components_proper >= 0.0,axis=-1) \ | np.all(components_improper >= 0.0,axis=-1) else: components = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['improper'], vector.shape+(3,)), + np.broadcast_to(self.structure.basis['improper'], vector.shape+(3,)), np.block([vector[...,:2],np.abs(vector[...,2:3])])), 12) return np.all(components >= 0.0,axis=-1) @@ -762,15 +731,15 @@ class Orientation(Rotation): vector_ = self.to_SST(vector,proper) if in_SST else \ self @ np.broadcast_to(vector,self.shape+(3,)) - if self.basis is None: # direct exit for no symmetry + if self.structure.basis is None: # direct exit for no symmetry return np.zeros_like(vector_) if proper: components_proper = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['proper'], vector_.shape+(3,)), + np.broadcast_to(self.structure.basis['proper'], vector_.shape+(3,)), vector_), 12) components_improper = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['improper'], vector_.shape+(3,)), + np.broadcast_to(self.structure.basis['improper'], vector_.shape+(3,)), vector_), 12) in_SST = np.all(components_proper >= 0.0,axis=-1) \ | np.all(components_improper >= 0.0,axis=-1) @@ -778,7 +747,7 @@ class Orientation(Rotation): components_proper,components_improper) else: components = np.around(np.einsum('...ji,...i', - np.broadcast_to(self.basis['improper'], vector_.shape+(3,)), + np.broadcast_to(self.structure.basis['improper'], vector_.shape+(3,)), np.block([vector_[...,:2],np.abs(vector_[...,2:3])])), 12) in_SST = np.all(components >= 0.0,axis=-1) @@ -813,7 +782,7 @@ class Orientation(Rotation): """ sym_ops = self.structure.symmetry_operations # ToDo: simplify 'with_symmetry' - v = self.to_frame(uvw=uvw,hkl=hkl) + v = self.structure.to_frame(uvw=uvw,hkl=hkl) if with_symmetry: v = sym_ops.broadcast_to(sym_ops.shape+v.shape[:-1],mode='right') \ @ np.broadcast_to(v,sym_ops.shape+v.shape) @@ -850,8 +819,8 @@ class Orientation(Rotation): """ try: - d = self.to_frame(uvw=self.kinematics(mode)['direction']) - p = self.to_frame(hkl=self.kinematics(mode)['plane']) + d = self.structure.to_frame(uvw=self.structure.kinematics(mode)['direction']) + p = self.structure.to_frame(hkl=self.structure.kinematics(mode)['plane']) except KeyError: raise (f'"{mode}" not defined for lattice "{self.lattice}"') P = np.einsum('...i,...j',d/np.linalg.norm(d,axis=-1,keepdims=True), @@ -869,14 +838,15 @@ class Orientation(Rotation): is added to the left of the Rotation array. """ - lattice,o = self.relation_operations(model) - target = Orientation(lattice=lattice) + lattice,o = self.structure.relation_operations(model) + target = Lattice(lattice=lattice) + struct = self.structure o = o.broadcast_to(o.shape+self.shape,mode='right') - return self.copy(rotation=o*Rotation(self.quaternion).broadcast_to(o.shape,mode='left'), - lattice=lattice, - b = self.b if target.ratio['b'] is None else self.a*target.ratio['b'], - c = self.c if target.ratio['c'] is None else self.a*target.ratio['c'], - alpha = None if 'alpha' in target.immutable else self.alpha, - beta = None if 'beta' in target.immutable else self.beta, - gamma = None if 'gamma' in target.immutable else self.gamma, - ) + return Orientation(rotation=o*Rotation(self.quaternion).broadcast_to(o.shape,mode='left'), + lattice=lattice, + b = struct.b if target.ratio['b'] is None else struct.a*target.ratio['b'], + c = struct.c if target.ratio['c'] is None else struct.a*target.ratio['c'], + alpha = None if 'alpha' in target.immutable else struct.alpha, + beta = None if 'beta' in target.immutable else struct.beta, + gamma = None if 'gamma' in target.immutable else struct.gamma, + ) diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index ced7022f1..5317ada19 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -409,7 +409,7 @@ class TestOrientation: **dict(zip(['a','b','c'],lengths)), **dict(zip(['alpha','beta','gamma'],np.arccos(cosines))), ) - assert np.allclose(o.to_frame(uvw=np.eye(3)),basis), 'Lattice basis disagrees with initialization' + assert np.allclose(o.structure.to_frame(uvw=np.eye(3)),basis), 'Lattice basis disagrees with initialization' @pytest.mark.parametrize('lattice,a,b,c,alpha,beta,gamma',