rename: Geom -> Grid

This commit is contained in:
Martin Diehl 2020-12-04 07:12:18 +01:00
parent 0fdefa5e78
commit 171d642dbd
74 changed files with 164 additions and 164 deletions

@ -1 +1 @@
Subproject commit fc27bbd6e028aa73545327aebdb206840063e135 Subproject commit a0475c50bfaf6f86f75345754188918a6e9d7134

View File

@ -65,7 +65,7 @@ if filenames == []: parser.error('no input file specified.')
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
geom = damask.Geom.load_DREAM3D(name,options.basegroup,options.pointwise) geom = damask.Grid.load_DREAM3D(name,options.basegroup,options.pointwise)
damask.util.croak(geom) damask.util.croak(geom)
geom.save_ASCII(os.path.splitext(name)[0]+'.geom') geom.save_ASCII(os.path.splitext(name)[0]+'.geom')

View File

@ -133,7 +133,7 @@ for i in range(3,np.max(microstructure)):
header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\ header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\
+ config_header + config_header
geom = damask.Geom(microstructure.reshape(grid), geom = damask.Grid(microstructure.reshape(grid),
size,-size/2, size,-size/2,
comments=header) comments=header)
damask.util.croak(geom) damask.util.croak(geom)

View File

@ -62,7 +62,7 @@ if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
geom = damask.Geom.load(StringIO(''.join(sys.stdin.read())) if name is None else name) geom = damask.Grid.load(StringIO(''.join(sys.stdin.read())) if name is None else name)
grid_original = geom.cells grid_original = geom.cells
damask.util.croak(geom) damask.util.croak(geom)
@ -169,7 +169,7 @@ for name in filenames:
# undo any changes involving immutable materials # undo any changes involving immutable materials
material = np.where(immutable, material_original,material) material = np.where(immutable, material_original,material)
damask.Geom(material = material[0:grid_original[0],0:grid_original[1],0:grid_original[2]], damask.Grid(material = material[0:grid_original[0],0:grid_original[1],0:grid_original[2]],
size = geom.size, size = geom.size,
origin = geom.origin, origin = geom.origin,
comments = geom.comments + [scriptID + ' ' + ' '.join(sys.argv[1:])], comments = geom.comments + [scriptID + ' ' + ' '.join(sys.argv[1:])],

View File

@ -196,7 +196,7 @@ if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
geom = damask.Geom.load(StringIO(''.join(sys.stdin.read())) if name is None else name) geom = damask.Grid.load(StringIO(''.join(sys.stdin.read())) if name is None else name)
material = geom.material.flatten(order='F') material = geom.material.flatten(order='F')
cmds = [\ cmds = [\

View File

@ -91,7 +91,7 @@ class myThread (threading.Thread):
perturbedSeedsTable.set('pos',coords).save(perturbedSeedsVFile,legacy=True) perturbedSeedsTable.set('pos',coords).save(perturbedSeedsVFile,legacy=True)
#--- do tesselation with perturbed seed file ------------------------------------------------------ #--- do tesselation with perturbed seed file ------------------------------------------------------
perturbedGeom = damask.Geom.from_Voronoi_tessellation(options.grid,np.ones(3),coords) perturbedGeom = damask.Grid.from_Voronoi_tessellation(options.grid,np.ones(3),coords)
#--- evaluate current seeds file ------------------------------------------------------------------ #--- evaluate current seeds file ------------------------------------------------------------------
@ -210,7 +210,7 @@ baseFile = os.path.splitext(os.path.basename(options.seedFile))[0]
points = np.array(options.grid).prod().astype('float') points = np.array(options.grid).prod().astype('float')
# ----------- calculate target distribution and bin edges # ----------- calculate target distribution and bin edges
targetGeom = damask.Geom.load_ASCII(os.path.splitext(os.path.basename(options.target))[0]+'.geom') targetGeom = damask.Grid.load_ASCII(os.path.splitext(os.path.basename(options.target))[0]+'.geom')
nMaterials = len(np.unique(targetGeom.material)) nMaterials = len(np.unique(targetGeom.material))
targetVolFrac = np.bincount(targetGeom.material.flatten())/targetGeom.cells.prod().astype(np.float) targetVolFrac = np.bincount(targetGeom.material.flatten())/targetGeom.cells.prod().astype(np.float)
target = [] target = []
@ -229,7 +229,7 @@ bestSeedsUpdate = time.time()
# ----------- tessellate initial seed file to get and evaluate geom file # ----------- tessellate initial seed file to get and evaluate geom file
bestSeedsVFile.seek(0) bestSeedsVFile.seek(0)
initialGeom = damask.Geom.from_Voronoi_tessellation(options.grid,np.ones(3),initial_seeds) initialGeom = damask.Grid.from_Voronoi_tessellation(options.grid,np.ones(3),initial_seeds)
if len(np.unique(targetGeom.material)) != nMaterials: if len(np.unique(targetGeom.material)) != nMaterials:
damask.util.croak('error. Material count mismatch') damask.util.croak('error. Material count mismatch')

View File

@ -52,7 +52,7 @@ options.box = np.array(options.box).reshape(3,2)
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
geom = damask.Geom.load_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) geom = damask.Grid.load_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
offset =(np.amin(options.box, axis=1)*geom.cells/geom.size).astype(int) offset =(np.amin(options.box, axis=1)*geom.cells/geom.size).astype(int)
box = np.amax(options.box, axis=1) \ box = np.amax(options.box, axis=1) \

View File

@ -32,7 +32,7 @@ from ._vtk import VTK # noqa
from ._colormap import Colormap # noqa from ._colormap import Colormap # noqa
from ._config import Config # noqa from ._config import Config # noqa
from ._configmaterial import ConfigMaterial # noqa from ._configmaterial import ConfigMaterial # noqa
from ._geom import Geom # noqa from ._grid import Grid # noqa
from ._result import Result # noqa from ._result import Result # noqa

View File

@ -16,21 +16,21 @@ from . import grid_filters
from . import Rotation from . import Rotation
class Geom: class Grid:
"""Geometry definition for grid solvers.""" """Geometry definition for grid solvers."""
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 materials, size, and origin. New grid definition from array of materials, size, and origin.
Parameters Parameters
---------- ----------
material : numpy.ndarray material : numpy.ndarray
Material index array (3D). Material index array (3D).
size : list or numpy.ndarray size : list or numpy.ndarray
Physical size of the geometry in meter. Physical size of the grid in meter.
origin : list or numpy.ndarray, optional origin : list or numpy.ndarray, optional
Physical origin of the geometry in meter. Physical origin of the grid in meter.
comments : list of str, optional comments : list of str, optional
Comment lines. Comment lines.
@ -42,7 +42,7 @@ class Geom:
def __repr__(self): def __repr__(self):
"""Basic information on geometry definition.""" """Basic information on grid definition."""
return util.srepr([ return util.srepr([
f'cells a b c: {util.srepr(self.cells, " x ")}', f'cells a b c: {util.srepr(self.cells, " x ")}',
f'size x y z: {util.srepr(self.size, " x ")}', f'size x y z: {util.srepr(self.size, " x ")}',
@ -53,12 +53,12 @@ class Geom:
def __copy__(self): def __copy__(self):
"""Copy geometry.""" """Copy grid."""
return copy.deepcopy(self) return copy.deepcopy(self)
def copy(self): def copy(self):
"""Copy geometry.""" """Copy grid."""
return self.__copy__() return self.__copy__()
@ -68,8 +68,8 @@ class Geom:
Parameters Parameters
---------- ----------
other : Geom other : damask.Grid
Geometry to compare self against. Grid to compare self against.
""" """
message = [] message = []
@ -117,7 +117,7 @@ class Geom:
@property @property
def size(self): def size(self):
"""Physical size of geometry in meter.""" """Physical size of grid in meter."""
return self._size return self._size
@size.setter @size.setter
@ -129,7 +129,7 @@ class Geom:
@property @property
def origin(self): def origin(self):
"""Coordinates of geometry origin in meter.""" """Coordinates of grid origin in meter."""
return self._origin return self._origin
@origin.setter @origin.setter
@ -141,7 +141,7 @@ class Geom:
@property @property
def comments(self): def comments(self):
"""Comments/history of geometry.""" """Comments, e.g. history of operations."""
return self._comments return self._comments
@comments.setter @comments.setter
@ -157,7 +157,7 @@ class Geom:
@property @property
def N_materials(self): def N_materials(self):
"""Number of (unique) material indices within geometry.""" """Number of (unique) material indices within grid."""
return np.unique(self.material).size return np.unique(self.material).size
@ -169,8 +169,8 @@ class Geom:
Parameters Parameters
---------- ----------
fname : str or or pathlib.Path fname : str or or pathlib.Path
Geometry file to read. Grid file to read. Valid extension is .vtr, which will be appended
Valid extension is .vtr, which will be appended if not given. 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')
@ -178,7 +178,7 @@ class Geom:
cells = np.array(v.vtk_data.GetDimensions())-1 cells = np.array(v.vtk_data.GetDimensions())-1
bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T
return Geom(material = v.get('material').reshape(cells,order='F'), return Grid(material = v.get('material').reshape(cells,order='F'),
size = bbox[1] - bbox[0], size = bbox[1] - bbox[0],
origin = bbox[0], origin = bbox[0],
comments=comments) comments=comments)
@ -248,7 +248,7 @@ class Geom:
if not np.any(np.mod(material,1) != 0.0): # no float present if not np.any(np.mod(material,1) != 0.0): # no float present
material = material.astype('int') - (1 if material.min() > 0 else 0) material = material.astype('int') - (1 if material.min() > 0 else 0)
return Geom(material.reshape(cells,order='F'),size,origin,comments) return Grid(material.reshape(cells,order='F'),size,origin,comments)
@staticmethod @staticmethod
@ -282,7 +282,7 @@ class Geom:
if point_data is None else \ if point_data is None else \
np.reshape(f[path.join(root_dir,base_group,point_data,material)],cells.prod()) np.reshape(f[path.join(root_dir,base_group,point_data,material)],cells.prod())
return Geom(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Geom','load_DREAM3D')) return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','load_DREAM3D'))
@staticmethod @staticmethod
@ -310,7 +310,7 @@ class Geom:
ma = np.arange(cells.prod()) if len(unique) == cells.prod() else \ ma = np.arange(cells.prod()) if len(unique) == cells.prod() else \
np.arange(unique.size)[np.argsort(pd.unique(unique_inverse))][unique_inverse] np.arange(unique.size)[np.argsort(pd.unique(unique_inverse))][unique_inverse]
return Geom(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Geom','from_table')) return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','from_table'))
@staticmethod @staticmethod
@ -327,7 +327,7 @@ class Geom:
cells : int numpy.ndarray of shape (3) cells : int numpy.ndarray of shape (3)
Number of cells in x,y,z direction. Number of cells in x,y,z direction.
size : list or numpy.ndarray of shape (3) size : list or numpy.ndarray of shape (3)
Physical size of the geometry in meter. Physical size of the grid in meter.
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.
weights : numpy.ndarray of shape (seeds.shape[0]) weights : numpy.ndarray of shape (seeds.shape[0])
@ -336,7 +336,7 @@ class Geom:
Material ID of the seeds. Material ID of the seeds.
Defaults to None, in which case materials are 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. Assume grid to be periodic. Defaults to True.
""" """
if periodic: if periodic:
@ -351,7 +351,7 @@ class Geom:
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
pool = mp.Pool(processes = int(environment.options['DAMASK_NUM_THREADS'])) pool = mp.Pool(processes = int(environment.options['DAMASK_NUM_THREADS']))
result = pool.map_async(partial(Geom._find_closest_seed,seeds_p,weights_p), [coord for coord in coords]) result = pool.map_async(partial(Grid._find_closest_seed,seeds_p,weights_p), [coord for coord in coords])
pool.close() pool.close()
pool.join() pool.join()
material_ = np.array(result.get()) material_ = np.array(result.get())
@ -362,9 +362,9 @@ class Geom:
else: else:
material_ = material_.reshape(cells) material_ = material_.reshape(cells)
return Geom(material = material_ if material is None else material[material_], return Grid(material = material_ if material is None else material[material_],
size = size, size = size,
comments = util.execution_stamp('Geom','from_Laguerre_tessellation'), comments = util.execution_stamp('Grid','from_Laguerre_tessellation'),
) )
@ -378,23 +378,23 @@ class Geom:
cells : int numpy.ndarray of shape (3) cells : int numpy.ndarray of shape (3)
Number of cells in x,y,z direction. Number of cells in x,y,z direction.
size : list or numpy.ndarray of shape (3) size : list or numpy.ndarray of shape (3)
Physical size of the geometry in meter. Physical size of the grid in meter.
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. Material ID of the seeds.
Defaults to None, in which case materials are 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. Assume grid to be periodic. Defaults to True.
""" """
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds) KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds)
devNull,material_ = KDTree.query(coords) devNull,material_ = KDTree.query(coords)
return Geom(material = (material_ if material is None else material[material_]).reshape(cells), return Grid(material = (material_ if material is None else material[material_]).reshape(cells),
size = size, size = size,
comments = util.execution_stamp('Geom','from_Voronoi_tessellation'), comments = util.execution_stamp('Grid','from_Voronoi_tessellation'),
) )
@ -450,7 +450,7 @@ class Geom:
cells : int numpy.ndarray of shape (3) cells : int numpy.ndarray of shape (3)
Number of cells in x,y,z direction. Number of cells in x,y,z direction.
size : list or numpy.ndarray of shape (3) size : list or numpy.ndarray of shape (3)
Physical size of the geometry in meter. Physical size of the grid in meter.
surface : str surface : str
Type of the minimal surface. See notes for details. Type of the minimal surface. See notes for details.
threshold : float, optional. threshold : float, optional.
@ -497,9 +497,9 @@ class Geom:
periods*2.0*np.pi*(np.arange(cells[1])+0.5)/cells[1], periods*2.0*np.pi*(np.arange(cells[1])+0.5)/cells[1],
periods*2.0*np.pi*(np.arange(cells[2])+0.5)/cells[2], periods*2.0*np.pi*(np.arange(cells[2])+0.5)/cells[2],
indexing='ij',sparse=True) indexing='ij',sparse=True)
return Geom(material = np.where(threshold < Geom._minimal_surface[surface](x,y,z),materials[1],materials[0]), return Grid(material = np.where(threshold < Grid._minimal_surface[surface](x,y,z),materials[1],materials[0]),
size = size, size = size,
comments = util.execution_stamp('Geom','from_minimal_surface'), comments = util.execution_stamp('Grid','from_minimal_surface'),
) )
@ -583,7 +583,7 @@ class Geom:
Retain original materials within primitive and fill outside. Retain original materials within primitive and fill outside.
Defaults to False. Defaults to False.
periodic : Boolean, optional periodic : Boolean, optional
Repeat primitive over boundaries. Defaults to True. Assume grid to be periodic. Defaults to True.
""" """
# radius and center # radius and center
@ -604,23 +604,23 @@ class Geom:
if periodic: # translate back to center if periodic: # translate back to center
mask = np.roll(mask,((c/self.size-0.5)*self.cells).round().astype(int),(0,1,2)) mask = np.roll(mask,((c/self.size-0.5)*self.cells).round().astype(int),(0,1,2))
return Geom(material = np.where(np.logical_not(mask) if inverse else mask, return Grid(material = np.where(np.logical_not(mask) if inverse else mask,
self.material, self.material,
np.nanmax(self.material)+1 if fill is None else fill), np.nanmax(self.material)+1 if fill is None else fill),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','add_primitive')], comments = self.comments+[util.execution_stamp('Grid','add_primitive')],
) )
def mirror(self,directions,reflect=False): def mirror(self,directions,reflect=False):
""" """
Mirror geometry along given directions. Mirror grid along given directions.
Parameters Parameters
---------- ----------
directions : iterable containing str directions : iterable containing str
Direction(s) along which the geometry is mirrored. Direction(s) along which the grid is mirrored.
Valid entries are 'x', 'y', 'z'. Valid entries are 'x', 'y', 'z'.
reflect : bool, optional reflect : bool, optional
Reflect (include) outermost layers. Defaults to False. Reflect (include) outermost layers. Defaults to False.
@ -640,21 +640,21 @@ class Geom:
if 'z' in directions: if 'z' in directions:
mat = np.concatenate([mat,mat[:,:,limits[0]:limits[1]:-1]],2) mat = np.concatenate([mat,mat[:,:,limits[0]:limits[1]:-1]],2)
return Geom(material = mat, return Grid(material = mat,
size = self.size/self.cells*np.asarray(mat.shape), size = self.size/self.cells*np.asarray(mat.shape),
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','mirror')], comments = self.comments+[util.execution_stamp('Grid','mirror')],
) )
def flip(self,directions): def flip(self,directions):
""" """
Flip geometry along given directions. Flip grid along given directions.
Parameters Parameters
---------- ----------
directions : iterable containing str directions : iterable containing str
Direction(s) along which the geometry is flipped. Direction(s) along which the grid is flipped.
Valid entries are 'x', 'y', 'z'. Valid entries are 'x', 'y', 'z'.
""" """
@ -664,26 +664,26 @@ class Geom:
mat = np.flip(self.material, (valid.index(d) for d in directions if d in valid)) mat = np.flip(self.material, (valid.index(d) for d in directions if d in valid))
return Geom(material = mat, return Grid(material = mat,
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','flip')], comments = self.comments+[util.execution_stamp('Grid','flip')],
) )
def scale(self,cells,periodic=True): def scale(self,cells,periodic=True):
""" """
Scale geometry to new cells. Scale grid to new cells.
Parameters Parameters
---------- ----------
cells : numpy.ndarray of shape (3) cells : numpy.ndarray of shape (3)
Number of cells in x,y,z direction. Number of cells in x,y,z direction.
periodic : Boolean, optional periodic : Boolean, optional
Assume geometry to be periodic. Defaults to True. Assume grid to be periodic. Defaults to True.
""" """
return Geom(material = ndimage.interpolation.zoom( return Grid(material = ndimage.interpolation.zoom(
self.material, self.material,
cells/self.cells, cells/self.cells,
output=self.material.dtype, output=self.material.dtype,
@ -693,13 +693,13 @@ class Geom:
), ),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','scale')], comments = self.comments+[util.execution_stamp('Grid','scale')],
) )
def clean(self,stencil=3,selection=None,periodic=True): def clean(self,stencil=3,selection=None,periodic=True):
""" """
Smooth geometry by selecting most frequent material index within given stencil at each location. Smooth grid by selecting most frequent material index within given stencil at each location.
Parameters Parameters
---------- ----------
@ -708,7 +708,7 @@ class Geom:
selection : list, optional selection : list, optional
Field values that can be altered. Defaults to all. Field values that can be altered. Defaults to all.
periodic : Boolean, optional periodic : Boolean, optional
Assume geometry to be periodic. Defaults to True. Assume grid to be periodic. Defaults to True.
""" """
def mostFrequent(arr,selection=None): def mostFrequent(arr,selection=None):
@ -719,7 +719,7 @@ class Geom:
else: else:
return me return me
return Geom(material = ndimage.filters.generic_filter( return Grid(material = ndimage.filters.generic_filter(
self.material, self.material,
mostFrequent, mostFrequent,
size=(stencil if selection is None else stencil//2*2+1,)*3, size=(stencil if selection is None else stencil//2*2+1,)*3,
@ -728,7 +728,7 @@ class Geom:
).astype(self.material.dtype), ).astype(self.material.dtype),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','clean')], comments = self.comments+[util.execution_stamp('Grid','clean')],
) )
@ -736,21 +736,21 @@ class Geom:
"""Renumber sorted material indices as 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.cells), return Grid(material = renumbered.reshape(self.cells),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','renumber')], comments = self.comments+[util.execution_stamp('Grid','renumber')],
) )
def rotate(self,R,fill=None): def rotate(self,R,fill=None):
""" """
Rotate geometry (pad if required). Rotate grid (pad if required).
Parameters Parameters
---------- ----------
R : damask.Rotation R : damask.Rotation
Rotation to apply to the geometry. Rotation to apply to the grid.
fill : int or float, optional fill : int or float, optional
Material index to fill the corners. Defaults to material.max() + 1. Material index to fill the corners. Defaults to material.max() + 1.
@ -774,23 +774,23 @@ class Geom:
origin = self.origin-(np.asarray(material_in.shape)-self.cells)*.5 * self.size/self.cells origin = self.origin-(np.asarray(material_in.shape)-self.cells)*.5 * self.size/self.cells
return Geom(material = material_in, return Grid(material = material_in,
size = self.size/self.cells*np.asarray(material_in.shape), size = self.size/self.cells*np.asarray(material_in.shape),
origin = origin, origin = origin,
comments = self.comments+[util.execution_stamp('Geom','rotate')], comments = self.comments+[util.execution_stamp('Grid','rotate')],
) )
def canvas(self,cells=None,offset=None,fill=None): def canvas(self,cells=None,offset=None,fill=None):
""" """
Crop or enlarge/pad geometry. Crop or enlarge/pad grid.
Parameters Parameters
---------- ----------
cells : numpy.ndarray of shape (3) cells : numpy.ndarray of shape (3)
Number of cells x,y,z direction. Number of cells x,y,z direction.
offset : numpy.ndarray of shape (3) offset : numpy.ndarray of shape (3)
Offset (measured in cells) from old to new geometry [0,0,0]. Offset (measured in cells) from old to new grid [0,0,0].
fill : int or float, optional fill : int or float, optional
Material index to fill the background. Defaults to material.max() + 1. Material index to fill the background. Defaults to material.max() + 1.
@ -808,10 +808,10 @@ class Geom:
canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.material[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.material[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]]
return Geom(material = canvas, return Grid(material = canvas,
size = self.size/self.cells*np.asarray(canvas.shape), size = self.size/self.cells*np.asarray(canvas.shape),
origin = self.origin+offset*self.size/self.cells, origin = self.origin+offset*self.size/self.cells,
comments = self.comments+[util.execution_stamp('Geom','canvas')], comments = self.comments+[util.execution_stamp('Grid','canvas')],
) )
@ -833,10 +833,10 @@ class Geom:
mp = np.vectorize(mp) mp = np.vectorize(mp)
mapper = dict(zip(from_material,to_material)) mapper = dict(zip(from_material,to_material))
return Geom(material = mp(self.material,mapper).reshape(self.cells), return Grid(material = mp(self.material,mapper).reshape(self.cells),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','substitute')], comments = self.comments+[util.execution_stamp('Grid','substitute')],
) )
@ -847,10 +847,10 @@ class Geom:
sort_idx = np.argsort(from_ma) sort_idx = np.argsort(from_ma)
ma = np.unique(a)[sort_idx][np.searchsorted(from_ma,a,sorter = sort_idx)] ma = np.unique(a)[sort_idx][np.searchsorted(from_ma,a,sorter = sort_idx)]
return Geom(material = ma.reshape(self.cells,order='F'), return Grid(material = ma.reshape(self.cells,order='F'),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','sort')], comments = self.comments+[util.execution_stamp('Grid','sort')],
) )
@ -860,7 +860,7 @@ class Geom:
Different from themselves (or listed as triggers) within a given (cubic) vicinity, Different from themselves (or listed as triggers) within a given (cubic) vicinity,
i.e. within the region close to a grain/phase boundary. i.e. within the region close to a grain/phase boundary.
ToDo: use include/exclude as in seeds.from_geom ToDo: use include/exclude as in seeds.from_grid
Parameters Parameters
---------- ----------
@ -874,7 +874,7 @@ class Geom:
List of material indices that trigger a change. List of material indices that trigger a change.
Defaults to [], meaning that any different neighbor triggers a change. Defaults to [], meaning that any different neighbor triggers a change.
periodic : Boolean, optional periodic : Boolean, optional
Assume geometry to be periodic. Defaults to True. Assume grid to be periodic. Defaults to True.
""" """
def tainted_neighborhood(stencil,trigger): def tainted_neighborhood(stencil,trigger):
@ -891,10 +891,10 @@ class Geom:
mode='wrap' if periodic else 'nearest', mode='wrap' if periodic else 'nearest',
extra_keywords={'trigger':trigger}) extra_keywords={'trigger':trigger})
return Geom(material = np.where(mask, self.material + offset_,self.material), return Grid(material = np.where(mask, self.material + offset_,self.material),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Geom','vicinity_offset')], comments = self.comments+[util.execution_stamp('Grid','vicinity_offset')],
) )
@ -904,10 +904,10 @@ class Geom:
Parameters Parameters
---------- ----------
periodic : bool, optional periodic : Boolean, optional
Show boundaries across periodicity. Defaults to True. Assume grid to be periodic. Defaults to True.
directions : iterable containing str, optional directions : iterable containing str, optional
Direction(s) along which the geometry is mirrored. Direction(s) along which the boundaries are determined.
Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'. Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'.
""" """

View File

@ -4,7 +4,7 @@ Filters for operations on regular grids.
Notes Notes
----- -----
The grids are defined as (x,y,z,...) where x is fastest and z is slowest. The grids are defined as (x,y,z,...) where x is fastest and z is slowest.
This convention is consistent with the geom file format. This convention is consistent with the layout in grid vtr files.
When converting to/from a plain list (e.g. storage in ASCII table), When converting to/from a plain list (e.g. storage in ASCII table),
the following operations are required for tensorial data: the following operations are required for tensorial data:

View File

@ -77,14 +77,14 @@ def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,rng_seed=
return coords return coords
def from_geom(geom,selection=None,invert=False,average=False,periodic=True): def from_grid(grid,selection=None,invert=False,average=False,periodic=True):
""" """
Create seed from existing geometry description. Create seed from existing grid description.
Parameters Parameters
---------- ----------
geom : damask.Geom grid : damask.Grid
Geometry, from which the material IDs are used as seeds. Grid, from which the material IDs are used as seeds.
selection : iterable of integers, optional selection : iterable of integers, optional
Material IDs to consider. Material IDs to consider.
invert : boolean, false invert : boolean, false
@ -95,10 +95,10 @@ def from_geom(geom,selection=None,invert=False,average=False,periodic=True):
Center of gravity with periodic boundaries. Center of gravity with periodic boundaries.
""" """
material = geom.material.reshape((-1,1),order='F') material = grid.material.reshape((-1,1),order='F')
mask = _np.full(geom.cells.prod(),True,dtype=bool) if selection is None else \ mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \
_np.isin(material,selection,invert=invert).flatten() _np.isin(material,selection,invert=invert).flatten()
coords = grid_filters.coordinates0_point(geom.cells,geom.size).reshape(-1,3,order='F') coords = grid_filters.coordinates0_point(grid.cells,grid.size).reshape(-1,3,order='F')
if not average: if not average:
return (coords[mask],material[mask]) return (coords[mask],material[mask])
@ -106,8 +106,8 @@ def from_geom(geom,selection=None,invert=False,average=False,periodic=True):
materials = _np.unique(material[mask]) materials = _np.unique(material[mask])
coords_ = _np.zeros((materials.size,3),dtype=float) coords_ = _np.zeros((materials.size,3),dtype=float)
for i,mat in enumerate(materials): for i,mat in enumerate(materials):
pc = (2*_np.pi*coords[material[:,0]==mat,:]-geom.origin)/geom.size pc = (2*_np.pi*coords[material[:,0]==mat,:]-grid.origin)/grid.size
coords_[i] = geom.origin + geom.size / 2 / _np.pi * (_np.pi + coords_[i] = grid.origin + grid.size / 2 / _np.pi * (_np.pi +
_np.arctan2(-_np.average(_np.sin(pc),axis=0), _np.arctan2(-_np.average(_np.sin(pc),axis=0),
-_np.average(_np.cos(pc),axis=0))) \ -_np.average(_np.cos(pc),axis=0))) \
if periodic else \ if periodic else \

View File

@ -2,7 +2,7 @@ import pytest
import numpy as np import numpy as np
from damask import VTK from damask import VTK
from damask import Geom from damask import Grid
from damask import Table from damask import Table
from damask import Rotation from damask import Rotation
from damask import util from damask import util
@ -10,7 +10,7 @@ from damask import seeds
from damask import grid_filters from damask import grid_filters
def geom_equal(a,b): def grid_equal(a,b):
return np.all(a.material == b.material) and \ return np.all(a.material == b.material) and \
np.all(a.cells == b.cells) and \ np.all(a.cells == b.cells) and \
np.allclose(a.size, b.size) and \ np.allclose(a.size, b.size) and \
@ -23,15 +23,15 @@ def default():
np.arange(2,42), np.arange(2,42),
np.ones(40,dtype=int)*2, np.ones(40,dtype=int)*2,
np.arange(1,41))).reshape(8,5,4,order='F') np.arange(1,41))).reshape(8,5,4,order='F')
return Geom(x,[8e-6,5e-6,4e-6]) return Grid(x,[8e-6,5e-6,4e-6])
@pytest.fixture @pytest.fixture
def ref_path(ref_path_base): def ref_path(ref_path_base):
"""Directory containing reference results.""" """Directory containing reference results."""
return ref_path_base/'Geom' return ref_path_base/'Grid'
class TestGeom: class TestGrid:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def _patch_execution_stamp(self, patch_execution_stamp): def _patch_execution_stamp(self, patch_execution_stamp):
@ -46,7 +46,7 @@ class TestGeom:
def test_diff_not_equal(self,default): def test_diff_not_equal(self,default):
new = Geom(default.material[1:,1:,1:]+1,default.size*.9,np.ones(3)-default.origin,comments=['modified']) new = Grid(default.material[1:,1:,1:]+1,default.size*.9,np.ones(3)-default.origin,comments=['modified'])
assert str(default.diff(new)) != '' assert str(default.diff(new)) != ''
def test_repr(self,default): def test_repr(self,default):
@ -54,36 +54,36 @@ class TestGeom:
def test_read_write_vtr(self,default,tmp_path): def test_read_write_vtr(self,default,tmp_path):
default.save(tmp_path/'default') default.save(tmp_path/'default')
new = Geom.load(tmp_path/'default.vtr') new = Grid.load(tmp_path/'default.vtr')
assert geom_equal(new,default) assert grid_equal(new,default)
def test_invalid_vtr(self,tmp_path): def test_invalid_vtr(self,tmp_path):
v = VTK.from_rectilinear_grid(np.random.randint(5,10,3)*2,np.random.random(3) + 1.0) v = VTK.from_rectilinear_grid(np.random.randint(5,10,3)*2,np.random.random(3) + 1.0)
v.save(tmp_path/'no_materialpoint.vtr',parallel=False) v.save(tmp_path/'no_materialpoint.vtr',parallel=False)
with pytest.raises(ValueError): with pytest.raises(ValueError):
Geom.load(tmp_path/'no_materialpoint.vtr') Grid.load(tmp_path/'no_materialpoint.vtr')
def test_invalid_material(self): def test_invalid_material(self):
with pytest.raises(TypeError): with pytest.raises(TypeError):
Geom(np.zeros((3,3,3),dtype='complex'),np.ones(3)) Grid(np.zeros((3,3,3),dtype='complex'),np.ones(3))
def test_cast_to_int(self): def test_cast_to_int(self):
g = Geom(np.zeros((3,3,3)),np.ones(3)) g = Grid(np.zeros((3,3,3)),np.ones(3))
assert g.material.dtype in np.sctypes['int'] assert g.material.dtype in np.sctypes['int']
def test_invalid_size(self,default): def test_invalid_size(self,default):
with pytest.raises(ValueError): with pytest.raises(ValueError):
Geom(default.material[1:,1:,1:], Grid(default.material[1:,1:,1:],
size=np.ones(2)) size=np.ones(2))
def test_save_load_ASCII(self,default,tmp_path): def test_save_load_ASCII(self,default,tmp_path):
default.save_ASCII(tmp_path/'ASCII') default.save_ASCII(tmp_path/'ASCII')
default.material -= 1 default.material -= 1
assert geom_equal(Geom.load_ASCII(tmp_path/'ASCII'),default) assert grid_equal(Grid.load_ASCII(tmp_path/'ASCII'),default)
def test_invalid_origin(self,default): def test_invalid_origin(self,default):
with pytest.raises(ValueError): with pytest.raises(ValueError):
Geom(default.material[1:,1:,1:], Grid(default.material[1:,1:,1:],
size=np.ones(3), size=np.ones(3),
origin=np.ones(4)) origin=np.ones(4))
@ -91,14 +91,14 @@ class TestGeom:
def test_invalid_materials_shape(self,default): def test_invalid_materials_shape(self,default):
material = np.ones((3,3)) material = np.ones((3,3))
with pytest.raises(ValueError): with pytest.raises(ValueError):
Geom(material, Grid(material,
size=np.ones(3)) size=np.ones(3))
def test_invalid_materials_type(self,default): def test_invalid_materials_type(self,default):
material = np.random.randint(1,300,(3,4,5))==1 material = np.random.randint(1,300,(3,4,5))==1
with pytest.raises(TypeError): with pytest.raises(TypeError):
Geom(material) Grid(material)
@pytest.mark.parametrize('directions,reflect',[ @pytest.mark.parametrize('directions,reflect',[
@ -113,7 +113,7 @@ class TestGeom:
tag = f'directions_{"-".join(directions)}+reflect_{reflect}' tag = f'directions_{"-".join(directions)}+reflect_{reflect}'
reference = ref_path/f'mirror_{tag}.vtr' reference = ref_path/f'mirror_{tag}.vtr'
if update: modified.save(reference) if update: modified.save(reference)
assert geom_equal(Geom.load(reference), assert grid_equal(Grid.load(reference),
modified) modified)
@ -135,17 +135,17 @@ class TestGeom:
tag = f'directions_{"-".join(directions)}' tag = f'directions_{"-".join(directions)}'
reference = ref_path/f'flip_{tag}.vtr' reference = ref_path/f'flip_{tag}.vtr'
if update: modified.save(reference) if update: modified.save(reference)
assert geom_equal(Geom.load(reference), assert grid_equal(Grid.load(reference),
modified) modified)
def test_flip_invariant(self,default): def test_flip_invariant(self,default):
assert geom_equal(default,default.flip([])) assert grid_equal(default,default.flip([]))
@pytest.mark.parametrize('direction',[['x'],['x','y']]) @pytest.mark.parametrize('direction',[['x'],['x','y']])
def test_flip_double(self,default,direction): def test_flip_double(self,default,direction):
assert geom_equal(default,default.flip(direction).flip(direction)) assert grid_equal(default,default.flip(direction).flip(direction))
@pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]]) @pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]])
@ -162,7 +162,7 @@ class TestGeom:
reference = ref_path/f'clean_{stencil}_{"+".join(map(str,[None] if selection is None else selection))}_{periodic}' reference = ref_path/f'clean_{stencil}_{"+".join(map(str,[None] if selection is None else selection))}_{periodic}'
if update and stencil > 1: if update and stencil > 1:
current.save(reference) current.save(reference)
assert geom_equal(Geom.load(reference) if stencil > 1 else default, assert grid_equal(Grid.load(reference) if stencil > 1 else default,
current current
) )
@ -181,7 +181,7 @@ class TestGeom:
tag = f'grid_{util.srepr(cells,"-")}' tag = f'grid_{util.srepr(cells,"-")}'
reference = ref_path/f'scale_{tag}.vtr' reference = ref_path/f'scale_{tag}.vtr'
if update: modified.save(reference) if update: modified.save(reference)
assert geom_equal(Geom.load(reference), assert grid_equal(Grid.load(reference),
modified) modified)
@ -190,21 +190,21 @@ class TestGeom:
for m in np.unique(material): for m in np.unique(material):
material[material==m] = material.max() + np.random.randint(1,30) material[material==m] = material.max() + np.random.randint(1,30)
default.material -= 1 default.material -= 1
modified = Geom(material, modified = Grid(material,
default.size, default.size,
default.origin) default.origin)
assert not geom_equal(modified,default) assert not grid_equal(modified,default)
assert geom_equal(default, assert grid_equal(default,
modified.renumber()) modified.renumber())
def test_substitute(self,default): def test_substitute(self,default):
offset = np.random.randint(1,500) offset = np.random.randint(1,500)
modified = Geom(default.material + offset, modified = Grid(default.material + offset,
default.size, default.size,
default.origin) default.origin)
assert not geom_equal(modified,default) assert not grid_equal(modified,default)
assert geom_equal(default, assert grid_equal(default,
modified.substitute(np.arange(default.material.max())+1+offset, modified.substitute(np.arange(default.material.max())+1+offset,
np.arange(default.material.max())+1)) np.arange(default.material.max())+1))
@ -212,12 +212,12 @@ class TestGeom:
f = np.unique(default.material.flatten())[:np.random.randint(1,default.material.max())] f = np.unique(default.material.flatten())[:np.random.randint(1,default.material.max())]
t = np.random.permutation(f) t = np.random.permutation(f)
modified = default.substitute(f,t) modified = default.substitute(f,t)
assert np.array_equiv(t,f) or (not geom_equal(modified,default)) assert np.array_equiv(t,f) or (not grid_equal(modified,default))
assert geom_equal(default, modified.substitute(t,f)) assert grid_equal(default, modified.substitute(t,f))
def test_sort(self): def test_sort(self):
cells = np.random.randint(5,20,3) cells = np.random.randint(5,20,3)
m = Geom(np.random.randint(1,20,cells)*3,np.ones(3)).sort().material.flatten(order='F') m = Grid(np.random.randint(1,20,cells)*3,np.ones(3)).sort().material.flatten(order='F')
for i,v in enumerate(m): for i,v in enumerate(m):
assert i==0 or v > m[:i].max() or v in m[:i] assert i==0 or v > m[:i].max() or v in m[:i]
@ -227,7 +227,7 @@ class TestGeom:
modified = default.copy() modified = default.copy()
for i in range(np.rint(360/axis_angle[3]).astype(int)): for i in range(np.rint(360/axis_angle[3]).astype(int)):
modified.rotate(Rotation.from_axis_angle(axis_angle,degrees=True)) modified.rotate(Rotation.from_axis_angle(axis_angle,degrees=True))
assert geom_equal(default,modified) assert grid_equal(default,modified)
@pytest.mark.parametrize('Eulers',[[32.0,68.0,21.0], @pytest.mark.parametrize('Eulers',[[32.0,68.0,21.0],
@ -237,7 +237,7 @@ class TestGeom:
tag = f'Eulers_{util.srepr(Eulers,"-")}' tag = f'Eulers_{util.srepr(Eulers,"-")}'
reference = ref_path/f'rotate_{tag}.vtr' reference = ref_path/f'rotate_{tag}.vtr'
if update: modified.save(reference) if update: modified.save(reference)
assert geom_equal(Geom.load(reference), assert grid_equal(Grid.load(reference),
modified) modified)
@ -263,8 +263,8 @@ class TestGeom:
o = np.random.random(3)-.5 o = np.random.random(3)-.5
g = np.random.randint(8,32,(3)) g = np.random.randint(8,32,(3))
s = np.random.random(3)+.5 s = np.random.random(3)+.5
G_1 = Geom(np.ones(g,'i'),s,o).add_primitive(diameter,center1,exponent) G_1 = Grid(np.ones(g,'i'),s,o).add_primitive(diameter,center1,exponent)
G_2 = Geom(np.ones(g,'i'),s,o).add_primitive(diameter,center2,exponent) G_2 = Grid(np.ones(g,'i'),s,o).add_primitive(diameter,center2,exponent)
assert np.count_nonzero(G_1.material!=2) == np.count_nonzero(G_2.material!=2) assert np.count_nonzero(G_1.material!=2) == np.count_nonzero(G_2.material!=2)
@ -279,9 +279,9 @@ class TestGeom:
g = np.random.randint(8,32,(3)) g = np.random.randint(8,32,(3))
s = np.random.random(3)+.5 s = np.random.random(3)+.5
fill = np.random.randint(10)+2 fill = np.random.randint(10)+2
G_1 = Geom(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,inverse=inverse,periodic=periodic) G_1 = Grid(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,inverse=inverse,periodic=periodic)
G_2 = Geom(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,Rotation.from_random(),inverse,periodic=periodic) G_2 = Grid(np.ones(g,'i'),s).add_primitive(.3,center,1,fill,Rotation.from_random(),inverse,periodic=periodic)
assert geom_equal(G_1,G_2) assert grid_equal(G_1,G_2)
@pytest.mark.parametrize('trigger',[[1],[]]) @pytest.mark.parametrize('trigger',[[1],[]])
@ -300,9 +300,9 @@ class TestGeom:
if len(trigger) > 0: if len(trigger) > 0:
m2[m==1] = 1 m2[m==1] = 1
geom = Geom(m,np.random.rand(3)).vicinity_offset(vicinity,offset,trigger=trigger) grid = Grid(m,np.random.rand(3)).vicinity_offset(vicinity,offset,trigger=trigger)
assert np.all(m2==geom.material) assert np.all(m2==grid.material)
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
@ -318,9 +318,9 @@ class TestGeom:
size = np.random.random(3) + 1.0 size = np.random.random(3) + 1.0
N_seeds= np.random.randint(10,30) N_seeds= np.random.randint(10,30)
seeds = np.random.rand(N_seeds,3) * np.broadcast_to(size,(N_seeds,3)) seeds = np.random.rand(N_seeds,3) * np.broadcast_to(size,(N_seeds,3))
Voronoi = Geom.from_Voronoi_tessellation( cells,size,seeds, np.arange(N_seeds)+5,periodic) Voronoi = Grid.from_Voronoi_tessellation( cells,size,seeds, np.arange(N_seeds)+5,periodic)
Laguerre = Geom.from_Laguerre_tessellation(cells,size,seeds,np.ones(N_seeds),np.arange(N_seeds)+5,periodic) Laguerre = Grid.from_Laguerre_tessellation(cells,size,seeds,np.ones(N_seeds),np.arange(N_seeds)+5,periodic)
assert geom_equal(Laguerre,Voronoi) assert grid_equal(Laguerre,Voronoi)
def test_Laguerre_weights(self): def test_Laguerre_weights(self):
@ -331,7 +331,7 @@ class TestGeom:
weights= np.full((N_seeds),-np.inf) weights= np.full((N_seeds),-np.inf)
ms = np.random.randint(N_seeds) ms = np.random.randint(N_seeds)
weights[ms] = np.random.random() weights[ms] = np.random.random()
Laguerre = Geom.from_Laguerre_tessellation(cells,size,seeds,weights,periodic=np.random.random()>0.5) Laguerre = Grid.from_Laguerre_tessellation(cells,size,seeds,weights,periodic=np.random.random()>0.5)
assert np.all(Laguerre.material == ms) assert np.all(Laguerre.material == ms)
@ -343,10 +343,10 @@ class TestGeom:
material = np.zeros(cells) material = np.zeros(cells)
material[:,cells[1]//2:,:] = 1 material[:,cells[1]//2:,:] = 1
if approach == 'Laguerre': if approach == 'Laguerre':
geom = Geom.from_Laguerre_tessellation(cells,size,seeds,np.ones(2),periodic=np.random.random()>0.5) grid = Grid.from_Laguerre_tessellation(cells,size,seeds,np.ones(2),periodic=np.random.random()>0.5)
elif approach == 'Voronoi': elif approach == 'Voronoi':
geom = Geom.from_Voronoi_tessellation(cells,size,seeds, periodic=np.random.random()>0.5) grid = Grid.from_Voronoi_tessellation(cells,size,seeds, periodic=np.random.random()>0.5)
assert np.all(geom.material == material) assert np.all(grid.material == material)
@pytest.mark.parametrize('surface',['Schwarz P', @pytest.mark.parametrize('surface',['Schwarz P',
@ -368,9 +368,9 @@ class TestGeom:
threshold = 2*np.random.rand()-1. threshold = 2*np.random.rand()-1.
periods = np.random.randint(2)+1 periods = np.random.randint(2)+1
materials = np.random.randint(0,40,2) materials = np.random.randint(0,40,2)
geom = Geom.from_minimal_surface(cells,size,surface,threshold,periods,materials) grid = Grid.from_minimal_surface(cells,size,surface,threshold,periods,materials)
assert set(geom.material.flatten()) | set(materials) == set(materials) \ assert set(grid.material.flatten()) | set(materials) == set(materials) \
and (geom.size == size).all() and (geom.cells == cells).all() and (grid.size == size).all() and (grid.cells == cells).all()
@pytest.mark.parametrize('surface,threshold',[('Schwarz P',0), @pytest.mark.parametrize('surface,threshold',[('Schwarz P',0),
('Double Primitive',-1./6.), ('Double Primitive',-1./6.),
@ -387,8 +387,8 @@ class TestGeom:
]) ])
def test_minimal_surface_volume(self,surface,threshold): def test_minimal_surface_volume(self,surface,threshold):
cells = np.ones(3,dtype=int)*64 cells = np.ones(3,dtype=int)*64
geom = Geom.from_minimal_surface(cells,np.ones(3),surface,threshold) grid = Grid.from_minimal_surface(cells,np.ones(3),surface,threshold)
assert np.isclose(np.count_nonzero(geom.material==1)/np.prod(geom.cells),.5,rtol=1e-3) assert np.isclose(np.count_nonzero(grid.material==1)/np.prod(grid.cells),.5,rtol=1e-3)
def test_from_table(self): def test_from_table(self):
@ -398,7 +398,7 @@ class TestGeom:
z=np.ones(cells.prod()) z=np.ones(cells.prod())
z[cells[:2].prod()*int(cells[2]/2):]=0 z[cells[:2].prod()*int(cells[2]/2):]=0
t = Table(np.column_stack((coords,z)),{'coords':3,'z':1}) t = Table(np.column_stack((coords,z)),{'coords':3,'z':1})
g = Geom.from_table(t,'coords',['1_coords','z']) g = Grid.from_table(t,'coords',['1_coords','z'])
assert g.N_materials == g.cells[0]*2 and (g.material[:,:,-1]-g.material[:,:,0] == cells[0]).all() assert g.N_materials == g.cells[0]*2 and (g.material[:,:,-1]-g.material[:,:,0] == cells[0]).all()
@ -406,16 +406,16 @@ class TestGeom:
cells = np.random.randint(60,100,3) cells = np.random.randint(60,100,3)
size = np.ones(3)+np.random.rand(3) size = np.ones(3)+np.random.rand(3)
s = seeds.from_random(size,np.random.randint(60,100)) s = seeds.from_random(size,np.random.randint(60,100))
geom = Geom.from_Voronoi_tessellation(cells,size,s) grid = Grid.from_Voronoi_tessellation(cells,size,s)
coords = grid_filters.coordinates0_point(cells,size) coords = grid_filters.coordinates0_point(cells,size)
t = Table(np.column_stack((coords.reshape(-1,3,order='F'),geom.material.flatten(order='F'))),{'c':3,'m':1}) t = Table(np.column_stack((coords.reshape(-1,3,order='F'),grid.material.flatten(order='F'))),{'c':3,'m':1})
assert geom_equal(geom.sort().renumber(),Geom.from_table(t,'c',['m'])) assert grid_equal(grid.sort().renumber(),Grid.from_table(t,'c',['m']))
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
@pytest.mark.parametrize('direction',['x','y','z',['x','y'],'zy','xz',['x','y','z']]) @pytest.mark.parametrize('direction',['x','y','z',['x','y'],'zy','xz',['x','y','z']])
def test_get_grain_boundaries(self,update,ref_path,periodic,direction): def test_get_grain_boundaries(self,update,ref_path,periodic,direction):
geom=Geom.load(ref_path/'get_grain_boundaries_8g12x15x20.vtr') grid=Grid.load(ref_path/'get_grain_boundaries_8g12x15x20.vtr')
current=geom.get_grain_boundaries(periodic,direction) current=grid.get_grain_boundaries(periodic,direction)
if update: if update:
current.save(ref_path/f'get_grain_boundaries_8g12x15x20_{direction}_{periodic}.vtu',parallel=False) current.save(ref_path/f'get_grain_boundaries_8g12x15x20_{direction}_{periodic}.vtu',parallel=False)
reference=VTK.load(ref_path/f'get_grain_boundaries_8g12x15x20_{"".join(direction)}_{periodic}.vtu') reference=VTK.load(ref_path/f'get_grain_boundaries_8g12x15x20_{"".join(direction)}_{periodic}.vtu')

View File

@ -4,7 +4,7 @@ from scipy.spatial import cKDTree
from damask import seeds from damask import seeds
from damask import grid_filters from damask import grid_filters
from damask import Geom from damask import Grid
class TestSeeds: class TestSeeds:
@ -26,37 +26,37 @@ class TestSeeds:
cKDTree(coords).query(coords, 2) cKDTree(coords).query(coords, 2)
assert (0<= coords).all() and (coords<size).all() and np.min(min_dists[:,1])>=distance assert (0<= coords).all() and (coords<size).all() and np.min(min_dists[:,1])>=distance
def test_from_geom_reconstruct(self): def test_from_grid_reconstruct(self):
cells = np.random.randint(10,20,3) cells = np.random.randint(10,20,3)
N_seeds = np.random.randint(30,300) N_seeds = np.random.randint(30,300)
size = np.ones(3) + np.random.random(3) size = np.ones(3) + np.random.random(3)
coords = seeds.from_random(size,N_seeds,cells) coords = seeds.from_random(size,N_seeds,cells)
geom_1 = Geom.from_Voronoi_tessellation(cells,size,coords) grid_1 = Grid.from_Voronoi_tessellation(cells,size,coords)
coords,material = seeds.from_geom(geom_1) coords,material = seeds.from_grid(grid_1)
geom_2 = Geom.from_Voronoi_tessellation(cells,size,coords,material) grid_2 = Grid.from_Voronoi_tessellation(cells,size,coords,material)
assert (geom_2.material==geom_1.material).all() assert (grid_2.material==grid_1.material).all()
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
@pytest.mark.parametrize('average',[True,False]) @pytest.mark.parametrize('average',[True,False])
def test_from_geom_grid(self,periodic,average): def test_from_grid_grid(self,periodic,average):
cells = np.random.randint(10,20,3) cells = np.random.randint(10,20,3)
size = np.ones(3) + np.random.random(3) size = np.ones(3) + np.random.random(3)
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
np.random.shuffle(coords) np.random.shuffle(coords)
geom_1 = Geom.from_Voronoi_tessellation(cells,size,coords) grid_1 = Grid.from_Voronoi_tessellation(cells,size,coords)
coords,material = seeds.from_geom(geom_1,average=average,periodic=periodic) coords,material = seeds.from_grid(grid_1,average=average,periodic=periodic)
geom_2 = Geom.from_Voronoi_tessellation(cells,size,coords,material) grid_2 = Grid.from_Voronoi_tessellation(cells,size,coords,material)
assert (geom_2.material==geom_1.material).all() assert (grid_2.material==grid_1.material).all()
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
@pytest.mark.parametrize('average',[True,False]) @pytest.mark.parametrize('average',[True,False])
@pytest.mark.parametrize('invert',[True,False]) @pytest.mark.parametrize('invert',[True,False])
def test_from_geom_selection(self,periodic,average,invert): def test_from_grid_selection(self,periodic,average,invert):
cells = np.random.randint(10,20,3) cells = np.random.randint(10,20,3)
N_seeds = np.random.randint(30,300) N_seeds = np.random.randint(30,300)
size = np.ones(3) + np.random.random(3) size = np.ones(3) + np.random.random(3)
coords = seeds.from_random(size,N_seeds,cells) coords = seeds.from_random(size,N_seeds,cells)
geom = Geom.from_Voronoi_tessellation(cells,size,coords) grid = Grid.from_Voronoi_tessellation(cells,size,coords)
selection=np.random.randint(N_seeds)+1 selection=np.random.randint(N_seeds)+1
coords,material = seeds.from_geom(geom,average=average,periodic=periodic,invert=invert,selection=[selection]) coords,material = seeds.from_grid(grid,average=average,periodic=periodic,invert=invert,selection=[selection])
assert selection not in material if invert else (selection==material).all() assert selection not in material if invert else (selection==material).all()