Merge remote-tracking branch 'origin/geom-attributes-as-checked-properties' into development

This commit is contained in:
Martin Diehl 2020-11-10 14:50:28 +01:00
commit e90c20ccd6
1 changed files with 92 additions and 55 deletions

View File

@ -20,7 +20,7 @@ class Geom:
def __init__(self,material,size,origin=[0.0,0.0,0.0],comments=[]): def __init__(self,material,size,origin=[0.0,0.0,0.0],comments=[]):
""" """
New geometry definition from array of material, size, and origin. New geometry definition from array of materials, size, and origin.
Parameters Parameters
---------- ----------
@ -34,28 +34,10 @@ class Geom:
Comment lines. Comment lines.
""" """
if len(material.shape) != 3: self.material = material
raise ValueError(f'Invalid material shape {material.shape}.') self.size = size
elif material.dtype not in np.sctypes['float'] + np.sctypes['int']: self.origin = origin
raise TypeError(f'Invalid material data type {material.dtype}.') self.comments = comments
else:
self.material = np.copy(material)
if self.material.dtype in np.sctypes['float'] and \
np.all(self.material == self.material.astype(int).astype(float)):
self.material = self.material.astype(int)
if len(size) != 3 or any(np.array(size) <= 0):
raise ValueError(f'Invalid size {size}.')
else:
self.size = np.array(size)
if len(origin) != 3:
raise ValueError(f'Invalid origin {origin}.')
else:
self.origin = np.array(origin)
self.comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)]
def __repr__(self): def __repr__(self):
@ -113,13 +95,68 @@ class Geom:
return util.return_message(message) return util.return_message(message)
@property
def material(self):
"""Material indices."""
return self._material
@material.setter
def material(self,material):
if len(material.shape) != 3:
raise ValueError(f'Invalid material shape {material.shape}.')
elif material.dtype not in np.sctypes['float'] + np.sctypes['int']:
raise TypeError(f'Invalid material data type {material.dtype}.')
else:
self._material = np.copy(material)
if self.material.dtype in np.sctypes['float'] and \
np.all(self.material == self.material.astype(int).astype(float)):
self._material = self.material.astype(int)
@property
def size(self):
"""Physical size of geometry in meter."""
return self._size
@size.setter
def size(self,size):
if len(size) != 3 or any(np.array(size) <= 0):
raise ValueError(f'Invalid size {size}.')
else:
self._size = np.array(size)
@property
def origin(self):
"""Coordinates of geometry origin in meter."""
return self._origin
@origin.setter
def origin(self,origin):
if len(origin) != 3:
raise ValueError(f'Invalid origin {origin}.')
else:
self._origin = np.array(origin)
@property
def comments(self):
"""Comments/history of geometry."""
return self._comments
@comments.setter
def comments(self,comments):
self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)]
@property @property
def grid(self): def grid(self):
"""Grid dimension of geometry."""
return np.asarray(self.material.shape) return np.asarray(self.material.shape)
@property @property
def N_materials(self): def N_materials(self):
"""Number of (unique) material indices within geometry."""
return np.unique(self.material).size return np.unique(self.material).size
@ -132,7 +169,7 @@ class Geom:
---------- ----------
fname : str or or pathlib.Path fname : str or or pathlib.Path
Geometry file to read. Geometry file to read.
Valid extension is .vtr, it will be appended if not given. Valid extension is .vtr, which will be appended if not given.
""" """
v = VTK.load(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr') v = VTK.load(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr')
@ -153,7 +190,7 @@ class Geom:
Parameters Parameters
---------- ----------
fname : str or file handle fname : str, pathlib.Path, or file handle
Geometry file to read. Geometry file to read.
""" """
@ -221,26 +258,26 @@ class Geom:
fname : str fname : str
Filename of the DREAM.3D file Filename of the DREAM.3D file
base_group : str base_group : str
Name of the group (folder) below 'DataContainers'. For example Name of the group (folder) below 'DataContainers',
'SyntheticVolumeDataContainer'. for example 'SyntheticVolumeDataContainer'.
point_data : str, optional point_data : str, optional
Name of the group (folder) containing the pointwise material data, Name of the group (folder) containing the pointwise material data,
for example 'CellData'. Defaults to None, in which case points consecutively numbered. for example 'CellData'. Defaults to None, in which case points are consecutively numbered.
material : str, optional material : str, optional
Name of the dataset containing the material ID. Defaults to Name of the dataset containing the material ID.
'FeatureIds'. Defaults to 'FeatureIds'.
""" """
root_dir ='DataContainers' root_dir ='DataContainers'
f = h5py.File(fname, 'r') f = h5py.File(fname, 'r')
g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY') 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')][()] grid = f[path.join(g,'DIMENSIONS')][()]
size = f[path.join(g,'SPACING')][()] * grid
origin = f[path.join(g,'ORIGIN')][()] 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 \ ma = np.arange(grid.prod(),dtype=int) \
np.reshape(f[path.join(group_pointwise,material)],grid.prod()) if point_data is None else \
np.reshape(f[path.join(root_dir,base_group,point_data,material)],grid.prod())
return Geom(ma.reshape(grid,order='F'),size,origin,util.execution_stamp('Geom','load_DREAM3D')) return Geom(ma.reshape(grid,order='F'),size,origin,util.execution_stamp('Geom','load_DREAM3D'))
@ -248,18 +285,18 @@ class Geom:
@staticmethod @staticmethod
def from_table(table,coordinates,labels): def from_table(table,coordinates,labels):
""" """
Load an ASCII table. Derive geometry from an ASCII table.
Parameters Parameters
---------- ----------
table : damask.Table table : damask.Table
Table that contains material information. Table that contains material information.
coordinates : str coordinates : str
Label of the column containing the vector of spatial coordinates. Label of the vector column containing the spatial coordinates.
Need to be ordered (1./x fast, 3./z slow). Need to be ordered (1./x fast, 3./z slow).
labels : str or list of str labels : str or list of str
Label(s) of the columns containing the material definition. Label(s) of the columns containing the material definition.
Each unique combintation of values results in a material. Each unique combintation of values results in one material ID.
""" """
grid,size,origin = grid_filters.cell_coord0_gridSizeOrigin(table.get(coordinates)) grid,size,origin = grid_filters.cell_coord0_gridSizeOrigin(table.get(coordinates))
@ -293,8 +330,8 @@ class Geom:
weights : numpy.ndarray of shape (seeds.shape[0]) weights : numpy.ndarray of shape (seeds.shape[0])
Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation. Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation.
material : numpy.ndarray of shape (seeds.shape[0]), optional material : numpy.ndarray of shape (seeds.shape[0]), optional
Material ID of the seeds. Defaults to None, in which case materials are Material ID of the seeds.
consecutively numbered. Defaults to None, in which case materials are consecutively numbered.
periodic : Boolean, optional periodic : Boolean, optional
Perform a periodic tessellation. Defaults to True. Perform a periodic tessellation. Defaults to True.
@ -342,8 +379,8 @@ class Geom:
seeds : numpy.ndarray of shape (:,3) seeds : numpy.ndarray of shape (:,3)
Position of the seed points in meter. All points need to lay within the box. Position of the seed points in meter. All points need to lay within the box.
material : numpy.ndarray of shape (seeds.shape[0]), optional material : numpy.ndarray of shape (seeds.shape[0]), optional
Material ID of the seeds. Defaults to None, in which case materials are Material ID of the seeds.
consecutively numbered. Defaults to None, in which case materials are consecutively numbered.
periodic : Boolean, optional periodic : Boolean, optional
Perform a periodic tessellation. Defaults to True. Perform a periodic tessellation. Defaults to True.
@ -438,19 +475,19 @@ class Geom:
References References
---------- ----------
Surface curvature in triply-periodic minimal surface architectures as
a distinct design parameter in preparing advanced tissue engineering scaffolds
Sébastien B G Blanquer, Maike Werner, Markus Hannula, Shahriar Sharifi, Sébastien B G Blanquer, Maike Werner, Markus Hannula, Shahriar Sharifi,
Guillaume P R Lajoinie, David Eglin, Jari Hyttinen, André A Poot, and Dirk W Grijpma Guillaume P R Lajoinie, David Eglin, Jari Hyttinen, André A Poot, and Dirk W Grijpma
10.1088/1758-5090/aa6553 Surface curvature in triply-periodic minimal surface architectures as
a distinct design parameter in preparing advanced tissue engineering scaffolds
https://doi.org/10.1088/1758-5090/aa6553
Triply Periodic Bicontinuous Cubic Microdomain Morphologies by Symmetries
Meinhard Wohlgemuth, Nataliya Yufa, James Hoffman, and Edwin L. Thomas Meinhard Wohlgemuth, Nataliya Yufa, James Hoffman, and Edwin L. Thomas
10.1021/ma0019499 Triply Periodic Bicontinuous Cubic Microdomain Morphologies by Symmetries
https://doi.org/10.1021/ma0019499
Minisurf A minimal surface generator for finite element modeling and additive manufacturing
Meng-Ting Hsieh, Lorenzo Valdevit Meng-Ting Hsieh, Lorenzo Valdevit
10.1016/j.simpa.2020.100026 Minisurf A minimal surface generator for finite element modeling and additive manufacturing
https://doi.org/10.1016/j.simpa.2020.100026
""" """
x,y,z = np.meshgrid(periods*2.0*np.pi*(np.arange(grid[0])+0.5)/grid[0], x,y,z = np.meshgrid(periods*2.0*np.pi*(np.arange(grid[0])+0.5)/grid[0],
@ -465,7 +502,7 @@ class Geom:
def save(self,fname,compress=True): def save(self,fname,compress=True):
""" """
Store as vtk rectilinear grid. Store as VTK rectilinear grid.
Parameters Parameters
---------- ----------
@ -689,7 +726,7 @@ class Geom:
def renumber(self): def renumber(self):
"""Renumber sorted material indices to 0,...,N-1.""" """Renumber sorted material indices as 0,...,N-1."""
_,renumbered = np.unique(self.material,return_inverse=True) _,renumbered = np.unique(self.material,return_inverse=True)
return Geom(material = renumbered.reshape(self.grid), return Geom(material = renumbered.reshape(self.grid),