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 Table
from . import Colormap
from ._typehints import FloatSequence, IntSequence, IntCollection
from ._typehints import FloatSequence, IntSequence, IntCollection, NumpyRngSeed
class Grid:
"""
@ -92,10 +92,10 @@ class Grid:
"""
if not isinstance(other, Grid):
return NotImplemented
return bool(np.allclose(other.size,self.size)
and np.allclose(other.origin,self.origin)
and np.all(other.cells == self.cells)
and np.all(other.material == self.material))
return bool( np.allclose(other.size,self.size)
and np.allclose(other.origin,self.origin)
and np.all(other.cells == self.cells)
and np.all(other.material == self.material))
@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'}}
return Grid(material = v.get('material').reshape(cells,order='F'),
size = bbox[1] - bbox[0],
origin = bbox[0],
size = bbox[1] - bbox[0],
origin = bbox[0],
comments = comments,
initial_conditions = ic)
@ -247,7 +247,7 @@ class Grid:
else:
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
for line in content[header_length:]:
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')
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)
@ -927,7 +927,7 @@ class Grid:
cells/self.cells,
output=self.material.dtype,
order=0,
mode=('wrap' if periodic else 'nearest'),
mode='wrap' if periodic else 'nearest',
prefilter=False
),
size = self.size,
@ -937,45 +937,62 @@ class Grid:
def clean(self,
stencil: int = 3,
distance: float = np.sqrt(3),
selection: IntCollection = None,
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.
Parameters
----------
stencil : int, optional
Size of smoothing stencil. Defaults to 3.
distance : float, optional
Voxel distance checked for presence of other materials.
Defaults to sqrt(3).
selection : int or collection of int, optional
Material IDs to consider.
invert_selection : bool, optional
Consider all material IDs except those in selection. Defaults to False.
periodic : bool, optional
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
-------
updated : damask.Grid
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):
me = arr[arr.size//2]
if selection is None or np.isin(me,selection,invert=invert):
unique, inverse = np.unique(arr, return_inverse=True)
return unique[np.argmax(np.bincount(inverse))]
def most_frequent(stencil: np.ndarray,
selection: set,
rng: NumpyRngSeed):
me = stencil[stencil.size//2]
if not selection or me in selection:
unique, counts = np.unique(stencil,return_counts=True)
return rng.choice(unique[counts==np.max(counts)])
else:
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(
self.material,
mostFrequent,
size=(stencil if selection is None else stencil//2*2+1,)*3,
mode=('wrap' if periodic else 'nearest'),
extra_keywords=extra_keywords,
most_frequent,
footprint=footprint,
mode='wrap' if periodic else 'nearest',
extra_keywords=dict(selection=selection_,rng=rng),
).astype(self.material.dtype)
return Grid(material = material,
size = self.size,
@ -1007,14 +1024,15 @@ class Grid:
R: Rotation,
fill: int = None) -> 'Grid':
"""
Rotate grid (pad if required).
Rotate grid (and pad if required).
Parameters
----------
R : damask.Rotation
Rotation to apply to the grid.
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
-------
@ -1054,9 +1072,11 @@ class Grid:
cells : sequence of int, len (3), optional
Number of cells x,y,z direction.
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
Material ID to fill the background. Defaults to material.max() + 1.
Material ID to fill the background.
Defaults to material.max() + 1.
Returns
-------
@ -1065,15 +1085,15 @@ class Grid:
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 damask
>>> 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
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
"""
@ -1150,29 +1170,31 @@ class Grid:
def vicinity_offset(self,
vicinity: int = 1,
distance: float = np.sqrt(3),
offset: int = None,
selection: IntCollection = None,
invert_selection: bool = False,
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
boundaries or explicitly given material IDs.
Parameters
----------
vicinity : int, optional
distance : float, optional
Voxel distance checked for presence of other materials.
Defaults to 1.
Defaults to sqrt(3).
offset : int, optional
Offset (positive or negative) to tag material indices,
defaults to material.max()+1.
Offset (positive or negative) to tag material IDs.
Defaults to material.max()+1.
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
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
Assume grid to be periodic. Defaults to True.
@ -1182,20 +1204,24 @@ class Grid:
Updated grid-based geometry.
"""
def tainted_neighborhood(stencil: np.ndarray, selection):
me = stencil[stencil.shape[0]//2]
return np.any(stencil != me if selection is None else
np.in1d(stencil,np.array(list(set(selection) - {me}))))
def tainted_neighborhood(stencil: np.ndarray, selection: set):
me = stencil[stencil.size//2]
return np.any(stencil != me if not selection else
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
selection_ = util.ensure_integer_list(selection)
if selection_ is not None and invert_selection:
selection_ = list(set(self.material.flatten()) - set(selection_))
selection_ = set(self.material.flatten()) - set(util.aslist(selection)) if invert_selection else \
set(util.aslist(selection))
mask = ndimage.filters.generic_filter(self.material,
tainted_neighborhood,
size=1+2*vicinity,
footprint=footprint,
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),
size = self.size,

View File

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

View File

@ -134,9 +134,8 @@ def from_grid(grid,
"""
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 \
_np.isin(material,selection_,invert=invert_selection).flatten()
mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \
_np.isin(material,_util.aslist(selection),invert=invert_selection).flatten()
coords = _grid_filters.coordinates0_point(grid.cells,grid.size).reshape(-1,3,order='F')
if not average:

View File

@ -767,14 +767,23 @@ def tail_repack(extended: Union[str, Sequence[str]],
list(extended[len(existing):]))
def ensure_integer_list(arg: Union[IntCollection,int,None]) -> Union[List,None]:
"""Convert to list of Integers."""
if arg is None:
return None
elif isinstance(arg,(np.ndarray,Collection)):
return list(arg)
else:
return [arg]
def aslist(arg: Union[IntCollection,int,None]) -> List:
"""
Transform argument to list.
Parameters
----------
arg : int or collection of int or None
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

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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData>
<CellData>
<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>
</CellData>
</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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAGQAAAA==eF5jZIAAxlF6lB4AmmmUHqUHkAYA/M8A8Q==
AQAAAACAAAAABQAAKwAAAA==eF5jZIAAxlGaLJoJjcYlTqw6Qvpx2U+pu0iVJ8QnJD5Kj9KDgQYAUc4BDA==
</DataArray>
</CellData>
</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">
<FieldData>
<Array type="String" Name="comments" NumberOfTuples="1" format="binary">
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wc0/Nz9VLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFT8EKY=
AQAAAACAAAA+AAAAQQAAAA==eF5LScxNLM7Wcy/KTNFLzklNzFMos7TUAyNdSyDQLagsSS0uUdAwMjC01DU01DUwUjA0tDK1sDIw0GQAAFSoEKQ=
</Array>
</FieldData>
<Piece Extent="0 8 0 5 0 4">
@ -11,7 +11,7 @@
</PointData>
<CellData>
<DataArray type="Int64" Name="material" format="binary" RangeMin="1" RangeMax="2">
AQAAAACAAAAABQAAGwAAAA==eF5jZIAAxlF6lB4AmmmUpogeDUfKaAD7jwDw
AQAAAACAAAAABQAAPwAAAA==eF5jZIAAxlGaLJqJAE2pPlx8atG4zCXkXmLFaeXuURqVJhQfhNIhLj4h9YTil1h7COkn5D9C+nGJAwBKngD7
</DataArray>
</CellData>
</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)
@pytest.mark.parametrize('stencil',[1,2,3,4])
@pytest.mark.parametrize('selection',[None,[1],[1,2,3]])
@pytest.mark.parametrize('distance',[1.,np.sqrt(3)])
@pytest.mark.parametrize('selection',[None,1,[1],[1,2,3]])
@pytest.mark.parametrize('periodic',[True,False])
def test_clean_reference(self,default,update,ref_path,stencil,selection,periodic):
current = default.clean(stencil,selection,periodic=periodic)
reference = ref_path/f'clean_{stencil}_{"+".join(map(str,[None] if selection is None else selection))}_{periodic}.vti'
if update and stencil > 1:
def test_clean_reference(self,default,update,ref_path,distance,selection,periodic):
current = default.clean(distance,selection,periodic=periodic,rng_seed=0)
reference = ref_path/f'clean_{distance}_{"+".join(map(str,util.aslist(selection)))}_{periodic}.vti'
if update:
current.save(reference)
assert grid_equal(Grid.load(reference) if stencil > 1 else default,
current
)
assert grid_equal(Grid.load(reference),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('invert',[True,False])
def test_clean_invert(self,random,selection,invert):
selection_inverse = set(random.material.flatten()) - set(selection)
assert random.clean(selection=selection,invert_selection=invert) == \
random.clean(selection=selection_inverse,invert_selection=not invert)
def test_clean_invert(self,default,selection,invert):
selection_inverse = set(default.material.flatten()) - set(selection)
assert default.clean(selection=selection,invert_selection=invert,rng_seed=0) == \
default.clean(selection=selection_inverse,invert_selection=not invert,rng_seed=0)
def test_clean_selection_empty(self,random):
assert random.clean(selection=[],invert_selection=False) == random and \
random.clean(selection=[],invert_selection=True) == random.clean()
assert random.clean(selection=None,invert_selection=True,rng_seed=0) == random.clean(rng_seed=0) and \
random.clean(selection=None,invert_selection=False,rng_seed=0) == random.clean(rng_seed=0)
@pytest.mark.parametrize('cells',[
@ -329,20 +327,20 @@ class TestGrid:
@pytest.mark.parametrize('selection',[1,None])
def test_vicinity_offset(self,selection):
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))
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
m2 = m.copy()
for i in [0,1,2]:
m2[(np.roll(m,+vicinity,i)-m)!=0] += offset
m2[(np.roll(m,-vicinity,i)-m)!=0] += offset
m2[(np.roll(m,+distance,i)-m)!=0] += offset
m2[(np.roll(m,-distance,i)-m)!=0] += offset
if selection == 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)

View File

@ -117,6 +117,10 @@ class TestUtil:
def test_decorate(self,style):
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])
def test_D3D_base_group(self,tmp_path,complete):
base_group = ''.join(random.choices('DAMASK', k=10))