Merge remote-tracking branch 'origin/development' into drop-old-DADF5-support

This commit is contained in:
Martin Diehl 2021-04-25 17:34:14 +02:00
commit d4a46b9be8
10 changed files with 80 additions and 44 deletions

@ -1 +1 @@
Subproject commit afffa8d04e110282e514a4e57d0bad9c76effe01 Subproject commit 7f0594060779d9a8a4e774d558134309ab77b96e

View File

@ -61,6 +61,11 @@ class Config(dict):
other : damask.Config or dict other : damask.Config or dict
Key-value pairs that update self. Key-value pairs that update self.
Returns
-------
updated : damask.Config
Updated configuration.
""" """
duplicate = self.copy() duplicate = self.copy()
duplicate.update(other) duplicate.update(other)
@ -81,6 +86,11 @@ class Config(dict):
keys : iterable or scalar keys : iterable or scalar
Label of the key(s) to remove. Label of the key(s) to remove.
Returns
-------
updated : damask.Config
Updated configuration.
""" """
duplicate = self.copy() duplicate = self.copy()
for k in keys if isinstance(keys, Iterable) and not isinstance(keys, str) else [keys]: for k in keys if isinstance(keys, Iterable) and not isinstance(keys, str) else [keys]:
@ -98,6 +108,11 @@ class Config(dict):
fname : file, str, or pathlib.Path fname : file, str, or pathlib.Path
Filename or file for writing. Filename or file for writing.
Returns
-------
loaded : damask.Config
Configuration from file.
""" """
try: try:
fhandle = open(fname) fhandle = open(fname)

View File

@ -54,7 +54,12 @@ class ConfigMaterial(Config):
Parameters Parameters
---------- ----------
fname : file, str, or pathlib.Path, optional fname : file, str, or pathlib.Path, optional
Filename or file for writing. Defaults to 'material.yaml'. Filename or file to read from. Defaults to 'material.yaml'.
Returns
-------
loaded : damask.ConfigMaterial
Material configuration from file.
""" """
return super(ConfigMaterial,cls).load(fname) return super(ConfigMaterial,cls).load(fname)
@ -103,6 +108,11 @@ class ConfigMaterial(Config):
and grain- or cell-wise data. Defaults to None, in which case and grain- or cell-wise data. Defaults to None, in which case
it is set as the path that contains _SIMPL_GEOMETRY/SPACING. it is set as the path that contains _SIMPL_GEOMETRY/SPACING.
Returns
-------
loaded : damask.ConfigMaterial
Material configuration from file.
""" """
b = util.DREAM3D_base_group(fname) if base_group is None else base_group b = util.DREAM3D_base_group(fname) if base_group is None else base_group
c = util.DREAM3D_cell_data_group(fname) if cell_data is None else cell_data c = util.DREAM3D_cell_data_group(fname) if cell_data is None else cell_data
@ -146,6 +156,11 @@ class ConfigMaterial(Config):
Keyword arguments where the key is the name and the value specifies Keyword arguments where the key is the name and the value specifies
the label of the data column in the table. the label of the data column in the table.
Returns
-------
new : damask.ConfigMaterial
Material configuration from values in table.
Examples Examples
-------- --------
>>> import damask >>> import damask

View File

@ -1012,6 +1012,11 @@ class Grid:
Direction(s) along which the boundaries are determined. Direction(s) along which the boundaries are determined.
Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'. Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'.
Returns
-------
grain_boundaries : damask.VTK
VTK-based geometry of grain boundary network.
""" """
valid = ['x','y','z'] valid = ['x','y','z']
if not set(directions).issubset(valid): if not set(directions).issubset(valid):

View File

@ -59,17 +59,17 @@ class Result:
""" """
Add data to and export data from a DADF5 file. Add data to and export data from a DADF5 file.
A DADF5 (DAMASK HDF5) file contain DAMASK results. A DADF5 (DAMASK HDF5) file contains DAMASK results.
Its group/folder structure reflects the layout in material.yaml. Its group/folder structure reflects the layout in material.yaml.
This class provides a customable view on the DADF5 file. This class provides a customizable view on the DADF5 file.
Upon initialization, all attributes are visible. Upon initialization, all attributes are visible.
Derived quantities are added to the file and existing data is Derived quantities are added to the file and existing data is
exported based on the current view. exported based on the current view.
Examples Examples
-------- --------
Open 'my_file.hdf5', which needs to contain deformation gradient 'F' Open 'my_file.hdf5', which is assumed to contain deformation gradient 'F'
and first Piola-Kirchhoff stress 'P', add the Mises equivalent of the and first Piola-Kirchhoff stress 'P', add the Mises equivalent of the
Cauchy stress, and export it to VTK (file) and numpy.ndarray (memory). Cauchy stress, and export it to VTK (file) and numpy.ndarray (memory).
@ -224,12 +224,12 @@ class Result:
def modification_enable(self): def modification_enable(self):
""" """
Allow to modify existing data. Allow modification of existing data.
Returns Returns
------- -------
modified_view : damask.Result modified_view : damask.Result
View where data is not write-protected. View without write-protection of existing data.
""" """
print(util.warn('Warning: Modification of existing datasets allowed!')) print(util.warn('Warning: Modification of existing datasets allowed!'))
@ -239,12 +239,12 @@ class Result:
def modification_disable(self): def modification_disable(self):
""" """
Disallow to modify existing data (default case). Prevent modification of existing data (default case).
Returns Returns
------- -------
modified_view : damask.Result modified_view : damask.Result
View where data is write-protected. View with write-protection of existing data.
""" """
dup = self.copy() dup = self.copy()
@ -316,7 +316,7 @@ class Result:
Returns Returns
------- -------
view : damask.Result view : damask.Result
View with where selected attributes are visible. View with only the selected attributes being visible.
Examples Examples
-------- --------
@ -326,7 +326,7 @@ class Result:
>>> r = damask.Result('my_file.hdf5') >>> r = damask.Result('my_file.hdf5')
>>> r_first = r.view('increment',0) >>> r_first = r.view('increment',0)
Get a view that shows all results of in simulation time [10,40]: Get a view that shows all results between simulation times of 10 to 40:
>>> import damask >>> import damask
>>> r = damask.Result('my_file.hdf5') >>> r = damask.Result('my_file.hdf5')
@ -351,7 +351,7 @@ class Result:
Returns Returns
------- -------
modified_view : damask.Result modified_view : damask.Result
View with more visible attributes. View with additional visible attributes.
Examples Examples
-------- --------
@ -368,7 +368,7 @@ class Result:
def view_less(self,what,datasets): def view_less(self,what,datasets):
""" """
Delete from view. Remove from view.
Parameters Parameters
---------- ----------
@ -381,11 +381,11 @@ class Result:
Returns Returns
------- -------
modified_view : damask.Result modified_view : damask.Result
View with less visible attributes. View with fewer visible attributes.
Examples Examples
-------- --------
Get a view that does not show the undeformed configuration: Get a view that omits the undeformed configuration:
>>> import damask >>> import damask
>>> r_all = damask.Result('my_file.hdf5') >>> r_all = damask.Result('my_file.hdf5')
@ -570,16 +570,17 @@ class Result:
'creator': 'add_calculation' 'creator': 'add_calculation'
} }
} }
def add_calculation(self,name,formula,unit='n/a',description=None): def add_calculation(self,formula,name,unit='n/a',description=None):
""" """
Add result of a general formula. Add result of a general formula.
Parameters Parameters
---------- ----------
formula : str
Formula to calculate resulting dataset.
Existing datasets are referenced by '#TheirName#'.
name : str name : str
Name of resulting dataset. Name of resulting dataset.
formula : str
Formula to calculate resulting dataset. Existing datasets are referenced by '#TheirName#'.
unit : str, optional unit : str, optional
Physical unit of the result. Physical unit of the result.
description : str, optional description : str, optional
@ -593,11 +594,11 @@ class Result:
>>> import damask >>> import damask
>>> r = damask.Result('my_file.hdf5') >>> r = damask.Result('my_file.hdf5')
>>> r.add_calculation('rho_mob_total','np.sum(#rho_mob#,axis=1)', >>> r.add_calculation('np.sum(#rho_mob#,axis=1)','rho_mob_total',
... '1/m²','total mobile dislocation density') ... '1/m²','total mobile dislocation density')
>>> r.add_calculation('rho_dip_total','np.sum(#rho_dip#,axis=1)', >>> r.add_calculation(''np.sum(#rho_dip#,axis=1)',rho_dip_total',
... '1/m²','total dislocation dipole density') ... '1/m²','total dislocation dipole density')
>>> r.add_calculation('rho_total','#rho_dip_total#+#rho_mob_total', >>> r.add_calculation('#rho_dip_total#+#rho_mob_total','rho_total',
... '1/m²','total dislocation density') ... '1/m²','total dislocation density')
Add Mises equivalent of the Cauchy stress without storage of Add Mises equivalent of the Cauchy stress without storage of
@ -609,7 +610,7 @@ class Result:
... return damask.mechanics.equivalent_stress_Mises(sigma) ... return damask.mechanics.equivalent_stress_Mises(sigma)
>>> r = damask.Result('my_file.hdf5') >>> r = damask.Result('my_file.hdf5')
>>> r.enable_user_function(equivalent_stress) >>> r.enable_user_function(equivalent_stress)
>>> r.add_calculation('sigma_vM','equivalent_stress(#F#,#P#)','Pa', >>> r.add_calculation('equivalent_stress(#F#,#P#)','sigma_vM','Pa',
... 'Mises equivalent of the Cauchy stress') ... 'Mises equivalent of the Cauchy stress')
""" """
@ -1378,7 +1379,7 @@ class Result:
Parameters Parameters
---------- ----------
output : (list of) str, optional output : (list of) str, optional
Names of the datasets included in the VTK file. Names of the datasets to export to the VTK file.
Defaults to '*', in which case all datasets are exported. Defaults to '*', in which case all datasets are exported.
mode : {'cell', 'point'} mode : {'cell', 'point'}
Export in cell format or point format. Export in cell format or point format.
@ -1502,7 +1503,7 @@ class Result:
in the DADF5 file. in the DADF5 file.
Multi-phase data is fused into a single output. Multi-phase data is fused into a single output.
`place` is equivalent to `read` if only one phase/homogenization `place` is equivalent to `get` if only one phase/homogenization
and one constituent is present. and one constituent is present.
Parameters Parameters
@ -1518,7 +1519,7 @@ class Result:
Remove branches with no data. Defaults to True. Remove branches with no data. Defaults to True.
constituents : (list of) int, optional constituents : (list of) int, optional
Constituents to consider. Constituents to consider.
Defaults to 'None', in which case all constituents are considered. Defaults to None, in which case all constituents are considered.
fill_float : float fill_float : float
Fill value for non-existent entries of floating point type. Fill value for non-existent entries of floating point type.
Defaults to NaN. Defaults to NaN.

View File

@ -46,9 +46,9 @@ class VTK:
grid : iterable of int, len (3) grid : iterable of int, len (3)
Number of cells along each dimension. Number of cells along each dimension.
size : iterable of float, len (3) size : iterable of float, len (3)
Physical lengths along each dimension. Physical length along each dimension.
origin : iterable of float, len (3), optional origin : iterable of float, len (3), optional
Spatial origin coordinates. Coordinates of grid origin.
Returns Returns
------- -------
@ -161,7 +161,7 @@ class VTK:
""" """
if not os.path.isfile(fname): # vtk has a strange error handling if not os.path.isfile(fname): # vtk has a strange error handling
raise FileNotFoundError(f'no such file: {fname}') raise FileNotFoundError(f'No such file: {fname}')
ext = Path(fname).suffix ext = Path(fname).suffix
if ext == '.vtk' or dataset_type is not None: if ext == '.vtk' or dataset_type is not None:
reader = vtk.vtkGenericDataObjectReader() reader = vtk.vtkGenericDataObjectReader()

View File

@ -493,7 +493,7 @@ def node_to_point(node_data):
def coordinates0_valid(coordinates0): def coordinates0_valid(coordinates0):
""" """
Check whether coordinates lie on a regular grid. Check whether coordinates form a regular grid.
Parameters Parameters
---------- ----------
@ -503,7 +503,7 @@ def coordinates0_valid(coordinates0):
Returns Returns
------- -------
valid : bool valid : bool
Wheter the coordinates lie on a regular grid. Whether the coordinates form a regular grid.
""" """
try: try:

View File

@ -1,3 +1,3 @@
"""Run simulations directly from python.""" """Run simulations directly from Python."""
from ._marc import Marc # noqa from ._marc import Marc # noqa

View File

@ -110,14 +110,14 @@ class TestResult:
def test_add_calculation(self,default,tmp_path,mode): def test_add_calculation(self,default,tmp_path,mode):
if mode == 'direct': if mode == 'direct':
default.add_calculation('x','2.0*np.abs(#F#)-1.0','-','my notes') default.add_calculation('2.0*np.abs(#F#)-1.0','x','-','my notes')
else: else:
with open(tmp_path/'f.py','w') as f: with open(tmp_path/'f.py','w') as f:
f.write("import numpy as np\ndef my_func(field):\n return 2.0*np.abs(field)-1.0\n") f.write("import numpy as np\ndef my_func(field):\n return 2.0*np.abs(field)-1.0\n")
sys.path.insert(0,str(tmp_path)) sys.path.insert(0,str(tmp_path))
import f import f
default.enable_user_function(f.my_func) default.enable_user_function(f.my_func)
default.add_calculation('x','my_func(#F#)','-','my notes') default.add_calculation('my_func(#F#)','x','-','my notes')
in_memory = 2.0*np.abs(default.place('F'))-1.0 in_memory = 2.0*np.abs(default.place('F'))-1.0
in_file = default.place('x') in_file = default.place('x')
@ -193,14 +193,14 @@ class TestResult:
def test_add_Mises_invalid(self,default): def test_add_Mises_invalid(self,default):
default.add_stress_Cauchy('P','F') default.add_stress_Cauchy('P','F')
default.add_calculation('sigma_y','#sigma#',unit='y') default.add_calculation('#sigma#','sigma_y',unit='y')
default.add_equivalent_Mises('sigma_y') default.add_equivalent_Mises('sigma_y')
assert default.get('sigma_y_vM') is None assert default.get('sigma_y_vM') is None
def test_add_Mises_stress_strain(self,default): def test_add_Mises_stress_strain(self,default):
default.add_stress_Cauchy('P','F') default.add_stress_Cauchy('P','F')
default.add_calculation('sigma_y','#sigma#',unit='y') default.add_calculation('#sigma#','sigma_y',unit='y')
default.add_calculation('sigma_x','#sigma#',unit='x') default.add_calculation('#sigma#','sigma_x',unit='x')
default.add_equivalent_Mises('sigma_y',kind='strain') default.add_equivalent_Mises('sigma_y',kind='strain')
default.add_equivalent_Mises('sigma_x',kind='stress') default.add_equivalent_Mises('sigma_x',kind='stress')
assert not np.allclose(default.place('sigma_y_vM'),default.place('sigma_x_vM')) assert not np.allclose(default.place('sigma_y_vM'),default.place('sigma_x_vM'))
@ -285,7 +285,7 @@ class TestResult:
time.sleep(2.) time.sleep(2.)
try: try:
last.add_calculation('sigma','#sigma#*0.0+311.','not the Cauchy stress') last.add_calculation('#sigma#*0.0+311.','sigma','not the Cauchy stress')
except ValueError: except ValueError:
pass pass
@ -362,7 +362,7 @@ class TestResult:
def test_XDMF(self,tmp_path,single_phase,update,ref_path): def test_XDMF(self,tmp_path,single_phase,update,ref_path):
for shape in [('scalar',()),('vector',(3,)),('tensor',(3,3)),('matrix',(12,))]: for shape in [('scalar',()),('vector',(3,)),('tensor',(3,3)),('matrix',(12,))]:
for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']: for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']:
single_phase.add_calculation(f'{shape[0]}_{dtype}',f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')") single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')",f'{shape[0]}_{dtype}')
fname = os.path.splitext(os.path.basename(single_phase.fname))[0]+'.xdmf' fname = os.path.splitext(os.path.basename(single_phase.fname))[0]+'.xdmf'
os.chdir(tmp_path) os.chdir(tmp_path)
single_phase.save_XDMF() single_phase.save_XDMF()