shortened material_add and allow for multi-constituent; broken from_table...

This commit is contained in:
Philip Eisenlohr 2021-02-22 22:44:12 -05:00
parent 0461c404f7
commit 4a00254dba
2 changed files with 60 additions and 99 deletions

View File

@ -3,6 +3,7 @@ import numpy as np
from . import Config from . import Config
from . import Rotation from . import Rotation
from . import Orientation from . import Orientation
from . import util
class ConfigMaterial(Config): class ConfigMaterial(Config):
"""Material configuration.""" """Material configuration."""
@ -46,7 +47,7 @@ class ConfigMaterial(Config):
@staticmethod @staticmethod
def from_table(table,constituents={},**kwargs): def from_table(table,**kwargs):
""" """
Load from an ASCII table. Load from an ASCII table.
@ -54,12 +55,9 @@ class ConfigMaterial(Config):
---------- ----------
table : damask.Table table : damask.Table
Table that contains material information. Table that contains material information.
constituents : dict, optional
Entries for 'constituents'. The key is the name and the value specifies
the label of the data column in the table
**kwargs **kwargs
Keyword arguments where the key is the name and the value specifies Keyword arguments where the key is the name and the value specifies
the label of the data column in the table the label of the data column in the table.
Examples Examples
-------- --------
@ -70,7 +68,7 @@ class ConfigMaterial(Config):
pos pos pos qu qu qu qu phase homog pos pos pos qu qu qu qu phase homog
0 0 0 0 0.19 0.8 0.24 -0.51 Aluminum SX 0 0 0 0 0.19 0.8 0.24 -0.51 Aluminum SX
1 1 0 0 0.8 0.19 0.24 -0.51 Steel SX 1 1 0 0 0.8 0.19 0.24 -0.51 Steel SX
>>> cm.from_table(t,{'O':'qu','phase':'phase'},homogenization='homog') >>> cm.from_table(t,O='qu',phase='phase',homogenization='homog')
material: material:
- constituents: - constituents:
- O: [0.19, 0.8, 0.24, -0.51] - O: [0.19, 0.8, 0.24, -0.51]
@ -86,16 +84,17 @@ class ConfigMaterial(Config):
phase: {} phase: {}
""" """
constituents_ = {k:table.get(v) for k,v in constituents.items()} # constituents_ = {k:table.get(v) for k,v in constituents.items()}
kwargs_ = {k:table.get(v) for k,v in kwargs.items()} kwargs_ = {k:table.get(v) for k,v in kwargs.items()}
_,idx = np.unique(np.hstack(list({**constituents_,**kwargs_}.values())),return_index=True,axis=0) _,idx = np.unique(kwargs_.values(),return_index=True,axis=0)
# _,idx = np.unique(np.hstack(list({**constituents_,**kwargs_}.values())),return_index=True,axis=0)
idx = np.sort(idx) idx = np.sort(idx)
constituents_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in constituents_.items()} # constituents_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in constituents_.items()}
kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()} kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()}
return ConfigMaterial().material_add(constituents_,**kwargs_) return ConfigMaterial().material_add(**kwargs_)
@property @property
@ -234,7 +233,7 @@ class ConfigMaterial(Config):
return dup return dup
def material_add(self,constituents=None,**kwargs): def material_add(self,**kwargs):
""" """
Add material entries. Add material entries.
@ -248,10 +247,9 @@ class ConfigMaterial(Config):
Examples Examples
-------- --------
>>> import damask >>> import damask
>>> O = damask.Rotation.from_random(3) >>> m = damask.ConfigMaterial().material_add(phase = ['Aluminum','Steel','Aluminum'],
>>> phase = ['Aluminum','Steel','Aluminum'] ... O = damask.Rotation.from_random(3)},
>>> m = damask.ConfigMaterial().material_add(constituents={'phase':phase,'O':O}, ... homogenization = 'SX')
... homogenization='SX')
>>> m >>> m
material: material:
- constituents: - constituents:
@ -273,54 +271,30 @@ class ConfigMaterial(Config):
phase: {} phase: {}
""" """
length = -1 N,n,shaped = 1,1,{}
for v in kwargs.values():
if hasattr(v,'__len__') and not isinstance(v,str):
if length != -1 and len(v) != length:
raise ValueError('Cannot add entries of different length')
else:
length = len(v)
length = max(1,length)
c = [{} for _ in range(length)] if constituents is None else \
[{'constituents':u} for u in ConfigMaterial._constituents(**constituents)]
if len(c) == 1: c = [c[0] for _ in range(length)]
if length != 1 and length != len(c):
raise ValueError('Cannot add entries of different length')
for k,v in kwargs.items(): for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str): shaped[k] = np.array(v)
for i,vv in enumerate(v): s = shaped[k].shape[:-1] if k=='O' else shaped[k].shape
c[i][k] = vv.item() if isinstance(vv,np.generic) else vv N = max(N,s[0]) if len(s)>0 else N
else: n = max(n,s[1]) if len(s)>1 else n
for i in range(len(c)):
c[i][k] = v mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
if 'v' not in kwargs:
shaped['v'] = np.broadcast_to(1/n,(N,n))
for k,v in shaped.items():
obj = np.broadcast_to(v.reshape(util.shapeshifter(v.shape,(N,n,4))),(N,n,4)) if k=='O' else \
np.broadcast_to(v.reshape(util.shapeshifter(v.shape,(N,n ))),(N,n))
for i in range(N):
if k in ['phase','O','v']:
for j in range(n):
mat[i]['constituents'][j][k] = obj[i,j].item() if isinstance(obj[i,j],np.generic) else obj[i,j]
else:
mat[i][k] = obj[i,0].item() if isinstance(obj[i,0],np.generic) else obj[i,0]
dup = self.copy() dup = self.copy()
dup['material'] = dup['material'] + c if 'material' in dup else c dup['material'] = dup['material'] + mat if 'material' in dup else mat
return dup return dup
@staticmethod
def _constituents(N=1,**kwargs):
"""Construct list of constituents."""
N_material=1
for v in kwargs.values():
if hasattr(v,'__len__') and not isinstance(v,str): N_material = len(v)
if N == 1:
m = [[{'v':1.0}] for _ in range(N_material)]
for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str):
if len(v) != N_material:
raise ValueError('Cannot add entries of different length')
for i,vv in enumerate(np.array(v)):
m[i][0][k] = vv.item() if isinstance(vv,np.generic) else vv
else:
for i in range(N_material):
m[i][0][k] = v
return m
else:
raise NotImplementedError

View File

@ -5,6 +5,7 @@ import numpy as np
from damask import ConfigMaterial from damask import ConfigMaterial
from damask import Table from damask import Table
from damask import Rotation
@pytest.fixture @pytest.fixture
def ref_path(ref_path_base): def ref_path(ref_path_base):
@ -85,42 +86,28 @@ 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])),np.ones(N*2),np.zeros(N*2),np.ones(N*2))).T 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))).T
t = Table(a,{'varying':2,'constant':2}) print(a)
c = ConfigMaterial.from_table(t,constituents={'a':'varying','b':'1_constant'},c='2_constant') t = Table(a,{'varying':1,'constant':4})
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant'})
assert len(c['material']) == N assert len(c['material']) == N
for i,m in enumerate(c['material']): print(c)
c = m['constituents'][0] # for i,m in enumerate(c['material']):
assert m['c'] == 1 and c['b'] == 0 and (c['a'] == [i,1]).all() # c = m['constituents'][0]
# assert m['c'] == 1 and c['b'] == 0 and (c['a'] == [i,1]).all()
def test_constituents(self): @pytest.mark.parametrize('N,n,kw',[
c = ConfigMaterial._constituents(c=1,v=[2,3]) (1,1,{'phase':'Gold',
assert c[0][0]['c'] == c[1][0]['c'] == 1 'O':[1,0,0,0],
assert c[0][0]['v'] == c[1][0]['v'] -1 ==2 'homogenization':'SX'}),
(3,1,{'phase':'Gold',
@pytest.mark.parametrize('constituents',[{'W':1,'X':[2,3]},{'Y':4},{'Z':[5,6]}]) 'O':Rotation.from_random(3),
@pytest.mark.parametrize('a',[[7.,8.],9.]) 'homogenization':'SX'}),
@pytest.mark.parametrize('b',['bd',['efg','hi']]) (2,3,{'phase':np.broadcast_to(['a','b','c'],(2,3)),
def test_material_add(self,tmp_path,constituents,a,b): 'O':Rotation.from_random((2,3)),
len_c = len(ConfigMaterial()._constituents(1,**constituents)) 'homogenization':['SX','PX']}),
len_a = len(a) if isinstance(a,list) else 1 ])
len_b = len(b) if isinstance(b,list) else 1 def test_material_add(self,kw,N,n):
m = ConfigMaterial().material_add(constituents,a=a,b=b) m = ConfigMaterial().material_add(**kw)
m.save() assert len(m['material']) == N
assert len(m['material']) == np.max([len_a,len_b,len_c]) assert len(m['material'][0]['constituents']) == n
@pytest.mark.parametrize('constituents',[{'W':1,'X':np.array([2,3])},{'Y':4},{'Z':np.array([5,6])}])
@pytest.mark.parametrize('a',[np.array([7,8]),9])
def test_material_add_np(self,tmp_path,constituents,a):
len_c = len(ConfigMaterial()._constituents(1,**constituents))
len_a = len(a) if isinstance(a,np.ndarray) else 1
m = ConfigMaterial().material_add(constituents,ld=a)
m.save()
assert len(m['material']) == np.max([len_a,len_c])
@pytest.mark.parametrize('constituents',[{'X':np.array([2,3,4,5])},{'Y':4}])
@pytest.mark.parametrize('a',[np.array([1,2,3]),[4,5,6]])
@pytest.mark.parametrize('b',[np.array([6.,7.]),[8.,9.]])
def test_material_add_invalid(self,constituents,a,b):
with pytest.raises(ValueError):
ConfigMaterial().material_add(constituents,a=a,u=b)