diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 0ad76d99c..3b3d22a0e 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -2,6 +2,7 @@ import copy import numpy as np +from . import grid_filters from . import Config from . import Lattice from . import Rotation @@ -18,7 +19,7 @@ class ConfigMaterial(Config): ---------- fname : file, str, or pathlib.Path, optional Filename or file for writing. Defaults to 'material.yaml'. - **kwargs : dict + **kwargs Keyword arguments parsed to yaml.dump. """ @@ -27,8 +28,50 @@ class ConfigMaterial(Config): @staticmethod def load_table(fname,coordinates=None,constituents={},**kwargs): + """ + Load from an ASCII table. + + Parameters + ---------- + fname : str, file handle, or damask.Table + Table that contains material information. + coordinates : str, optional + Label of spatial coordiates. Used for sorting and performing a + sanity check. Default to None, in which case no sorting or checking is + peformed. + 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 + Keyword arguments where the key is the name and the value specifies + the label of the data column in the table + + Examples + -------- + >>> import damask + >>> import damask.ConfigMaterial as cm + >>> damask.Table.load('small.txt') + 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 + >>> cm.load_table('small.txt','pos',{'O':'qu','phase':'phase'},homogenization='h') + material: + - constituents: + - O: [0.19, 0.8, 0.24, -0.51] + fraction: 1.0 + phase: Aluminum + homogenization: SX + - constituents: + - O: [0.8, 0.19, 0.24, -0.51] + fraction: 1.0 + phase: Steel + homogenization: SX + + """ t = Table.load(fname) - if coordinates is not None: t = t.sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)]) + if coordinates is not None: + t = t.sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)]) + grid_filters.coord0_check(t.get(coordinates)) constituents_ = {k:t.get(v) for k,v in constituents.items()} kwargs_ = {k:t.get(v) for k,v in kwargs.items()} @@ -183,17 +226,37 @@ class ConfigMaterial(Config): Parameters ---------- - constituents: scalar or numpy.ndarray - **kwargs: tbd + constituents : dict + Entries for 'constituents'. The key is the name and the value specifies + the label of the data column in the table + **kwargs + Keyword arguments where the key is the name and the value specifies + the label of the data column in the table Examples -------- - m = damask.ConfigMaterial() - O = damask.Rotation.from_random(3).as_quaternion() - phase = ['Aluminum','Steel','Aluminum'] - - m.material_add(constituents={'phase':phase,'O':O},homogenization='SX') - + >>> import damask + >>> m = damask.ConfigMaterial() + >>> O = damask.Rotation.from_random(3).as_quaternion() + >>> phase = ['Aluminum','Steel','Aluminum'] + >>> m.material_add(constituents={'phase':phase,'O':O},homogenization='SX') + material: + - constituents: + - O: [0.577764, -0.146299, -0.617669, 0.513010] + fraction: 1.0 + phase: Aluminum + homogenization: SX + - constituents: + - O: [0.184176, 0.340305, 0.737247, 0.553840] + fraction: 1.0 + phase: Steel + homogenization: SX + - constituents: + - O: [0.0886257, -0.144848, 0.615674, -0.769487] + fraction: 1.0 + phase: Aluminum + homogenization: SX + """ c = [{'constituents':u} for u in ConfigMaterial._constituents(**constituents)] for k,v in kwargs.items(): diff --git a/python/damask/_geom.py b/python/damask/_geom.py index ec65154bb..7a5b20fcc 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -210,6 +210,69 @@ class Geom: return Geom(material.reshape(grid,order='F'),size,origin,comments) + + @staticmethod + def load_DREAM3D(fname,base_group,point_data=None,material='FeatureIds'): + """ + Load a DREAM.3D file. + + Parameters + ---------- + fname : str + Filename of the DREAM.3D file + base_group : str + Name of the group (folder) below 'DataContainers'. For example + 'SyntheticVolumeDataContainer'. + point_data : str, optional + Name of the group (folder) containing the point wise material data, + for example 'CellData'. Defaults to None, in which case points consecutively numbered. + material : str, optional + Name of the dataset containing the material ID. Defaults to + 'FeatureIds'. + + """ + root_dir ='DataContainers' + f = h5py.File(fname, 'r') + g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY') + size = f[path.join(g,'DIMENSIONS')][()] * f[path.join(g,'SPACING')][()] + grid = f[path.join(g,'DIMENSIONS')][()] + origin = f[path.join(g,'ORIGIN')][()] + group_pointwise = path.join(root_dir,base_group,point_data) + + ma = np.arange(1,np.product(grid)+1,dtype=int) if point_data is None else \ + np.reshape(f[path.join(group_pointwise,material)],grid.prod()) + + return Geom(ma.reshape(grid,order='F'),size,origin,util.execution_stamp('Geom','load_DREAM3D')) + + + @staticmethod + def load_table(fname,coordinates,labels): + """ + Load an ASCII table. + + Parameters + ---------- + fname : str, file handle, or damask.Table + Table that contains geometry information. + coordinates : str + Label of the column containing the spatial coordinates. + labels : str or list of str + Label(s) of the columns containing the material definition. + Each unique combintation of values results in a material. + + """ + table = (fname if isinstance(fname,Table) else Table.load(fname)). \ + sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)]) + + grid,size,origin = grid_filters.cell_coord0_gridSizeOrigin(table.get(coordinates)) + + labels_ = [labels] if isinstance(labels,str) else labels + _,unique_inverse = np.unique(np.hstack([table.get(l) for l in labels_]),return_inverse=True,axis=0) + ma = unique_inverse.reshape(grid,order='F') + 1 + + return Geom(ma,size,origin,util.execution_stamp('Geom','load_table')) + + @staticmethod def _find_closest_seed(seeds, weights, point): return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) @@ -400,38 +463,9 @@ class Geom: ) - @staticmethod - def load_DREAM3D(fname,base_group,point_data=None,material='FeatureIds'): - root_dir ='DataContainers' - f = h5py.File(fname, 'r') - g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY') - size = f[path.join(g,'DIMENSIONS')][()] * f[path.join(g,'SPACING')][()] - grid = f[path.join(g,'DIMENSIONS')][()] - origin = f[path.join(g,'ORIGIN')][()] - group_pointwise = path.join(root_dir,base_group,point_data) - - ma = np.arange(1,np.product(grid)+1,dtype=int) if point_data is None else \ - np.reshape(f[path.join(group_pointwise,material)],grid.prod()) - - return Geom(ma.reshape(grid,order='F'),size,origin,util.execution_stamp('Geom','from_DREAM3D')) - - - @staticmethod - def load_table(fname,coordinates,labels): - table = Table.load(fname).sort_by([f'{i}_{coordinates}' for i in range(3,0,-1)]) - - grid,size,origin = grid_filters.cell_coord0_gridSizeOrigin(table.get(coordinates)) - - labels_ = [labels] if isinstance(labels,str) else labels - _,unique_inverse = np.unique(np.hstack([table.get(l) for l in labels_]),return_inverse=True,axis=0) - ma = unique_inverse.reshape(grid,order='F') + 1 - - return Geom(ma,size,origin,util.execution_stamp('Geom','from_table')) - - def save(self,fname,compress=True): """ - Generates vtk rectilinear grid. + Store as vtk rectilinear grid. Parameters ----------