allow flexible arguments for 1D arguments

This commit is contained in:
Martin Diehl 2022-01-12 13:18:38 +00:00 committed by Daniel Otto de Mentock
parent dd6e9a016e
commit 410a515afc
6 changed files with 130 additions and 115 deletions

View File

@ -8,6 +8,7 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
version = _re.sub(r'^v','',_f.readline().strip()) version = _re.sub(r'^v','',_f.readline().strip())
__version__ = version __version__ = version
from . import _typehints # noqa
from . import util # noqa from . import util # noqa
from . import seeds # noqa from . import seeds # noqa
from . import tensor # noqa from . import tensor # noqa

View File

@ -3,13 +3,9 @@ import json
import functools import functools
import colorsys import colorsys
from pathlib import Path from pathlib import Path
from typing import Sequence, Union, TextIO from typing import Union, TextIO
import numpy as np import numpy as np
try:
from numpy.typing import ArrayLike
except ImportError:
ArrayLike = Union[np.ndarray,Sequence[float]] # type: ignore
import scipy.interpolate as interp import scipy.interpolate as interp
import matplotlib as mpl import matplotlib as mpl
if os.name == 'posix' and 'DISPLAY' not in os.environ: if os.name == 'posix' and 'DISPLAY' not in os.environ:
@ -18,6 +14,7 @@ import matplotlib.pyplot as plt
from matplotlib import cm from matplotlib import cm
from PIL import Image from PIL import Image
from ._typehints import FloatSequence, FileHandle
from . import util from . import util
from . import Table from . import Table
@ -82,8 +79,8 @@ class Colormap(mpl.colors.ListedColormap):
@staticmethod @staticmethod
def from_range(low: ArrayLike, def from_range(low: FloatSequence,
high: ArrayLike, high: FloatSequence,
name: str = 'DAMASK colormap', name: str = 'DAMASK colormap',
N: int = 256, N: int = 256,
model: str = 'rgb') -> 'Colormap': model: str = 'rgb') -> 'Colormap':
@ -197,7 +194,7 @@ class Colormap(mpl.colors.ListedColormap):
def at(self, def at(self,
fraction : Union[float,Sequence[float]]) -> np.ndarray: fraction : Union[float,FloatSequence]) -> np.ndarray:
""" """
Interpolate color at fraction. Interpolate color at fraction.
@ -229,7 +226,7 @@ class Colormap(mpl.colors.ListedColormap):
def shade(self, def shade(self,
field: np.ndarray, field: np.ndarray,
bounds: ArrayLike = None, bounds: FloatSequence = None,
gap: float = None) -> Image: gap: float = None) -> Image:
""" """
Generate PIL image of 2D field using colormap. Generate PIL image of 2D field using colormap.
@ -296,7 +293,7 @@ class Colormap(mpl.colors.ListedColormap):
def _get_file_handle(self, def _get_file_handle(self,
fname: Union[TextIO, str, Path, None], fname: Union[FileHandle, None],
suffix: str = '') -> TextIO: suffix: str = '') -> TextIO:
""" """
Provide file handle. Provide file handle.
@ -323,7 +320,7 @@ class Colormap(mpl.colors.ListedColormap):
return fname return fname
def save_paraview(self, fname: Union[TextIO, str, Path] = None): def save_paraview(self, fname: FileHandle = None):
""" """
Save as JSON file for use in Paraview. Save as JSON file for use in Paraview.
@ -350,7 +347,7 @@ class Colormap(mpl.colors.ListedColormap):
fhandle.write('\n') fhandle.write('\n')
def save_ASCII(self, fname: Union[TextIO, str, Path] = None): def save_ASCII(self, fname: FileHandle = None):
""" """
Save as ASCII file. Save as ASCII file.
@ -365,7 +362,7 @@ class Colormap(mpl.colors.ListedColormap):
t.save(self._get_file_handle(fname,'.txt')) t.save(self._get_file_handle(fname,'.txt'))
def save_GOM(self, fname: Union[TextIO, str, Path] = None): def save_GOM(self, fname: FileHandle = None):
""" """
Save as ASCII file for use in GOM Aramis. Save as ASCII file for use in GOM Aramis.
@ -385,7 +382,7 @@ class Colormap(mpl.colors.ListedColormap):
self._get_file_handle(fname,'.legend').write(GOM_str) self._get_file_handle(fname,'.legend').write(GOM_str)
def save_gmsh(self, fname: Union[TextIO, str, Path] = None): def save_gmsh(self, fname: FileHandle = None):
""" """
Save as ASCII file for use in gmsh. Save as ASCII file for use in gmsh.

View File

@ -0,0 +1,11 @@
"""Functionality for typehints."""
from typing import Sequence, Union, TextIO
from pathlib import Path
import numpy as np
FloatSequence = Union[np.ndarray,Sequence[float]]
IntSequence = Union[np.ndarray,Sequence[int]]
FileHandle = Union[TextIO, str, Path]

View File

@ -12,21 +12,23 @@ the following operations are required for tensorial data:
""" """
from typing import Sequence, Tuple, Union from typing import Tuple as _Tuple
from scipy import spatial as _spatial from scipy import spatial as _spatial
import numpy as _np import numpy as _np
from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence
def _ks(size: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]], first_order: bool = False) -> _np.ndarray:
def _ks(size: _FloatSequence, cells: _IntSequence, first_order: bool = False) -> _np.ndarray:
""" """
Get wave numbers operator. Get wave numbers operator.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
cells : numpy.ndarray of shape (3) cells : sequence of int, len (3)
Number of cells. Number of cells.
first_order : bool, optional first_order : bool, optional
Correction for first order derivatives, defaults to False. Correction for first order derivatives, defaults to False.
@ -45,20 +47,20 @@ def _ks(size: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]], first_order:
return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1) return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1)
def curl(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray: def curl(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray:
u""" u"""
Calculate curl of a vector or tensor field in Fourier space. Calculate curl of a vector or tensor field in Fourier space.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
f : numpy.ndarray of shape (:,:,:,3) or (:,:,:,3,3) f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
Periodic field of which the curl is calculated. Periodic field of which the curl is calculated.
Returns Returns
------- -------
× f : numpy.ndarray × f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
Curl of f. Curl of f.
""" """
@ -76,20 +78,20 @@ def curl(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3]) return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3])
def divergence(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray: def divergence(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray:
u""" u"""
Calculate divergence of a vector or tensor field in Fourier space. Calculate divergence of a vector or tensor field in Fourier space.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
f : numpy.ndarray of shape (:,:,:,3) or (:,:,:,3,3) f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
Periodic field of which the divergence is calculated. Periodic field of which the divergence is calculated.
Returns Returns
------- -------
· f : numpy.ndarray · f : numpy.ndarray, shape (:,:,:,1) or (:,:,:,3)
Divergence of f. Divergence of f.
""" """
@ -103,20 +105,20 @@ def divergence(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3]) return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3])
def gradient(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray: def gradient(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray:
u""" u"""
Calculate gradient of a scalar or vector fieldin Fourier space. Calculate gradient of a scalar or vector field in Fourier space.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
f : numpy.ndarray of shape (:,:,:,1) or (:,:,:,3) f : numpy.ndarray, shape (:,:,:,1) or (:,:,:,3)
Periodic field of which the gradient is calculated. Periodic field of which the gradient is calculated.
Returns Returns
------- -------
f : numpy.ndarray f : numpy.ndarray, shape (:,:,:,3) or (:,:,:,3,3)
Divergence of f. Divergence of f.
""" """
@ -130,29 +132,30 @@ def gradient(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray:
return _np.fft.irfftn(grad_,axes=(0,1,2),s=f.shape[:3]) return _np.fft.irfftn(grad_,axes=(0,1,2),s=f.shape[:3])
def coordinates0_point(cells: Union[ _np.ndarray,Sequence[int]], def coordinates0_point(cells: _IntSequence,
size: _np.ndarray, size: _FloatSequence,
origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
""" """
Cell center positions (undeformed). Cell center positions (undeformed).
Parameters Parameters
---------- ----------
cells : numpy.ndarray of shape (3) cells : sequence of int, len (3)
Number of cells. Number of cells.
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
origin : numpy.ndarray, optional origin : sequence of float, len(3), optional
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
Returns Returns
------- -------
x_p_0 : numpy.ndarray x_p_0 : numpy.ndarray, shape (:,:,:,3)
Undeformed cell center coordinates. Undeformed cell center coordinates.
""" """
start = origin + size/_np.array(cells)*.5 size_ = _np.array(size,float)
end = origin + size - size/_np.array(cells)*.5 start = origin + size_/_np.array(cells,int)*.5
end = origin + size_ - size_/_np.array(cells,int)*.5
return _np.stack(_np.meshgrid(_np.linspace(start[0],end[0],cells[0]), return _np.stack(_np.meshgrid(_np.linspace(start[0],end[0],cells[0]),
_np.linspace(start[1],end[1],cells[1]), _np.linspace(start[1],end[1],cells[1]),
@ -160,24 +163,24 @@ def coordinates0_point(cells: Union[ _np.ndarray,Sequence[int]],
axis = -1) axis = -1)
def displacement_fluct_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_fluct_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Cell center displacement field from fluctuation part of the deformation gradient field. Cell center displacement field from fluctuation part of the deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_p_fluct : numpy.ndarray u_p_fluct : numpy.ndarray, shape (:,:,:,3)
Fluctuating part of the cell center displacements. Fluctuating part of the cell center displacements.
""" """
integrator = 0.5j*size/_np.pi integrator = 0.5j*_np.array(size,float)/_np.pi
k_s = _ks(size,F.shape[:3],False) k_s = _ks(size,F.shape[:3],False)
k_s_squared = _np.einsum('...l,...l',k_s,k_s) k_s_squared = _np.einsum('...l,...l',k_s,k_s)
@ -192,20 +195,20 @@ def displacement_fluct_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3]) return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3])
def displacement_avg_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_avg_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Cell center displacement field from average part of the deformation gradient field. Cell center displacement field from average part of the deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_p_avg : numpy.ndarray u_p_avg : numpy.ndarray, shape (:,:,:,3)
Average part of the cell center displacements. Average part of the cell center displacements.
""" """
@ -213,42 +216,42 @@ def displacement_avg_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size)) return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size))
def displacement_point(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Cell center displacement field from deformation gradient field. Cell center displacement field from deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_p : numpy.ndarray u_p : numpy.ndarray, shape (:,:,:,3)
Cell center displacements. Cell center displacements.
""" """
return displacement_avg_point(size,F) + displacement_fluct_point(size,F) return displacement_avg_point(size,F) + displacement_fluct_point(size,F)
def coordinates_point(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: def coordinates_point(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
""" """
Cell center positions. Cell center positions.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
origin : numpy.ndarray of shape (3), optional origin : sequence of float, len(3), optional
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
Returns Returns
------- -------
x_p : numpy.ndarray x_p : numpy.ndarray, shape (:,:,:,3)
Cell center coordinates. Cell center coordinates.
""" """
@ -256,14 +259,14 @@ def coordinates_point(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _
def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray, def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
ordered: bool = True) -> Tuple[_np.ndarray,_np.ndarray,_np.ndarray]: ordered: bool = True) -> _Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
""" """
Return grid 'DNA', i.e. cells, size, and origin from 1D array of point positions. Return grid 'DNA', i.e. cells, size, and origin from 1D array of point positions.
Parameters Parameters
---------- ----------
coordinates0 : numpy.ndarray of shape (:,3) coordinates0 : numpy.ndarray, shape (:,3)
Undeformed cell coordinates. Undeformed cell center coordinates.
ordered : bool, optional ordered : bool, optional
Expect coordinates0 data to be ordered (x fast, z slow). Expect coordinates0 data to be ordered (x fast, z slow).
Defaults to True. Defaults to True.
@ -277,7 +280,7 @@ def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
coords = [_np.unique(coordinates0[:,i]) for i in range(3)] coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
mincorner = _np.array(list(map(min,coords))) mincorner = _np.array(list(map(min,coords)))
maxcorner = _np.array(list(map(max,coords))) maxcorner = _np.array(list(map(max,coords)))
cells = _np.array(list(map(len,coords)),'i') cells = _np.array(list(map(len,coords)),int)
size = cells/_np.maximum(cells-1,1) * (maxcorner-mincorner) size = cells/_np.maximum(cells-1,1) * (maxcorner-mincorner)
delta = size/cells delta = size/cells
origin = mincorner - delta*.5 origin = mincorner - delta*.5
@ -305,24 +308,24 @@ def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray,
return (cells,size,origin) return (cells,size,origin)
def coordinates0_node(cells: Union[_np.ndarray,Sequence[int]], def coordinates0_node(cells: _IntSequence,
size: _np.ndarray, size: _FloatSequence,
origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
""" """
Nodal positions (undeformed). Nodal positions (undeformed).
Parameters Parameters
---------- ----------
cells : numpy.ndarray of shape (3) cells : sequence of int, len (3)
Number of cells. Number of cells.
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
origin : numpy.ndarray of shape (3), optional origin : sequence of float, len(3), optional
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
Returns Returns
------- -------
x_n_0 : numpy.ndarray x_n_0 : numpy.ndarray, shape (:,:,:,3)
Undeformed nodal coordinates. Undeformed nodal coordinates.
""" """
@ -332,40 +335,40 @@ def coordinates0_node(cells: Union[_np.ndarray,Sequence[int]],
axis = -1) axis = -1)
def displacement_fluct_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_fluct_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Nodal displacement field from fluctuation part of the deformation gradient field. Nodal displacement field from fluctuation part of the deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_n_fluct : numpy.ndarray u_n_fluct : numpy.ndarray, shape (:,:,:,3)
Fluctuating part of the nodal displacements. Fluctuating part of the nodal displacements.
""" """
return point_to_node(displacement_fluct_point(size,F)) return point_to_node(displacement_fluct_point(size,F))
def displacement_avg_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_avg_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Nodal displacement field from average part of the deformation gradient field. Nodal displacement field from average part of the deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_n_avg : numpy.ndarray u_n_avg : numpy.ndarray, shape (:,:,:,3)
Average part of the nodal displacements. Average part of the nodal displacements.
""" """
@ -373,42 +376,42 @@ def displacement_avg_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray:
return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size)) return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size))
def displacement_node(size: _np.ndarray, F: _np.ndarray) -> _np.ndarray: def displacement_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray:
""" """
Nodal displacement field from deformation gradient field. Nodal displacement field from deformation gradient field.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
Returns Returns
------- -------
u_p : numpy.ndarray u_p : numpy.ndarray, shape (:,:,:,3)
Nodal displacements. Nodal displacements.
""" """
return displacement_avg_node(size,F) + displacement_fluct_node(size,F) return displacement_avg_node(size,F) + displacement_fluct_node(size,F)
def coordinates_node(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: def coordinates_node(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray:
""" """
Nodal positions. Nodal positions.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the periodic field. Physical size of the periodic field.
F : numpy.ndarray F : numpy.ndarray, shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
origin : numpy.ndarray of shape (3), optional origin : sequence of float, len(3), optional
Physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. Physical origin of the periodic field. Defaults to [0.0,0.0,0.0].
Returns Returns
------- -------
x_n : numpy.ndarray x_n : numpy.ndarray, shape (:,:,:,3)
Nodal coordinates. Nodal coordinates.
""" """
@ -416,13 +419,13 @@ def coordinates_node(size: _np.ndarray, F: _np.ndarray, origin: _np.ndarray = _n
def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray, def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray,
ordered: bool = True) -> Tuple[_np.ndarray,_np.ndarray,_np.ndarray]: ordered: bool = True) -> _Tuple[_np.ndarray,_np.ndarray,_np.ndarray]:
""" """
Return grid 'DNA', i.e. cells, size, and origin from 1D array of nodal positions. Return grid 'DNA', i.e. cells, size, and origin from 1D array of nodal positions.
Parameters Parameters
---------- ----------
coordinates0 : numpy.ndarray of shape (:,3) coordinates0 : numpy.ndarray, shape (:,3)
Undeformed nodal coordinates. Undeformed nodal coordinates.
ordered : bool, optional ordered : bool, optional
Expect coordinates0 data to be ordered (x fast, z slow). Expect coordinates0 data to be ordered (x fast, z slow).
@ -437,7 +440,7 @@ def cellsSizeOrigin_coordinates0_node(coordinates0: _np.ndarray,
coords = [_np.unique(coordinates0[:,i]) for i in range(3)] coords = [_np.unique(coordinates0[:,i]) for i in range(3)]
mincorner = _np.array(list(map(min,coords))) mincorner = _np.array(list(map(min,coords)))
maxcorner = _np.array(list(map(max,coords))) maxcorner = _np.array(list(map(max,coords)))
cells = _np.array(list(map(len,coords)),'i') - 1 cells = _np.array(list(map(len,coords)),int) - 1
size = maxcorner-mincorner size = maxcorner-mincorner
origin = mincorner origin = mincorner
@ -463,12 +466,12 @@ def point_to_node(cell_data: _np.ndarray) -> _np.ndarray:
Parameters Parameters
---------- ----------
cell_data : numpy.ndarray of shape (:,:,:,...) cell_data : numpy.ndarray, shape (:,:,:,...)
Data defined on the cell centers of a periodic grid. Data defined on the cell centers of a periodic grid.
Returns Returns
------- -------
node_data : numpy.ndarray of shape (:,:,:,...) node_data : numpy.ndarray, shape (:,:,:,...)
Data defined on the nodes of a periodic grid. Data defined on the nodes of a periodic grid.
""" """
@ -485,12 +488,12 @@ def node_to_point(node_data: _np.ndarray) -> _np.ndarray:
Parameters Parameters
---------- ----------
node_data : numpy.ndarray of shape (:,:,:,...) node_data : numpy.ndarray, shape (:,:,:,...)
Data defined on the nodes of a periodic grid. Data defined on the nodes of a periodic grid.
Returns Returns
------- -------
cell_data : numpy.ndarray of shape (:,:,:,...) cell_data : numpy.ndarray, shape (:,:,:,...)
Data defined on the cell centers of a periodic grid. Data defined on the cell centers of a periodic grid.
""" """
@ -507,7 +510,7 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool:
Parameters Parameters
---------- ----------
coordinates0 : numpy.ndarray coordinates0 : numpy.ndarray, shape (:,3)
Array of undeformed cell coordinates. Array of undeformed cell coordinates.
Returns Returns
@ -523,17 +526,17 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool:
return False return False
def regrid(size: _np.ndarray, F: _np.ndarray, cells: Union[_np.ndarray,Sequence[int]]) -> _np.ndarray: def regrid(size: _FloatSequence, F: _np.ndarray, cells: _IntSequence) -> _np.ndarray:
""" """
Return mapping from coordinates in deformed configuration to a regular grid. Return mapping from coordinates in deformed configuration to a regular grid.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size. Physical size.
F : numpy.ndarray of shape (:,:,:,3,3) F : numpy.ndarray, shape (:,:,:,3,3), shape (:,:,:,3,3)
Deformation gradient field. Deformation gradient field.
cells : numpy.ndarray of shape (3) cells : sequence of int, len (3)
Cell count along x,y,z of remapping grid. Cell count along x,y,z of remapping grid.
""" """

View File

@ -5,7 +5,7 @@ All routines operate on numpy.ndarrays of shape (...,3,3).
""" """
from typing import Sequence from typing import Sequence as _Sequence
import numpy as _np import numpy as _np
@ -243,7 +243,7 @@ def stretch_right(T: _np.ndarray) -> _np.ndarray:
return _polar_decomposition(T,'U')[0] return _polar_decomposition(T,'U')[0]
def _polar_decomposition(T: _np.ndarray, requested: Sequence[str]) -> tuple: def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple:
""" """
Perform singular value decomposition. Perform singular value decomposition.

View File

@ -1,25 +1,27 @@
"""Functionality for generation of seed points for Voronoi or Laguerre tessellation.""" """Functionality for generation of seed points for Voronoi or Laguerre tessellation."""
from typing import Sequence,Tuple from typing import Tuple as _Tuple
from scipy import spatial as _spatial from scipy import spatial as _spatial
import numpy as _np import numpy as _np
from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence
from . import util as _util from . import util as _util
from . import grid_filters as _grid_filters from . import grid_filters as _grid_filters
def from_random(size: _np.ndarray, N_seeds: int, cells: _np.ndarray = None, rng_seed=None) -> _np.ndarray: def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None,
rng_seed=None) -> _np.ndarray:
""" """
Place seeds randomly in space. Place seeds randomly in space.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the seeding domain. Physical size of the seeding domain.
N_seeds : int N_seeds : int
Number of seeds. Number of seeds.
cells : numpy.ndarray of shape (3), optional. cells : sequence of int, len (3), optional.
If given, ensures that each seed results in a grain when a standard Voronoi If given, ensures that each seed results in a grain when a standard Voronoi
tessellation is performed using the given grid resolution (i.e. size/cells). tessellation is performed using the given grid resolution (i.e. size/cells).
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
@ -28,29 +30,30 @@ def from_random(size: _np.ndarray, N_seeds: int, cells: _np.ndarray = None, rng_
Returns Returns
------- -------
coords : numpy.ndarray of shape (N_seeds,3) coords : numpy.ndarray, shape (N_seeds,3)
Seed coordinates in 3D space. Seed coordinates in 3D space.
""" """
size_ = _np.array(size,float)
rng = _np.random.default_rng(rng_seed) rng = _np.random.default_rng(rng_seed)
if cells is None: if cells is None:
coords = rng.random((N_seeds,3)) * size coords = rng.random((N_seeds,3)) * size_
else: else:
grid_coords = _grid_filters.coordinates0_point(cells,size).reshape(-1,3,order='F') grid_coords = _grid_filters.coordinates0_point(cells,size).reshape(-1,3,order='F')
coords = grid_coords[rng.choice(_np.prod(cells),N_seeds, replace=False)] \ coords = grid_coords[rng.choice(_np.prod(cells),N_seeds, replace=False)] \
+ _np.broadcast_to(size/cells,(N_seeds,3))*(rng.random((N_seeds,3))*.5-.25) # wobble without leaving cells + _np.broadcast_to(size_/_np.array(cells,int),(N_seeds,3))*(rng.random((N_seeds,3))*.5-.25) # wobble w/o leaving grid
return coords return coords
def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distance: float, def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, distance: float,
periodic: bool = True, rng_seed=None) -> _np.ndarray: periodic: bool = True, rng_seed=None) -> _np.ndarray:
""" """
Place seeds according to a Poisson disc distribution. Place seeds according to a Poisson disc distribution.
Parameters Parameters
---------- ----------
size : numpy.ndarray of shape (3) size : sequence of float, len (3)
Physical size of the seeding domain. Physical size of the seeding domain.
N_seeds : int N_seeds : int
Number of seeds. Number of seeds.
@ -66,13 +69,13 @@ def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distan
Returns Returns
------- -------
coords : numpy.ndarray of shape (N_seeds,3) coords : numpy.ndarray, shape (N_seeds,3)
Seed coordinates in 3D space. Seed coordinates in 3D space.
""" """
rng = _np.random.default_rng(rng_seed) rng = _np.random.default_rng(rng_seed)
coords = _np.empty((N_seeds,3)) coords = _np.empty((N_seeds,3))
coords[0] = rng.random(3) * size coords[0] = rng.random(3) * _np.array(size,float)
s = 1 s = 1
i = 0 i = 0
@ -96,8 +99,8 @@ def from_Poisson_disc(size: _np.ndarray, N_seeds: int, N_candidates: int, distan
return coords return coords
def from_grid(grid, selection: Sequence[int] = None, def from_grid(grid, selection: _IntSequence = None,
invert: bool = False, average: bool = False, periodic: bool = True) -> Tuple[_np.ndarray, _np.ndarray]: invert: bool = False, average: bool = False, periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]:
""" """
Create seeds from grid description. Create seeds from grid description.
@ -105,7 +108,7 @@ def from_grid(grid, selection: Sequence[int] = None,
---------- ----------
grid : damask.Grid grid : damask.Grid
Grid 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 : sequence of int, optional
Material IDs to consider. Material IDs to consider.
invert : boolean, false invert : boolean, false
Consider all material IDs except those in selection. Defaults to False. Consider all material IDs except those in selection. Defaults to False.
@ -116,7 +119,7 @@ def from_grid(grid, selection: Sequence[int] = None,
Returns Returns
------- -------
coords, materials : numpy.ndarray of shape (:,3), numpy.ndarray of shape (:) coords, materials : numpy.ndarray, shape (:,3); numpy.ndarray, shape (:)
Seed coordinates in 3D space, material IDs. Seed coordinates in 3D space, material IDs.
""" """