diff --git a/PRIVATE b/PRIVATE index e3d9c0cc3..3561f74a5 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit e3d9c0cc3ffa1435003f934a0f0e6c7d969a022a +Subproject commit 3561f74a5852c32e2c3da4dc48090b517cfa8e90 diff --git a/python/damask/_grid.py b/python/damask/_grid.py index d4a7ea02f..471ba36bd 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -4,7 +4,7 @@ import warnings import multiprocessing as mp from functools import partial import typing -from typing import Union, Optional, TextIO, List, Sequence +from typing import Union, Optional, TextIO, List, Sequence, Dict from pathlib import Path import numpy as np @@ -34,8 +34,8 @@ class Grid: material: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3), - comments: Union[str, Sequence[str]] = None, - initial_conditions = None): + initial_conditions: Dict[str,np.ndarray] = None, + comments: Union[str, Sequence[str]] = None): """ New geometry definition for grid solvers. @@ -48,15 +48,17 @@ class Grid: Physical size of grid in meter. origin : sequence of float, len (3), optional Coordinates of grid origin in meter. Defaults to [0.0,0.0,0.0]. + initial_conditions : dictionary, optional + Labels and values of the inital conditions at each material point. comments : (list of) str, optional Comments, e.g. history of operations. """ self.material = material - self.size = size # type: ignore - self.origin = origin # type: ignore - self.comments = [] if comments is None else comments # type: ignore - self.ic = initial_conditions if initial_conditions is not None else {} + self.size = size # type: ignore + self.origin = origin # type: ignore + self.initial_conditions = {} if initial_conditions is None else initial_conditions + self.comments = [] if comments is None else comments # type: ignore def __repr__(self) -> str: """Give short human-readable summary.""" @@ -69,7 +71,7 @@ class Grid: f'origin: {util.srepr(self.origin," ")} m', f'# materials: {mat_N}' + ('' if mat_min == 0 and mat_max+1 == mat_N else f' (min: {mat_min}, max: {mat_max})') - ]+(['initial_conditions:']+[f' - {f}' for f in self.ic.keys()] if self.ic else [])) + ]+(['initial_conditions:']+[f' - {f}' for f in self.initial_conditions] if self.initial_conditions else [])) def __copy__(self) -> 'Grid': @@ -144,6 +146,22 @@ class Grid: self._origin = np.array(origin) + @property + def initial_conditions(self) -> Dict[str,np.ndarray]: + """Fields of initial conditions.""" + self._ic = dict(zip(self._ic.keys(), # type: ignore + [v if isinstance(v,np.ndarray) else + np.broadcast_to(v,self.cells) for v in self._ic.values()])) # type: ignore + return self._ic + + @initial_conditions.setter + def initial_conditions(self, + ic: Dict[str,np.ndarray]): + if not isinstance(ic,dict): + raise TypeError('initial conditions is not a dictionary') + + self._ic = ic + @property def comments(self) -> List[str]: """Comments, e.g. history of operations.""" @@ -193,11 +211,12 @@ class Grid: return Grid(material = v.get('material').reshape(cells,order='F'), size = bbox[1] - bbox[0], origin = bbox[0], + initial_conditions = ic, comments = comments, - initial_conditions = ic) + ) - @typing. no_type_check + @typing.no_type_check @staticmethod def load_ASCII(fname)-> 'Grid': """ @@ -267,7 +286,10 @@ class Grid: if not np.any(np.mod(material,1) != 0.0): # no float present material = material.astype(int) - (1 if material.min() > 0 else 0) - return Grid(material.reshape(cells,order='F'),size,origin,comments) + return Grid(material = material.reshape(cells,order='F'), + size = size, + origin = origin, + comments = comments) @staticmethod @@ -304,9 +326,11 @@ class Grid: cells = np.array(v.vtk_data.GetDimensions())-1 bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T - return Grid(v.get('MaterialId').reshape(cells,order='F').astype('int32',casting='unsafe') - 1, - bbox[1] - bbox[0], bbox[0], - util.execution_stamp('Grid','load_Neper')) + return Grid(material = v.get('MaterialId').reshape(cells,order='F').astype('int32',casting='unsafe') - 1, + size = bbox[1] - bbox[0], + origin = bbox[0], + comments = util.execution_stamp('Grid','load_Neper'), + ) @staticmethod @@ -369,7 +393,11 @@ class Grid: else: ma = f['/'.join([b,c,feature_IDs])][()].flatten() - return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','load_DREAM3D')) + return Grid(material = ma.reshape(cells,order='F'), + size = size, + origin = origin, + comments = util.execution_stamp('Grid','load_DREAM3D'), + ) @staticmethod @@ -404,7 +432,11 @@ class Grid: ma = np.arange(cells.prod()) if len(unique) == cells.prod() else \ np.arange(unique.size)[np.argsort(pd.unique(unique_inverse))][unique_inverse] - return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','from_table')) + return Grid(material = ma.reshape(cells,order='F'), + size = size, + origin = origin, + comments = util.execution_stamp('Grid','from_table'), + ) @staticmethod @@ -625,7 +657,7 @@ class Grid: origin: 0.0 0.0 0.0 m # materials: 2 - Minimal surface of 'Neovius' type. non-default material IDs. + Minimal surface of 'Neovius' type with non-default material IDs. >>> import numpy as np >>> import damask @@ -663,7 +695,7 @@ class Grid: """ v = VTK.from_image_data(self.cells,self.size,self.origin)\ .add('material',self.material.flatten(order='F')) - for label,data in self.ic.items(): + for label,data in self.initial_conditions.items(): v = v.add(label,data.flatten(order='F')) v.comments = self.comments @@ -927,13 +959,13 @@ class Grid: """ return Grid(material = ndimage.interpolation.zoom( - self.material, - cells/self.cells, - output=self.material.dtype, - order=0, - mode='wrap' if periodic else 'nearest', - prefilter=False - ), + self.material, + cells/self.cells, + output=self.material.dtype, + order=0, + mode='wrap' if periodic else 'nearest', + prefilter=False + ), size = self.size, origin = self.origin, comments = self.comments+[util.execution_stamp('Grid','scale')], @@ -955,6 +987,7 @@ class Grid: return Grid(material = renumbered.reshape(self.cells), size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','renumber')], ) @@ -986,6 +1019,7 @@ class Grid: return Grid(material = material, size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','substitute')], ) @@ -1008,6 +1042,7 @@ class Grid: return Grid(material = ma.reshape(self.cells,order='F'), size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','sort')], ) @@ -1075,6 +1110,7 @@ class Grid: return Grid(material = material, size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','clean')], ) @@ -1167,6 +1203,7 @@ class Grid: np.nanmax(self.material)+1 if fill is None else fill), size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','add_primitive')], ) @@ -1229,6 +1266,7 @@ class Grid: return Grid(material = np.where(mask, self.material + offset_,self.material), size = self.size, origin = self.origin, + initial_conditions = self.initial_conditions, comments = self.comments+[util.execution_stamp('Grid','vicinity_offset')], )