check for invalid materialpoint configuration
This commit is contained in:
parent
fd84406903
commit
46ad436d76
|
@ -8,6 +8,7 @@ from . import Config
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
from . import Orientation
|
from . import Orientation
|
||||||
from . import util
|
from . import util
|
||||||
|
from . import tensor
|
||||||
from . import Table
|
from . import Table
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,7 +444,7 @@ class ConfigMaterial(Config):
|
||||||
Phase label (per constituent).
|
Phase label (per constituent).
|
||||||
v: (array-like) of float, optional
|
v: (array-like) of float, optional
|
||||||
Constituent volume fraction (per constituent).
|
Constituent volume fraction (per constituent).
|
||||||
Defaults to 1/N_constituents
|
Defaults to 1/N_constituent.
|
||||||
O: (array-like) of damask.Rotation or np.array/list of shape(4), optional
|
O: (array-like) of damask.Rotation or np.array/list of shape(4), optional
|
||||||
Orientation as unit quaternion (per constituent).
|
Orientation as unit quaternion (per constituent).
|
||||||
V_e: (array-like) of np.array/list of shape(3,3), optional
|
V_e: (array-like) of np.array/list of shape(3,3), optional
|
||||||
|
@ -536,48 +537,44 @@ class ConfigMaterial(Config):
|
||||||
phase: {Austenite: null, Ferrite: null}
|
phase: {Austenite: null, Ferrite: null}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
kwargs = {}
|
dim = {'O':(4,),'V_e':(3,3,)}
|
||||||
for keyword,value in zip(['homogenization','phase','v','O','V_e'],[homogenization,phase,v,O,V_e]):
|
ex = dict((keyword, -len(val)) for keyword,val in dim.items())
|
||||||
if value is not None: kwargs[keyword] = value
|
|
||||||
|
|
||||||
_constituent_properties = ['phase','O','v','V_e']
|
|
||||||
_dim = {'O':(4,),'V_e':(3,3,)}
|
|
||||||
_ex = dict((k, -len(v)) for k, v in _dim.items())
|
|
||||||
|
|
||||||
N_materials,N_constituents = 1,1
|
N_materials,N_constituents = 1,1
|
||||||
shaped : Dict[str, Union[None,np.ndarray]] = \
|
shaped = {}
|
||||||
{'v': None,
|
for arg,val in zip(['homogenization','phase','v','O','V_e'],[homogenization,phase,v,O,V_e]):
|
||||||
'phase': None,
|
if val is None: continue
|
||||||
'homogenization': None,
|
shaped[arg] = np.array(val)
|
||||||
}
|
s = shaped[arg].shape[:ex.get(arg,None)] # type: ignore
|
||||||
|
|
||||||
for arg,value in kwargs.items():
|
|
||||||
shaped[arg] = np.array(value)
|
|
||||||
s = shaped[arg].shape[:_ex.get(arg,None)] # type: ignore
|
|
||||||
N_materials = max(N_materials,s[0]) if len(s)>0 else N_materials
|
N_materials = max(N_materials,s[0]) if len(s)>0 else N_materials
|
||||||
N_constituents = max(N_constituents,s[1]) if len(s)>1 else N_constituents
|
N_constituents = max(N_constituents,s[1]) if len(s)>1 else N_constituents
|
||||||
|
|
||||||
shaped['v'] = np.array(1./N_constituents) if shaped['v'] is None else shaped['v']
|
shaped['v'] = np.array(shaped.get('v',1./N_constituents),float)
|
||||||
|
|
||||||
mat: Sequence[dict] = [{'constituents':[{} for _ in range(N_constituents)]} for _ in range(N_materials)]
|
mat: Sequence[dict] = [{'constituents':[{} for _ in range(N_constituents)]} for _ in range(N_materials)]
|
||||||
|
|
||||||
for k,v in shaped.items():
|
for k,v in shaped.items():
|
||||||
target = (N_materials,N_constituents) + _dim.get(k,())
|
target = (N_materials,N_constituents) + dim.get(k,())
|
||||||
obj = np.broadcast_to(np.array(v).reshape(util.shapeshifter(() if v is None else v.shape,
|
obj = np.broadcast_to(np.array(v).reshape(util.shapeshifter(np.array(v).shape,target,'right')),target)
|
||||||
target,
|
if k == 'v':
|
||||||
mode = 'right')),
|
total = obj if len(np.atleast_1d(obj)) == 1 else np.sum(obj,axis=-1)
|
||||||
target)
|
if np.min(obj) < 0 or np.min(total) < 0 or np.max(total) > 1:
|
||||||
|
raise ValueError('volume fraction "v" out of range')
|
||||||
|
if k == 'O' and not np.allclose(1.0,np.linalg.norm(obj,axis=-1)):
|
||||||
|
raise ValueError('orientation "O" is not a unit quaterion')
|
||||||
|
elif k == 'V_e' and not np.allclose(obj,tensor.symmetric(obj)):
|
||||||
|
raise ValueError('elastic stretch "V_e" is not symmetric')
|
||||||
for i in range(N_materials):
|
for i in range(N_materials):
|
||||||
if k in _constituent_properties:
|
if k == 'homogenization':
|
||||||
for j in range(N_constituents):
|
mat[i][k] = obj[i,0]
|
||||||
mat[i]['constituents'][j][k] = obj[i,j].item() if isinstance(obj[i,j],np.generic) else obj[i,j]
|
|
||||||
else:
|
else:
|
||||||
mat[i][k] = obj[i,0].item() if isinstance(obj[i,0],np.generic) else obj[i,0]
|
for j in range(N_constituents):
|
||||||
|
mat[i]['constituents'][j][k] = obj[i,j]
|
||||||
|
|
||||||
dup = self.copy()
|
dup = self.copy()
|
||||||
dup['material'] = dup['material'] + mat if 'material' in dup else mat
|
dup['material'] = dup['material'] + mat if 'material' in dup else mat
|
||||||
|
|
||||||
for what in [item for item in ['phase','homogenization'] if shaped[item] is not None]:
|
for what in [item for item in ['phase','homogenization'] if item in shaped]:
|
||||||
for k in np.unique(shaped[what]): # type: ignore
|
for k in np.unique(shaped[what]): # type: ignore
|
||||||
if k not in dup[what]: dup[what][str(k)] = None
|
if k not in dup[what]: dup[what][str(k)] = None
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,27 @@ def ref_path(ref_path_base):
|
||||||
|
|
||||||
class TestConfigMaterial:
|
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'])
|
@pytest.mark.parametrize('fname',[None,'test.yaml'])
|
||||||
def test_load_save(self,ref_path,tmp_path,fname):
|
def test_load_save(self,ref_path,tmp_path,fname):
|
||||||
reference = ConfigMaterial.load(ref_path/'material.yaml')
|
reference = ConfigMaterial.load(ref_path/'material.yaml')
|
||||||
|
@ -88,14 +109,14 @@ class TestConfigMaterial:
|
||||||
def test_from_table(self):
|
def test_from_table(self):
|
||||||
N = np.random.randint(3,10)
|
N = np.random.randint(3,10)
|
||||||
a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])),
|
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.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2),
|
||||||
np.ones(N*2),
|
np.ones(N*2),
|
||||||
)).T
|
)).T
|
||||||
t = Table({'varying':1,'constant':4,'ones':1},a)
|
t = Table({'varying':1,'constant':4,'ones':1},a)
|
||||||
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':'ones'})
|
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':'ones'})
|
||||||
assert len(c['material']) == N
|
assert len(c['material']) == N
|
||||||
for i,m in enumerate(c['material']):
|
for i,m in enumerate(c['material']):
|
||||||
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all()
|
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [0,1,0,0]).all()
|
||||||
|
|
||||||
def test_updated_dicts(self,ref_path):
|
def test_updated_dicts(self,ref_path):
|
||||||
m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX')
|
m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX')
|
||||||
|
@ -109,14 +130,14 @@ class TestConfigMaterial:
|
||||||
def test_from_table_with_constant(self):
|
def test_from_table_with_constant(self):
|
||||||
N = np.random.randint(3,10)
|
N = np.random.randint(3,10)
|
||||||
a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])),
|
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.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2),
|
||||||
np.ones(N*2),
|
np.ones(N*2),
|
||||||
)).T
|
)).T
|
||||||
t = Table({'varying':1,'constant':4,'ones':1},a)
|
t = Table({'varying':1,'constant':4,'ones':1},a)
|
||||||
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':1})
|
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':1})
|
||||||
assert len(c['material']) == N
|
assert len(c['material']) == N
|
||||||
for i,m in enumerate(c['material']):
|
for i,m in enumerate(c['material']):
|
||||||
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all()
|
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [0,1,0,0]).all()
|
||||||
|
|
||||||
@pytest.mark.parametrize('N,n,kw',[
|
@pytest.mark.parametrize('N,n,kw',[
|
||||||
(1,1,{'phase':'Gold',
|
(1,1,{'phase':'Gold',
|
||||||
|
@ -137,6 +158,14 @@ class TestConfigMaterial:
|
||||||
assert len(m['material']) == N
|
assert len(m['material']) == N
|
||||||
assert len(m['material'][0]['constituents']) == 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('cell_ensemble_data',[None,'CellEnsembleData'])
|
@pytest.mark.parametrize('cell_ensemble_data',[None,'CellEnsembleData'])
|
||||||
def test_load_DREAM3D(self,ref_path,cell_ensemble_data):
|
def test_load_DREAM3D(self,ref_path,cell_ensemble_data):
|
||||||
|
|
Loading…
Reference in New Issue