From 443d79664325874559a6241a5e41fcfede1638f2 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 9 Nov 2022 22:58:51 +0100 Subject: [PATCH 1/9] phase and homogenization dict to be updated when new material added --- python/damask/_configmaterial.py | 22 ++++++++++++---------- python/tests/test_ConfigMaterial.py | 7 +++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 7a06a2c69..c02a1e056 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -209,8 +209,8 @@ class ConfigMaterial(Config): v: 1.0 phase: Steel homogenization: SX - homogenization: {} - phase: {} + homogenization: {SX: {t.b.d}} + phase: {Aluminum: {t.b.d}, Steel: {t.b.d}} >>> cm.from_table(t,O='qu',phase='phase',homogenization='single_crystal') material: @@ -224,8 +224,8 @@ class ConfigMaterial(Config): v: 1.0 phase: Steel homogenization: single_crystal - homogenization: {} - phase: {} + homogenization: {single_crystal: {t.b.d}} + phase: {Aluminum: {t.b.d}, Steel: {t.b.d}} """ kwargs_ = {k:table.get(v) if v in table.labels else np.atleast_2d([v]*len(table)).T for k,v in kwargs.items()} @@ -428,7 +428,6 @@ class ConfigMaterial(Config): -------- Create a dual-phase steel microstructure for micromechanical simulations: - >>> import numpy as np >>> import damask >>> m = damask.ConfigMaterial() >>> m = m.material_add(phase = ['Ferrite','Martensite'], @@ -446,12 +445,11 @@ class ConfigMaterial(Config): v: 1.0 phase: Martensite homogenization: SX - homogenization: {} - phase: {} + homogenization: {SX: {t.b.d}} + phase: {Ferrite: {t.b.d}, Martensite: {t.b.d}} Create a duplex stainless steel microstructure for forming simulations: - >>> import numpy as np >>> import damask >>> m = damask.ConfigMaterial() >>> m = m.material_add(phase = np.array(['Austenite','Ferrite']).reshape(1,2), @@ -476,8 +474,8 @@ class ConfigMaterial(Config): O: [0.6545817158479885, -0.08004812803625233, -0.6226561293931374, 0.4212059104577611] v: 0.8 homogenization: Taylor - homogenization: {} - phase: {} + homogenization: {Taylor: {t.b.d}} + phase: {Austenite: {t.b.d}, Ferrite: {t.b.d}} """ N,n,shaped = 1,1,{} @@ -507,5 +505,9 @@ class ConfigMaterial(Config): dup = self.copy() dup['material'] = dup['material'] + mat if 'material' in dup else mat + for k in np.unique(shaped['phase']): + if k not in dup['phase']: dup['phase'][str(k)] = {'t.b.d'} + for k in np.unique(shaped['homogenization']): + if k not in dup['homogenization']: dup['homogenization'][str(k)] = {'t.b.d'} return dup diff --git a/python/tests/test_ConfigMaterial.py b/python/tests/test_ConfigMaterial.py index f003e254e..60d0bcd50 100644 --- a/python/tests/test_ConfigMaterial.py +++ b/python/tests/test_ConfigMaterial.py @@ -98,6 +98,13 @@ class TestConfigMaterial: for i,m in enumerate(c['material']): assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all() + def test_updated_dicts(self,ref_path): + m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX') + m2 = ConfigMaterial.load(ref_path/'material.yaml').material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX') + assert m1['phase'] == {'Aluminum': {'t.b.d'}} + assert m1['homogenization'] == {'SX': {'t.b.d'}} + assert not m2['phase']['Aluminum'] == {} + 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])), From 13df12be1bc18e12d817cd743f1c1edbe05a5191 Mon Sep 17 00:00:00 2001 From: Sharan Date: Fri, 11 Nov 2022 01:14:16 +0100 Subject: [PATCH 2/9] initialising dummy arguments with None, making few changes on what is_complete should do --- python/damask/_configmaterial.py | 52 +++++++++---------- .../ConfigMaterial/measured.material.yaml | 2 +- python/tests/test_ConfigMaterial.py | 31 +++++------ 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index c02a1e056..1e77c0b18 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -160,7 +160,7 @@ class ConfigMaterial(Config): pass - base_config = ConfigMaterial({'phase':{k if isinstance(k,int) else str(k):'t.b.d.' for k in np.unique(phase)}, + base_config = ConfigMaterial({'phase':{k if isinstance(k,int) else str(k): None for k in np.unique(phase)}, 'homogenization':{'direct':{'N_constituents':1}}}) constituent = {k:np.atleast_1d(v[idx].squeeze()) for k,v in zip(['O','phase'],[O,phase])} @@ -209,8 +209,8 @@ class ConfigMaterial(Config): v: 1.0 phase: Steel homogenization: SX - homogenization: {SX: {t.b.d}} - phase: {Aluminum: {t.b.d}, Steel: {t.b.d}} + homogenization: {SX: null} + phase: {Aluminum: null, Steel: null} >>> cm.from_table(t,O='qu',phase='phase',homogenization='single_crystal') material: @@ -224,8 +224,8 @@ class ConfigMaterial(Config): v: 1.0 phase: Steel homogenization: single_crystal - homogenization: {single_crystal: {t.b.d}} - phase: {Aluminum: {t.b.d}, Steel: {t.b.d}} + homogenization: {single_crystal: null} + phase: {Aluminum: null, Steel: null} """ kwargs_ = {k:table.get(v) if v in table.labels else np.atleast_2d([v]*len(table)).T for k,v in kwargs.items()} @@ -282,22 +282,22 @@ class ConfigMaterial(Config): print(f'No phase specified in constituent {ii} of material {i}') ok = False - for k,v in self['phase'].items(): - if 'lattice' not in v: - print(f'No lattice specified in phase {k}') + if self['phase'] is None: + print('Description of phase dictionary is missing') + ok = False + else: + if phase - set(self['phase']): + print(f'Phase(s) {phase-set(self["phase"])} missing') ok = False - for k,v in self['homogenization'].items(): - if 'N_constituents' not in v: - print(f'No. of constituents not specified in homogenization {k}') + if self['homogenization'] is None: + print('Description of homogenization dictionary is missing') + ok = False + else: + if homogenization - set(self['homogenization']): + print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing') ok = False - if phase - set(self['phase']): - print(f'Phase(s) {phase-set(self["phase"])} missing') - ok = False - if homogenization - set(self['homogenization']): - print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing') - ok = False return ok @@ -320,7 +320,7 @@ class ConfigMaterial(Config): if 'phase' in self: for k,v in self['phase'].items(): - if 'lattice' in v: + if v is not None and 'lattice' in v: try: Orientation(lattice=v['lattice']) except KeyError: @@ -445,8 +445,8 @@ class ConfigMaterial(Config): v: 1.0 phase: Martensite homogenization: SX - homogenization: {SX: {t.b.d}} - phase: {Ferrite: {t.b.d}, Martensite: {t.b.d}} + homogenization: {SX: null} + phase: {Ferrite: null, Martensite: null} Create a duplex stainless steel microstructure for forming simulations: @@ -474,8 +474,8 @@ class ConfigMaterial(Config): O: [0.6545817158479885, -0.08004812803625233, -0.6226561293931374, 0.4212059104577611] v: 0.8 homogenization: Taylor - homogenization: {Taylor: {t.b.d}} - phase: {Austenite: {t.b.d}, Ferrite: {t.b.d}} + homogenization: {Taylor: null} + phase: {Austenite: null, Ferrite: null} """ N,n,shaped = 1,1,{} @@ -505,9 +505,9 @@ class ConfigMaterial(Config): dup = self.copy() dup['material'] = dup['material'] + mat if 'material' in dup else mat - for k in np.unique(shaped['phase']): - if k not in dup['phase']: dup['phase'][str(k)] = {'t.b.d'} - for k in np.unique(shaped['homogenization']): - if k not in dup['homogenization']: dup['homogenization'][str(k)] = {'t.b.d'} + + for what in ['phase','homogenization']: + for k in np.unique(shaped[what]): + if k not in dup[what]: dup[what][str(k)] = None return dup diff --git a/python/tests/reference/ConfigMaterial/measured.material.yaml b/python/tests/reference/ConfigMaterial/measured.material.yaml index bc7e73968..508d03039 100644 --- a/python/tests/reference/ConfigMaterial/measured.material.yaml +++ b/python/tests/reference/ConfigMaterial/measured.material.yaml @@ -1,4 +1,4 @@ -phase: {'1': t.b.d., '2': t.b.d.} +phase: {'1': null, '2': null} homogenization: direct: {N_constituents: 1} diff --git a/python/tests/test_ConfigMaterial.py b/python/tests/test_ConfigMaterial.py index 60d0bcd50..a9cf9089d 100644 --- a/python/tests/test_ConfigMaterial.py +++ b/python/tests/test_ConfigMaterial.py @@ -65,17 +65,6 @@ class TestConfigMaterial: 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'}) @@ -86,6 +75,16 @@ class TestConfigMaterial: new = material_config.material_rename_homogenization({'Taylor':'isostrain'}) assert not new.is_complete + def test_empty_phase(self,ref_path): + material_config = ConfigMaterial.load(ref_path/'material.yaml') + material_config['phase'] = None + assert not material_config.is_complete + + def test_empty_homogenization(self,ref_path): + material_config = ConfigMaterial.load(ref_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])), @@ -100,10 +99,12 @@ class TestConfigMaterial: def test_updated_dicts(self,ref_path): m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX') - m2 = ConfigMaterial.load(ref_path/'material.yaml').material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX') - assert m1['phase'] == {'Aluminum': {'t.b.d'}} - assert m1['homogenization'] == {'SX': {'t.b.d'}} - assert not m2['phase']['Aluminum'] == {} + m2 = ConfigMaterial.load(ref_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) From 4fc5ba54df7aea899521c02309291f93f592c7a9 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Fri, 11 Nov 2022 17:38:02 +0100 Subject: [PATCH 3/9] dummy phase dict need to be added for any new material added (similar to dream3D) --- python/damask/_configmaterial.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 1e77c0b18..87fb8be79 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -193,10 +193,10 @@ class ConfigMaterial(Config): >>> import damask.ConfigMaterial as cm >>> t = damask.Table.load('small.txt') >>> t - pos pos pos qu qu qu qu phase homog - 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 1 0 0.8 0.19 0.24 -0.51 Steel SX + 3:pos pos pos 4:qu qu qu qu phase homog + 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 + 2 1 1 0 0.8 0.19 0.24 -0.51 Steel SX >>> cm.from_table(t,O='qu',phase='phase',homogenization='homog') material: - constituents: @@ -233,6 +233,8 @@ class ConfigMaterial(Config): _,idx = np.unique(np.hstack(list(kwargs_.values())),return_index=True,axis=0) idx = np.sort(idx) kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()} + for what in ['phase','homogenization']: + if what not in kwargs_: kwargs_[what]= what+'_label' return ConfigMaterial().material_add(**kwargs_) From 2e7d59ab435b4ac892605fcccb9faf9fbf347cba Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 11 Nov 2022 18:07:48 -0500 Subject: [PATCH 4/9] brief but comprehensive "is_complete" reporting --- python/damask/_configmaterial.py | 50 +++++++++++++++++--------------- python/damask/util.py | 14 +++++---- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 87fb8be79..4d0df7768 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -245,7 +245,7 @@ class ConfigMaterial(Config): Check for completeness. Only the general file layout is considered. - This check does not consider whether parameters for + This check does not consider whether specific parameters for a particular phase/homogenization model are missing. Returns @@ -255,51 +255,53 @@ class ConfigMaterial(Config): """ ok = True - for top_level in ['homogenization','phase','material']: - ok &= top_level in self - if top_level not in self: print(f'{top_level} entry missing') + msg = [] + all = set(['homogenization','phase','material']) + miss = set([item for item in all if item not in self]) + empty = set([item for item in all-miss if self[item] is None]) + + if miss: + msg.append(f'Top-level{"s" if len(miss)>1 else ""} {util.srepr(miss,",",quote=True)} missing') + ok = False + if empty: + msg.append(f'Top-level{"s" if len(empty)>1 else ""} {util.srepr(empty,",",quote=True)} empty') if ok: - ok &= len(self['material']) > 0 - if len(self['material']) < 1: print('Incomplete material definition') + ok &= len(self['material']) > 0 + if len(self['material']) < 1: msg.append('No materials defined') - if ok: homogenization = set() phase = set() for i,v in enumerate(self['material']): if 'homogenization' in v: homogenization.add(v['homogenization']) else: - print(f'No homogenization specified in material {i}') + msg.append(f'No homogenization specified for material {i}') ok = False if 'constituents' in v: for ii,vv in enumerate(v['constituents']): if 'O' not in vv: - print('No orientation specified in constituent {ii} of material {i}') + msg.append(f'No orientation specified for constituent {ii} of material {i}') ok = False if 'phase' in vv: phase.add(vv['phase']) else: - print(f'No phase specified in constituent {ii} of material {i}') + msg.append(f'No phase specified for constituent {ii} of material {i}') ok = False - if self['phase'] is None: - print('Description of phase dictionary is missing') - ok = False - else: - if phase - set(self['phase']): - print(f'Phase(s) {phase-set(self["phase"])} missing') - ok = False - - if self['homogenization'] is None: - print('Description of homogenization dictionary is missing') - ok = False - else: - if homogenization - set(self['homogenization']): - print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing') + for v,other in {'phase':phase, + 'homogenization':homogenization}.items(): + me = set([] if v in empty else self[v]) + if _miss := other - me: + msg.append(f'{v.capitalize()}{"s" if len(_miss)>1 else ""} {util.srepr(_miss,",",quote=True)} missing') + ok = False + _empty = [item for item in me if self[v][item] is None] + if len(_empty) > 0: + msg.append(f'{v.capitalize()}{"s" if len(_empty)>1 else ""} {util.srepr(_empty,",",quote=True)} undefined') ok = False + print(util.srepr(msg)) return ok diff --git a/python/damask/util.py b/python/damask/util.py index ec42dede0..16f0c4c95 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -40,9 +40,10 @@ _colors = { # Functions #################################################################################################### def srepr(msg, - glue: str = '\n') -> str: + glue: str = '\n', + quote: bool = False) -> str: r""" - Join items with glue string. + Join (quoted) items with glue string. Parameters ---------- @@ -50,19 +51,22 @@ def srepr(msg, Items to join. glue : str, optional Glue used for joining operation. Defaults to '\n'. + quote : bool, optional + Quote items. Defaults to False. Returns ------- joined : str - String representation of the joined items. + String representation of the joined and quoted items. """ + q = '"' if quote else '' if (not hasattr(msg, 'strip') and (hasattr(msg, '__getitem__') or hasattr(msg, '__iter__'))): - return glue.join(str(x) for x in msg) + return glue.join(q+str(x)+q for x in msg) else: - return msg if isinstance(msg,str) else repr(msg) + return q+(msg if isinstance(msg,str) else repr(msg))+q def emph(msg) -> str: From 045f1d39a1150b47f0b4fb23f549fc11837862e2 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 14 Nov 2022 14:52:07 -0500 Subject: [PATCH 5/9] add shorthand function for formatting --- python/damask/_configmaterial.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 4d0df7768..6fd671de1 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -254,6 +254,9 @@ class ConfigMaterial(Config): Whether the material.yaml definition is complete. """ + def LabeledList(label,items): + return f'{label.capitalize()}{"s" if len(items)>1 else ""} {util.srepr(items,",",quote=True)}' + ok = True msg = [] all = set(['homogenization','phase','material']) @@ -261,10 +264,10 @@ class ConfigMaterial(Config): empty = set([item for item in all-miss if self[item] is None]) if miss: - msg.append(f'Top-level{"s" if len(miss)>1 else ""} {util.srepr(miss,",",quote=True)} missing') + msg.append(f'{LabeledList("top-level",miss)} missing') ok = False if empty: - msg.append(f'Top-level{"s" if len(empty)>1 else ""} {util.srepr(empty,",",quote=True)} empty') + msg.append(f'{LabeledList("top-level",empty)} empty') if ok: ok &= len(self['material']) > 0 @@ -294,11 +297,10 @@ class ConfigMaterial(Config): 'homogenization':homogenization}.items(): me = set([] if v in empty else self[v]) if _miss := other - me: - msg.append(f'{v.capitalize()}{"s" if len(_miss)>1 else ""} {util.srepr(_miss,",",quote=True)} missing') + msg.append(f'{LabeledList(v,_miss)} missing') ok = False - _empty = [item for item in me if self[v][item] is None] - if len(_empty) > 0: - msg.append(f'{v.capitalize()}{"s" if len(_empty)>1 else ""} {util.srepr(_empty,",",quote=True)} undefined') + if len(_empty := [item for item in me if self[v][item] is None]) > 0: + msg.append(f'{LabeledList(v,_empty)} undefined') ok = False print(util.srepr(msg)) From 822a09865935091868a0befe343f4c2abfe3ab16 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 18 Nov 2022 10:06:15 -0500 Subject: [PATCH 6/9] cleaner way to specify default dict entries --- python/damask/_configmaterial.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 6fd671de1..e678dab03 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -232,9 +232,9 @@ class ConfigMaterial(Config): _,idx = np.unique(np.hstack(list(kwargs_.values())),return_index=True,axis=0) idx = np.sort(idx) - kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()} - for what in ['phase','homogenization']: - if what not in kwargs_: kwargs_[what]= what+'_label' + kwargs_ = {'phase':'phase_label', + 'homogenization': 'homogenization_label'} \ + | {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()} return ConfigMaterial().material_add(**kwargs_) From d374f6a02c3e434c652ce57e4a38a1840b157534 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 18 Nov 2022 11:01:01 -0500 Subject: [PATCH 7/9] revert, since not working in python3.8... --- python/damask/_configmaterial.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index e678dab03..dbf6edf1f 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -232,9 +232,9 @@ class ConfigMaterial(Config): _,idx = np.unique(np.hstack(list(kwargs_.values())),return_index=True,axis=0) idx = np.sort(idx) - kwargs_ = {'phase':'phase_label', - 'homogenization': 'homogenization_label'} \ - | {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()} + for what in ['phase','homogenization']: + if what not in kwargs_: kwargs_[what] = what+'_label' return ConfigMaterial().material_add(**kwargs_) From 7e5a3a12abdfd6a03427b20f7bde249907f666ce Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 18 Nov 2022 16:30:26 -0500 Subject: [PATCH 8/9] proper dealing with default/mandatory items in material_add --- python/damask/_configmaterial.py | 92 +++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index dbf6edf1f..873577771 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -424,6 +424,8 @@ class ConfigMaterial(Config): ---------- **kwargs Key-value pairs. + First index of array-like values runs over materials, + whereas second index runs over constituents. Returns ------- @@ -432,12 +434,12 @@ class ConfigMaterial(Config): Examples -------- - Create a dual-phase steel microstructure for micromechanical simulations: + Create two grains of ferrite and one grain of martensite, each with random orientation: >>> import damask >>> m = damask.ConfigMaterial() - >>> m = m.material_add(phase = ['Ferrite','Martensite'], - ... O = damask.Rotation.from_random(2), + >>> m = m.material_add(phase = ['Ferrite','Martensite','Ferrite'], + ... O = damask.Rotation.from_random(3), ... homogenization = 'SX') >>> m material: @@ -451,59 +453,89 @@ class ConfigMaterial(Config): v: 1.0 phase: Martensite homogenization: SX + - constituents: + - O: [0.47925185, -0.04294454, 0.78760173, -0.3849116 ] + v: 1.0 + phase: Ferrite + homogenization: SX homogenization: {SX: null} phase: {Ferrite: null, Martensite: null} - Create a duplex stainless steel microstructure for forming simulations: + Create hundred materials that each approximate a duplex stainless steel microstructure + with three austenite and one relatively bigger ferrite grain of random orientation each: >>> import damask >>> m = damask.ConfigMaterial() - >>> m = m.material_add(phase = np.array(['Austenite','Ferrite']).reshape(1,2), - ... O = damask.Rotation.from_random((2,2)), - ... v = np.array([0.2,0.8]).reshape(1,2), + >>> m = m.material_add(phase = np.array(['Austenite']*3+['Ferrite']), + ... O = damask.Rotation.from_random((100,4)), + ... v = np.array([0.2]*3+[0.4]), ... homogenization = 'Taylor') >>> m material: - constituents: - - phase: Austenite - O: [0.659802978293224, 0.6953785848195171, 0.22426295326327111, -0.17554139512785227] - v: 0.2 - - phase: Ferrite - O: [0.49356745891301596, 0.2841806579193434, -0.7487679215072818, -0.339085707289975] - v: 0.8 + - v: 0.2 + phase: Austenite + O: [0.46183665006602664, 0.2215160420973196, -0.5594313187331139, 0.6516702781083836] + - v: 0.2 + phase: Austenite + O: [0.11321658382410027, 0.6354079414360444, 0.00562701344273936, 0.7638108992590535] + - v: 0.2 + phase: Austenite + O: [0.050991978809077604, 0.8069522034362003, -0.11352928955610851, -0.5773552285027659] + - v: 0.4 + phase: Ferrite + O: [0.9460076150721788, 0.15880754622367604, -0.0069841062241482385, -0.28249066842661014] homogenization: Taylor + . + . + . - constituents: - - phase: Austenite - O: [0.26542221365204055, 0.7268854930702071, 0.4474726435701472, -0.44828201137283735] - v: 0.2 - - phase: Ferrite - O: [0.6545817158479885, -0.08004812803625233, -0.6226561293931374, 0.4212059104577611] - v: 0.8 + - v: 0.2 + phase: Austenite + O: [0.12531400788494199, -0.18637769037997565, 0.31737548053338394, -0.9213210951197429] + - v: 0.2 + phase: Austenite + O: [0.37453930577161404, -0.33529507696450805, -0.3266564259130028, -0.800370601162502] + - v: 0.2 + phase: Austenite + O: [0.035776891752713764, -0.720706371010592, -0.4540438656728926, -0.5226342017569017] + - v: 0.4 + phase: Ferrite + O: [0.6782596727966124, -0.20800082041703685, -0.138636083554039, 0.6909989227925536] homogenization: Taylor + homogenization: {Taylor: null} + phase: {Austenite: null, Ferrite: null} """ - N,n,shaped = 1,1,{} + _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,n,shaped = 1,1,{'v': None, + 'phase': None, + 'homogenization': None, + } - map_dim = {'O':-1,'V_e':-2} for k,v in kwargs.items(): shaped[k] = np.array(v) - s = shaped[k].shape[:map_dim.get(k,None)] + s = shaped[k].shape[:_ex.get(k,None)] N = max(N,s[0]) if len(s)>0 else N n = max(n,s[1]) if len(s)>1 else n + shaped['v'] = np.array(1./n) if shaped['v'] is None else shaped['v'] + mat: Sequence[dict] = [{'constituents':[{} for _ in range(n)]} for _ in range(N)] - if 'v' not in kwargs: - shaped['v'] = np.broadcast_to(1/n,(N,n)) - - map_shape = {'O':(N,n,4),'V_e':(N,n,3,3)} for k,v in shaped.items(): - target = map_shape.get(k,(N,n)) - obj = np.broadcast_to(v.reshape(util.shapeshifter(v.shape, target, mode = 'right')), target) + target = (N,n) + _dim.get(k,()) + obj = np.broadcast_to(np.array(v).reshape(util.shapeshifter(() if v is None else v.shape, + target, + mode = 'right')), + target) for i in range(N): - if k in ['phase','O','v','V_e']: + if k in _constituent_properties: 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: @@ -514,6 +546,6 @@ class ConfigMaterial(Config): for what in ['phase','homogenization']: for k in np.unique(shaped[what]): - if k not in dup[what]: dup[what][str(k)] = None + if not (k is None or k in dup[what]): dup[what][str(k)] = None return dup From 6907ca60b3268d0262bb611f9765b9faa453af06 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sat, 19 Nov 2022 20:55:23 -0500 Subject: [PATCH 9/9] adjustments to make mypy happy --- python/damask/_configmaterial.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 873577771..d98f277fe 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -1,6 +1,6 @@ import numpy as np import h5py -from typing import Sequence, Dict, Any, Collection +from typing import Union, Sequence, Dict, Any, Collection from ._typehints import FileHandle from . import Config @@ -513,14 +513,16 @@ class ConfigMaterial(Config): _dim = {'O':(4,),'V_e':(3,3,)} _ex = dict((k, -len(v)) for k, v in _dim.items()) - N,n,shaped = 1,1,{'v': None, - 'phase': None, - 'homogenization': None, - } + N,n = 1,1 + shaped : Dict[str, Union[None,np.ndarray]] = \ + {'v': None, + 'phase': None, + 'homogenization': None, + } for k,v in kwargs.items(): shaped[k] = np.array(v) - s = shaped[k].shape[:_ex.get(k,None)] + s = shaped[k].shape[:_ex.get(k,None)] # type: ignore N = max(N,s[0]) if len(s)>0 else N n = max(n,s[1]) if len(s)>1 else n @@ -544,8 +546,8 @@ class ConfigMaterial(Config): dup = self.copy() dup['material'] = dup['material'] + mat if 'material' in dup else mat - for what in ['phase','homogenization']: - for k in np.unique(shaped[what]): - if not (k is None or k in dup[what]): dup[what][str(k)] = None + for what in [item for item in ['phase','homogenization'] if shaped[item] is not None]: + for k in np.unique(shaped[what]): # type: ignore + if k not in dup[what]: dup[what][str(k)] = None return dup