grid.clean/vicinity now uses ball neighborhood; lots of polishing

This commit is contained in:
Philip Eisenlohr 2022-03-09 18:24:05 -05:00
parent 3d9ac817bb
commit f13a4c82da
26 changed files with 173 additions and 251 deletions

View File

@ -18,7 +18,7 @@ from . import grid_filters
from . import Rotation from . import Rotation
from . import Table from . import Table
from . import Colormap from . import Colormap
from ._typehints import FloatSequence, IntSequence, IntCollection from ._typehints import FloatSequence, IntSequence, IntCollection, NumpyRngSeed
class Grid: class Grid:
""" """
@ -92,10 +92,10 @@ class Grid:
""" """
if not isinstance(other, Grid): if not isinstance(other, Grid):
return NotImplemented return NotImplemented
return bool(np.allclose(other.size,self.size) return bool( np.allclose(other.size,self.size)
and np.allclose(other.origin,self.origin) and np.allclose(other.origin,self.origin)
and np.all(other.cells == self.cells) and np.all(other.cells == self.cells)
and np.all(other.material == self.material)) and np.all(other.material == self.material))
@property @property
@ -191,8 +191,8 @@ class Grid:
ic = {label:v.get(label).reshape(cells,order='F') for label in set(v.labels['Cell Data']) - {'material'}} ic = {label:v.get(label).reshape(cells,order='F') for label in set(v.labels['Cell Data']) - {'material'}}
return Grid(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,
initial_conditions = ic) initial_conditions = ic)
@ -247,7 +247,7 @@ class Grid:
else: else:
comments.append(line.strip()) comments.append(line.strip())
material = np.empty(int(cells.prod())) # initialize as flat array material = np.empty(cells.prod()) # initialize as flat array
i = 0 i = 0
for line in content[header_length:]: for line in content[header_length:]:
if len(items := line.split('#')[0].split()) == 3: if len(items := line.split('#')[0].split()) == 3:
@ -265,7 +265,7 @@ class Grid:
raise TypeError(f'mismatch between {cells.prod()} expected entries and {i} found') raise TypeError(f'mismatch between {cells.prod()} expected entries and {i} found')
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 Grid(material.reshape(cells,order='F'),size,origin,comments) return Grid(material.reshape(cells,order='F'),size,origin,comments)
@ -927,7 +927,7 @@ class Grid:
cells/self.cells, cells/self.cells,
output=self.material.dtype, output=self.material.dtype,
order=0, order=0,
mode=('wrap' if periodic else 'nearest'), mode='wrap' if periodic else 'nearest',
prefilter=False prefilter=False
), ),
size = self.size, size = self.size,
@ -937,45 +937,62 @@ class Grid:
def clean(self, def clean(self,
stencil: int = 3, distance: float = np.sqrt(3),
selection: IntCollection = None, selection: IntCollection = None,
invert_selection: bool = False, invert_selection: bool = False,
periodic: bool = True) -> 'Grid': periodic: bool = True,
rng_seed: NumpyRngSeed = None) -> 'Grid':
""" """
Smooth grid by selecting most frequent material ID within given stencil at each location. Smooth grid by selecting most frequent material ID within given stencil at each location.
Parameters Parameters
---------- ----------
stencil : int, optional distance : float, optional
Size of smoothing stencil. Defaults to 3. Voxel distance checked for presence of other materials.
Defaults to sqrt(3).
selection : int or collection of int, optional selection : int or collection of int, optional
Material IDs to consider. Material IDs to consider.
invert_selection : bool, optional invert_selection : bool, optional
Consider all material IDs except those in selection. Defaults to False. Consider all material IDs except those in selection. Defaults to False.
periodic : bool, optional periodic : bool, optional
Assume grid to be periodic. Defaults to True. Assume grid to be periodic. Defaults to True.
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
A seed to initialize the BitGenerator. Defaults to None.
If None, then fresh, unpredictable entropy will be pulled from the OS.
Returns Returns
------- -------
updated : damask.Grid updated : damask.Grid
Updated grid-based geometry. Updated grid-based geometry.
Notes
-----
If multiple material IDs are most frequent within a stencil, a random choice is taken.
""" """
def mostFrequent(arr: np.ndarray, selection: List, invert: bool): def most_frequent(stencil: np.ndarray,
me = arr[arr.size//2] selection: set,
if selection is None or np.isin(me,selection,invert=invert): rng: NumpyRngSeed):
unique, inverse = np.unique(arr, return_inverse=True) me = stencil[stencil.size//2]
return unique[np.argmax(np.bincount(inverse))] if not selection or me in selection:
unique, counts = np.unique(stencil,return_counts=True)
return rng.choice(unique[counts==np.max(counts)])
else: else:
return me return me
extra_keywords = dict(selection=util.ensure_integer_list(selection),invert=invert_selection) rng = np.random.default_rng(rng_seed)
d = np.floor(distance).astype(int)
ext = np.linspace(-d,d,1+2*d,dtype=float),
xx,yy,zz = np.meshgrid(ext,ext,ext)
footprint = xx**2+yy**2+zz**2 <= distance**2+distance*1e-8
selection_ = set(self.material.flatten()) - set(util.aslist(selection)) if invert_selection else \
set(util.aslist(selection))
material = ndimage.filters.generic_filter( material = ndimage.filters.generic_filter(
self.material, self.material,
mostFrequent, most_frequent,
size=(stencil if selection is None else stencil//2*2+1,)*3, footprint=footprint,
mode=('wrap' if periodic else 'nearest'), mode='wrap' if periodic else 'nearest',
extra_keywords=extra_keywords, extra_keywords=dict(selection=selection_,rng=rng),
).astype(self.material.dtype) ).astype(self.material.dtype)
return Grid(material = material, return Grid(material = material,
size = self.size, size = self.size,
@ -1007,14 +1024,15 @@ class Grid:
R: Rotation, R: Rotation,
fill: int = None) -> 'Grid': fill: int = None) -> 'Grid':
""" """
Rotate grid (pad if required). Rotate grid (and pad if required).
Parameters Parameters
---------- ----------
R : damask.Rotation R : damask.Rotation
Rotation to apply to the grid. Rotation to apply to the grid.
fill : int, optional fill : int, optional
Material ID to fill the corners. Defaults to material.max() + 1. Material ID to fill enlarged bounding box.
Defaults to material.max() + 1.
Returns Returns
------- -------
@ -1054,9 +1072,11 @@ class Grid:
cells : sequence of int, len (3), optional cells : sequence of int, len (3), optional
Number of cells x,y,z direction. Number of cells x,y,z direction.
offset : sequence of int, len (3), optional offset : sequence of int, len (3), optional
Offset (measured in cells) from old to new grid [0,0,0]. Offset (measured in cells) from old to new grid.
Defaults to [0,0,0].
fill : int, optional fill : int, optional
Material ID to fill the background. Defaults to material.max() + 1. Material ID to fill the background.
Defaults to material.max() + 1.
Returns Returns
------- -------
@ -1065,15 +1085,15 @@ class Grid:
Examples Examples
-------- --------
Remove 1/2 of the microstructure in z-direction. Remove lower 1/2 of the microstructure in z-direction.
>>> import numpy as np >>> import numpy as np
>>> import damask >>> import damask
>>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4) >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4)
>>> g.canvas([32,32,16]) >>> g.canvas([32,32,16],[0,0,16])
cells : 33 x 32 x 16 cells : 33 x 32 x 16
size : 0.0001 x 0.0001 x 5e-05 size : 0.0001 x 0.0001 x 5e-05
origin: 0.0 0.0 0.0 m origin: 0.0 0.0 5e-05 m
# materials: 1 # materials: 1
""" """
@ -1150,29 +1170,31 @@ class Grid:
def vicinity_offset(self, def vicinity_offset(self,
vicinity: int = 1, distance: float = np.sqrt(3),
offset: int = None, offset: int = None,
selection: IntCollection = None, selection: IntCollection = None,
invert_selection: bool = False, invert_selection: bool = False,
periodic: bool = True) -> 'Grid': periodic: bool = True) -> 'Grid':
""" """
Offset material ID of points in the vicinity of a trigger point. Offset material ID of points in the vicinity of selected (or just other) material IDs.
Trigger points are variations in material ID, i.e. grain/phase Trigger points are variations in material ID, i.e. grain/phase
boundaries or explicitly given material IDs. boundaries or explicitly given material IDs.
Parameters Parameters
---------- ----------
vicinity : int, optional distance : float, optional
Voxel distance checked for presence of other materials. Voxel distance checked for presence of other materials.
Defaults to 1. Defaults to sqrt(3).
offset : int, optional offset : int, optional
Offset (positive or negative) to tag material indices, Offset (positive or negative) to tag material IDs.
defaults to material.max()+1. Defaults to material.max()+1.
selection : int or collection of int, optional selection : int or collection of int, optional
Material IDs that triger the offset. Material IDs that trigger an offset.
Defaults to any other than own material ID.
invert_selection : bool, optional invert_selection : bool, optional
Consider all material IDs except those in selection. Defaults to False. Consider all material IDs except those in selection.
Defaults to False.
periodic : bool, optional periodic : bool, optional
Assume grid to be periodic. Defaults to True. Assume grid to be periodic. Defaults to True.
@ -1182,20 +1204,24 @@ class Grid:
Updated grid-based geometry. Updated grid-based geometry.
""" """
def tainted_neighborhood(stencil: np.ndarray, selection): def tainted_neighborhood(stencil: np.ndarray, selection: set):
me = stencil[stencil.shape[0]//2] me = stencil[stencil.size//2]
return np.any(stencil != me if selection is None else return np.any(stencil != me if not selection else
np.in1d(stencil,np.array(list(set(selection) - {me})))) np.in1d(stencil,np.array(list(selection - {me}))))
d = np.floor(distance).astype(int)
ext = np.linspace(-d,d,1+2*d,dtype=float),
xx,yy,zz = np.meshgrid(ext,ext,ext)
footprint = xx**2+yy**2+zz**2 <= distance**2+distance*1e-8
offset_ = np.nanmax(self.material)+1 if offset is None else offset offset_ = np.nanmax(self.material)+1 if offset is None else offset
selection_ = util.ensure_integer_list(selection) selection_ = set(self.material.flatten()) - set(util.aslist(selection)) if invert_selection else \
if selection_ is not None and invert_selection: set(util.aslist(selection))
selection_ = list(set(self.material.flatten()) - set(selection_))
mask = ndimage.filters.generic_filter(self.material, mask = ndimage.filters.generic_filter(self.material,
tainted_neighborhood, tainted_neighborhood,
size=1+2*vicinity, footprint=footprint,
mode='wrap' if periodic else 'nearest', mode='wrap' if periodic else 'nearest',
extra_keywords=dict(selection=selection_)) extra_keywords=dict(selection=selection_),
)
return Grid(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,

View File

@ -870,23 +870,23 @@ class Orientation(Rotation,Crystal):
def related(self: MyType, def related(self: MyType,
model: str) -> MyType: model: str) -> MyType:
""" """
Orientations derived from the given relationship. All orientations related to self by given relationship model.
Parameters Parameters
---------- ----------
model : str model : str
Model for orientation relationship. Orientation relationship model selected from self.orientation_relationships.
Must be out of self.orientation_relationships.
Returns Returns
------- -------
Orientations with crystal structure according to Orientations related to self following the selected
the selected model for the orienation relationship. model for the orientation relationship.
Examples Examples
-------- --------
Rotations of the Bain orientation relationship (cI -> cF) Face-centered cubic orientations following from a
of a crystal in "Cube" orientation. body-centered cubic crystal in "Cube" orientation according
to the Bain orientation relationship (cI -> cF).
>>> import numpy as np >>> import numpy as np
>>> import damask >>> import damask

View File

@ -134,9 +134,8 @@ def from_grid(grid,
""" """
material = grid.material.reshape((-1,1),order='F') material = grid.material.reshape((-1,1),order='F')
selection_ = _util.ensure_integer_list(selection) mask = _np.full(grid.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,_util.aslist(selection),invert=invert_selection).flatten()
_np.isin(material,selection_,invert=invert_selection).flatten()
coords = _grid_filters.coordinates0_point(grid.cells,grid.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:

View File

@ -767,14 +767,23 @@ def tail_repack(extended: Union[str, Sequence[str]],
list(extended[len(existing):])) list(extended[len(existing):]))
def ensure_integer_list(arg: Union[IntCollection,int,None]) -> Union[List,None]: def aslist(arg: Union[IntCollection,int,None]) -> List:
"""Convert to list of Integers.""" """
if arg is None: Transform argument to list.
return None
elif isinstance(arg,(np.ndarray,Collection)): Parameters
return list(arg) ----------
else: arg : int or collection of int or None
return [arg] Entity to transform into list.
Returns
-------
transformed : list
Entity transformed into list.
"""
return [] if arg is None else list(arg) if isinstance(arg,(np.ndarray,Collection)) else [arg]
#################################################################################################### ####################################################################################################
# Classes # Classes

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData> </PointData>
<CellData> <CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41"> <DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41">
AQAAAACAAAAABQAAagAAAA==eF7t0rkOglAARFExLrgCKuKuqLj8/w9acCoSY7B+05x+cqNOvSj4l92GPfY54JAxRxxzwilnnDNhyowLLrlizjULbrjljnseeOSJZ15Y8sob76z44JMvvtn8L9jObz2GDuv96vADk5QHBg== AQAAAACAAAAABQAAhAAAAA==eF7t0jcOAjEURVGGnHOOQ4b9b5CC8xtLNAwlbk5hPUuWblZ6n+zvV5ZZYZU11tlgky22E+PdPnsccsARx+ww9jPOuWDOFddM/3Pljfvk/sgTz7ww3d/54JPlv4X8VYexj466jP6ix+gvekw7nHDKTx0umXa44ZY7Rn8H5iza4QtoVQaf
</DataArray> </DataArray>
</CellData> </CellData>
</Piece> </Piece>

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="40">
AQAAAACAAAAABQAAkAAAAA==eF7t070OgkAQRWExKo0GDREMaNjCv/d/QgvPbU5CQw3Nl5nZZZPlUm3+T7W6yK3c4Un9rK/V9/youlN9wzO2ml/xobrHghfM+Xcc0edPWDTP/ie+5AHf+MEv+h5Wl+nvsVff+ZvLcfKUHHtdctegc9RK5zL7Cmb/IJPf5DLvT36Sx7n/MHnMPTh/8QfFJwU8
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41">
AQAAAACAAAAABQAAZwAAAA==eF7t0rcOgmAAhVEgNmyo2AuoWN//BR04EwsJcfzvcvabL47qxcFOJg177HPAIUdMOeaEU844Z8YFl1wx55obbrnjngceeeKZFxYseeWNd1Z88MkX3/zwy+Z/wf8YOqzX1uEPlgwHCA==
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData> </PointData>
<CellData> <CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2"> <DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAGQAAAA==eF5jZIAAxlF6lB4AmmmUHqUHkAYA/M8A8Q== AQAAAACAAAAABQAAKwAAAA==eF5jZIAAxlGaLJoJjcYlTqw6Qvpx2U+pu0iVJ8QnJD5Kj9KDgQYAUc4BDA==
</DataArray> </DataArray>
</CellData> </CellData>
</Piece> </Piece>

View File

@ -3,7 +3,7 @@
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1"> <ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData> <FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary"> <Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY= AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array> </Array>
</FieldData> </FieldData>
<Piece Extent="0 8 0 5 0 4"> <Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData> </PointData>
<CellData> <CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2"> <DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAGwAAAA==eF5jZIAAxlF6lB4AmmmUpogeDUfKaAD7jwDw AQAAAACAAAAABQAAPwAAAA==eF5jZIAAxlGaLJqJAE2pPlx8atG4zCXkXmLFaeXuURqVJhQfhNIhLj4h9YTil1h7COkn5D9C+nGJAwBKngD7
</DataArray> </DataArray>
</CellData> </CellData>
</Piece> </Piece>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41">
AQAAAACAAAAABQAAagAAAA==eF7t0rkOglAARFExLrgCKuKuqLj8/w9acCoSY7B+05x+cqNOvSj4l92GPfY54JAxRxxzwilnnDNhyowLLrlizjULbrjljnseeOSJZ15Y8sob76z44JMvvtn8L9jObz2GDuv96vADk5QHBg==
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAIgAAAA==eF5jZIAAxlGaLJoJjSakntr6hzqN7v9RepSmJw0AC04A9Q==
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAALwAAAA==eF5jZIAAxlGaLJoJjSakHpc+cvUTUkdrmlL3j9KU0dROF5TqH2iaVPcDAALOANU=
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41">
AQAAAACAAAAABQAAcQAAAA==eF7t0rkOglAUBFAxKu6igvsKrv//gxYcm9fQGEPBNKe6yc1kolaZqPEndthljzH7HHDIEceccMoZE8654JIpM6645oZb7rjngUeeeOaFV+YseOOdDz754pthf+3Aqr7rdv9vw3+/NjssU7XDD0/8BuQ=
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="41">
AQAAAACAAAAABQAAYQAAAA==eF7t0scVglAAAEHgqZgBA2ZExdR/gx6YCpDj38s0sEnUlgR7ccAhR0w55oRTzjjngktmzFlwxTU33LLkjnseeOSJZ15Y8cqaN975YMMnX3zzwy/j4F+GD9u6fvgD+gwHCA==
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="2" RangeMax="41">
AQAAAACAAAAABQAAZAAAAA==eF7t0rcSglAARFEHE0bAgBkE8///oAWnF8b2bXP6nRv1mkXBv+xzwCFHHDPmhFPOOOeCSyZMmXHFNTfcMueOex545IlnXliw5JUVa95454NPvvjmh79+DXYzdNisbYdfSqMHMg==
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAIAAAAA==eF5jZIAAxlF6lB4AmokAPdj1DzRNyP2jNH4aAMufANU=
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<ImageData WholeExtent="0 8 0 5 0 4" Origin="0 0 0" Spacing="0.000001 0.0000010000000000000002 0.000001" Direction="1 0 0 0 1 0 0 0 1">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
<PointData>
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAMAAAAA==eF5jYoAAJhw0IwEalz566aeUptT+oa6fUppS+4e6fkppSu0f6voppSm1HwBAngDh
</DataArray>
</CellData>
</Piece>
</ImageData>
</VTKFile>

View File

@ -165,28 +165,26 @@ class TestGrid:
default.flip(directions) default.flip(directions)
@pytest.mark.parametrize('stencil',[1,2,3,4]) @pytest.mark.parametrize('distance',[1.,np.sqrt(3)])
@pytest.mark.parametrize('selection',[None,[1],[1,2,3]]) @pytest.mark.parametrize('selection',[None,1,[1],[1,2,3]])
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
def test_clean_reference(self,default,update,ref_path,stencil,selection,periodic): def test_clean_reference(self,default,update,ref_path,distance,selection,periodic):
current = default.clean(stencil,selection,periodic=periodic) current = default.clean(distance,selection,periodic=periodic,rng_seed=0)
reference = ref_path/f'clean_{stencil}_{"+".join(map(str,[None] if selection is None else selection))}_{periodic}.vti' reference = ref_path/f'clean_{distance}_{"+".join(map(str,util.aslist(selection)))}_{periodic}.vti'
if update and stencil > 1: if update:
current.save(reference) current.save(reference)
assert grid_equal(Grid.load(reference) if stencil > 1 else default, assert grid_equal(Grid.load(reference),current)
current
)
@pytest.mark.parametrize('selection',[list(np.random.randint(1,20,6)),set(np.random.randint(1,20,6)),np.random.randint(1,20,6)]) @pytest.mark.parametrize('selection',[list(np.random.randint(1,20,6)),set(np.random.randint(1,20,6)),np.random.randint(1,20,6)])
@pytest.mark.parametrize('invert',[True,False]) @pytest.mark.parametrize('invert',[True,False])
def test_clean_invert(self,random,selection,invert): def test_clean_invert(self,default,selection,invert):
selection_inverse = set(random.material.flatten()) - set(selection) selection_inverse = set(default.material.flatten()) - set(selection)
assert random.clean(selection=selection,invert_selection=invert) == \ assert default.clean(selection=selection,invert_selection=invert,rng_seed=0) == \
random.clean(selection=selection_inverse,invert_selection=not invert) default.clean(selection=selection_inverse,invert_selection=not invert,rng_seed=0)
def test_clean_selection_empty(self,random): def test_clean_selection_empty(self,random):
assert random.clean(selection=[],invert_selection=False) == random and \ assert random.clean(selection=None,invert_selection=True,rng_seed=0) == random.clean(rng_seed=0) and \
random.clean(selection=[],invert_selection=True) == random.clean() random.clean(selection=None,invert_selection=False,rng_seed=0) == random.clean(rng_seed=0)
@pytest.mark.parametrize('cells',[ @pytest.mark.parametrize('cells',[
@ -329,20 +327,20 @@ class TestGrid:
@pytest.mark.parametrize('selection',[1,None]) @pytest.mark.parametrize('selection',[1,None])
def test_vicinity_offset(self,selection): def test_vicinity_offset(self,selection):
offset = np.random.randint(2,4) offset = np.random.randint(2,4)
vicinity = np.random.randint(2,4) distance = np.random.randint(2,4)
g = np.random.randint(28,40,(3)) g = np.random.randint(28,40,(3))
m = np.ones(g,'i') m = np.ones(g,'i')
x = (g*np.random.permutation(np.array([.5,1,1]))).astype('i') x = (g*np.random.permutation(np.array([.5,1,1]))).astype(int)
m[slice(0,x[0]),slice(0,x[1]),slice(0,x[2])] = 2 m[slice(0,x[0]),slice(0,x[1]),slice(0,x[2])] = 2
m2 = m.copy() m2 = m.copy()
for i in [0,1,2]: for i in [0,1,2]:
m2[(np.roll(m,+vicinity,i)-m)!=0] += offset m2[(np.roll(m,+distance,i)-m)!=0] += offset
m2[(np.roll(m,-vicinity,i)-m)!=0] += offset m2[(np.roll(m,-distance,i)-m)!=0] += offset
if selection == 1: if selection == 1:
m2[m==1] = 1 m2[m==1] = 1
grid = Grid(m,np.random.rand(3)).vicinity_offset(vicinity,offset,selection=selection) grid = Grid(m,np.random.rand(3)).vicinity_offset(distance,offset,selection=selection)
assert np.all(m2==grid.material) assert np.all(m2==grid.material)

View File

@ -117,6 +117,10 @@ class TestUtil:
def test_decorate(self,style): def test_decorate(self,style):
assert 'DAMASK' in style('DAMASK') assert 'DAMASK' in style('DAMASK')
@pytest.mark.parametrize('lst',[1,[1,2],set([1,2,3]),np.arange(4)])
def test_aslist(self,lst):
assert len(util.aslist(lst)) > 0
@pytest.mark.parametrize('complete',[True,False]) @pytest.mark.parametrize('complete',[True,False])
def test_D3D_base_group(self,tmp_path,complete): def test_D3D_base_group(self,tmp_path,complete):
base_group = ''.join(random.choices('DAMASK', k=10)) base_group = ''.join(random.choices('DAMASK', k=10))