DAMASK_EICMD/python/tests/test_ConfigMaterial.py

204 lines
9.3 KiB
Python

import sys
import os
import pytest
import numpy as np
from damask import ConfigMaterial
from damask import Table
from damask import Rotation
from damask import GeomGrid
@pytest.fixture
def res_path(res_path_base):
"""Directory containing testing resources."""
return res_path_base/'ConfigMaterial'
class TestConfigMaterial:
def test_init_empty(self):
c = ConfigMaterial()
assert len(c) == 3
assert c['homogenization'] == {}
assert c['phase'] == {}
assert c['material'] == []
def test_init_d(self):
c = ConfigMaterial(config={'phase':4})
assert len(c) == 1
assert c['phase'] == 4
@pytest.mark.parametrize('kwargs',[{'homogenization':{'SX':{}}},
{'phase':{'Aluminum':{}}},
{'material':[{'A':1},{'B':2}]}])
def test_init_some(self,kwargs):
c = ConfigMaterial(**kwargs)
assert len(c) == 3
for k,v in kwargs.items():
if k in kwargs: assert v == kwargs[k]
@pytest.mark.parametrize('fname',[None,'test.yaml'])
def test_load_save(self,res_path,tmp_path,fname):
reference = ConfigMaterial.load(res_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,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
assert material_config.is_valid and material_config.is_complete
def test_invalid_lattice(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
material_config['phase']['Aluminum']['lattice']='fxc'
assert not material_config.is_valid
def test_invalid_orientation(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
material_config['material'][0]['constituents'][0]['O']=[0,0,0,0]
assert not material_config.is_valid
@pytest.mark.xfail(sys.platform == 'win32', reason='utf8 "not equal" might cause trouble')
def test_invalid_fraction(self,res_path):
material_config = ConfigMaterial.load(res_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,res_path,item):
material_config = ConfigMaterial.load(res_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,res_path,item):
material_config = ConfigMaterial.load(res_path/'material.yaml')
del material_config['material'][0]['constituents'][0][item]
assert not material_config.is_complete
def test_incomplete_material_homogenization(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
del material_config['material'][0]['homogenization']
assert not material_config.is_complete
def test_incomplete_wrong_phase(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
new = material_config.material_rename_phase({'Steel':'FeNbC'})
assert not new.is_complete
def test_incomplete_wrong_homogenization(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
new = material_config.material_rename_homogenization({'Taylor':'isostrain'})
assert not new.is_complete
def test_empty_phase(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
material_config['phase'] = None
assert not material_config.is_complete
def test_empty_homogenization(self,res_path):
material_config = ConfigMaterial.load(res_path/'material.yaml')
material_config['homogenization'] = None
assert not material_config.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.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2),
np.ones(N*2),
)).T
t = Table({'varying':1,'constant':4,'ones':1},a)
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'] == [0,1,0,0]).all()
def test_updated_dicts(self,res_path):
m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX')
m2 = ConfigMaterial.load(res_path/'material.yaml')
for k in m2['phase']:
m2 = m2.material_add(phase=[k],O=[1.0,0.0,0.0,0.0],homogenization='SX')
assert not m2['phase'].get(k) is None
assert m1['phase'].get('Aluminum') is None
assert m1['homogenization'].get('SX') is None
def test_from_table_with_constant(self):
N = np.random.randint(3,10)
a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])),
np.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2),
np.ones(N*2),
)).T
t = Table({'varying':1,'constant':4,'ones':1},a)
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':1})
assert len(c['material']) == N
for i,m in enumerate(c['material']):
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [0,1,0,0]).all()
@pytest.mark.parametrize('N,n,kw',[
(1,1,{'phase':'Gold',
'O':[1,0,0,0],
'V_e':np.eye(3),
'homogenization':'SX'}),
(3,1,{'phase':'Gold',
'O':Rotation.from_random(3),
'V_e':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)),
'V_e':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('shape',[(),(4,),(5,2)])
@pytest.mark.parametrize('kw',[{'V_e':np.random.rand(3,3)},
{'O':np.random.rand(4)},
{'v':np.array(2)}])
def test_material_add_invalid(self,kw,shape):
kw = {arg:np.broadcast_to(val,shape+val.shape) for arg,val in kw.items()}
with pytest.raises(ValueError):
ConfigMaterial().material_add(**kw)
@pytest.mark.parametrize('v',[2,np.ones(3)*2,np.ones((2,2))])
def test_material_add_invalid_v(self,v):
with pytest.raises(ValueError):
ConfigMaterial().material_add(v=v)
@pytest.mark.parametrize('cell_ensemble_data',[None,'CellEnsembleData'])
def test_load_DREAM3D(self,res_path,cell_ensemble_data):
grain_c = ConfigMaterial.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d','Grain Data',
cell_ensemble_data = cell_ensemble_data)
point_c = ConfigMaterial.load_DREAM3D(res_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 = GeomGrid.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d','FeatureIds').material.flatten()
point_m = GeomGrid.load_DREAM3D(res_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,res_path,update):
cur = ConfigMaterial.load_DREAM3D(res_path/'measured.dream3d')
ref = ConfigMaterial.load(res_path/'measured.material.yaml')
if update:
cur.save(res_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']