def seeds_from_random(size, num_grains, phase_label, grid_size=None, orientation_coordinate_system=None): from damask import seeds from damask import Rotation size = np.array(size) grid_size = grid_size and np.array(grid_size) position = seeds.from_random(size, num_grains, cells=grid_size) rotation = Rotation.from_random(shape=(num_grains,)) out = { 'microstructure_seeds': { 'position': position, 'orientations': { 'type': 'quat', 'quaternions': rotation.quaternion, 'orientation_coordinate_system': orientation_coordinate_system, 'unit_cell_alignment': { 'x': 'a', 'z': 'c', }, 'P': -1, }, 'size': size, 'random_seed': None, 'phase_label': phase_label, } } return out
def test_IPF(self, lattice): direction = np.random.random(3) * 2.0 - 1 for rot in [Rotation.from_random() for r in range(n // 100)]: R = damask.Orientation(rot, lattice) color = R.IPFcolor(direction) for equivalent in R.equivalentOrientations(): assert np.allclose(color, R.IPFcolor(direction))
def test_add_primitive_rotation(self,center,inverse,periodic): """Rotation should not change result for sphere.""" g = np.random.randint(8,32,(3)) s = np.random.random(3)+.5 fill = np.random.randint(10)+2 G_1 = Grid(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,inverse=inverse,periodic=periodic) G_2 = Grid(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,Rotation.from_random(),inverse,periodic=periodic) assert grid_equal(G_1,G_2)
def test_broadcast(self, shape): rot = Rotation.from_random(shape) new_shape = tuple(np.random.randint(8,32,(3))) if shape is None else \ rot.shape + (np.random.randint(8,32),) rot_broadcast = rot.broadcast_to(tuple(new_shape)) for i in range(rot_broadcast.shape[-1]): assert np.allclose(rot_broadcast.quaternion[..., i, :], rot.quaternion)
def test_vectorize_rotation(self): epsilon = Rotation.from_random(self.n).as_matrix() epsilon_vec = np.reshape(epsilon, (self.n // 10, 10, 3, 3)) for i, v in enumerate( np.reshape( mechanics.rotation(epsilon_vec).as_matrix(), mechanics.rotation(epsilon).as_matrix().shape)): assert np.allclose(rotation(epsilon[i]), v)
def test_spherical_component(self, N, sigma): p = [] for run in range(5): c = Rotation.from_random() o = Rotation.from_spherical_component(c, sigma, N) _, angles = c.misorientation(o).as_axis_angle(pair=True, degrees=True) angles[:: 2] *= -1 # flip angle for every second to symmetrize distribution p.append(stats.normaltest(angles)[1]) sigma_out = np.std(angles) p = np.average(p) assert (.9 < sigma / sigma_out < 1.1) and p > 1e-2, f'{sigma/sigma_out},{p}'
def test_rotate_inverse_array(self, data): R = Rotation.from_random() assert np.allclose(data, ~R @ (R @ data))
def test_rotate_inverse(self): R = Rotation.from_random() assert np.allclose(np.eye(3), (~R @ R).as_matrix())
def test_strain_rotation(self, m, t): """Ensure that pure rotation results in no strain.""" F = Rotation.from_random(self.n).as_matrix() assert np.allclose(mechanics.strain(F, t, m), 0.0)
def test_unequal(self, lattice, shape): R = Rotation.from_random(shape) assert not ( Orientation(R,lattice) != Orientation(R,lattice) if shape is None else \ (Orientation(R,lattice) != Orientation(R,lattice)).any())
def test_equal(self, family, shape): R = Rotation.from_random(shape) assert Orientation(R,family=family) == Orientation(R,family=family) if shape is None else \ (Orientation(R,family=family) == Orientation(R,family=family)).all()
def test_invalid_P(self, fr, to): R = Rotation.from_random(np.random.randint(8, 32, (3))) # noqa with pytest.raises(ValueError): fr(eval(f'R.{to}()'), P=-30)
def test_rotate_invalid_type(self, data): R = Rotation.from_random() with pytest.raises(TypeError): R * data
def test_relationship_forward_backward(self, model, lattice): ori = Orientation(Rotation.from_random(), lattice) for i, r in enumerate(ori.relatedOrientations(model)): ori2 = r.relatedOrientations(model)[i] misorientation = ori.rotation.misorientation(ori2.rotation) assert misorientation.asAxisAngle(degrees=True)[3] < 1.0e-5
def test_unequal(self, family, shape): R = Rotation.from_random(shape) assert not ( Orientation(R,family=family) != Orientation(R,family=family) if shape is None else \ (Orientation(R,family=family) != Orientation(R,family=family)).any())
def test_rotate_inverse(self, data): R = Rotation.from_random() assert np.allclose(data, R.inversed() * (R * data))
def test_from_average(self, lattice): R_1 = Orientation(Rotation.from_random(), lattice) eqs = [r for r in R_1.equivalent] R_2 = Orientation.from_average(eqs) assert np.allclose(R_1.rotation.quaternion, R_2.rotation.quaternion)
def default(): """A set of n random rotations.""" specials = np.array([ [1.0, 0.0, 0.0, 0.0], #---------------------- [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, -1.0], #---------------------- [1.0, 1.0, 0.0, 0.0], [1.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 1.0], [0.0, 1.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0], [0.0, 0.0, 1.0, 1.0], #---------------------- [1.0, -1.0, 0.0, 0.0], [1.0, 0.0, -1.0, 0.0], [1.0, 0.0, 0.0, -1.0], [0.0, 1.0, -1.0, 0.0], [0.0, 1.0, 0.0, -1.0], [0.0, 0.0, 1.0, -1.0], #---------------------- [0.0, 1.0, -1.0, 0.0], [0.0, 1.0, 0.0, -1.0], [0.0, 0.0, 1.0, -1.0], #---------------------- [0.0, -1.0, -1.0, 0.0], [0.0, -1.0, 0.0, -1.0], [0.0, 0.0, -1.0, -1.0], #---------------------- [1.0, 1.0, 1.0, 0.0], [1.0, 1.0, 0.0, 1.0], [1.0, 0.0, 1.0, 1.0], [1.0, -1.0, 1.0, 0.0], [1.0, -1.0, 0.0, 1.0], [1.0, 0.0, -1.0, 1.0], [1.0, 1.0, -1.0, 0.0], [1.0, 1.0, 0.0, -1.0], [1.0, 0.0, 1.0, -1.0], [1.0, -1.0, -1.0, 0.0], [1.0, -1.0, 0.0, -1.0], [1.0, 0.0, -1.0, -1.0], #---------------------- [0.0, 1.0, 1.0, 1.0], [0.0, 1.0, -1.0, 1.0], [0.0, 1.0, 1.0, -1.0], [0.0, -1.0, 1.0, 1.0], [0.0, -1.0, -1.0, 1.0], [0.0, -1.0, 1.0, -1.0], [0.0, -1.0, -1.0, -1.0], #---------------------- [1.0, 1.0, 1.0, 1.0], [1.0, -1.0, 1.0, 1.0], [1.0, 1.0, -1.0, 1.0], [1.0, 1.0, 1.0, -1.0], [1.0, -1.0, -1.0, 1.0], [1.0, -1.0, 1.0, -1.0], [1.0, 1.0, -1.0, -1.0], [1.0, -1.0, -1.0, -1.0], ]) specials /= np.linalg.norm(specials, axis=1).reshape(-1, 1) specials_scatter = specials + np.broadcast_to( np.random.rand(4) * scatter, specials.shape) specials_scatter /= np.linalg.norm(specials_scatter, axis=1).reshape(-1, 1) specials_scatter[specials_scatter[:, 0] < 0] *= -1 return [Rotation.from_quaternion(s) for s in specials] + \ [Rotation.from_quaternion(s) for s in specials_scatter] + \ [Rotation.from_random() for _ in range(n-len(specials)-len(specials_scatter))]
def test_misorientation(self): R = Rotation.from_random() assert np.allclose(R.misorientation(R).as_matrix(), np.eye(3))
class TestConfigMaterial: @pytest.mark.parametrize('fname', [None, 'test.yaml']) def test_load_save(self, ref_path, tmp_path, fname): reference = ConfigMaterial.load(ref_path / 'material.yaml') os.chdir(tmp_path) if fname is None: reference.save() new = ConfigMaterial.load('material.yaml') else: reference.save(fname) new = ConfigMaterial.load(fname) assert reference == new def test_valid_complete(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') assert material_config.is_valid and material_config.is_complete def test_invalid_lattice(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') material_config['phase']['Aluminum']['lattice'] = 'fxc' assert not material_config.is_valid def test_invalid_orientation(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') material_config['material'][0]['constituents'][0]['O'] = [0, 0, 0, 0] assert not material_config.is_valid def test_invalid_fraction(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') material_config['material'][0]['constituents'][0]['v'] = .9 assert not material_config.is_valid @pytest.mark.parametrize('item', ['homogenization', 'phase', 'material']) def test_incomplete_missing(self, ref_path, item): material_config = ConfigMaterial.load(ref_path / 'material.yaml') del material_config[item] assert not material_config.is_complete @pytest.mark.parametrize('item', ['O', 'phase']) def test_incomplete_material_constituent(self, ref_path, item): material_config = ConfigMaterial.load(ref_path / 'material.yaml') del material_config['material'][0]['constituents'][0][item] assert not material_config.is_complete def test_incomplete_material_homogenization(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') del material_config['material'][0]['homogenization'] assert not material_config.is_complete def test_incomplete_homogenization_N_constituents(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') for h in material_config['homogenization'].keys(): del material_config['homogenization'][h]['N_constituents'] assert not material_config.is_complete def test_incomplete_phase_lattice(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') del material_config['phase']['Aluminum']['lattice'] assert not material_config.is_complete def test_incomplete_wrong_phase(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') new = material_config.material_rename_phase({'Steel': 'FeNbC'}) assert not new.is_complete def test_incomplete_wrong_homogenization(self, ref_path): material_config = ConfigMaterial.load(ref_path / 'material.yaml') new = material_config.material_rename_homogenization( {'Taylor': 'isostrain'}) assert not new.is_complete def test_from_table(self): N = np.random.randint(3, 10) a = np.vstack(( np.hstack((np.arange(N), np.arange(N)[::-1])), np.ones(N * 2), np.zeros(N * 2), np.ones(N * 2), np.ones(N * 2), np.ones(N * 2), )).T t = Table(a, {'varying': 1, 'constant': 4, 'ones': 1}) c = ConfigMaterial.from_table( t, **{ 'phase': 'varying', 'O': 'constant', 'homogenization': 'ones' }) assert len(c['material']) == N for i, m in enumerate(c['material']): assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1, 0, 1, 1]).all() @pytest.mark.parametrize('N,n,kw', [ (1, 1, { 'phase': 'Gold', 'O': [1, 0, 0, 0], 'F_i': np.eye(3), 'homogenization': 'SX' }), (3, 1, { 'phase': 'Gold', 'O': Rotation.from_random(3), 'F_i': np.broadcast_to(np.eye(3), (3, 3, 3)), 'homogenization': 'SX' }), (2, 3, { 'phase': np.broadcast_to(['a', 'b', 'c'], (2, 3)), 'O': Rotation.from_random((2, 3)), 'F_i': np.broadcast_to(np.eye(3), (2, 3, 3, 3)), 'homogenization': ['SX', 'PX'] }), ]) def test_material_add(self, kw, N, n): m = ConfigMaterial().material_add(**kw) assert len(m['material']) == N assert len(m['material'][0]['constituents']) == n @pytest.mark.parametrize('cell_ensemble_data', [None, 'CellEnsembleData']) def test_load_DREAM3D(self, ref_path, cell_ensemble_data): grain_c = ConfigMaterial.load_DREAM3D( ref_path / '2phase_irregularGrid.dream3d', 'Grain Data', cell_ensemble_data=cell_ensemble_data) point_c = ConfigMaterial.load_DREAM3D( ref_path / '2phase_irregularGrid.dream3d', cell_ensemble_data=cell_ensemble_data) assert point_c.is_valid and grain_c.is_valid and \ len(point_c['material'])+1 == len(grain_c['material']) grain_m = Grid.load_DREAM3D(ref_path / '2phase_irregularGrid.dream3d', 'FeatureIds').material.flatten() point_m = Grid.load_DREAM3D( ref_path / '2phase_irregularGrid.dream3d').material.flatten() for i in np.unique(point_m): j = int(grain_m[(point_m == i).nonzero()[0][0]]) assert np.allclose(point_c['material'][i]['constituents'][0]['O'], grain_c['material'][j]['constituents'][0]['O']) assert point_c['material'][i]['constituents'][0]['phase'] == \ grain_c['material'][j]['constituents'][0]['phase'] def test_load_DREAM3D_reference(self, tmp_path, ref_path, update): cur = ConfigMaterial.load_DREAM3D(ref_path / 'measured.dream3d') ref = ConfigMaterial.load(ref_path / 'measured.material.yaml') if update: cur.save(ref_path / 'measured.material.yaml') for i, m in enumerate(ref['material']): assert Rotation(m['constituents'][0]['O']).isclose( Rotation(cur['material'][i]['constituents'][0]['O'])) assert cur.is_valid and cur['phase'] == ref['phase'] and cur[ 'homogenization'] == ref['homogenization']
def test_random(self, shape): Rotation.from_random(shape)
def test_copy(self, kwargs): o = Orientation.from_random(**kwargs) p = o.copy(rotation=Rotation.from_random()) assert o != p
def test_equal(self, lattice, shape): R = Rotation.from_random(shape) assert Orientation(R,lattice) == Orientation(R,lattice) if shape is None else \ (Orientation(R,lattice) == Orientation(R,lattice)).all()
class TestConfig: @pytest.mark.parametrize('flow_style', [None, True, False]) def test_load_save_str(self, tmp_path, flow_style): config = Config() config['A'] = 1 config['B'] = [2, 3] config.save(tmp_path / 'config.yaml', default_flow_style=flow_style) assert Config.load(tmp_path / 'config.yaml') == config def test_load_save_file(self, tmp_path): config = Config() config['A'] = 1 config['B'] = [2, 3] with open(tmp_path / 'config.yaml', 'w') as f: config.save(f) with open(tmp_path / 'config.yaml') as f: assert Config.load(f) == config def test_add_remove(self): dummy = {'hello': 'world', 'foo': 'bar'} config = Config() config |= dummy assert config == Config() | dummy config = config.delete(dummy) assert config == Config() assert (config | dummy).delete('hello') == config | {'foo': 'bar'} assert (config | dummy).delete(['hello', 'foo']) == config assert (config | Config(dummy)).delete({ 'hello': 1, 'foo': 2 }) == config assert (config | Config(dummy)).delete(Config({'hello': 1})) == config | { 'foo': 'bar' } def test_repr(self, tmp_path): config = Config() config['A'] = 1 config['B'] = [2, 3] with open(tmp_path / 'config.yaml', 'w') as f: f.write(config.__repr__()) assert Config.load(tmp_path / 'config.yaml') == config def test_numpy(self, tmp_path): assert Config({ 'A': np.ones(3, 'i') }).__repr__() == Config({ 'A': [1, 1, 1] }).__repr__() def test_abstract_is_valid(self): with pytest.raises(NotImplementedError): Config().is_valid def test_abstract_is_complete(self): with pytest.raises(NotImplementedError): Config().is_complete @pytest.mark.parametrize( 'data', [Rotation.from_random(), Orientation.from_random(lattice='cI')]) def test_rotation_orientation(self, data): assert str(Config(a=data)) == str(Config(a=data.as_quaternion())) def test_initialize(self): yml = """ a: - 1 - 2 """ assert Config(yml) == Config('{"a":[1,2]}') == Config( a=[1, 2]) == Config(dict(a=[1, 2]))