Merge remote-tracking branch 'origin/development' into typehints_table

This commit is contained in:
Martin Diehl 2022-01-23 12:45:06 +01:00
commit 803c85c2ef
26 changed files with 550 additions and 380 deletions

View File

@ -46,7 +46,7 @@ variables:
# ++++++++++++ PETSc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ++++++++++++ PETSc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PETSC_GNU: "Libraries/PETSc/3.16.1/GNU-10-OpenMPI-4.1.1" PETSC_GNU: "Libraries/PETSc/3.16.1/GNU-10-OpenMPI-4.1.1"
PETSC_INTELLLVM: "Libraries/PETSc/3.16.3/oneAPI-2022.0.1-IntelMPI-2021.5.0" PETSC_INTELLLVM: "Libraries/PETSc/3.16.3/oneAPI-2022.0.1-IntelMPI-2021.5.0"
PETSC_INTEL: "Libraries/PETSc/3.16.2/Intel-2022.0.1-IntelMPI-2021.5.0" PETSC_INTEL: "Libraries/PETSc/3.16.3/Intel-2022.0.1-IntelMPI-2021.5.0"
# ++++++++++++ MSC Marc +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ++++++++++++ MSC Marc +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSC: "FEM/MSC/2021.3.1" MSC: "FEM/MSC/2021.3.1"
IntelMarc: "Compiler/Intel/19.1.2 Libraries/IMKL/2020" IntelMarc: "Compiler/Intel/19.1.2 Libraries/IMKL/2020"
@ -79,63 +79,63 @@ mypy:
################################################################################################### ###################################################################################################
test_grid_GNU: grid_GNU:
stage: compile stage: compile
script: script:
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU} - module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU - pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU
test_mesh_GNU: mesh_GNU:
stage: compile stage: compile
script: script:
- module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU} - module load ${COMPILER_GNU} ${MPI_GNU} ${PETSC_GNU}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU - pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU
test_grid_GNU-64bit: grid_GNU-64bit:
stage: compile stage: compile
script: script:
- module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit - module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU-64bit - pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_GNU-64bit
test_mesh_GNU-64bit: mesh_GNU-64bit:
stage: compile stage: compile
script: script:
- module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit - module load Compiler/GNU/10 Libraries/PETSc/3.16.2/64bit
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU-64bit - pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_GNU-64bit
test_grid_IntelLLVM: grid_IntelLLVM:
stage: compile stage: compile
script: script:
- module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM} - module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_IntelLLVM - pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_IntelLLVM
test_mesh_IntelLLVM: mesh_IntelLLVM:
stage: compile stage: compile
script: script:
- module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM} - module load ${COMPILER_INTELLLVM} ${MPI_INTELLLVM} ${PETSC_INTELLLVM}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_IntelLLVM - pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_IntelLLVM
test_grid_Intel: grid_Intel:
stage: compile stage: compile
script: script:
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL} - module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_Intel - pytest -k 'compile and grid' --basetemp ${TESTROOT}/compile_grid_Intel
test_mesh_Intel: mesh_Intel:
stage: compile stage: compile
script: script:
- module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL} - module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL}
- cd PRIVATE/testing/pytest - cd PRIVATE/testing/pytest
- pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_Intel - pytest -k 'compile and mesh' --basetemp ${TESTROOT}/compile_mesh_Intel
test_Marc: Marc_Intel:
stage: compile stage: compile
script: script:
- module load $IntelMarc $HDF5Marc $MSC - module load $IntelMarc $HDF5Marc $MSC
@ -158,7 +158,7 @@ setup_mesh:
- cmake -DDAMASK_SOLVER=MESH -DCMAKE_INSTALL_PREFIX=${TESTROOT} ${CI_PROJECT_DIR} - cmake -DDAMASK_SOLVER=MESH -DCMAKE_INSTALL_PREFIX=${TESTROOT} ${CI_PROJECT_DIR}
- make -j2 all install - make -j2 all install
compile_Marc: setup_Marc:
stage: compile stage: compile
script: script:
- module load $IntelMarc $HDF5Marc $MSC - module load $IntelMarc $HDF5Marc $MSC

@ -1 +1 @@
Subproject commit b898a8b5552bd9d1c555edc3d8134564dd32fe53 Subproject commit d570b4a1fac5b9b99d026d3ff9bf593615e22ce5

View File

@ -6,7 +6,7 @@ references:
output: [xi_sl, xi_tw] output: [xi_sl, xi_tw]
N_sl: [3, 3, 6, 0, 6] # basal, prism, -, 1. pyr<a>, -, 2. pyr<c+a> N_sl: [3, 3, 6, 0, 6] # basal, prism, 1. pyr<a>, -, 2. pyr<c+a>
N_tw: [6, 0, 6] # tension, -, compression N_tw: [6, 0, 6] # tension, -, compression
xi_0_sl: [10.e+6, 55.e+6, 60.e+6, 0., 60.e+6] xi_0_sl: [10.e+6, 55.e+6, 60.e+6, 0., 60.e+6]
@ -23,9 +23,13 @@ f_sat_sl-tw: 10.0
h_0_sl-sl: 500.0e+6 h_0_sl-sl: 500.0e+6
h_0_tw-tw: 50.0e+6 h_0_tw-tw: 50.0e+6
h_0_tw-sl: 150.0e+6 h_0_tw-sl: 150.0e+6
h_sl-sl: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, +1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, +1.0, 1.0] # unused entries are indicated by -1.0 -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # unused entries are indicated by -1.0
h_tw-tw: [+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, h_tw-tw: [+1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0,
-1.0, 1.0] # unused entries are indicated by -1.0 -1.0, 1.0] # unused entries are indicated by -1.0
h_tw-sl: [1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, h_tw-sl: [1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0,

View File

@ -8,7 +8,7 @@ references:
https://doi.org/10.1016/j.actamat.2017.05.015 https://doi.org/10.1016/j.actamat.2017.05.015
output: [gamma_sl] output: [gamma_sl]
N_sl: [3, 3, 0, 12] # basal, 1. prism, -, 1. pyr<c+a> N_sl: [3, 3, 0, 12] # basal, prism, -, 1. pyr<c+a>
n_sl: 20 n_sl: 20
a_sl: 2.0 a_sl: 2.0
dot_gamma_0_sl: 0.001 dot_gamma_0_sl: 0.001
@ -20,5 +20,8 @@ xi_inf_sl: [568.e+6, 150.e+7, 0.0, 3420.e+6]
# L. Wang et al. : # L. Wang et al. :
# xi_0_sl: [127.e+6, 96.e+6, 0.0, 240.e+6] # xi_0_sl: [127.e+6, 96.e+6, 0.0, 240.e+6]
h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, h_sl-sl: [+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0,
-1.0, -1.0, +1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0] # unused entries are indicated by -1.0 -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # unused entries are indicated by -1.0

View File

@ -1 +1 @@
v3.0.0-alpha5-389-ga000e477c v3.0.0-alpha5-475-g160eb1c60

View File

@ -21,8 +21,8 @@ from ._rotation import Rotation # noqa
from ._crystal import Crystal # noqa from ._crystal import Crystal # noqa
from ._orientation import Orientation # noqa from ._orientation import Orientation # noqa
from ._table import Table # noqa from ._table import Table # noqa
from ._vtk import VTK # noqa
from ._colormap import Colormap # noqa from ._colormap import Colormap # noqa
from ._vtk import VTK # noqa
from ._config import Config # noqa from ._config import Config # noqa
from ._configmaterial import ConfigMaterial # noqa from ._configmaterial import ConfigMaterial # noqa
from ._grid import Grid # noqa from ._grid import Grid # noqa

View File

@ -250,7 +250,7 @@ class Colormap(mpl.colors.ListedColormap):
np.logical_or (np.isnan(field), field == gap)) # mask NaN (and gap if present) np.logical_or (np.isnan(field), field == gap)) # mask NaN (and gap if present)
l,r = (field[mask].min(),field[mask].max()) if bounds is None else \ l,r = (field[mask].min(),field[mask].max()) if bounds is None else \
np.array(bounds,float)[:2] (bounds[0],bounds[1])
delta,avg = r-l,0.5*abs(r+l) delta,avg = r-l,0.5*abs(r+l)

View File

@ -4,7 +4,7 @@ import warnings
import multiprocessing as mp import multiprocessing as mp
from functools import partial from functools import partial
import typing import typing
from typing import Union, Optional, TextIO, List, Sequence from typing import Union, Optional, TextIO, List, Sequence, Literal
from pathlib import Path from pathlib import Path
import numpy as np import numpy as np
@ -70,7 +70,7 @@ class Grid:
]) ])
def __copy__(self) -> "Grid": def __copy__(self) -> 'Grid':
"""Create deep copy.""" """Create deep copy."""
return copy.deepcopy(self) return copy.deepcopy(self)
@ -161,7 +161,7 @@ class Grid:
@staticmethod @staticmethod
def load(fname: Union[str, Path]) -> "Grid": def load(fname: Union[str, Path]) -> 'Grid':
""" """
Load from VTK image data file. Load from VTK image data file.
@ -190,7 +190,7 @@ class Grid:
@typing. no_type_check @typing. no_type_check
@staticmethod @staticmethod
def load_ASCII(fname)-> "Grid": def load_ASCII(fname)-> 'Grid':
""" """
Load from geom file. Load from geom file.
@ -264,7 +264,7 @@ class Grid:
@staticmethod @staticmethod
def load_Neper(fname: Union[str, Path]) -> "Grid": def load_Neper(fname: Union[str, Path]) -> 'Grid':
""" """
Load from Neper VTK file. Load from Neper VTK file.
@ -279,7 +279,7 @@ class Grid:
Grid-based geometry from file. Grid-based geometry from file.
""" """
v = VTK.load(fname,'vtkImageData') v = VTK.load(fname,'ImageData')
cells = np.array(v.vtk_data.GetDimensions())-1 cells = np.array(v.vtk_data.GetDimensions())-1
bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T
@ -292,7 +292,7 @@ class Grid:
def load_DREAM3D(fname: Union[str, Path], def load_DREAM3D(fname: Union[str, Path],
feature_IDs: str = None, cell_data: str = None, feature_IDs: str = None, cell_data: str = None,
phases: str = 'Phases', Euler_angles: str = 'EulerAngles', phases: str = 'Phases', Euler_angles: str = 'EulerAngles',
base_group: str = None) -> "Grid": base_group: str = None) -> 'Grid':
""" """
Load DREAM.3D (HDF5) file. Load DREAM.3D (HDF5) file.
@ -354,7 +354,7 @@ class Grid:
@staticmethod @staticmethod
def from_table(table: Table, def from_table(table: Table,
coordinates: str, coordinates: str,
labels: Union[str, Sequence[str]]) -> "Grid": labels: Union[str, Sequence[str]]) -> 'Grid':
""" """
Create grid from ASCII table. Create grid from ASCII table.
@ -422,13 +422,14 @@ class Grid:
Grid-based geometry from tessellation. Grid-based geometry from tessellation.
""" """
weights_p: FloatSequence
if periodic: if periodic:
weights_p = np.tile(weights,27) # Laguerre weights (1,2,3,1,2,3,...,1,2,3) weights_p = np.tile(weights,27) # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.]))) seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.])))
seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.]))) seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.])))
seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]]))) seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]])))
else: else:
weights_p = weights weights_p = np.array(weights,float)
seeds_p = seeds seeds_p = seeds
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
@ -452,7 +453,7 @@ class Grid:
size: FloatSequence, size: FloatSequence,
seeds: np.ndarray, seeds: np.ndarray,
material: IntSequence = None, material: IntSequence = None,
periodic: bool = True) -> "Grid": periodic: bool = True) -> 'Grid':
""" """
Create grid from Voronoi tessellation. Create grid from Voronoi tessellation.
@ -538,7 +539,7 @@ class Grid:
surface: str, surface: str,
threshold: float = 0.0, threshold: float = 0.0,
periods: int = 1, periods: int = 1,
materials: IntSequence = (0,1)) -> "Grid": materials: IntSequence = (0,1)) -> 'Grid':
""" """
Create grid from definition of triply periodic minimal surface. Create grid from definition of triply periodic minimal surface.
@ -674,7 +675,7 @@ class Grid:
def show(self) -> None: def show(self) -> None:
"""Show on screen.""" """Show on screen."""
VTK.from_rectilinear_grid(self.cells,self.size,self.origin).show() VTK.from_image_data(self.cells,self.size,self.origin).show()
def add_primitive(self, def add_primitive(self,
@ -684,7 +685,7 @@ class Grid:
fill: int = None, fill: int = None,
R: Rotation = Rotation(), R: Rotation = Rotation(),
inverse: bool = False, inverse: bool = False,
periodic: bool = True) -> "Grid": periodic: bool = True) -> 'Grid':
""" """
Insert a primitive geometric object at a given position. Insert a primitive geometric object at a given position.
@ -769,7 +770,7 @@ class Grid:
) )
def mirror(self, directions: Sequence[str], reflect: bool = False) -> "Grid": def mirror(self, directions: Sequence[str], reflect: bool = False) -> 'Grid':
""" """
Mirror grid along given directions. Mirror grid along given directions.
@ -821,7 +822,7 @@ class Grid:
) )
def flip(self, directions: Sequence[str]) -> "Grid": def flip(self, directions: Union[Literal['x', 'y', 'z'], Sequence[Literal['x', 'y', 'z']]]) -> 'Grid':
""" """
Flip grid along given directions. Flip grid along given directions.
@ -841,7 +842,8 @@ class Grid:
if not set(directions).issubset(valid): if not set(directions).issubset(valid):
raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') raise ValueError(f'invalid direction {set(directions).difference(valid)} specified')
mat = np.flip(self.material, (valid.index(d) for d in directions if d in valid))
mat = np.flip(self.material, [valid.index(d) for d in directions if d in valid])
return Grid(material = mat, return Grid(material = mat,
size = self.size, size = self.size,
@ -850,7 +852,7 @@ class Grid:
) )
def scale(self, cells: IntSequence, periodic: bool = True) -> "Grid": def scale(self, cells: IntSequence, periodic: bool = True) -> 'Grid':
""" """
Scale grid to new cells. Scale grid to new cells.
@ -897,7 +899,7 @@ class Grid:
def clean(self, def clean(self,
stencil: int = 3, stencil: int = 3,
selection: IntSequence = None, selection: IntSequence = None,
periodic: bool = True) -> "Grid": periodic: bool = True) -> 'Grid':
""" """
Smooth grid by selecting most frequent material index within given stencil at each location. Smooth grid by selecting most frequent material index within given stencil at each location.
@ -937,7 +939,7 @@ class Grid:
) )
def renumber(self) -> "Grid": def renumber(self) -> 'Grid':
""" """
Renumber sorted material indices as 0,...,N-1. Renumber sorted material indices as 0,...,N-1.
@ -956,7 +958,7 @@ class Grid:
) )
def rotate(self, R: Rotation, fill: int = None) -> "Grid": def rotate(self, R: Rotation, fill: int = None) -> 'Grid':
""" """
Rotate grid (pad if required). Rotate grid (pad if required).
@ -973,14 +975,13 @@ class Grid:
Updated grid-based geometry. Updated grid-based geometry.
""" """
if fill is None: fill = np.nanmax(self.material) + 1
dtype = float if isinstance(fill,float) or self.material.dtype in np.sctypes['float'] else int
material = self.material material = self.material
# These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'') # These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'')
# see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf # see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]): for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]):
material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,output=dtype,cval=fill) material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,
output=self.material.dtype,
cval=np.nanmax(self.material) + 1 if fill is None else fill)
# avoid scipy interpolation errors for rotations close to multiples of 90° # avoid scipy interpolation errors for rotations close to multiples of 90°
material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \ material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \
np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes) np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes)
@ -997,7 +998,7 @@ class Grid:
def canvas(self, def canvas(self,
cells: IntSequence = None, cells: IntSequence = None,
offset: IntSequence = None, offset: IntSequence = None,
fill: int = None) -> "Grid": fill: int = None) -> 'Grid':
""" """
Crop or enlarge/pad grid. Crop or enlarge/pad grid.
@ -1031,10 +1032,8 @@ class Grid:
""" """
offset_ = np.array(offset,int) if offset is not None else np.zeros(3,int) offset_ = np.array(offset,int) if offset is not None else np.zeros(3,int)
cells_ = np.array(cells,int) if cells is not None else self.cells cells_ = np.array(cells,int) if cells is not None else self.cells
if fill is None: fill = np.nanmax(self.material) + 1
dtype = float if int(fill) != fill or self.material.dtype in np.sctypes['float'] else int
canvas = np.full(cells_,fill,dtype) canvas = np.full(cells_,np.nanmax(self.material) + 1 if fill is None else fill,self.material.dtype)
LL = np.clip( offset_, 0,np.minimum(self.cells, cells_+offset_)) LL = np.clip( offset_, 0,np.minimum(self.cells, cells_+offset_))
UR = np.clip( offset_+cells_, 0,np.minimum(self.cells, cells_+offset_)) UR = np.clip( offset_+cells_, 0,np.minimum(self.cells, cells_+offset_))
@ -1050,7 +1049,7 @@ class Grid:
) )
def substitute(self, from_material: IntSequence, to_material: IntSequence) -> "Grid": def substitute(self, from_material: IntSequence, to_material: IntSequence) -> 'Grid':
""" """
Substitute material indices. Substitute material indices.
@ -1067,20 +1066,18 @@ class Grid:
Updated grid-based geometry. Updated grid-based geometry.
""" """
def mp(entry, mapper): material = self.material.copy()
return mapper[entry] if entry in mapper else entry for f,t in zip(from_material,to_material): # ToDo Python 3.10 has strict mode for zip
material[self.material==f] = t
mp = np.vectorize(mp) return Grid(material = material,
mapper = dict(zip(from_material,to_material))
return Grid(material = mp(self.material,mapper).reshape(self.cells),
size = self.size, size = self.size,
origin = self.origin, origin = self.origin,
comments = self.comments+[util.execution_stamp('Grid','substitute')], comments = self.comments+[util.execution_stamp('Grid','substitute')],
) )
def sort(self) -> "Grid": def sort(self) -> 'Grid':
""" """
Sort material indices such that min(material) is located at (0,0,0). Sort material indices such that min(material) is located at (0,0,0).
@ -1106,7 +1103,7 @@ class Grid:
vicinity: int = 1, vicinity: int = 1,
offset: int = None, offset: int = None,
trigger: IntSequence = [], trigger: IntSequence = [],
periodic: bool = True) -> "Grid": periodic: bool = True) -> 'Grid':
""" """
Offset material index of points in the vicinity of xxx. Offset material index of points in the vicinity of xxx.

View File

@ -981,7 +981,7 @@ class Result:
t = 'tensor' t = 'tensor'
if o is None: o = 'fro' if o is None: o = 'fro'
else: else:
raise ValueError(f'invalid norm order {ord}') raise ValueError(f'invalid shape of {x["label"]}')
return { return {
'data': np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True), 'data': np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True),

View File

@ -812,8 +812,7 @@ class Rotation:
return Rotation.from_basis(R) return Rotation.from_basis(R)
@staticmethod @staticmethod
def from_parallel(a,b, def from_parallel(a,b):
**kwargs):
""" """
Initialize from pairs of two orthogonal lattice basis vectors. Initialize from pairs of two orthogonal lattice basis vectors.
@ -963,8 +962,7 @@ class Rotation:
N = 500, N = 500,
degrees = True, degrees = True,
fractions = True, fractions = True,
rng_seed = None, rng_seed = None):
**kwargs):
""" """
Sample discrete values from a binned orientation distribution function (ODF). Sample discrete values from a binned orientation distribution function (ODF).

View File

@ -2,6 +2,7 @@ import os
import warnings import warnings
import multiprocessing as mp import multiprocessing as mp
from pathlib import Path from pathlib import Path
from typing import Union, Literal, List
import numpy as np import numpy as np
import vtk import vtk
@ -9,6 +10,7 @@ from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk
from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
from ._typehints import FloatSequence, IntSequence
from . import util from . import util
from . import Table from . import Table
@ -20,7 +22,7 @@ class VTK:
High-level interface to VTK. High-level interface to VTK.
""" """
def __init__(self,vtk_data): def __init__(self, vtk_data: vtk.vtkDataSet):
""" """
New spatial visualization. New spatial visualization.
@ -36,7 +38,7 @@ class VTK:
@staticmethod @staticmethod
def from_image_data(cells,size,origin=np.zeros(3)): def from_image_data(cells: IntSequence, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK':
""" """
Create VTK of type vtk.vtkImageData. Create VTK of type vtk.vtkImageData.
@ -60,13 +62,13 @@ class VTK:
vtk_data = vtk.vtkImageData() vtk_data = vtk.vtkImageData()
vtk_data.SetDimensions(*(np.array(cells)+1)) vtk_data.SetDimensions(*(np.array(cells)+1))
vtk_data.SetOrigin(*(np.array(origin))) vtk_data.SetOrigin(*(np.array(origin)))
vtk_data.SetSpacing(*(size/cells)) vtk_data.SetSpacing(*(np.array(size)/np.array(cells)))
return VTK(vtk_data) return VTK(vtk_data)
@staticmethod @staticmethod
def from_rectilinear_grid(grid,size,origin=np.zeros(3)): def from_rectilinear_grid(grid: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK':
""" """
Create VTK of type vtk.vtkRectilinearGrid. Create VTK of type vtk.vtkRectilinearGrid.
@ -98,7 +100,7 @@ class VTK:
@staticmethod @staticmethod
def from_unstructured_grid(nodes,connectivity,cell_type): def from_unstructured_grid(nodes: np.ndarray, connectivity: np.ndarray, cell_type: str) -> 'VTK':
""" """
Create VTK of type vtk.vtkUnstructuredGrid. Create VTK of type vtk.vtkUnstructuredGrid.
@ -138,7 +140,7 @@ class VTK:
@staticmethod @staticmethod
def from_poly_data(points): def from_poly_data(points: np.ndarray) -> 'VTK':
""" """
Create VTK of type vtk.polyData. Create VTK of type vtk.polyData.
@ -172,15 +174,17 @@ class VTK:
@staticmethod @staticmethod
def load(fname,dataset_type=None): def load(fname: Union[str, Path],
dataset_type: Literal['ImageData', 'UnstructuredGrid', 'PolyData'] = None) -> 'VTK':
""" """
Load from VTK file. Load from VTK file.
Parameters Parameters
---------- ----------
fname : str or pathlib.Path fname : str or pathlib.Path
Filename for reading. Valid extensions are .vti, .vtr, .vtu, .vtp, and .vtk. Filename for reading.
dataset_type : {'vtkImageData', ''vtkRectilinearGrid', 'vtkUnstructuredGrid', 'vtkPolyData'}, optional Valid extensions are .vti, .vtr, .vtu, .vtp, and .vtk.
dataset_type : {'ImageData', 'UnstructuredGrid', 'PolyData'}, optional
Name of the vtk.vtkDataSet subclass when opening a .vtk file. Name of the vtk.vtkDataSet subclass when opening a .vtk file.
Returns Returns
@ -234,7 +238,7 @@ class VTK:
def _write(writer): def _write(writer):
"""Wrapper for parallel writing.""" """Wrapper for parallel writing."""
writer.Write() writer.Write()
def save(self,fname,parallel=True,compress=True): def save(self, fname: Union[str, Path], parallel: bool = True, compress: bool = True):
""" """
Save as VTK file. Save as VTK file.
@ -280,7 +284,7 @@ class VTK:
# Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data # Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data
# Needs support for damask.Table # Needs support for damask.Table
def add(self,data,label=None): def add(self, data: Union[np.ndarray, np.ma.MaskedArray], label: str = None):
""" """
Add data to either cells or points. Add data to either cells or points.
@ -327,7 +331,7 @@ class VTK:
raise TypeError raise TypeError
def get(self,label): def get(self, label: str) -> np.ndarray:
""" """
Get either cell or point data. Get either cell or point data.
@ -369,7 +373,7 @@ class VTK:
raise ValueError(f'Array "{label}" not found.') raise ValueError(f'Array "{label}" not found.')
def get_comments(self): def get_comments(self) -> List[str]:
"""Return the comments.""" """Return the comments."""
fielddata = self.vtk_data.GetFieldData() fielddata = self.vtk_data.GetFieldData()
for a in range(fielddata.GetNumberOfArrays()): for a in range(fielddata.GetNumberOfArrays()):
@ -379,7 +383,7 @@ class VTK:
return [] return []
def set_comments(self,comments): def set_comments(self, comments: Union[str, List[str]]):
""" """
Set comments. Set comments.
@ -396,7 +400,7 @@ class VTK:
self.vtk_data.GetFieldData().AddArray(s) self.vtk_data.GetFieldData().AddArray(s)
def add_comments(self,comments): def add_comments(self, comments: Union[str, List[str]]):
""" """
Add comments. Add comments.
@ -409,7 +413,7 @@ class VTK:
self.set_comments(self.get_comments() + ([comments] if isinstance(comments,str) else comments)) self.set_comments(self.get_comments() + ([comments] if isinstance(comments,str) else comments))
def __repr__(self): def __repr__(self) -> str:
"""ASCII representation of the VTK data.""" """ASCII representation of the VTK data."""
writer = vtk.vtkDataSetWriter() writer = vtk.vtkDataSetWriter()
writer.SetHeader(f'# {util.execution_stamp("VTK")}') writer.SetHeader(f'# {util.execution_stamp("VTK")}')
@ -419,7 +423,7 @@ class VTK:
return writer.GetOutputString() return writer.GetOutputString()
def show(self) -> None: def show(self):
""" """
Render. Render.
@ -442,22 +446,24 @@ class VTK:
mapper = vtk.vtkDataSetMapper() mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(self.vtk_data) mapper.SetInputData(self.vtk_data)
actor = vtk.vtkActor() actor = vtk.vtkActor()
actor.SetMapper(mapper) actor.SetMapper(mapper)
actor.GetProperty().SetColor(230/255,150/255,68/255)
ren = vtk.vtkRenderer() ren = vtk.vtkRenderer()
ren.AddActor(actor)
ren.SetBackground(67/255,128/255,208/255)
window = vtk.vtkRenderWindow() window = vtk.vtkRenderWindow()
window.AddRenderer(ren) window.AddRenderer(ren)
ren.AddActor(actor)
ren.SetBackground(0.2,0.2,0.2)
window.SetSize(width,height) window.SetSize(width,height)
window.SetWindowName(util.execution_stamp('VTK','show'))
iren = vtk.vtkRenderWindowInteractor() iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(window) iren.SetRenderWindow(window)
if os.name == 'posix' and 'DISPLAY' not in os.environ:
iren.Initialize() print('Found no rendering device')
else:
window.Render() window.Render()
iren.Start() iren.Start()

View File

@ -79,7 +79,7 @@ def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, dis
s = 1 s = 1
i = 0 i = 0
progress = _util._ProgressBar(N_seeds+1,'',50) progress = _util.ProgressBar(N_seeds+1,'',50)
while s < N_seeds: while s < N_seeds:
i += 1 i += 1
candidates = rng.random((N_candidates,3))*_np.broadcast_to(size,(N_candidates,3)) candidates = rng.random((N_candidates,3))*_np.broadcast_to(size,(N_candidates,3))

View File

@ -7,12 +7,16 @@ import subprocess
import shlex import shlex
import re import re
import fractions import fractions
import collections.abc as abc
from functools import reduce from functools import reduce
from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, Optional
from pathlib import Path
import numpy as np import numpy as np
import h5py import h5py
from . import version from . import version
from ._typehints import FloatSequence
# limit visibility # limit visibility
__all__=[ __all__=[
@ -50,16 +54,16 @@ _colors = {
#################################################################################################### ####################################################################################################
# Functions # Functions
#################################################################################################### ####################################################################################################
def srepr(arg,glue = '\n'): def srepr(msg, glue: str = '\n') -> str:
r""" r"""
Join items with glue string. Join items with glue string.
Parameters Parameters
---------- ----------
arg : iterable msg : object with __repr__ or sequence of objects with __repr__
Items to join. Items to join.
glue : str, optional glue : str, optional
Glue used for joining operation. Defaults to \n. Glue used for joining operation. Defaults to '\n'.
Returns Returns
------- -------
@ -67,21 +71,21 @@ def srepr(arg,glue = '\n'):
String representation of the joined items. String representation of the joined items.
""" """
if (not hasattr(arg, 'strip') and if (not hasattr(msg, 'strip') and
(hasattr(arg, '__getitem__') or (hasattr(msg, '__getitem__') or
hasattr(arg, '__iter__'))): hasattr(msg, '__iter__'))):
return glue.join(str(x) for x in arg) return glue.join(str(x) for x in msg)
else: else:
return arg if isinstance(arg,str) else repr(arg) return msg if isinstance(msg,str) else repr(msg)
def emph(what): def emph(msg) -> str:
""" """
Format with emphasis. Format with emphasis.
Parameters Parameters
---------- ----------
what : object with __repr__ or iterable of objects with __repr__. msg : object with __repr__ or sequence of objects with __repr__
Message to format. Message to format.
Returns Returns
@ -90,15 +94,15 @@ def emph(what):
Formatted string representation of the joined items. Formatted string representation of the joined items.
""" """
return _colors['bold']+srepr(what)+_colors['end_color'] return _colors['bold']+srepr(msg)+_colors['end_color']
def deemph(what): def deemph(msg) -> str:
""" """
Format with deemphasis. Format with deemphasis.
Parameters Parameters
---------- ----------
what : object with __repr__ or iterable of objects with __repr__. msg : object with __repr__ or sequence of objects with __repr__
Message to format. Message to format.
Returns Returns
@ -107,15 +111,15 @@ def deemph(what):
Formatted string representation of the joined items. Formatted string representation of the joined items.
""" """
return _colors['dim']+srepr(what)+_colors['end_color'] return _colors['dim']+srepr(msg)+_colors['end_color']
def warn(what): def warn(msg) -> str:
""" """
Format for warning. Format for warning.
Parameters Parameters
---------- ----------
what : object with __repr__ or iterable of objects with __repr__. msg : object with __repr__ or sequence of objects with __repr__
Message to format. Message to format.
Returns Returns
@ -124,15 +128,15 @@ def warn(what):
Formatted string representation of the joined items. Formatted string representation of the joined items.
""" """
return _colors['warning']+emph(what)+_colors['end_color'] return _colors['warning']+emph(msg)+_colors['end_color']
def strikeout(what): def strikeout(msg) -> str:
""" """
Format as strikeout. Format as strikeout.
Parameters Parameters
---------- ----------
what : object with __repr__ or iterable of objects with __repr__. msg : object with __repr__ or iterable of objects with __repr__
Message to format. Message to format.
Returns Returns
@ -141,10 +145,10 @@ def strikeout(what):
Formatted string representation of the joined items. Formatted string representation of the joined items.
""" """
return _colors['crossout']+srepr(what)+_colors['end_color'] return _colors['crossout']+srepr(msg)+_colors['end_color']
def run(cmd,wd='./',env=None,timeout=None): def run(cmd: str, wd: str = './', env: Dict[str, str] = None, timeout: int = None) -> Tuple[str, str]:
""" """
Run a command. Run a command.
@ -153,7 +157,7 @@ def run(cmd,wd='./',env=None,timeout=None):
cmd : str cmd : str
Command to be executed. Command to be executed.
wd : str, optional wd : str, optional
Working directory of process. Defaults to ./ . Working directory of process. Defaults to './'.
env : dict, optional env : dict, optional
Environment for execution. Environment for execution.
timeout : integer, optional timeout : integer, optional
@ -185,7 +189,7 @@ def run(cmd,wd='./',env=None,timeout=None):
execute = run execute = run
def natural_sort(key): def natural_sort(key: str) -> List[Union[int, str]]:
""" """
Natural sort. Natural sort.
@ -200,7 +204,10 @@ def natural_sort(key):
return [ convert(c) for c in re.split('([0-9]+)', key) ] return [ convert(c) for c in re.split('([0-9]+)', key) ]
def show_progress(iterable,N_iter=None,prefix='',bar_length=50): def show_progress(iterable: Iterable,
N_iter: int = None,
prefix: str = '',
bar_length: int = 50) -> Any:
""" """
Decorate a loop with a progress bar. Decorate a loop with a progress bar.
@ -208,39 +215,49 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50):
Parameters Parameters
---------- ----------
iterable : iterable or function with yield statement iterable : iterable
Iterable (or function with yield statement) to be decorated. Iterable to be decorated.
N_iter : int, optional N_iter : int, optional
Total number of iterations. Required unless obtainable as len(iterable). Total number of iterations. Required if iterable is not a sequence.
prefix : str, optional prefix : str, optional
Prefix string. Prefix string.
bar_length : int, optional bar_length : int, optional
Length of progress bar in characters. Defaults to 50. Length of progress bar in characters. Defaults to 50.
""" """
if N_iter in [0,1] or (hasattr(iterable,'__len__') and len(iterable) <= 1): if isinstance(iterable,abc.Sequence):
if N_iter is None:
N = len(iterable)
else:
raise ValueError('N_iter given for sequence')
else:
if N_iter is None:
raise ValueError('N_iter not given')
else:
N = N_iter
if N <= 1:
for item in iterable: for item in iterable:
yield item yield item
else: else:
status = _ProgressBar(N_iter if N_iter is not None else len(iterable),prefix,bar_length) status = ProgressBar(N,prefix,bar_length)
for i,item in enumerate(iterable): for i,item in enumerate(iterable):
yield item yield item
status.update(i) status.update(i)
def scale_to_coprime(v): def scale_to_coprime(v: FloatSequence) -> np.ndarray:
""" """
Scale vector to co-prime (relatively prime) integers. Scale vector to co-prime (relatively prime) integers.
Parameters Parameters
---------- ----------
v : numpy.ndarray of shape (:) v : sequence of float, len (:)
Vector to scale. Vector to scale.
Returns Returns
------- -------
m : numpy.ndarray of shape (:) m : numpy.ndarray, shape (:)
Vector scaled to co-prime numbers. Vector scaled to co-prime numbers.
""" """
@ -257,17 +274,21 @@ def scale_to_coprime(v):
except AttributeError: except AttributeError:
return a * b // np.gcd(a, b) return a * b // np.gcd(a, b)
m = (np.array(v) * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v)) ** 0.5).astype(int) v_ = np.array(v)
m = (v_ * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v_))**0.5).astype(int)
m = m//reduce(np.gcd,m) m = m//reduce(np.gcd,m)
with np.errstate(invalid='ignore'): with np.errstate(invalid='ignore'):
if not np.allclose(np.ma.masked_invalid(v/m),v[np.argmax(abs(v))]/m[np.argmax(abs(v))]): if not np.allclose(np.ma.masked_invalid(v_/m),v_[np.argmax(abs(v_))]/m[np.argmax(abs(v_))]):
raise ValueError(f'Invalid result {m} for input {v}. Insufficient precision?') raise ValueError(f'Invalid result {m} for input {v_}. Insufficient precision?')
return m return m
def project_equal_angle(vector,direction='z',normalize=True,keepdims=False): def project_equal_angle(vector: np.ndarray,
direction: Literal['x', 'y', 'z'] = 'z',
normalize: bool = True,
keepdims: bool = False) -> np.ndarray:
""" """
Apply equal-angle projection to vector. Apply equal-angle projection to vector.
@ -275,9 +296,8 @@ def project_equal_angle(vector,direction='z',normalize=True,keepdims=False):
---------- ----------
vector : numpy.ndarray, shape (...,3) vector : numpy.ndarray, shape (...,3)
Vector coordinates to be projected. Vector coordinates to be projected.
direction : str direction : {'x', 'y', 'z'}
Projection direction 'x', 'y', or 'z'. Projection direction. Defaults to 'z'.
Defaults to 'z'.
normalize : bool normalize : bool
Ensure unit length of input vector. Defaults to True. Ensure unit length of input vector. Defaults to True.
keepdims : bool keepdims : bool
@ -309,7 +329,10 @@ def project_equal_angle(vector,direction='z',normalize=True,keepdims=False):
return np.roll(np.block([v[...,:2]/(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]), return np.roll(np.block([v[...,:2]/(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2] -shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
def project_equal_area(vector,direction='z',normalize=True,keepdims=False): def project_equal_area(vector: np.ndarray,
direction: Literal['x', 'y', 'z'] = 'z',
normalize: bool = True,
keepdims: bool = False) -> np.ndarray:
""" """
Apply equal-area projection to vector. Apply equal-area projection to vector.
@ -317,9 +340,8 @@ def project_equal_area(vector,direction='z',normalize=True,keepdims=False):
---------- ----------
vector : numpy.ndarray, shape (...,3) vector : numpy.ndarray, shape (...,3)
Vector coordinates to be projected. Vector coordinates to be projected.
direction : str direction : {'x', 'y', 'z'}
Projection direction 'x', 'y', or 'z'. Projection direction. Defaults to 'z'.
Defaults to 'z'.
normalize : bool normalize : bool
Ensure unit length of input vector. Defaults to True. Ensure unit length of input vector. Defaults to True.
keepdims : bool keepdims : bool
@ -351,15 +373,14 @@ def project_equal_area(vector,direction='z',normalize=True,keepdims=False):
return np.roll(np.block([v[...,:2]/np.sqrt(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]), return np.roll(np.block([v[...,:2]/np.sqrt(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]),
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2] -shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
def execution_stamp(class_name: str, function_name: str = None) -> str:
def execution_stamp(class_name,function_name=None):
"""Timestamp the execution of a (function within a) class.""" """Timestamp the execution of a (function within a) class."""
now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z') now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z')
_function_name = '' if function_name is None else f'.{function_name}' _function_name = '' if function_name is None else f'.{function_name}'
return f'damask.{class_name}{_function_name} v{version} ({now})' return f'damask.{class_name}{_function_name} v{version} ({now})'
def hybrid_IA(dist,N,rng_seed=None): def hybrid_IA(dist: np.ndarray, N: int, rng_seed = None) -> np.ndarray:
""" """
Hybrid integer approximation. Hybrid integer approximation.
@ -387,7 +408,10 @@ def hybrid_IA(dist,N,rng_seed=None):
return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]] return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]]
def shapeshifter(fro,to,mode='left',keep_ones=False): def shapeshifter(fro: Tuple[int, ...],
to: Tuple[int, ...],
mode: Literal['left','right'] = 'left',
keep_ones: bool = False) -> Tuple[Optional[int], ...]:
""" """
Return dimensions that reshape 'fro' to become broadcastable to 'to'. Return dimensions that reshape 'fro' to become broadcastable to 'to'.
@ -398,9 +422,9 @@ def shapeshifter(fro,to,mode='left',keep_ones=False):
to : tuple to : tuple
Target shape of array after broadcasting. Target shape of array after broadcasting.
len(to) cannot be less than len(fro). len(to) cannot be less than len(fro).
mode : str, optional mode : {'left', 'right'}, optional
Indicates whether new axes are preferably added to Indicates whether new axes are preferably added to
either 'left' or 'right' of the original shape. either left or right of the original shape.
Defaults to 'left'. Defaults to 'left'.
keep_ones : bool, optional keep_ones : bool, optional
Treat '1' in fro as literal value instead of dimensional placeholder. Treat '1' in fro as literal value instead of dimensional placeholder.
@ -434,21 +458,22 @@ def shapeshifter(fro,to,mode='left',keep_ones=False):
fro = (1,) if not len(fro) else fro fro = (1,) if not len(fro) else fro
to = (1,) if not len(to) else to to = (1,) if not len(to) else to
try: try:
grp = re.match(beg[mode] match = re.match(beg[mode]
+f',{sep[mode]}'.join(map(lambda x: f'{x}' +f',{sep[mode]}'.join(map(lambda x: f'{x}'
if x>1 or (keep_ones and len(fro)>1) else if x>1 or (keep_ones and len(fro)>1) else
'\\d+',fro)) '\\d+',fro))
+f',{end[mode]}', +f',{end[mode]}',','.join(map(str,to))+',')
','.join(map(str,to))+',').groups() assert match
except AttributeError: grp = match.groups()
except AssertionError:
raise ValueError(f'Shapes can not be shifted {fro} --> {to}') raise ValueError(f'Shapes can not be shifted {fro} --> {to}')
fill = () fill: Tuple[Optional[int], ...] = ()
for g,d in zip(grp,fro+(None,)): for g,d in zip(grp,fro+(None,)):
fill += (1,)*g.count(',')+(d,) fill += (1,)*g.count(',')+(d,)
return fill[:-1] return fill[:-1]
def shapeblender(a,b): def shapeblender(a: Tuple[int, ...], b: Tuple[int, ...]) -> Tuple[int, ...]:
""" """
Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'. Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'.
@ -476,7 +501,7 @@ def shapeblender(a,b):
return a + b[i:] return a + b[i:]
def extend_docstring(extra_docstring): def extend_docstring(extra_docstring: str) -> Callable:
""" """
Decorator: Append to function's docstring. Decorator: Append to function's docstring.
@ -492,7 +517,7 @@ def extend_docstring(extra_docstring):
return _decorator return _decorator
def extended_docstring(f,extra_docstring): def extended_docstring(f: Callable, extra_docstring: str) -> Callable:
""" """
Decorator: Combine another function's docstring with a given docstring. Decorator: Combine another function's docstring with a given docstring.
@ -510,7 +535,7 @@ def extended_docstring(f,extra_docstring):
return _decorator return _decorator
def DREAM3D_base_group(fname): def DREAM3D_base_group(fname: Union[str, Path]) -> str:
""" """
Determine the base group of a DREAM.3D file. Determine the base group of a DREAM.3D file.
@ -536,7 +561,7 @@ def DREAM3D_base_group(fname):
return base_group return base_group
def DREAM3D_cell_data_group(fname): def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str:
""" """
Determine the cell data group of a DREAM.3D file. Determine the cell data group of a DREAM.3D file.
@ -568,18 +593,18 @@ def DREAM3D_cell_data_group(fname):
return cell_data_group return cell_data_group
def Bravais_to_Miller(*,uvtw=None,hkil=None): def Bravais_to_Miller(*, uvtw: np.ndarray = None, hkil: np.ndarray = None) -> np.ndarray:
""" """
Transform 4 MillerBravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). Transform 4 MillerBravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl).
Parameters Parameters
---------- ----------
uvtw|hkil : numpy.ndarray of shape (...,4) uvtw|hkil : numpy.ndarray, shape (...,4)
MillerBravais indices of crystallographic direction [uvtw] or plane normal (hkil). MillerBravais indices of crystallographic direction [uvtw] or plane normal (hkil).
Returns Returns
------- -------
uvw|hkl : numpy.ndarray of shape (...,3) uvw|hkl : numpy.ndarray, shape (...,3)
Miller indices of [uvw] direction or (hkl) plane normal. Miller indices of [uvw] direction or (hkl) plane normal.
""" """
@ -595,18 +620,18 @@ def Bravais_to_Miller(*,uvtw=None,hkil=None):
return np.einsum('il,...l',basis,axis) return np.einsum('il,...l',basis,axis)
def Miller_to_Bravais(*,uvw=None,hkl=None): def Miller_to_Bravais(*, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray:
""" """
Transform 3 Miller indices to 4 MillerBravais indices of crystal direction [uvtw] or plane normal (hkil). Transform 3 Miller indices to 4 MillerBravais indices of crystal direction [uvtw] or plane normal (hkil).
Parameters Parameters
---------- ----------
uvw|hkl : numpy.ndarray of shape (...,3) uvw|hkl : numpy.ndarray, shape (...,3)
Miller indices of crystallographic direction [uvw] or plane normal (hkl). Miller indices of crystallographic direction [uvw] or plane normal (hkl).
Returns Returns
------- -------
uvtw|hkil : numpy.ndarray of shape (...,4) uvtw|hkil : numpy.ndarray, shape (...,4)
MillerBravais indices of [uvtw] direction or (hkil) plane normal. MillerBravais indices of [uvtw] direction or (hkil) plane normal.
""" """
@ -624,7 +649,7 @@ def Miller_to_Bravais(*,uvw=None,hkl=None):
return np.einsum('il,...l',basis,axis) return np.einsum('il,...l',basis,axis)
def dict_prune(d): def dict_prune(d: Dict) -> Dict:
""" """
Recursively remove empty dictionaries. Recursively remove empty dictionaries.
@ -650,7 +675,7 @@ def dict_prune(d):
return new return new
def dict_flatten(d): def dict_flatten(d: Dict) -> Dict:
""" """
Recursively remove keys of single-entry dictionaries. Recursively remove keys of single-entry dictionaries.
@ -678,14 +703,14 @@ def dict_flatten(d):
#################################################################################################### ####################################################################################################
# Classes # Classes
#################################################################################################### ####################################################################################################
class _ProgressBar: class ProgressBar:
""" """
Report progress of an interation as a status bar. Report progress of an interation as a status bar.
Works for 0-based loops, ETA is estimated by linear extrapolation. Works for 0-based loops, ETA is estimated by linear extrapolation.
""" """
def __init__(self,total,prefix,bar_length): def __init__(self, total: int, prefix: str, bar_length: int):
""" """
Set current time as basis for ETA estimation. Set current time as basis for ETA estimation.
@ -708,7 +733,7 @@ class _ProgressBar:
sys.stderr.write(f"{self.prefix} {''*self.bar_length} 0% ETA n/a") sys.stderr.write(f"{self.prefix} {''*self.bar_length} 0% ETA n/a")
sys.stderr.flush() sys.stderr.flush()
def update(self,iteration): def update(self, iteration: int) -> None:
fraction = (iteration+1) / self.total fraction = (iteration+1) / self.total
filled_length = int(self.bar_length * fraction) filled_length = int(self.bar_length * fraction)

View File

@ -81,6 +81,7 @@ class TestColormap:
assert Colormap.from_predefined('strain') == Colormap.from_predefined('strain') assert Colormap.from_predefined('strain') == Colormap.from_predefined('strain')
assert Colormap.from_predefined('strain') != Colormap.from_predefined('stress') assert Colormap.from_predefined('strain') != Colormap.from_predefined('stress')
assert Colormap.from_predefined('strain',N=128) != Colormap.from_predefined('strain',N=64) assert Colormap.from_predefined('strain',N=128) != Colormap.from_predefined('strain',N=64)
assert not Colormap.from_predefined('strain',N=128) == 1
@pytest.mark.parametrize('low,high',[((0,0,0),(1,1,1)), @pytest.mark.parametrize('low,high',[((0,0,0),(1,1,1)),
([0,0,0],[1,1,1])]) ([0,0,0],[1,1,1])])

View File

@ -40,6 +40,9 @@ class TestCrystal:
alpha=alpha,beta=beta,gamma=gamma) alpha=alpha,beta=beta,gamma=gamma)
assert np.allclose(np.eye(3),np.einsum('ik,jk',c.basis_real,c.basis_reciprocal)) assert np.allclose(np.eye(3),np.einsum('ik,jk',c.basis_real,c.basis_reciprocal))
def test_basis_invalid(self):
with pytest.raises(KeyError):
Crystal(family='cubic').basis_real
@pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),]) @pytest.mark.parametrize('keyFrame,keyLattice',[('uvw','direction'),('hkl','plane'),])
@pytest.mark.parametrize('vector',np.array([ @pytest.mark.parametrize('vector',np.array([

View File

@ -44,6 +44,7 @@ class TestGrid:
def test_equal(self,default): def test_equal(self,default):
assert default == default assert default == default
assert not default == 42
def test_repr(self,default): def test_repr(self,default):
print(default) print(default)

View File

@ -364,6 +364,11 @@ class TestOrientation:
table.save(reference) table.save(reference)
assert np.allclose(P,Table.load(reference).get('Schmid')) assert np.allclose(P,Table.load(reference).get('Schmid'))
def test_Schmid_invalid(self):
with pytest.raises(KeyError):
Orientation(lattice='fcc').Schmid()
### vectorization tests ### ### vectorization tests ###
@pytest.mark.parametrize('lattice',['hP','cI','cF']) # tI not included yet @pytest.mark.parametrize('lattice',['hP','cI','cF']) # tI not included yet
@ -505,3 +510,7 @@ class TestOrientation:
for loc in np.random.randint(0,blend,(10,len(blend))): for loc in np.random.randint(0,blend,(10,len(blend))):
assert np.allclose(o[tuple(loc[:len(o.shape)])].to_pole(uvw=v[tuple(loc[-len(v.shape[:-1]):])]), assert np.allclose(o[tuple(loc[:len(o.shape)])].to_pole(uvw=v[tuple(loc[-len(v.shape[:-1]):])]),
o.to_pole(uvw=v)[tuple(loc)]) o.to_pole(uvw=v)[tuple(loc)])
def test_mul_invalid(self):
with pytest.raises(TypeError):
Orientation.from_random(lattice='cF')*np.ones(3)

View File

@ -102,6 +102,9 @@ class TestResult:
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
default.view('invalid',True) default.view('invalid',True)
def test_add_invalid(self,default):
default.add_absolute('xxxx')
def test_add_absolute(self,default): def test_add_absolute(self,default):
default.add_absolute('F_e') default.add_absolute('F_e')
in_memory = np.abs(default.place('F_e')) in_memory = np.abs(default.place('F_e'))

View File

@ -792,6 +792,11 @@ class TestRotation:
R = Rotation.from_random(shape,rng_seed=1) R = Rotation.from_random(shape,rng_seed=1)
assert R == R if shape is None else (R == R).all() assert R == R if shape is None else (R == R).all()
@pytest.mark.parametrize('shape',[None,5,(4,6)])
def test_allclose(self,shape):
R = Rotation.from_random(shape,rng_seed=1)
assert R.allclose(R)
@pytest.mark.parametrize('shape',[None,5,(4,6)]) @pytest.mark.parametrize('shape',[None,5,(4,6)])
def test_unequal(self,shape): def test_unequal(self,shape):
R = Rotation.from_random(shape,rng_seed=1) R = Rotation.from_random(shape,rng_seed=1)
@ -1124,3 +1129,7 @@ class TestRotation:
weights_r = np.histogramdd(Eulers_r,steps,rng)[0].flatten(order='F')/N * np.sum(weights) weights_r = np.histogramdd(Eulers_r,steps,rng)[0].flatten(order='F')/N * np.sum(weights)
assert np.sqrt(((weights_r - weights) ** 2).mean()) < 5 assert np.sqrt(((weights_r - weights) ** 2).mean()) < 5
def test_mul_invalid(self):
with pytest.raises(TypeError):
Rotation.from_random()*np.ones(3)

View File

@ -28,6 +28,10 @@ class TestVTK:
def _patch_execution_stamp(self, patch_execution_stamp): def _patch_execution_stamp(self, patch_execution_stamp):
print('patched damask.util.execution_stamp') print('patched damask.util.execution_stamp')
def test_show(sef,default,monkeypatch):
monkeypatch.delenv('DISPLAY',raising=False)
default.show()
def test_rectilinearGrid(self,tmp_path): def test_rectilinearGrid(self,tmp_path):
cells = np.random.randint(5,10,3)*2 cells = np.random.randint(5,10,3)*2
size = np.random.random(3) + 1.0 size = np.random.random(3) + 1.0

View File

@ -62,6 +62,8 @@ module YAML_types
tNode_get_byKey_as1dString => tNode_get_byKey_as1dString tNode_get_byKey_as1dString => tNode_get_byKey_as1dString
procedure :: & procedure :: &
getKey => tNode_get_byIndex_asKey getKey => tNode_get_byIndex_asKey
procedure :: &
Keys => tNode_getKeys
procedure :: & procedure :: &
getIndex => tNode_get_byKey_asIndex getIndex => tNode_get_byKey_asIndex
procedure :: & procedure :: &
@ -117,7 +119,7 @@ module YAML_types
type, extends(tNode), public :: tList type, extends(tNode), public :: tList
class(tItem), pointer :: first => null() class(tItem), pointer :: first => NULL()
contains contains
procedure :: asFormattedString => tList_asFormattedString procedure :: asFormattedString => tList_asFormattedString
@ -144,8 +146,8 @@ module YAML_types
type :: tItem type :: tItem
character(len=:), allocatable :: key character(len=:), allocatable :: key
class(tNode), pointer :: node => null() class(tNode), pointer :: node => NULL()
class(tItem), pointer :: next => null() class(tItem), pointer :: next => NULL()
contains contains
final :: tItem_finalize final :: tItem_finalize
@ -332,9 +334,12 @@ function tNode_asScalar(self) result(scalar)
class(tNode), intent(in), target :: self class(tNode), intent(in), target :: self
class(tScalar), pointer :: scalar class(tScalar), pointer :: scalar
select type(self) select type(self)
class is(tScalar) class is(tScalar)
scalar => self scalar => self
class default
nullify(scalar)
end select end select
end function tNode_asScalar end function tNode_asScalar
@ -348,9 +353,12 @@ function tNode_asList(self) result(list)
class(tNode), intent(in), target :: self class(tNode), intent(in), target :: self
class(tList), pointer :: list class(tList), pointer :: list
select type(self) select type(self)
class is(tList) class is(tList)
list => self list => self
class default
nullify(list)
end select end select
end function tNode_asList end function tNode_asList
@ -364,9 +372,12 @@ function tNode_asDict(self) result(dict)
class(tNode), intent(in), target :: self class(tNode), intent(in), target :: self
class(tDict), pointer :: dict class(tDict), pointer :: dict
select type(self) select type(self)
class is(tDict) class is(tDict)
dict => self dict => self
class default
nullify(dict)
end select end select
end function tNode_asDict end function tNode_asDict
@ -385,6 +396,7 @@ function tNode_get_byIndex(self,i) result(node)
class(tItem), pointer :: item class(tItem), pointer :: item
integer :: j integer :: j
select type(self) select type(self)
class is(tList) class is(tList)
self_ => self%asList() self_ => self%asList()
@ -409,15 +421,14 @@ end function tNode_get_byIndex
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_asFloat(self,i) result(nodeAsFloat) function tNode_get_byIndex_asFloat(self,i) result(nodeAsFloat)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
real(pReal) :: nodeAsFloat real(pReal) :: nodeAsFloat
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsFloat = scalar%asFloat() nodeAsFloat = scalar%asFloat()
@ -433,15 +444,15 @@ end function tNode_get_byIndex_asFloat
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_asInt(self,i) result(nodeAsInt) function tNode_get_byIndex_asInt(self,i) result(nodeAsInt)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
integer :: nodeAsInt integer :: nodeAsInt
class(tNode), pointer :: node class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsInt = scalar%asInt() nodeAsInt = scalar%asInt()
@ -457,15 +468,14 @@ end function tNode_get_byIndex_asInt
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_asBool(self,i) result(nodeAsBool) function tNode_get_byIndex_asBool(self,i) result(nodeAsBool)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
logical :: nodeAsBool logical :: nodeAsBool
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsBool = scalar%asBool() nodeAsBool = scalar%asBool()
@ -481,15 +491,14 @@ end function tNode_get_byIndex_asBool
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_asString(self,i) result(nodeAsString) function tNode_get_byIndex_asString(self,i) result(nodeAsString)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
character(len=:), allocatable :: nodeAsString character(len=:), allocatable :: nodeAsString
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsString = scalar%asString() nodeAsString = scalar%asString()
@ -505,15 +514,14 @@ end function tNode_get_byIndex_asString
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_as1dFloat(self,i) result(nodeAs1dFloat) function tNode_get_byIndex_as1dFloat(self,i) result(nodeAs1dFloat)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
real(pReal), dimension(:), allocatable :: nodeAs1dFloat real(pReal), dimension(:), allocatable :: nodeAs1dFloat
class(tNode), pointer :: node
class(tList), pointer :: list class(tList), pointer :: list
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dFloat = list%as1dFloat() nodeAs1dFloat = list%as1dFloat()
@ -529,15 +537,14 @@ end function tNode_get_byIndex_as1dFloat
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_as1dInt(self,i) result(nodeAs1dInt) function tNode_get_byIndex_as1dInt(self,i) result(nodeAs1dInt)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
integer, dimension(:), allocatable :: nodeAs1dInt integer, dimension(:), allocatable :: nodeAs1dInt
class(tNode), pointer :: node
class(tList), pointer :: list class(tList), pointer :: list
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dInt = list%as1dInt() nodeAs1dInt = list%as1dInt()
@ -553,15 +560,14 @@ end function tNode_get_byIndex_as1dInt
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_as1dBool(self,i) result(nodeAs1dBool) function tNode_get_byIndex_as1dBool(self,i) result(nodeAs1dBool)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
logical, dimension(:), allocatable :: nodeAs1dBool logical, dimension(:), allocatable :: nodeAs1dBool
class(tNode), pointer :: node
class(tList), pointer :: list class(tList), pointer :: list
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dBool = list%as1dBool() nodeAs1dBool = list%as1dBool()
@ -577,15 +583,14 @@ end function tNode_get_byIndex_as1dBool
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byIndex_as1dString(self,i) result(nodeAs1dString) function tNode_get_byIndex_as1dString(self,i) result(nodeAs1dString)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
integer, intent(in) :: i integer, intent(in) :: i
character(len=:), allocatable, dimension(:) :: nodeAs1dString character(len=:), allocatable, dimension(:) :: nodeAs1dString
class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
node => self%get(i)
select type(node) select type(node => self%get(i))
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dString = list%as1dString() nodeAs1dString = list%as1dString()
@ -609,6 +614,7 @@ function tNode_get_byIndex_asKey(self,i) result(key)
type(tDict), pointer :: dict type(tDict), pointer :: dict
type(tItem), pointer :: item type(tItem), pointer :: item
select type(self) select type(self)
class is(tDict) class is(tDict)
dict => self%asDict() dict => self%asDict()
@ -625,6 +631,33 @@ function tNode_get_byIndex_asKey(self,i) result(key)
end function tNode_get_byIndex_asKey end function tNode_get_byIndex_asKey
!--------------------------------------------------------------------------------------------------
!> @brief Get all keys from a dictionary
!--------------------------------------------------------------------------------------------------
function tNode_getKeys(self) result(keys)
class(tNode), intent(in) :: self
character(len=:), dimension(:), allocatable :: keys
character(len=pStringLen), dimension(:), allocatable :: temp
integer :: j, l
allocate(temp(self%length))
l = 0
do j = 1, self%length
temp(j) = self%getKey(j)
l = max(len_trim(temp(j)),l)
end do
allocate(character(l)::keys(self%length))
do j = 1, self%length
keys(j) = trim(temp(j))
end do
end function tNode_getKeys
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
!> @brief Checks if a given key/item is present in the dict/list !> @brief Checks if a given key/item is present in the dict/list
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
@ -713,17 +746,16 @@ end function tNode_get_byKey
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat) function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
real(pReal), intent(in), optional :: defaultVal real(pReal), intent(in), optional :: defaultVal
real(pReal) :: nodeAsFloat real(pReal) :: nodeAsFloat
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsFloat = scalar%asFloat() nodeAsFloat = scalar%asFloat()
@ -744,17 +776,16 @@ end function tNode_get_byKey_asFloat
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_asInt(self,k,defaultVal) result(nodeAsInt) function tNode_get_byKey_asInt(self,k,defaultVal) result(nodeAsInt)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
integer, intent(in), optional :: defaultVal integer, intent(in), optional :: defaultVal
integer :: nodeAsInt integer :: nodeAsInt
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsInt = scalar%asInt() nodeAsInt = scalar%asInt()
@ -775,17 +806,16 @@ end function tNode_get_byKey_asInt
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_asBool(self,k,defaultVal) result(nodeAsBool) function tNode_get_byKey_asBool(self,k,defaultVal) result(nodeAsBool)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
logical, intent(in), optional :: defaultVal logical, intent(in), optional :: defaultVal
logical :: nodeAsBool logical :: nodeAsBool
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsBool = scalar%asBool() nodeAsBool = scalar%asBool()
@ -806,17 +836,16 @@ end function tNode_get_byKey_asBool
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_asString(self,k,defaultVal) result(nodeAsString) function tNode_get_byKey_asString(self,k,defaultVal) result(nodeAsString)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
character(len=*), intent(in), optional :: defaultVal character(len=*), intent(in), optional :: defaultVal
character(len=:), allocatable :: nodeAsString character(len=:), allocatable :: nodeAsString
class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tScalar) class is(tScalar)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsString = scalar%asString() nodeAsString = scalar%asString()
@ -837,19 +866,18 @@ end function tNode_get_byKey_asString
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_as1dFloat(self,k,defaultVal,requiredSize) result(nodeAs1dFloat) function tNode_get_byKey_as1dFloat(self,k,defaultVal,requiredSize) result(nodeAs1dFloat)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
real(pReal), intent(in), dimension(:), optional :: defaultVal real(pReal), intent(in), dimension(:), optional :: defaultVal
integer, intent(in), optional :: requiredSize integer, intent(in), optional :: requiredSize
real(pReal), dimension(:), allocatable :: nodeAs1dFloat real(pReal), dimension(:), allocatable :: nodeAs1dFloat
class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dFloat = list%as1dFloat() nodeAs1dFloat = list%as1dFloat()
@ -874,19 +902,18 @@ end function tNode_get_byKey_as1dFloat
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_as2dFloat(self,k,defaultVal,requiredShape) result(nodeAs2dFloat) function tNode_get_byKey_as2dFloat(self,k,defaultVal,requiredShape) result(nodeAs2dFloat)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
real(pReal), intent(in), dimension(:,:), optional :: defaultVal real(pReal), intent(in), dimension(:,:), optional :: defaultVal
integer, intent(in), dimension(2), optional :: requiredShape integer, intent(in), dimension(2), optional :: requiredShape
real(pReal), dimension(:,:), allocatable :: nodeAs2dFloat real(pReal), dimension(:,:), allocatable :: nodeAs2dFloat
class(tNode), pointer :: node
type(tList), pointer :: rows type(tList), pointer :: rows
if(self%contains(k)) then if(self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tList) class is(tList)
rows => node%asList() rows => node%asList()
nodeAs2dFloat = rows%as2dFloat() nodeAs2dFloat = rows%as2dFloat()
@ -911,18 +938,16 @@ end function tNode_get_byKey_as2dFloat
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_as1dInt(self,k,defaultVal,requiredSize) result(nodeAs1dInt) function tNode_get_byKey_as1dInt(self,k,defaultVal,requiredSize) result(nodeAs1dInt)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
integer, dimension(:), intent(in), optional :: defaultVal integer, dimension(:), intent(in), optional :: defaultVal
integer, intent(in), optional :: requiredSize integer, intent(in), optional :: requiredSize
integer, dimension(:), allocatable :: nodeAs1dInt integer, dimension(:), allocatable :: nodeAs1dInt
class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dInt = list%as1dInt() nodeAs1dInt = list%as1dInt()
@ -947,17 +972,16 @@ end function tNode_get_byKey_as1dInt
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_as1dBool(self,k,defaultVal) result(nodeAs1dBool) function tNode_get_byKey_as1dBool(self,k,defaultVal) result(nodeAs1dBool)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
logical, dimension(:), intent(in), optional :: defaultVal logical, dimension(:), intent(in), optional :: defaultVal
logical, dimension(:), allocatable :: nodeAs1dBool logical, dimension(:), allocatable :: nodeAs1dBool
class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dBool = list%as1dBool() nodeAs1dBool = list%as1dBool()
@ -978,17 +1002,16 @@ end function tNode_get_byKey_as1dBool
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function tNode_get_byKey_as1dString(self,k,defaultVal) result(nodeAs1dString) function tNode_get_byKey_as1dString(self,k,defaultVal) result(nodeAs1dString)
class(tNode), intent(in), target :: self class(tNode), intent(in) :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
character(len=*), intent(in), dimension(:), optional :: defaultVal character(len=*), intent(in), dimension(:), optional :: defaultVal
character(len=:), allocatable, dimension(:) :: nodeAs1dString character(len=:), allocatable, dimension(:) :: nodeAs1dString
class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if (self%contains(k)) then if (self%contains(k)) then
node => self%get(k) select type(node => self%get(k))
select type(node)
class is(tList) class is(tList)
list => node%asList() list => node%asList()
nodeAs1dString = list%as1dString() nodeAs1dString = list%as1dString()
@ -1190,6 +1213,7 @@ function tList_as1dFloat(self)
type(tItem), pointer :: item type(tItem), pointer :: item
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
allocate(tList_as1dFloat(self%length)) allocate(tList_as1dFloat(self%length))
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length
@ -1213,6 +1237,7 @@ function tList_as2dFloat(self)
class(tNode), pointer :: row class(tNode), pointer :: row
type(tList), pointer :: row_data type(tList), pointer :: row_data
row => self%get(1) row => self%get(1)
row_data => row%asList() row_data => row%asList()
allocate(tList_as2dFloat(self%length,row_data%length)) allocate(tList_as2dFloat(self%length,row_data%length))
@ -1239,6 +1264,7 @@ function tList_as1dInt(self)
type(tItem), pointer :: item type(tItem), pointer :: item
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
allocate(tList_as1dInt(self%length)) allocate(tList_as1dInt(self%length))
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length
@ -1262,6 +1288,7 @@ function tList_as1dBool(self)
type(tItem), pointer :: item type(tItem), pointer :: item
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
allocate(tList_as1dBool(self%length)) allocate(tList_as1dBool(self%length))
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length
@ -1285,6 +1312,7 @@ function tList_as1dString(self)
type(tItem), pointer :: item type(tItem), pointer :: item
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
len_max = 0 len_max = 0
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length

View File

@ -156,7 +156,7 @@ subroutine spectral_utilities_init
integer(C_INTPTR_T) :: alloc_local, local_K, local_K_offset integer(C_INTPTR_T) :: alloc_local, local_K, local_K_offset
integer(C_INTPTR_T), parameter :: & integer(C_INTPTR_T), parameter :: &
scalarSize = 1_C_INTPTR_T, & scalarSize = 1_C_INTPTR_T, &
vecSize = 3_C_INTPTR_T, & vectorSize = 3_C_INTPTR_T, &
tensorSize = 9_C_INTPTR_T tensorSize = 9_C_INTPTR_T
character(len=*), parameter :: & character(len=*), parameter :: &
PETSCDEBUG = ' -snes_view -snes_monitor ' PETSCDEBUG = ' -snes_view -snes_monitor '
@ -274,7 +274,7 @@ subroutine spectral_utilities_init
call c_f_pointer(tensorField, tensorField_fourier, [3_C_INTPTR_T,3_C_INTPTR_T, & call c_f_pointer(tensorField, tensorField_fourier, [3_C_INTPTR_T,3_C_INTPTR_T, &
gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T , gridFFTW(2),local_K]) ! place a pointer for a fourier tensor representation gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T , gridFFTW(2),local_K]) ! place a pointer for a fourier tensor representation
vectorField = fftw_alloc_complex(vecSize*alloc_local) vectorField = fftw_alloc_complex(vectorSize*alloc_local)
call c_f_pointer(vectorField, vectorField_real, [3_C_INTPTR_T,& call c_f_pointer(vectorField, vectorField_real, [3_C_INTPTR_T,&
2_C_INTPTR_T*(gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T),gridFFTW(2),local_K]) ! place a pointer for a real vector representation 2_C_INTPTR_T*(gridFFTW(1)/2_C_INTPTR_T + 1_C_INTPTR_T),gridFFTW(2),local_K]) ! place a pointer for a real vector representation
call c_f_pointer(vectorField, vectorField_fourier,[3_C_INTPTR_T,& call c_f_pointer(vectorField, vectorField_fourier,[3_C_INTPTR_T,&
@ -288,42 +288,42 @@ subroutine spectral_utilities_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! tensor MPI fftw plans ! tensor MPI fftw plans
planTensorForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order planTensorForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),tensorSize, &
tensorSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
tensorField_real, tensorField_fourier, & ! input data, output data tensorField_real,tensorField_fourier, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision PETSC_COMM_WORLD,FFTW_planner_flag)
if (.not. c_associated(planTensorForth)) error stop 'FFTW error' if (.not. c_associated(planTensorForth)) error stop 'FFTW error'
planTensorBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order planTensorBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),tensorSize, &
tensorSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
tensorField_fourier,tensorField_real, & ! input data, output data tensorField_fourier,tensorField_real, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! all processors, planer precision PETSC_COMM_WORLD, FFTW_planner_flag)
if (.not. c_associated(planTensorBack)) error stop 'FFTW error' if (.not. c_associated(planTensorBack)) error stop 'FFTW error'
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! vector MPI fftw plans ! vector MPI fftw plans
planVectorForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order planVectorForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),vectorSize, &
vecSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK,&! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
vectorField_real, vectorField_fourier, & ! input data, output data vectorField_real,vectorField_fourier, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision PETSC_COMM_WORLD,FFTW_planner_flag)
if (.not. C_ASSOCIATED(planVectorForth)) error stop 'FFTW error' if (.not. c_associated(planVectorForth)) error stop 'FFTW error'
planVectorBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order planVectorBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),vectorSize, &
vecSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, & ! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
vectorField_fourier,vectorField_real, & ! input data, output data vectorField_fourier,vectorField_real, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! all processors, planer precision PETSC_COMM_WORLD, FFTW_planner_flag)
if (.not. C_ASSOCIATED(planVectorBack)) error stop 'FFTW error' if (.not. c_associated(planVectorBack)) error stop 'FFTW error'
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! scalar MPI fftw plans ! scalar MPI fftw plans
planScalarForth = fftw_mpi_plan_many_dft_r2c(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order planScalarForth = fftw_mpi_plan_many_dft_r2c(3,gridFFTW(3:1:-1),scalarSize, &
scalarSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK,FFTW_MPI_DEFAULT_BLOCK, &
scalarField_real, scalarField_fourier, & ! input data, output data scalarField_real,scalarField_fourier, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision PETSC_COMM_WORLD,FFTW_planner_flag)
if (.not. C_ASSOCIATED(planScalarForth)) error stop 'FFTW error' if (.not. c_associated(planScalarForth)) error stop 'FFTW error'
planScalarBack = fftw_mpi_plan_many_dft_c2r(3, [gridFFTW(3),gridFFTW(2),gridFFTW(1)], & ! dimension, logical length in each dimension in reversed order, no. of transforms planScalarBack = fftw_mpi_plan_many_dft_c2r(3,gridFFTW(3:1:-1),scalarSize, &
scalarSize, FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &! no. of transforms, default iblock and oblock FFTW_MPI_DEFAULT_BLOCK, FFTW_MPI_DEFAULT_BLOCK, &
scalarField_fourier,scalarField_real, & ! input data, output data scalarField_fourier,scalarField_real, &
PETSC_COMM_WORLD, FFTW_planner_flag) ! use all processors, planer precision PETSC_COMM_WORLD, FFTW_planner_flag)
if (.not. C_ASSOCIATED(planScalarBack)) error stop 'FFTW error' if (.not. c_associated(planScalarBack)) error stop 'FFTW error'
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! calculation of discrete angular frequencies, ordered as in FFTW (wrap around) ! calculation of discrete angular frequencies, ordered as in FFTW (wrap around)

View File

@ -587,8 +587,8 @@ function lattice_C66_trans(Ntrans,C_parent66,lattice_target, &
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Non-schmid projections for bcc with up to 6 coefficients !> @brief Non-schmid projections for bcc with up to 6 coefficients
! Koester et al. 2012, Acta Materialia 60 (2012) 38943901, eq. (17) ! https://doi.org/10.1016/j.actamat.2012.03.053, eq. (17)
! Gröger et al. 2008, Acta Materialia 56 (2008) 54125425, table 1 ! https://doi.org/10.1016/j.actamat.2008.07.037, table 1
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSchmidMatrix) function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSchmidMatrix)
@ -602,6 +602,7 @@ function lattice_nonSchmidMatrix(Nslip,nonSchmidCoefficients,sense) result(nonSc
type(rotation) :: R type(rotation) :: R
integer :: i integer :: i
if (abs(sense) /= 1) error stop 'Sense in lattice_nonSchmidMatrix' if (abs(sense) /= 1) error stop 'Sense in lattice_nonSchmidMatrix'
coordinateSystem = buildCoordinateSystem(Nslip,BCC_NSLIPSYSTEM,BCC_SYSTEMSLIP,'cI',0.0_pReal) coordinateSystem = buildCoordinateSystem(Nslip,BCC_NSLIPSYSTEM,BCC_SYSTEMSLIP,'cI',0.0_pReal)
@ -634,7 +635,9 @@ end function lattice_nonSchmidMatrix
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Slip-slip interaction matrix !> @brief Slip-slip interaction matrix
!> details only active slip systems are considered !> @details only active slip systems are considered
!> @details https://doi.org/10.1016/j.actamat.2016.12.040 (fcc: Tab S4-1, bcc: Tab S5-1)
!> @details https://doi.org/10.1016/j.ijplas.2014.06.010 (hex: Tab 3b)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(interactionMatrix) function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(interactionMatrix)
@ -646,6 +649,7 @@ function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(
integer, dimension(:), allocatable :: NslipMax integer, dimension(:), allocatable :: NslipMax
integer, dimension(:,:), allocatable :: interactionTypes integer, dimension(:,:), allocatable :: interactionTypes
integer, dimension(FCC_NSLIP,FCC_NSLIP), parameter :: & integer, dimension(FCC_NSLIP,FCC_NSLIP), parameter :: &
FCC_INTERACTIONSLIPSLIP = reshape( [& FCC_INTERACTIONSLIPSLIP = reshape( [&
1, 2, 2, 4, 7, 5, 3, 5, 5, 4, 6, 7, 10,11,10,11,12,13, & ! -----> acting (forest) 1, 2, 2, 4, 7, 5, 3, 5, 5, 4, 6, 7, 10,11,10,11,12,13, & ! -----> acting (forest)
@ -750,41 +754,113 @@ function lattice_interaction_SlipBySlip(Nslip,interactionValues,lattice) result(
integer, dimension(HEX_NSLIP,HEX_NSLIP), parameter :: & integer, dimension(HEX_NSLIP,HEX_NSLIP), parameter :: &
HEX_INTERACTIONSLIPSLIP = reshape( [& HEX_INTERACTIONSLIPSLIP = reshape( [&
! basal prism 1. pyr<a> 1. pyr<c+a> 2. pyr<c+a> ! basal prism 1. pyr<a> 1. pyr<c+a> 2. pyr<c+a>
1, 2, 2, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! -----> acting (forest) 1, 2, 2, 3, 4, 4, 9,10, 9, 9,10, 9, 20,21,22,22,21,20,20,21,22,22,21,20, 47,47,48,47,47,48, & ! -----> acting (forest)
2, 1, 2, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! | basal 2, 1, 2, 4, 3, 4, 10, 9, 9,10, 9, 9, 22,22,21,20,20,21,22,22,21,20,20,21, 47,48,47,47,48,47, & ! | basal
2, 2, 1, 3, 3, 3, 7, 7, 7, 7, 7, 7, 13,13,13,13,13,13,13,13,13,13,13,13, 21,21,21,21,21,21, & ! | 2, 2, 1, 4, 4, 3, 9, 9,10, 9, 9,10, 21,20,20,21,22,22,21,20,20,21,22,22, 48,47,47,48,47,47, & ! |
! v ! v
6, 6, 6, 4, 5, 5, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, & ! reacting (primary) 7, 8, 8, 5, 6, 6, 11,12,11,11,12,11, 23,24,25,25,24,23,23,24,25,25,24,23, 49,49,50,49,49,50, & ! reacting (primary)
6, 6, 6, 5, 4, 5, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, & ! prism 8, 7, 8, 6, 5, 6, 12,11,11,12,11,11, 25,25,24,23,23,24,25,25,24,23,23,24, 49,50,49,49,50,49, & ! prism
6, 6, 6, 5, 5, 4, 8, 8, 8, 8, 8, 8, 14,14,14,14,14,14,14,14,14,14,14,14, 22,22,22,22,22,22, & 8, 8, 7, 6, 6, 5, 11,11,12,11,11,12, 24,23,23,24,25,25,24,23,23,24,25,25, 50,49,49,50,49,49, &
12,12,12, 11,11,11, 9,10,10,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & 18,19,18, 16,17,16, 13,14,14,15,14,14, 26,26,27,28,28,27,29,29,27,28,28,27, 51,52,51,51,52,51, &
12,12,12, 11,11,11, 10, 9,10,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & 19,18,18, 17,16,16, 14,13,14,14,15,14, 28,27,26,26,27,28,28,27,29,29,27,28, 51,51,52,51,51,52, &
12,12,12, 11,11,11, 10,10, 9,10,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & 18,18,19, 16,16,17, 14,14,13,14,14,15, 27,28,28,27,26,26,27,28,28,27,29,29, 52,51,51,52,51,51, &
12,12,12, 11,11,11, 10,10,10, 9,10,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & ! 1. pyr<a> 18,19,18, 16,17,16, 15,14,14,13,14,14, 29,29,27,28,28,27,26,26,27,28,28,27, 51,52,51,51,52,51, & ! 1. pyr<a>
12,12,12, 11,11,11, 10,10,10,10, 9,10, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & 19,18,18, 17,16,16, 14,15,14,14,13,14, 28,27,29,29,27,28,28,27,26,26,27,28, 51,51,52,51,51,52, &
12,12,12, 11,11,11, 10,10,10,10,10, 9, 15,15,15,15,15,15,15,15,15,15,15,15, 23,23,23,23,23,23, & 18,18,19, 16,16,17, 14,14,15,14,14,13, 27,28,28,27,29,29,27,28,28,27,26,26, 52,51,51,52,51,51, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 16,17,17,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, & 44,45,46, 41,42,43, 37,38,39,40,38,39, 30,31,32,32,32,33,34,35,32,32,32,36, 53,54,55,53,54,56, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,16,17,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, & 46,45,44, 43,42,41, 37,39,38,40,39,38, 31,30,36,32,32,32,35,34,33,32,32,32, 56,54,53,55,54,53, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,16,17,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, & 45,46,44, 42,43,41, 39,37,38,39,40,38, 32,36,30,31,32,32,32,33,34,35,32,32, 56,53,54,55,53,54, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,16,17,17,17,17,17,17,17,17, 24,24,24,24,24,24, & 45,44,46, 42,41,43, 38,37,39,38,40,39, 32,32,31,30,36,32,32,32,35,34,33,32, 53,56,54,53,55,54, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,16,17,17,17,17,17,17,17, 24,24,24,24,24,24, & 46,44,45, 43,41,42, 38,39,37,38,39,40, 32,32,32,36,30,31,32,32,32,33,34,35, 54,56,53,54,55,53, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,16,17,17,17,17,17,17, 24,24,24,24,24,24, & 44,46,45, 41,43,42, 39,38,37,39,38,40, 33,32,32,32,31,30,36,32,32,32,35,34, 54,53,56,54,53,55, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,16,17,17,17,17,17, 24,24,24,24,24,24, & ! 1. pyr<c+a> 44,45,46, 41,42,43, 40,38,39,37,38,39, 34,35,32,32,32,36,30,31,32,32,32,33, 53,54,56,53,54,55, & ! 1. pyr<c+a>
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,16,17,17,17,17, 24,24,24,24,24,24, & 46,45,44, 43,42,41, 40,39,38,37,39,38, 35,34,33,32,32,32,31,30,36,32,32,32, 55,54,53,56,54,53, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,16,17,17,17, 24,24,24,24,24,24, & 45,46,44, 42,43,41, 39,40,38,39,37,38, 32,33,34,35,32,32,32,36,30,31,32,32, 55,53,54,56,53,54, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,16,17,17, 24,24,24,24,24,24, & 45,44,46, 42,41,43, 38,40,39,38,37,39, 32,32,35,34,33,32,32,32,31,30,36,32, 53,55,54,53,56,54, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,17,16,17, 24,24,24,24,24,24, & 46,44,45, 43,41,42, 38,39,40,38,39,37, 32,32,32,33,34,35,32,32,32,36,30,31, 54,55,53,54,56,53, &
20,20,20, 19,19,19, 18,18,18,18,18,18, 17,17,17,17,17,17,17,17,17,17,17,16, 24,24,24,24,24,24, & 44,46,45, 41,43,42, 39,38,40,39,38,37, 36,32,32,32,35,34,33,32,32,32,31,30, 54,53,55,54,53,56, &
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 25,26,26,26,26,26, & 68,68,69, 66,66,67, 64,64,65,64,65,65, 60,61,61,60,62,62,60,63,63,60,62,62, 57,58,58,59,58,58, &
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,25,26,26,26,26, & 68,69,68, 66,67,66, 65,64,64,65,64,64, 62,62,60,61,61,60,62,62,60,63,63,60, 58,57,58,58,59,58, &
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,25,26,26,26, & 69,68,68, 67,66,66, 64,65,64,64,65,64, 63,60,62,62,60,61,61,60,62,62,60,63, 58,58,57,58,58,59, &
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,25,26,26, & ! 2. pyr<c+a> 68,68,69, 66,66,67, 64,64,65,64,64,65, 60,63,63,60,62,62,60,61,61,60,62,62, 59,58,58,57,58,58, & ! 2. pyr<c+a>
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,26,25,26, & 68,69,68, 66,67,66, 65,64,64,65,64,64, 62,62,60,63,63,60,62,62,60,61,61,60, 58,59,58,58,57,58, &
30,30,30, 29,29,29, 28,28,28,28,28,28, 27,27,27,27,27,27,27,27,27,27,27,27, 26,26,26,26,26,25 & 69,68,68, 67,66,66, 64,65,64,64,65,64, 61,60,62,62,60,63,63,60,62,62,60,61, 58,58,59,58,58,57 &
],shape(HEX_INTERACTIONSLIPSLIP)) !< Slip-slip interaction types for hex (onion peel naming scheme) ],shape(HEX_INTERACTIONSLIPSLIP)) !< Slip-slip interaction types for hex (onion peel naming scheme)
!< 10.1016/j.ijplas.2014.06.010 table 3
!< 10.1080/14786435.2012.699689 table 2 and 3
!< index & label & description
!< 1 & S1 & basal self-interaction
!< 2 & 1 & basal/basal coplanar
!< 3 & 3 & basal/prismatic collinear
!< 4 & 4 & basal/prismatic non-collinear
!< 5 & S2 & prismatic self-interaction
!< 6 & 2 & prismatic/prismatic
!< 7 & 5 & prismatic/basal collinear
!< 8 & 6 & prismatic/basal non-collinear
!< 9 & - & basal/pyramidal <a> non-collinear
!< 10 & - & basal/pyramidal <a> collinear
!< 11 & - & prismatic/pyramidal <a> non-collinear
!< 12 & - & prismatic/pyramidal <a> collinear
!< 13 & - & pyramidal <a> self-interaction
!< 14 & - & pyramidal <a> non-collinear
!< 15 & - & pyramidal <a> collinear
!< 16 & - & pyramidal <a>/prismatic non-collinear
!< 17 & - & pyramidal <a>/prismatic collinear
!< 18 & - & pyramidal <a>/basal non-collinear
!< 19 & - & pyramidal <a>/basal collinear
!< 20 & - & basal/1. order pyramidal <c+a> semi-collinear
!< 21 & - & basal/1. order pyramidal <c+a>
!< 22 & - & basal/1. order pyramidal <c+a>
!< 23 & - & prismatic/1. order pyramidal <c+a> semi-collinear
!< 24 & - & prismatic/1. order pyramidal <c+a>
!< 25 & - & prismatic/1. order pyramidal <c+a> semi-coplanar?
!< 26 & - & pyramidal <a>/1. order pyramidal <c+a> coplanar
!< 27 & - & pyramidal <a>/1. order pyramidal <c+a>
!< 28 & - & pyramidal <a>/1. order pyramidal <c+a> semi-collinear
!< 29 & - & pyramidal <a>/1. order pyramidal <c+a> semi-coplanar
!< 30 & - & 1. order pyramidal <c+a> self-interaction
!< 31 & - & 1. order pyramidal <c+a> coplanar
!< 32 & - & 1. order pyramidal <c+a>
!< 33 & - & 1. order pyramidal <c+a>
!< 34 & - & 1. order pyramidal <c+a> semi-coplanar
!< 35 & - & 1. order pyramidal <c+a> semi-coplanar
!< 36 & - & 1. order pyramidal <c+a> collinear
!< 37 & - & 1. order pyramidal <c+a>/pyramidal <a> coplanar
!< 38 & - & 1. order pyramidal <c+a>/pyramidal <a> semi-collinear
!< 39 & - & 1. order pyramidal <c+a>/pyramidal <a>
!< 40 & - & 1. order pyramidal <c+a>/pyramidal <a> semi-coplanar
!< 41 & - & 1. order pyramidal <c+a>/prismatic semi-collinear
!< 42 & - & 1. order pyramidal <c+a>/prismatic semi-coplanar
!< 43 & - & 1. order pyramidal <c+a>/prismatic
!< 44 & - & 1. order pyramidal <c+a>/basal semi-collinear
!< 45 & - & 1. order pyramidal <c+a>/basal
!< 46 & - & 1. order pyramidal <c+a>/basal
!< 47 & 8 & basal/2. order pyramidal <c+a> non-collinear
!< 48 & 7 & basal/2. order pyramidal <c+a> semi-collinear
!< 49 & 10 & prismatic/2. order pyramidal <c+a>
!< 50 & 9 & prismatic/2. order pyramidal <c+a> semi-collinear
!< 51 & - & pyramidal <a>/2. order pyramidal <c+a>
!< 52 & - & pyramidal <a>/2. order pyramidal <c+a> semi collinear
!< 53 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
!< 54 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
!< 55 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a>
!< 56 & - & 1. order pyramidal <c+a>/2. order pyramidal <c+a> collinear
!< 57 & S3 & 2. order pyramidal <c+a> self-interaction
!< 58 & 16 & 2. order pyramidal <c+a> non-collinear
!< 59 & 15 & 2. order pyramidal <c+a> semi-collinear
!< 60 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
!< 61 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a> collinear
!< 62 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
!< 63 & - & 2. order pyramidal <c+a>/1. order pyramidal <c+a>
!< 64 & - & 2. order pyramidal <c+a>/pyramidal <a> non-collinear
!< 65 & - & 2. order pyramidal <c+a>/pyramidal <a> semi-collinear
!< 66 & 14 & 2. order pyramidal <c+a>/prismatic non-collinear
!< 67 & 13 & 2. order pyramidal <c+a>/prismatic semi-collinear
!< 68 & 12 & 2. order pyramidal <c+a>/basal non-collinear
!< 69 & 11 & 2. order pyramidal <c+a>/basal semi-collinear
integer, dimension(BCT_NSLIP,BCT_NSLIP), parameter :: & integer, dimension(BCT_NSLIP,BCT_NSLIP), parameter :: &
BCT_INTERACTIONSLIPSLIP = reshape( [& BCT_INTERACTIONSLIPSLIP = reshape( [&

View File

@ -108,8 +108,14 @@ subroutine parse()
homogenizations => config_material%get('homogenization') homogenizations => config_material%get('homogenization')
call sanityCheck(materials, homogenizations) call sanityCheck(materials, homogenizations)
#if defined (__GFORTRAN__)
material_name_phase = getKeys(phases) material_name_phase = getKeys(phases)
material_name_homogenization = getKeys(homogenizations) material_name_homogenization = getKeys(homogenizations)
#else
material_name_phase = phases%Keys()
material_name_homogenization = homogenizations%Keys()
#endif
allocate(homogenization_Nconstituents(homogenizations%length)) allocate(homogenization_Nconstituents(homogenizations%length))
do h=1, homogenizations%length do h=1, homogenizations%length
@ -203,9 +209,9 @@ subroutine sanityCheck(materials,homogenizations)
end subroutine sanityCheck end subroutine sanityCheck
#if defined (__GFORTRAN__)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Get all keys from a dictionary !> @brief %keys() is broken on gfortran
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function getKeys(dict) function getKeys(dict)
@ -228,5 +234,6 @@ function getKeys(dict)
end do end do
end function getKeys end function getKeys
#endif
end module material end module material

View File

@ -84,38 +84,34 @@ contains
subroutine math_init subroutine math_init
real(pReal), dimension(4) :: randTest real(pReal), dimension(4) :: randTest
integer :: & integer :: randSize
randSize, & integer, dimension(:), allocatable :: seed
randomSeed !< fixed seeding for pseudo-random number generator, Default 0: use random seed
integer, dimension(:), allocatable :: randInit
class(tNode), pointer :: & class(tNode), pointer :: &
num_generic num_generic
print'(/,1x,a)', '<<<+- math init -+>>>'; flush(IO_STDOUT) print'(/,1x,a)', '<<<+- math init -+>>>'; flush(IO_STDOUT)
num_generic => config_numerics%get('generic',defaultVal=emptyDict) num_generic => config_numerics%get('generic',defaultVal=emptyDict)
randomSeed = num_generic%get_asInt('random_seed', defaultVal = 0)
call random_seed(size=randSize) call random_seed(size=randSize)
allocate(randInit(randSize)) allocate(seed(randSize))
if (randomSeed > 0) then
randInit = randomSeed if (num_generic%contains('random_seed')) then
seed = num_generic%get_as1dInt('random_seed',requiredSize=randSize)
else else
call random_seed() call random_seed()
call random_seed(get = randInit) call random_seed(get = seed)
randInit(2:randSize) = randInit(1)
end if end if
call random_seed(put = randInit) call random_seed(put = seed)
call random_number(randTest) call random_number(randTest)
print'(/,a,i2)', ' size of random seed: ', randSize print'(/,a,i2)', ' size of random seed: ', randSize
print'( a,i0)', ' value of random seed: ', randInit(1) print*, 'value of random seed: ', seed
print'( a,4(/,26x,f17.14),/)', ' start of random sequence: ', randTest print'( a,4(/,26x,f17.14))', ' start of random sequence: ', randTest
call random_seed(put = randInit) call selfTest()
call selfTest
end subroutine math_init end subroutine math_init

View File

@ -270,7 +270,7 @@ pure elemental subroutine standardize(self)
class(rotation), intent(inout) :: self class(rotation), intent(inout) :: self
if (self%q(1) < 0.0_pReal) self%q = - self%q if (sign(1.0_pReal,self%q(1)) < 0.0_pReal) self%q = - self%q
end subroutine standardize end subroutine standardize
@ -450,7 +450,7 @@ pure function qu2om(qu) result(om)
om(3,2) = 2.0_pReal*(qu(4)*qu(3)+qu(1)*qu(2)) om(3,2) = 2.0_pReal*(qu(4)*qu(3)+qu(1)*qu(2))
om(1,3) = 2.0_pReal*(qu(2)*qu(4)+qu(1)*qu(3)) om(1,3) = 2.0_pReal*(qu(2)*qu(4)+qu(1)*qu(3))
if (P < 0.0_pReal) om = transpose(om) if (sign(1.0_pReal,P) < 0.0_pReal) om = transpose(om)
end function qu2om end function qu2om
@ -480,7 +480,7 @@ pure function qu2eu(qu) result(eu)
atan2( 2.0_pReal*chi, q03-q12 ), & atan2( 2.0_pReal*chi, q03-q12 ), &
atan2(( P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)+qu(3)*qu(4))*chi )] atan2(( P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)+qu(3)*qu(4))*chi )]
endif degenerated endif degenerated
where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) where(sign(1.0_pReal,eu)<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
end function qu2eu end function qu2eu
@ -602,7 +602,7 @@ pure function om2qu(om) result(qu)
qu = [ (om(2,1) - om(1,2)) /s,(om(1,3) + om(3,1)) / s,(om(2,3) + om(3,2)) / s,0.25_pReal * s] qu = [ (om(2,1) - om(1,2)) /s,(om(1,3) + om(3,1)) / s,(om(2,3) + om(3,2)) / s,0.25_pReal * s]
endif endif
endif endif
if(qu(1)<0._pReal) qu =-1.0_pReal * qu if(sign(1.0_pReal,qu(1))<0.0_pReal) qu =-1.0_pReal * qu
qu = qu*[1.0_pReal,P,P,P] qu = qu*[1.0_pReal,P,P,P]
end function om2qu end function om2qu
@ -628,7 +628,7 @@ pure function om2eu(om) result(eu)
eu = [atan2(om(1,2),om(1,1)), 0.5_pReal*PI*(1.0_pReal-om(3,3)),0.0_pReal ] eu = [atan2(om(1,2),om(1,1)), 0.5_pReal*PI*(1.0_pReal-om(3,3)),0.0_pReal ]
end if end if
where(abs(eu) < 1.e-8_pReal) eu = 0.0_pReal where(abs(eu) < 1.e-8_pReal) eu = 0.0_pReal
where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) where(sign(1.0_pReal,eu)<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI])
end function om2eu end function om2eu
@ -735,7 +735,7 @@ pure function eu2qu(eu) result(qu)
-P*sPhi*cos(ee(1)-ee(3)), & -P*sPhi*cos(ee(1)-ee(3)), &
-P*sPhi*sin(ee(1)-ee(3)), & -P*sPhi*sin(ee(1)-ee(3)), &
-P*cPhi*sin(ee(1)+ee(3))] -P*cPhi*sin(ee(1)+ee(3))]
if(qu(1) < 0.0_pReal) qu = qu * (-1.0_pReal) if(sign(1.0_pReal,qu(1)) < 0.0_pReal) qu = qu * (-1.0_pReal)
end function eu2qu end function eu2qu
@ -792,7 +792,7 @@ pure function eu2ax(eu) result(ax)
else else
ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front
ax(4) = alpha ax(4) = alpha
if (alpha < 0.0_pReal) ax = -ax ! ensure alpha is positive if (sign(1.0_pReal,alpha) < 0.0_pReal) ax = -ax ! ensure alpha is positive
end if end if
end function eu2ax end function eu2ax