From e80d91e30ac4aab3c7aaca666a2b144f917aa9bc Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Mon, 10 Jan 2022 20:34:50 +0100 Subject: [PATCH 01/36] thermal restart (WIP) --- src/grid/DAMASK_grid.f90 | 9 ++++- src/grid/grid_thermal_spectral.f90 | 57 ++++++++++++++++++++++++++---- src/phase.f90 | 11 ++++++ src/phase_thermal.f90 | 32 +++++++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/src/grid/DAMASK_grid.f90 b/src/grid/DAMASK_grid.f90 index b1da0c2a2..a5f441cc0 100644 --- a/src/grid/DAMASK_grid.f90 +++ b/src/grid/DAMASK_grid.f90 @@ -466,7 +466,14 @@ program DAMASK_grid call MPI_Allreduce(interface_SIGUSR2,signal,1,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,ierr) if (ierr /= 0) error stop 'MPI error' if (mod(inc,loadCases(l)%f_restart) == 0 .or. signal) then - call mechanical_restartWrite + do field = 1, nActiveFields + select case (ID(field)) + case(FIELD_MECH_ID) + call mechanical_restartWrite + case(FIELD_THERMAL_ID) + call grid_thermal_spectral_restartWrite + end select + end do call CPFEM_restartWrite endif if (signal) call interface_setSIGUSR2(.false.) diff --git a/src/grid/grid_thermal_spectral.f90 b/src/grid/grid_thermal_spectral.f90 index 67c7ba1c3..0f539b73b 100644 --- a/src/grid/grid_thermal_spectral.f90 +++ b/src/grid/grid_thermal_spectral.f90 @@ -17,6 +17,9 @@ module grid_thermal_spectral use parallelization use IO use spectral_utilities + use DAMASK_interface + use HDF5 + use HDF5_utilities use discretization_grid use homogenization use YAML_types @@ -55,6 +58,7 @@ module grid_thermal_spectral public :: & grid_thermal_spectral_init, & grid_thermal_spectral_solution, & + grid_thermal_spectral_restartWrite, & grid_thermal_spectral_forward contains @@ -70,7 +74,9 @@ subroutine grid_thermal_spectral_init(T_0) PetscInt, dimension(0:worldsize-1) :: localK integer :: i, j, k, ce DM :: thermal_grid + real(pReal), dimension(:), allocatable :: T_restart, T_lastInc_restart PetscScalar, dimension(:,:,:), pointer :: T_PETSc + integer(HID_T) :: fileHandle, groupHandle PetscErrorCode :: ierr class(tNode), pointer :: & num_grid @@ -130,17 +136,26 @@ subroutine grid_thermal_spectral_init(T_0) xend = xstart + xend - 1 yend = ystart + yend - 1 zend = zstart + zend - 1 - allocate(T_current(grid(1),grid(2),grid3), source=0.0_pReal) - allocate(T_lastInc(grid(1),grid(2),grid3), source=0.0_pReal) - allocate(T_stagInc(grid(1),grid(2),grid3), source=0.0_pReal) + allocate(T_current(grid(1),grid(2),grid3), source=T_0) + allocate(T_lastInc(grid(1),grid(2),grid3), source=T_0) + allocate(T_stagInc(grid(1),grid(2),grid3), source=T_0) + + restartRead: if (interface_restartInc > 0) then + print'(/,1x,a,i0,a)', 'reading restart data of increment ', interface_restartInc, ' from file' + + fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r') + groupHandle = HDF5_openGroup(fileHandle,'solver') + + call HDF5_read(T_restart,groupHandle,'T',.false.) + T_current = reshape(T_restart,[grid(1),grid(2),grid3]) + call HDF5_read(T_lastInc_restart,groupHandle,'T_lastInc',.false.) + T_lastInc = reshape(T_lastInc_restart,[grid(1),grid(2),grid3]) + end if restartRead ce = 0 do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) ce = ce + 1 - T_current(i,j,k) = T_0 - T_lastInc(i,j,k) = T_current(i,j,k) - T_stagInc(i,j,k) = T_current(i,j,k) - call homogenization_thermal_setField(T_0,0.0_pReal,ce) + call homogenization_thermal_setField(T_current(i,j,k),0.0_pReal,ce) end do; end do; end do call DMDAVecGetArrayF90(thermal_grid,solution_vec,T_PETSc,ierr); CHKERRQ(ierr) @@ -242,6 +257,34 @@ subroutine grid_thermal_spectral_forward(cutBack) end subroutine grid_thermal_spectral_forward +!-------------------------------------------------------------------------------------------------- +!> @brief Write current solver and constitutive data for restart to file +!-------------------------------------------------------------------------------------------------- +subroutine grid_thermal_spectral_restartWrite + + PetscErrorCode :: ierr + DM :: dm_local + integer(HID_T) :: fileHandle, groupHandle + PetscScalar, dimension(:,:,:), pointer :: T + + call SNESGetDM(thermal_snes,dm_local,ierr); CHKERRQ(ierr) + call DMDAVecGetArrayF90(dm_local,solution_vec,T,ierr); CHKERRQ(ierr) + + print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT) + + fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w') + groupHandle = HDF5_addGroup(fileHandle,'solver') + call HDF5_write(T,groupHandle,'T') + call HDF5_write(T_lastInc,groupHandle,'T_lastInc') + call HDF5_closeGroup(groupHandle) + call HDF5_closeFile(fileHandle) + + call DMDAVecRestoreArrayF90(dm_local,solution_vec,T,ierr); CHKERRQ(ierr) + +end subroutine grid_thermal_spectral_restartWrite + + + !-------------------------------------------------------------------------------------------------- !> @brief forms the spectral thermal residual vector !-------------------------------------------------------------------------------------------------- diff --git a/src/phase.f90 b/src/phase.f90 index 6035b4491..9ee3d5a4b 100644 --- a/src/phase.f90 +++ b/src/phase.f90 @@ -123,11 +123,20 @@ module phase integer, intent(in) :: ph end subroutine mechanical_restartWrite + module subroutine thermal_restartWrite(groupHandle,ph) + integer(HID_T), intent(in) :: groupHandle + integer, intent(in) :: ph + end subroutine thermal_restartWrite + module subroutine mechanical_restartRead(groupHandle,ph) integer(HID_T), intent(in) :: groupHandle integer, intent(in) :: ph end subroutine mechanical_restartRead + module subroutine thermal_restartRead(groupHandle,ph) + integer(HID_T), intent(in) :: groupHandle + integer, intent(in) :: ph + end subroutine thermal_restartRead module function mechanical_S(ph,en) result(S) integer, intent(in) :: ph,en @@ -640,6 +649,7 @@ subroutine phase_restartWrite(fileHandle) groupHandle(2) = HDF5_addGroup(groupHandle(1),material_name_phase(ph)) call mechanical_restartWrite(groupHandle(2),ph) + call thermal_restartWrite(groupHandle(2),ph) call HDF5_closeGroup(groupHandle(2)) @@ -668,6 +678,7 @@ subroutine phase_restartRead(fileHandle) groupHandle(2) = HDF5_openGroup(groupHandle(1),material_name_phase(ph)) call mechanical_restartRead(groupHandle(2),ph) + call thermal_restartRead(groupHandle(2),ph) call HDF5_closeGroup(groupHandle(2)) diff --git a/src/phase_thermal.f90 b/src/phase_thermal.f90 index a3e4dd628..fb98039fd 100644 --- a/src/phase_thermal.f90 +++ b/src/phase_thermal.f90 @@ -254,6 +254,38 @@ function integrateThermalState(Delta_t, ph,en) result(broken) end function integrateThermalState +module subroutine thermal_restartWrite(groupHandle,ph) + + integer(HID_T), intent(in) :: groupHandle + integer, intent(in) :: ph + + integer(HID_T) :: new_group + integer :: so + + do so = 1,thermal_Nsources(ph) + !new_group = HDF5_addGroup(groupHandle, + call HDF5_write(thermalState(ph)%p(so)%state,groupHandle,'omega2') + enddo + +end subroutine thermal_restartWrite + + +module subroutine thermal_restartRead(groupHandle,ph) + + integer(HID_T), intent(in) :: groupHandle + integer, intent(in) :: ph + + integer(HID_T) :: new_group + integer :: so + + do so = 1,thermal_Nsources(ph) + !new_group = HDF5_addGroup(groupHandle, + call HDF5_read(thermalState(ph)%p(so)%state0,groupHandle,'omega2') + enddo + +end subroutine thermal_restartRead + + module subroutine thermal_forward() integer :: ph, so From 29cbf1304b2ed5420fd3aa9f3c1fe1f040191cd1 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 12 Jan 2022 07:48:09 +0100 Subject: [PATCH 02/36] grain growth not maintained and has issues the grain growth model is based on the Voronoi Implicit Interface Method (https://doi.org/10.1016/j.jcp.2012.04.004). The last step in this algorithm is the assignment of the new phase/material ID to the voxels in the 'thick boundary' which is done with distance_transform_edt from ndimage. This problem can have multiple solution and can lead to the translation of grains. In the original publication, the position of the boundary is calculated with subvoxel resolution by solving the eikonal equation. The following python packages might help: https://pypi.org/project/eikonalfm https://pypi.org/project/scikit-fmm https://github.com/malcolmw/pykonal --- processing/legacy/geom_grainGrowth.py | 178 -------------------------- 1 file changed, 178 deletions(-) delete mode 100755 processing/legacy/geom_grainGrowth.py diff --git a/processing/legacy/geom_grainGrowth.py b/processing/legacy/geom_grainGrowth.py deleted file mode 100755 index d969b415c..000000000 --- a/processing/legacy/geom_grainGrowth.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from io import StringIO -from optparse import OptionParser - -import numpy as np -from scipy import ndimage - -import damask - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - - -getInterfaceEnergy = lambda A,B: np.float32((A != B)*1.0) # 1.0 if A & B are distinct, 0.0 otherwise -struc = ndimage.generate_binary_structure(3,1) # 3D von Neumann neighborhood - - -#-------------------------------------------------------------------------------------------------- -# MAIN -#-------------------------------------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog option(s) [geomfile(s)]', description = """ -Smoothen interface roughness by simulated curvature flow. -This is achieved by the diffusion of each initially sharply bounded grain volume within the periodic domain -up to a given distance 'd' voxels. -The final geometry is assembled by selecting at each voxel that grain index for which the concentration remains largest. -References 10.1073/pnas.1111557108 (10.1006/jcph.1994.1105) - -""", version = scriptID) - -parser.add_option('-d', '--distance', - dest = 'd', - type = 'float', metavar = 'float', - help = 'diffusion distance in voxels [%default]') -parser.add_option('-N', '--iterations', - dest = 'N', - type = 'int', metavar = 'int', - help = 'curvature flow iterations [%default]') -parser.add_option('-i', '--immutable', - action = 'extend', dest = 'immutable', metavar = '', - help = 'list of immutable material indices') -parser.add_option('--ndimage', - dest = 'ndimage', action='store_true', - help = 'use ndimage.gaussian_filter in lieu of explicit FFT') - -parser.set_defaults(d = 1, - N = 1, - immutable = [], - ndimage = False, - ) - -(options, filenames) = parser.parse_args() - -options.immutable = list(map(int,options.immutable)) - - -if filenames == []: filenames = [None] - -for name in filenames: - damask.util.report(scriptName,name) - - geom = damask.Grid.load(StringIO(''.join(sys.stdin.read())) if name is None else name) - - grid_original = geom.cells - damask.util.croak(geom) - material = np.tile(geom.material,np.where(grid_original == 1, 2,1)) # make one copy along dimensions with grid == 1 - grid = np.array(material.shape) - -# --- initialize support data --------------------------------------------------------------------- - -# store a copy of the initial material indices to find locations of immutable indices - material_original = np.copy(material) - - if not options.ndimage: - X,Y,Z = np.mgrid[0:grid[0],0:grid[1],0:grid[2]] - - # Calculates gaussian weights for simulating 3d diffusion - gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d),dtype=np.float32) \ - /np.power(2.0*np.pi*options.d*options.d,(3.0 - np.count_nonzero(grid_original == 1))/2.,dtype=np.float32) - - gauss[:,:,:grid[2]//2:-1] = gauss[:,:,1:(grid[2]+1)//2] # trying to cope with uneven (odd) grid size - gauss[:,:grid[1]//2:-1,:] = gauss[:,1:(grid[1]+1)//2,:] - gauss[:grid[0]//2:-1,:,:] = gauss[1:(grid[0]+1)//2,:,:] - gauss = np.fft.rfftn(gauss).astype(np.complex64) - - for smoothIter in range(options.N): - - interfaceEnergy = np.zeros(material.shape,dtype=np.float32) - for i in (-1,0,1): - for j in (-1,0,1): - for k in (-1,0,1): - # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood) - interfaceEnergy = np.maximum(interfaceEnergy, - getInterfaceEnergy(material,np.roll(np.roll(np.roll( - material,i,axis=0), j,axis=1), k,axis=2))) - - # periodically extend interfacial energy array by half a grid size in positive and negative directions - periodic_interfaceEnergy = np.tile(interfaceEnergy,(3,3,3))[grid[0]//2:-grid[0]//2, - grid[1]//2:-grid[1]//2, - grid[2]//2:-grid[2]//2] - - # transform bulk volume (i.e. where interfacial energy remained zero), store index of closest boundary voxel - index = ndimage.morphology.distance_transform_edt(periodic_interfaceEnergy == 0., - return_distances = False, - return_indices = True) - - # want array index of nearest voxel on periodically extended boundary - periodic_bulkEnergy = periodic_interfaceEnergy[index[0], - index[1], - index[2]].reshape(2*grid) # fill bulk with energy of nearest interface - - if options.ndimage: - periodic_diffusedEnergy = ndimage.gaussian_filter( - np.where(ndimage.morphology.binary_dilation(periodic_interfaceEnergy > 0., - structure = struc, - iterations = int(round(options.d*2.))-1, # fat boundary - ), - periodic_bulkEnergy, # ...and zero everywhere else - 0.), - sigma = options.d) - else: - diffusedEnergy = np.fft.irfftn(np.fft.rfftn( - np.where( - ndimage.morphology.binary_dilation(interfaceEnergy > 0., - structure = struc, - iterations = int(round(options.d*2.))-1),# fat boundary - periodic_bulkEnergy[grid[0]//2:-grid[0]//2, # retain filled energy on fat boundary... - grid[1]//2:-grid[1]//2, - grid[2]//2:-grid[2]//2], # ...and zero everywhere else - 0.)).astype(np.complex64) * - gauss).astype(np.float32) - - periodic_diffusedEnergy = np.tile(diffusedEnergy,(3,3,3))[grid[0]//2:-grid[0]//2, - grid[1]//2:-grid[1]//2, - grid[2]//2:-grid[2]//2] # periodically extend the smoothed bulk energy - - - # transform voxels close to interface region - index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.95*np.amax(periodic_diffusedEnergy), - return_distances = False, - return_indices = True) # want index of closest bulk grain - - periodic_material = np.tile(material,(3,3,3))[grid[0]//2:-grid[0]//2, - grid[1]//2:-grid[1]//2, - grid[2]//2:-grid[2]//2] # periodically extend the geometry - - material = periodic_material[index[0], - index[1], - index[2]].reshape(2*grid)[grid[0]//2:-grid[0]//2, - grid[1]//2:-grid[1]//2, - grid[2]//2:-grid[2]//2] # extent grains into interface region - - # replace immutable materials with closest mutable ones - index = ndimage.morphology.distance_transform_edt(np.in1d(material,options.immutable).reshape(grid), - return_distances = False, - return_indices = True) - material = material[index[0], - index[1], - index[2]] - - immutable = np.zeros(material.shape, dtype=np.bool) - # find locations where immutable materials have been in original structure - for micro in options.immutable: - immutable += material_original == micro - - # undo any changes involving immutable materials - material = np.where(immutable, material_original,material) - - damask.Grid(material = material[0:grid_original[0],0:grid_original[1],0:grid_original[2]], - size = geom.size, - origin = geom.origin, - comments = geom.comments + [scriptID + ' ' + ' '.join(sys.argv[1:])], - )\ - .save(sys.stdout if name is None else name) From 236f0297ac21b76bfd8d69124a0ffff1443c9d2d Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 12 Jan 2022 20:42:37 +0100 Subject: [PATCH 03/36] test added --- PRIVATE | 2 +- src/grid/grid_thermal_spectral.f90 | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/PRIVATE b/PRIVATE index b898a8b55..f3b0cfa68 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit b898a8b5552bd9d1c555edc3d8134564dd32fe53 +Subproject commit f3b0cfa68febbc90369e414c38733ccdc22258bb diff --git a/src/grid/grid_thermal_spectral.f90 b/src/grid/grid_thermal_spectral.f90 index 0f539b73b..3b4ded7e6 100644 --- a/src/grid/grid_thermal_spectral.f90 +++ b/src/grid/grid_thermal_spectral.f90 @@ -74,7 +74,6 @@ subroutine grid_thermal_spectral_init(T_0) PetscInt, dimension(0:worldsize-1) :: localK integer :: i, j, k, ce DM :: thermal_grid - real(pReal), dimension(:), allocatable :: T_restart, T_lastInc_restart PetscScalar, dimension(:,:,:), pointer :: T_PETSc integer(HID_T) :: fileHandle, groupHandle PetscErrorCode :: ierr @@ -146,10 +145,8 @@ subroutine grid_thermal_spectral_init(T_0) fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r') groupHandle = HDF5_openGroup(fileHandle,'solver') - call HDF5_read(T_restart,groupHandle,'T',.false.) - T_current = reshape(T_restart,[grid(1),grid(2),grid3]) - call HDF5_read(T_lastInc_restart,groupHandle,'T_lastInc',.false.) - T_lastInc = reshape(T_lastInc_restart,[grid(1),grid(2),grid3]) + call HDF5_read(T_current,groupHandle,'T',.false.) + call HDF5_read(T_lastInc,groupHandle,'T_lastInc',.false.) end if restartRead ce = 0 @@ -270,10 +267,10 @@ subroutine grid_thermal_spectral_restartWrite call SNESGetDM(thermal_snes,dm_local,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(dm_local,solution_vec,T,ierr); CHKERRQ(ierr) - print'(1x,a)', 'writing solver data required for restart to file'; flush(IO_STDOUT) + print'(1x,a)', 'writing thermal solver data required for restart to file'; flush(IO_STDOUT) - fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w') - groupHandle = HDF5_addGroup(fileHandle,'solver') + fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','a') + groupHandle = HDF5_openGroup(fileHandle,'solver') call HDF5_write(T,groupHandle,'T') call HDF5_write(T_lastInc,groupHandle,'T_lastInc') call HDF5_closeGroup(groupHandle) From e8c39077df2c0cdda72987756ea712224b6b69aa Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 26 Jan 2022 06:26:37 +0100 Subject: [PATCH 04/36] optional is usually not needed --- python/damask/_table.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/damask/_table.py b/python/damask/_table.py index fed309439..d20372d2e 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -1,7 +1,7 @@ import re import copy from pathlib import Path -from typing import Union, Optional, Tuple, List +from typing import Union, Tuple, List import pandas as pd import numpy as np @@ -12,7 +12,7 @@ from . import util class Table: """Manipulate multi-dimensional spreadsheet-like data.""" - def __init__(self, data: np.ndarray, shapes: dict, comments: Optional[Union[str, list]] = None): + def __init__(self, data: np.ndarray, shapes: dict, comments: Union[str, list] = None): """ New spreadsheet. @@ -147,7 +147,7 @@ class Table: self.data.columns = self._label(self.shapes,how) #type: ignore - def _add_comment(self, label: str, shape: Tuple[int, ...], info: Optional[str]): + def _add_comment(self, label: str, shape: Tuple[int, ...], info: str = None): if info is not None: specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}' general = util.execution_stamp('Table') From 0c21b6a8e0aa7a221e29908560be4590f4ffe5f3 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 26 Jan 2022 16:25:27 +0100 Subject: [PATCH 05/36] [skip ci] changed almost all function definition lines to multiline for colormap, grid, table, vtk and util modules --- python/damask/_colormap.py | 3 ++- python/damask/_grid.py | 47 +++++++++++++++++++++++++---------- python/damask/_table.py | 51 ++++++++++++++++++++++++++++---------- python/damask/_vtk.py | 34 ++++++++++++++++++------- python/damask/util.py | 37 +++++++++++++++++++-------- 5 files changed, 126 insertions(+), 46 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 93bd83cdc..30ae2677e 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -161,7 +161,8 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod - def from_predefined(name: str, N: int = 256) -> 'Colormap': + def from_predefined(name: str, + N: int = 256) -> 'Colormap': """ Select from a set of predefined colormaps. diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 94f7eefd0..c62d00cbb 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -101,7 +101,8 @@ class Grid: return self._material @material.setter - def material(self, material: np.ndarray): + def material(self, + material: np.ndarray): if len(material.shape) != 3: raise ValueError(f'invalid material shape {material.shape}') elif material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: @@ -120,7 +121,8 @@ class Grid: return self._size @size.setter - def size(self, size: FloatSequence): + def size(self, + size: FloatSequence): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') else: @@ -132,7 +134,8 @@ class Grid: return self._origin @origin.setter - def origin(self, origin: FloatSequence): + def origin(self, + origin: FloatSequence): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') else: @@ -144,7 +147,8 @@ class Grid: return self._comments @comments.setter - def comments(self, comments: Union[str, Sequence[str]]): + def comments(self, + comments: Union[str, Sequence[str]]): self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] @@ -387,7 +391,9 @@ class Grid: @staticmethod - def _find_closest_seed(seeds: np.ndarray, weights: np.ndarray, point: np.ndarray) -> np.integer: + def _find_closest_seed(seeds: np.ndarray, + weights: np.ndarray, + point: np.ndarray) -> np.integer: return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) @staticmethod @@ -624,7 +630,9 @@ class Grid: ) - def save(self, fname: Union[str, Path], compress: bool = True): + def save(self, + fname: Union[str, Path], + compress: bool = True): """ Save as VTK image data file. @@ -643,7 +651,8 @@ class Grid: v.save(fname,parallel=False,compress=compress) - def save_ASCII(self, fname: Union[str, TextIO]): + def save_ASCII(self, + fname: Union[str, TextIO]): """ Save as geom file. @@ -770,7 +779,9 @@ 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. @@ -822,7 +833,9 @@ class Grid: ) - def flip(self, directions: Union[Literal['x', 'y', 'z'], Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': + def flip(self, + directions: Union[Literal['x', 'y', 'z'], + Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': """ Flip grid along given directions. @@ -852,7 +865,9 @@ 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. @@ -958,7 +973,9 @@ 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). @@ -1049,7 +1066,9 @@ 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. @@ -1150,7 +1169,9 @@ class Grid: ) - def get_grain_boundaries(self, periodic: bool = True, directions: Sequence[str] = 'xyz'): + def get_grain_boundaries(self, + periodic: bool = True, + directions: Sequence[str] = 'xyz'): """ Create VTK unstructured grid containing grain boundaries. diff --git a/python/damask/_table.py b/python/damask/_table.py index d20372d2e..16779b83d 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -12,7 +12,10 @@ from . import util class Table: """Manipulate multi-dimensional spreadsheet-like data.""" - def __init__(self, data: np.ndarray, shapes: dict, comments: Union[str, list] = None): + def __init__(self, + data: np.ndarray, + shapes: dict, + comments: Union[str, list] = None): """ New spreadsheet. @@ -41,7 +44,8 @@ class Table: return '\n'.join(['# '+c for c in self.comments])+'\n'+data_repr - def __getitem__(self, item: Union[slice, Tuple[slice, ...]]) -> 'Table': + def __getitem__(self, + item: Union[slice, Tuple[slice, ...]]) -> 'Table': """ Slice the Table according to item. @@ -100,7 +104,9 @@ class Table: copy = __copy__ - def _label(self, what: Union[str, List[str]], how: str) -> List[str]: + def _label(self, + what: Union[str, List[str]], + how: str) -> List[str]: """ Expand labels according to data shape. @@ -147,7 +153,10 @@ class Table: self.data.columns = self._label(self.shapes,how) #type: ignore - def _add_comment(self, label: str, shape: Tuple[int, ...], info: str = None): + def _add_comment(self, + label: str, + shape: Tuple[int, ...], + info: str = None): if info is not None: specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}' general = util.execution_stamp('Table') @@ -321,7 +330,8 @@ class Table: return list(self.shapes) - def get(self, label: str) -> np.ndarray: + def get(self, + label: str) -> np.ndarray: """ Get column data. @@ -341,7 +351,10 @@ class Table: return data.astype(type(data.flatten()[0])) - def set(self, label: str, data: np.ndarray, info: str = None) -> 'Table': + def set(self, + label: str, + data: np.ndarray, + info: str = None) -> 'Table': """ Set column data. @@ -374,7 +387,10 @@ class Table: return dup - def add(self, label: str, data: np.ndarray, info: str = None) -> 'Table': + def add(self, + label: str, + data: np.ndarray, + info: str = None) -> 'Table': """ Add column data. @@ -406,7 +422,8 @@ class Table: return dup - def delete(self, label: str) -> 'Table': + def delete(self, + label: str) -> 'Table': """ Delete column data. @@ -427,7 +444,10 @@ class Table: return dup - def rename(self, old: Union[str, List[str]], new: Union[str, List[str]], info: str = None) -> 'Table': + def rename(self, + old: Union[str, List[str]], + new: Union[str, List[str]], + info: str = None) -> 'Table': """ Rename column data. @@ -453,7 +473,9 @@ class Table: return dup - def sort_by(self, labels: Union[str, List[str]], ascending: Union[bool, List[bool]] = True) -> 'Table': + def sort_by(self, + labels: Union[str, List[str]], + ascending: Union[bool, List[bool]] = True) -> 'Table': """ Sort table by values of given labels. @@ -486,7 +508,8 @@ class Table: return dup - def append(self, other: 'Table') -> 'Table': + def append(self, + other: 'Table') -> 'Table': """ Append other table vertically (similar to numpy.vstack). @@ -511,7 +534,8 @@ class Table: return dup - def join(self, other: 'Table') -> 'Table': + def join(self, + other: 'Table') -> 'Table': """ Append other table horizontally (similar to numpy.hstack). @@ -538,7 +562,8 @@ class Table: return dup - def save(self, fname: FileHandle): + def save(self, + fname: FileHandle): """ Save as plain text file. diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 4e3f27e0e..601608520 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -22,7 +22,8 @@ class VTK: High-level interface to VTK. """ - def __init__(self, vtk_data: vtk.vtkDataSet): + def __init__(self, + vtk_data: vtk.vtkDataSet): """ New spatial visualization. @@ -38,7 +39,9 @@ class VTK: @staticmethod - def from_image_data(cells: IntSequence, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK': + def from_image_data(cells: IntSequence, + size: FloatSequence, + origin: FloatSequence = np.zeros(3)) -> 'VTK': """ Create VTK of type vtk.vtkImageData. @@ -68,7 +71,9 @@ class VTK: @staticmethod - def from_rectilinear_grid(grid: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK': + def from_rectilinear_grid(grid: np.ndarray, + size: FloatSequence, + origin: FloatSequence = np.zeros(3)) -> 'VTK': """ Create VTK of type vtk.vtkRectilinearGrid. @@ -100,7 +105,9 @@ class VTK: @staticmethod - def from_unstructured_grid(nodes: np.ndarray, connectivity: np.ndarray, cell_type: str) -> 'VTK': + def from_unstructured_grid(nodes: np.ndarray, + connectivity: np.ndarray, + cell_type: str) -> 'VTK': """ Create VTK of type vtk.vtkUnstructuredGrid. @@ -238,7 +245,11 @@ class VTK: def _write(writer): """Wrapper for parallel writing.""" writer.Write() - def save(self, fname: Union[str, Path], parallel: bool = True, compress: bool = True): + + def save(self, + fname: Union[str, Path], + parallel: bool = True, + compress: bool = True): """ Save as VTK file. @@ -284,7 +295,9 @@ class VTK: # Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data # Needs support for damask.Table - def add(self, data: Union[np.ndarray, np.ma.MaskedArray], label: str = None): + def add(self, + data: Union[np.ndarray, np.ma.MaskedArray], + label: str = None): """ Add data to either cells or points. @@ -331,7 +344,8 @@ class VTK: raise TypeError - def get(self, label: str) -> np.ndarray: + def get(self, + label: str) -> np.ndarray: """ Get either cell or point data. @@ -383,7 +397,8 @@ class VTK: return [] - def set_comments(self, comments: Union[str, List[str]]): + def set_comments(self, + comments: Union[str, List[str]]): """ Set comments. @@ -400,7 +415,8 @@ class VTK: self.vtk_data.GetFieldData().AddArray(s) - def add_comments(self, comments: Union[str, List[str]]): + def add_comments(self, + comments: Union[str, List[str]]): """ Add comments. diff --git a/python/damask/util.py b/python/damask/util.py index 2872762b9..7c1803e80 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -54,7 +54,8 @@ _colors = { #################################################################################################### # Functions #################################################################################################### -def srepr(msg, glue: str = '\n') -> str: +def srepr(msg, + glue: str = '\n') -> str: r""" Join items with glue string. @@ -148,7 +149,10 @@ def strikeout(msg) -> str: return _colors['crossout']+srepr(msg)+_colors['end_color'] -def run(cmd: str, wd: str = './', env: Dict[str, str] = None, timeout: int = None) -> Tuple[str, str]: +def run(cmd: str, + wd: str = './', + env: Dict[str, str] = None, + timeout: int = None) -> Tuple[str, str]: """ Run a command. @@ -373,14 +377,17 @@ def project_equal_area(vector: np.ndarray, 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] -def execution_stamp(class_name: str, function_name: str = None) -> str: +def execution_stamp(class_name: str, + function_name: str = None) -> str: """Timestamp the execution of a (function within a) class.""" now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z') _function_name = '' if function_name is None else f'.{function_name}' return f'damask.{class_name}{_function_name} v{version} ({now})' -def hybrid_IA(dist: np.ndarray, N: int, rng_seed = None) -> np.ndarray: +def hybrid_IA(dist: np.ndarray, + N: int, + rng_seed = None) -> np.ndarray: """ Hybrid integer approximation. @@ -473,7 +480,8 @@ def shapeshifter(fro: Tuple[int, ...], return fill[:-1] -def shapeblender(a: Tuple[int, ...], b: Tuple[int, ...]) -> Tuple[int, ...]: +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'. @@ -517,7 +525,8 @@ def extend_docstring(extra_docstring: str) -> Callable: return _decorator -def extended_docstring(f: Callable, extra_docstring: str) -> Callable: +def extended_docstring(f: Callable, + extra_docstring: str) -> Callable: """ Decorator: Combine another function's docstring with a given docstring. @@ -593,7 +602,9 @@ def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str: return cell_data_group -def Bravais_to_Miller(*, uvtw: np.ndarray = None, hkil: np.ndarray = None) -> np.ndarray: +def Bravais_to_Miller(*, + uvtw: np.ndarray = None, + hkil: np.ndarray = None) -> np.ndarray: """ Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). @@ -620,7 +631,9 @@ def Bravais_to_Miller(*, uvtw: np.ndarray = None, hkil: np.ndarray = None) -> np return np.einsum('il,...l',basis,axis) -def Miller_to_Bravais(*, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: +def Miller_to_Bravais(*, + uvw: np.ndarray = None, + hkl: np.ndarray = None) -> np.ndarray: """ Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil). @@ -710,7 +723,10 @@ class ProgressBar: Works for 0-based loops, ETA is estimated by linear extrapolation. """ - def __init__(self, total: int, prefix: str, bar_length: int): + def __init__(self, + total: int, + prefix: str, + bar_length: int): """ Set current time as basis for ETA estimation. @@ -733,7 +749,8 @@ class ProgressBar: sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a") sys.stderr.flush() - def update(self, iteration: int) -> None: + def update(self, + iteration: int) -> None: fraction = (iteration+1) / self.total filled_length = int(self.bar_length * fraction) From 8e514bf6f42dae2b012ba2cad432d28bbbd10dde Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 26 Jan 2022 16:36:26 +0100 Subject: [PATCH 06/36] added missing utils typehint --- python/damask/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index 7c1803e80..e1db35007 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -16,7 +16,7 @@ import numpy as np import h5py from . import version -from ._typehints import FloatSequence +from ._typehints import IntSequence, FloatSequence # limit visibility __all__=[ @@ -387,7 +387,7 @@ def execution_stamp(class_name: str, def hybrid_IA(dist: np.ndarray, N: int, - rng_seed = None) -> np.ndarray: + rng_seed: Union[int, IntSequence] = None) -> np.ndarray: """ Hybrid integer approximation. From bc667888ce196586f6b9588e7d50a186af0a5c1b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 26 Jan 2022 23:37:07 +0100 Subject: [PATCH 07/36] consistent style --- python/damask/_colormap.py | 33 ++++++++++++++++++++++----------- python/damask/_grid.py | 3 ++- python/damask/_table.py | 3 ++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 30ae2677e..5c77cf61e 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -47,27 +47,32 @@ class Colormap(mpl.colors.ListedColormap): """ - def __eq__(self, other: object) -> bool: + def __eq__(self, + other: object) -> bool: """Test equality of colormaps.""" if not isinstance(other, Colormap): return NotImplemented return len(self.colors) == len(other.colors) \ and bool(np.all(self.colors == other.colors)) - def __add__(self, other: 'Colormap') -> 'Colormap': + def __add__(self, + other: 'Colormap') -> 'Colormap': """Concatenate.""" return Colormap(np.vstack((self.colors,other.colors)), f'{self.name}+{other.name}') - def __iadd__(self, other: 'Colormap') -> 'Colormap': + def __iadd__(self, + other: 'Colormap') -> 'Colormap': """Concatenate (in-place).""" return self.__add__(other) - def __mul__(self, factor: int) -> 'Colormap': + def __mul__(self, + factor: int) -> 'Colormap': """Repeat.""" return Colormap(np.vstack([self.colors]*factor),f'{self.name}*{factor}') - def __imul__(self, factor: int) -> 'Colormap': + def __imul__(self, + factor: int) -> 'Colormap': """Repeat (in-place).""" return self.__mul__(factor) @@ -276,7 +281,8 @@ class Colormap(mpl.colors.ListedColormap): mode='RGBA') - def reversed(self, name: str = None) -> 'Colormap': + def reversed(self, + name: str = None) -> 'Colormap': """ Reverse. @@ -329,7 +335,8 @@ class Colormap(mpl.colors.ListedColormap): return fname - def save_paraview(self, fname: FileHandle = None): + def save_paraview(self, + fname: FileHandle = None): """ Save as JSON file for use in Paraview. @@ -356,7 +363,8 @@ class Colormap(mpl.colors.ListedColormap): fhandle.write('\n') - def save_ASCII(self, fname: FileHandle = None): + def save_ASCII(self, + fname: FileHandle = None): """ Save as ASCII file. @@ -391,7 +399,8 @@ class Colormap(mpl.colors.ListedColormap): self._get_file_handle(fname,'.legend').write(GOM_str) - def save_gmsh(self, fname: FileHandle = None): + def save_gmsh(self, + fname: FileHandle = None): """ Save as ASCII file for use in gmsh. @@ -622,7 +631,8 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod - def _lab2xyz(lab: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: + def _lab2xyz(lab: np.ndarray, + ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: """ CIE Lab to CIE Xyz. @@ -653,7 +663,8 @@ class Colormap(mpl.colors.ListedColormap): ])*ref_white @staticmethod - def _xyz2lab(xyz: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: + def _xyz2lab(xyz: np.ndarray, + ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: """ CIE Xyz to CIE Lab. diff --git a/python/damask/_grid.py b/python/damask/_grid.py index c62d00cbb..b188873a4 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -77,7 +77,8 @@ class Grid: copy = __copy__ - def __eq__(self, other: object) -> bool: + def __eq__(self, + other: object) -> bool: """ Test equality of other. diff --git a/python/damask/_table.py b/python/damask/_table.py index 16779b83d..44a04b40a 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -137,7 +137,8 @@ class Table: return labels - def _relabel(self, how: str): + def _relabel(self, + how: str): """ Modify labeling of data in-place. From 4ca501c73f221924729d695cd0e73dae004e200e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 27 Jan 2022 08:53:27 +0100 Subject: [PATCH 08/36] small changes in logic for type hints --- python/damask/_crystal.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index 7a21f9245..a8b2ccf79 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -33,9 +33,9 @@ class Crystal(): def __init__(self,*, family = None, lattice = None, - a = None,b = None,c = None, - alpha = None,beta = None,gamma = None, - degrees = False): + a: float = None, b: float = None, c: float = None, + alpha: float = None, beta: float = None, gamma: float = None, + degrees: bool = False): """ Representation of crystal in terms of crystal family or Bravais lattice. @@ -62,7 +62,7 @@ class Crystal(): Angles are given in degrees. Defaults to False. """ - if family not in [None] + list(lattice_symmetries.values()): + if family is not None and family not in list(lattice_symmetries.values()): raise KeyError(f'invalid crystal family "{family}"') if lattice is not None and family is not None and family != lattice_symmetries[lattice]: raise KeyError(f'incompatible family "{family}" for lattice "{lattice}"') @@ -107,9 +107,6 @@ class Crystal(): if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0] >= np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]): raise ValueError ('each lattice angle must be less than sum of others') - else: - self.a = self.b = self.c = None - self.alpha = self.beta = self.gamma = None def __repr__(self): @@ -139,8 +136,7 @@ class Crystal(): @property def parameters(self): """Return lattice parameters a, b, c, alpha, beta, gamma.""" - return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) - + if hasattr(self,'a'): return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) @property def immutable(self): @@ -269,7 +265,7 @@ class Crystal(): https://doi.org/10.1063/1.1661333 """ - if None in self.parameters: + if self.parameters is None: raise KeyError('missing crystal lattice parameters') return np.array([ [1,0,0], From a12135fe7786b2ca0ca90a9bf2c7cb48a801f1c0 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Thu, 27 Jan 2022 10:45:14 +0100 Subject: [PATCH 09/36] [skip ci] changed function definition to multiline layout for crystal, seeds and tensor module --- python/damask/_crystal.py | 15 +++++++++++---- python/damask/seeds.py | 19 ++++++++++++++----- python/damask/tensor.py | 6 ++++-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index a8b2ccf79..c97f75d01 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -311,7 +311,9 @@ class Crystal(): + _lattice_points.get(self.lattice if self.lattice == 'hP' else \ self.lattice[-1],None),dtype=float) - def to_lattice(self, *, direction: np.ndarray = None, plane: np.ndarray = None) -> np.ndarray: + def to_lattice(self, + *, direction: np.ndarray = None, + plane: np.ndarray = None) -> np.ndarray: """ Calculate lattice vector corresponding to crystal frame direction or plane normal. @@ -335,7 +337,10 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def to_frame(self, *, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: + def to_frame(self, + *, + uvw: np.ndarray = None, + hkl: np.ndarray = None) -> np.ndarray: """ Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl). @@ -358,7 +363,8 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def kinematics(self, mode: str) -> Dict[str, List[np.ndarray]]: + def kinematics(self, + mode: str) -> Dict[str, List[np.ndarray]]: """ Return crystal kinematics systems. @@ -617,7 +623,8 @@ class Crystal(): 'plane': [m[:,3:6] for m in master]} - def relation_operations(self, model: str) -> Tuple[str, Rotation]: + def relation_operations(self, + model: str) -> Tuple[str, Rotation]: """ Crystallographic orientation relationships for phase transformations. diff --git a/python/damask/seeds.py b/python/damask/seeds.py index e6d1f9613..1a3af7a64 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -10,7 +10,9 @@ from . import util as _util from . import grid_filters as _grid_filters -def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None, +def from_random(size: _FloatSequence, + N_seeds: int, + cells: _IntSequence = None, rng_seed=None) -> _np.ndarray: """ Place seeds randomly in space. @@ -46,8 +48,12 @@ def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None, return coords -def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, distance: float, - periodic: bool = True, rng_seed=None) -> _np.ndarray: +def from_Poisson_disc(size: _FloatSequence, + N_seeds: int, + N_candidates: int, + distance: float, + periodic: bool = True, + rng_seed=None) -> _np.ndarray: """ Place seeds according to a Poisson disc distribution. @@ -99,8 +105,11 @@ def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, dis return coords -def from_grid(grid, selection: _IntSequence = None, invert_selection: bool = False, - average: bool = False, periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]: +def from_grid(grid, + selection: _IntSequence = None, + invert_selection: bool = False, + average: bool = False, + periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]: """ Create seeds from grid description. diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 4f6cb36ea..73cdd7400 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -45,7 +45,8 @@ def eigenvalues(T_sym: _np.ndarray) -> _np.ndarray: return _np.linalg.eigvalsh(symmetric(T_sym)) -def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray: +def eigenvectors(T_sym: _np.ndarray, + RHS: bool = False) -> _np.ndarray: """ Eigenvectors of a symmetric tensor. @@ -70,7 +71,8 @@ def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray: return v -def spherical(T: _np.ndarray, tensor: bool = True) -> _np.ndarray: +def spherical(T: _np.ndarray, + tensor: bool = True) -> _np.ndarray: """ Calculate spherical part of a tensor. From 19a73bbf3b50a61ca866c8a9d3d805eb6df36bf5 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Thu, 27 Jan 2022 12:14:54 +0100 Subject: [PATCH 10/36] [skip ci] adjusted function argument alignment with asterisk --- python/damask/_crystal.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index c97f75d01..e42622210 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -311,8 +311,8 @@ class Crystal(): + _lattice_points.get(self.lattice if self.lattice == 'hP' else \ self.lattice[-1],None),dtype=float) - def to_lattice(self, - *, direction: np.ndarray = None, + def to_lattice(self, *, + direction: np.ndarray = None, plane: np.ndarray = None) -> np.ndarray: """ Calculate lattice vector corresponding to crystal frame direction or plane normal. @@ -337,8 +337,7 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def to_frame(self, - *, + def to_frame(self, *, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: """ From e2437ee9b556b72fbed947b9f908a5b38f4164a0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 27 Jan 2022 15:29:33 +0100 Subject: [PATCH 11/36] adjusting style + documentation --- python/damask/_crystal.py | 5 ++++- python/damask/mechanics.py | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index e42622210..0b1c00458 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -119,7 +119,8 @@ class Crystal(): 'α={:.5g}°, β={:.5g}°, γ={:.5g}°'.format(*np.degrees(self.parameters[3:]))]) - def __eq__(self,other): + def __eq__(self, + other: object) -> bool: """ Equal to other. @@ -129,6 +130,8 @@ class Crystal(): Crystal to check for equality. """ + if not isinstance(other, Crystal): + return NotImplemented return self.lattice == other.lattice and \ self.parameters == other.parameters and \ self.family == other.family diff --git a/python/damask/mechanics.py b/python/damask/mechanics.py index 7c1af6c5f..65ec1ef3b 100644 --- a/python/damask/mechanics.py +++ b/python/damask/mechanics.py @@ -122,7 +122,9 @@ def rotation(T: _np.ndarray) -> _rotation.Rotation: return _rotation.Rotation.from_matrix(_polar_decomposition(T,'R')[0]) -def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray: +def strain(F: _np.ndarray, + t: str, + m: float) -> _np.ndarray: """ Calculate strain tensor (Seth–Hill family). @@ -162,7 +164,8 @@ def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray: return eps -def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: +def stress_Cauchy(P: _np.ndarray, + F: _np.ndarray) -> _np.ndarray: """ Calculate the Cauchy stress (true stress). @@ -184,7 +187,8 @@ def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: return _tensor.symmetric(_np.einsum('...,...ij,...kj',1.0/_np.linalg.det(F),P,F)) -def stress_second_Piola_Kirchhoff(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: +def stress_second_Piola_Kirchhoff(P: _np.ndarray, + F: _np.ndarray) -> _np.ndarray: """ Calculate the second Piola-Kirchhoff stress. @@ -243,7 +247,8 @@ def stretch_right(T: _np.ndarray) -> _np.ndarray: return _polar_decomposition(T,'U')[0] -def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: +def _polar_decomposition(T: _np.ndarray, + requested: _Sequence[str]) -> tuple: """ Perform singular value decomposition. @@ -251,7 +256,7 @@ def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: ---------- T : numpy.ndarray, shape (...,3,3) Tensor of which the singular values are computed. - requested : iterable of str + requested : sequence of {'R', 'U', 'V'} Requested outputs: ‘R’ for the rotation tensor, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. @@ -273,7 +278,8 @@ def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: return tuple(output) -def _equivalent_Mises(T_sym: _np.ndarray, s: float) -> _np.ndarray: +def _equivalent_Mises(T_sym: _np.ndarray, + s: float) -> _np.ndarray: """ Base equation for Mises equivalent of a stress or strain tensor. From 609f13c590ea29c0ce835e023d468767be94b8cb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 18:16:19 +0100 Subject: [PATCH 12/36] Python 3.8 magic: The walrus operator ":=" --- python/damask/_colormap.py | 4 +--- python/damask/_grid.py | 15 +++++---------- python/damask/_table.py | 9 +++------ python/damask/_vtk.py | 5 ++--- python/damask/seeds.py | 5 ++--- python/damask/tensor.py | 3 +-- python/damask/util.py | 3 +-- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 5c77cf61e..e7982ec52 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -266,9 +266,7 @@ class Colormap(mpl.colors.ListedColormap): l,r = (field[mask].min(),field[mask].max()) if bounds is None else \ (bounds[0],bounds[1]) - delta,avg = r-l,0.5*abs(r+l) - - if abs(delta) * 1e8 <= avg: # delta is similar to numerical noise + if abs(delta := r-l) * 1e8 <= (avg := 0.5*abs(r+l)): # delta is similar to numerical noise l,r = l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta), # extend range to have actual data centered within return Image.fromarray( diff --git a/python/damask/_grid.py b/python/damask/_grid.py index b188873a4..639b4e91f 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -234,8 +234,7 @@ class Grid: content = f.readlines() for i,line in enumerate(content[:header_length]): items = line.split('#')[0].lower().strip().split() - key = items[0] if items else '' - if key == 'grid': + if (key := items[0] if items else '') == 'grid': cells = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) elif key == 'size': size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) @@ -247,8 +246,7 @@ class Grid: material = np.empty(int(cells.prod())) # initialize as flat array i = 0 for line in content[header_length:]: - items = line.split('#')[0].split() - if len(items) == 3: + if len(items := line.split('#')[0].split()) == 3: if items[1].lower() == 'of': material_entry = np.ones(int(items[0]))*float(items[2]) elif items[1].lower() == 'to': @@ -813,8 +811,7 @@ class Grid: # materials: 1 """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') limits: Sequence[Optional[int]] = [None,None] if reflect else [-2,0] @@ -852,8 +849,7 @@ class Grid: Updated grid-based geometry. """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') @@ -1190,8 +1186,7 @@ class Grid: VTK-based geometry of grain boundary network. """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') o = [[0, self.cells[0]+1, np.prod(self.cells[:2]+1)+self.cells[0]+1, np.prod(self.cells[:2]+1)], diff --git a/python/damask/_table.py b/python/damask/_table.py index 44a04b40a..bd82dc134 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -319,8 +319,7 @@ class Table: data = np.loadtxt(content) shapes = {'eu':3, 'pos':2, 'IQ':1, 'CI':1, 'ID':1, 'intensity':1, 'fit':1} - remainder = data.shape[1]-sum(shapes.values()) - if remainder > 0: # 3.8 can do: if (remainder := data.shape[1]-sum(shapes.values())) > 0 + if (remainder := data.shape[1]-sum(shapes.values())) > 0: shapes['unknown'] = remainder return Table(data,shapes,comments) @@ -376,8 +375,7 @@ class Table: """ dup = self.copy() dup._add_comment(label, data.shape[1:], info) - m = re.match(r'(.*)\[((\d+,)*(\d+))\]',label) - if m: + if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',label): key = m.group(1) idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(","))), self.shapes[key]) @@ -495,8 +493,7 @@ class Table: """ labels_ = [labels] if isinstance(labels,str) else labels.copy() for i,l in enumerate(labels_): - m = re.match(r'(.*)\[((\d+,)*(\d+))\]',l) - if m: + if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',l): idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(','))), self.shapes[m.group(1)]) labels_[i] = f'{1+idx}_{m.group(1)}' diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 601608520..8247bb6c8 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -22,7 +22,7 @@ class VTK: High-level interface to VTK. """ - def __init__(self, + def __init__(self, vtk_data: vtk.vtkDataSet): """ New spatial visualization. @@ -202,8 +202,7 @@ class VTK: """ if not os.path.isfile(fname): # vtk has a strange error handling raise FileNotFoundError(f'No such file: {fname}') - ext = Path(fname).suffix - if ext == '.vtk' or dataset_type is not None: + if (ext := Path(fname).suffix) == '.vtk' or dataset_type is not None: reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(str(fname)) if dataset_type is None: diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 1a3af7a64..47e34d871 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -92,10 +92,9 @@ def from_Poisson_disc(size: _FloatSequence, tree = _spatial.cKDTree(coords[:s],boxsize=size) if periodic else \ _spatial.cKDTree(coords[:s]) distances = tree.query(candidates)[0] - best = distances.argmax() - if distances[best] > distance: # require minimum separation + if distances.max() > distance: # require minimum separation i = 0 - coords[s] = candidates[best] # maximum separation to existing point cloud + coords[s] = candidates[distances.argmax()] # maximum separation to existing point cloud s += 1 progress.update(s) diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 73cdd7400..0e2118002 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -66,8 +66,7 @@ def eigenvectors(T_sym: _np.ndarray, """ (u,v) = _np.linalg.eigh(symmetric(T_sym)) - if RHS: - v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 + if RHS: v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 return v diff --git a/python/damask/util.py b/python/damask/util.py index e1db35007..c042e4dd4 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -753,9 +753,8 @@ class ProgressBar: iteration: int) -> None: fraction = (iteration+1) / self.total - filled_length = int(self.bar_length * fraction) - if filled_length > int(self.bar_length * self.fraction_last) or \ + if filled_length := int(self.bar_length * fraction) > int(self.bar_length * self.fraction_last) or \ datetime.datetime.now() - self.time_last_update > datetime.timedelta(seconds=10): self.time_last_update = datetime.datetime.now() bar = '█' * filled_length + '░' * (self.bar_length - filled_length) From 03b0decfcfe6d0fa35f7b1222d77ba202af4d402 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 18:32:04 +0100 Subject: [PATCH 13/36] starting to configure mypy --- python/mypy.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/mypy.ini b/python/mypy.ini index 01001daa6..5ef04daee 100644 --- a/python/mypy.ini +++ b/python/mypy.ini @@ -1,3 +1,5 @@ +[mypy] +warn_redundant_casts = True [mypy-scipy.*] ignore_missing_imports = True [mypy-h5py.*] From ce4591fa29f4066451d6b3e3cde4e5a5ff1c28a3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 19:10:12 +0100 Subject: [PATCH 14/36] silence prospector on Python 3.9 --- python/damask/_colormap.py | 2 +- python/damask/_vtk.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index e7982ec52..9d9776821 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -484,7 +484,7 @@ class Colormap(mpl.colors.ListedColormap): 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']} - _predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], + _predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], # noqa 'high': [0.250980,0.007843,0.000000]}, 'strain': {'low': [0.941177,0.941177,0.870588], 'high': [0.266667,0.266667,0.000000]}, diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 8247bb6c8..3d9e5011c 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -455,7 +455,7 @@ class VTK: width = tk.winfo_screenwidth() height = tk.winfo_screenheight() tk.destroy() - except Exception as e: + except Exception: width = 1024 height = 768 From df96110733c85da52615c8f1b05794c0ac95e2cc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 22:38:17 +0100 Subject: [PATCH 15/36] some suggestions from prospector/pylint --- python/damask/_colormap.py | 18 +++++++++--------- python/damask/_grid.py | 24 ++++++++++++------------ python/damask/_table.py | 22 +++++++++++----------- python/damask/tensor.py | 2 +- python/damask/util.py | 26 +++++++++++++------------- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 9d9776821..005cf80d6 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -267,7 +267,7 @@ class Colormap(mpl.colors.ListedColormap): (bounds[0],bounds[1]) if abs(delta := r-l) * 1e8 <= (avg := 0.5*abs(r+l)): # delta is similar to numerical noise - l,r = l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta), # extend range to have actual data centered within + l,r = (l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta)) # extend range to have actual data centered within return Image.fromarray( (np.dstack(( @@ -301,7 +301,7 @@ class Colormap(mpl.colors.ListedColormap): >>> damask.Colormap.from_predefined('stress').reversed() """ - rev = super(Colormap,self).reversed(name) + rev = super().reversed(name) return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name) @@ -436,11 +436,11 @@ class Colormap(mpl.colors.ListedColormap): def adjust_hue(msh_sat, msh_unsat): """If saturation of one of the two colors is much less than the other, hue of the less.""" if msh_sat[0] >= msh_unsat[0]: - return msh_sat[2] - else: - hSpin = msh_sat[1]/np.sin(msh_sat[1])*np.sqrt(msh_unsat[0]**2.0-msh_sat[0]**2)/msh_sat[0] - if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0 - return msh_sat[2] + hSpin + return msh_sat[2] + + hSpin = msh_sat[1]/np.sin(msh_sat[1])*np.sqrt(msh_unsat[0]**2.0-msh_sat[0]**2)/msh_sat[0] + if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0 + return msh_sat[2] + hSpin lo = np.array(low) hi = np.array(high) @@ -453,9 +453,9 @@ class Colormap(mpl.colors.ListedColormap): else: lo = np.array([M_mid,0.0,0.0]) frac = 2.0*frac - 1.0 - if lo[1] < 0.05 and hi[1] > 0.05: + if lo[1] < 0.05 < hi[1]: lo[2] = adjust_hue(hi,lo) - elif lo[1] > 0.05 and hi[1] < 0.05: + elif hi[1] < 0.05 < lo[1]: hi[2] = adjust_hue(lo,hi) return (1.0 - frac) * lo + frac * hi diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 639b4e91f..0b3a067e2 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -33,7 +33,7 @@ class Grid: material: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3), - comments: Union[str, Sequence[str]] = []): + comments: Union[str, Sequence[str]] = None): """ New geometry definition for grid solvers. @@ -53,7 +53,7 @@ class Grid: self.material = material self.size = size # type: ignore self.origin = origin # type: ignore - self.comments = comments # type: ignore + self.comments = [] if comments is None else comments # type: ignore def __repr__(self) -> str: @@ -106,14 +106,14 @@ class Grid: material: np.ndarray): if len(material.shape) != 3: raise ValueError(f'invalid material shape {material.shape}') - elif material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: + if material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: raise TypeError(f'invalid material data type {material.dtype}') - else: - self._material = np.copy(material) - if self.material.dtype in np.sctypes['float'] and \ - np.all(self.material == self.material.astype(int).astype(float)): - self._material = self.material.astype(int) + self._material = np.copy(material) + + if self.material.dtype in np.sctypes['float'] and \ + np.all(self.material == self.material.astype(int).astype(float)): + self._material = self.material.astype(int) @property @@ -126,8 +126,8 @@ class Grid: size: FloatSequence): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') - else: - self._size = np.array(size) + + self._size = np.array(size) @property def origin(self) -> np.ndarray: @@ -139,8 +139,8 @@ class Grid: origin: FloatSequence): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') - else: - self._origin = np.array(origin) + + self._origin = np.array(origin) @property def comments(self) -> List[str]: diff --git a/python/damask/_table.py b/python/damask/_table.py index bd82dc134..1572c4f76 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -14,7 +14,7 @@ class Table: def __init__(self, data: np.ndarray, - shapes: dict, + shapes: dict, comments: Union[str, list] = None): """ New spreadsheet. @@ -526,10 +526,10 @@ class Table: """ if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns): raise KeyError('Labels or shapes or order do not match') - else: - dup = self.copy() - dup.data = dup.data.append(other.data,ignore_index=True) - return dup + + dup = self.copy() + dup.data = dup.data.append(other.data,ignore_index=True) + return dup def join(self, @@ -552,12 +552,12 @@ class Table: """ if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]: raise KeyError('Duplicated keys or row count mismatch') - else: - dup = self.copy() - dup.data = dup.data.join(other.data) - for key in other.shapes: - dup.shapes[key] = other.shapes[key] - return dup + + dup = self.copy() + dup.data = dup.data.join(other.data) + for key in other.shapes: + dup.shapes[key] = other.shapes[key] + return dup def save(self, diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 0e2118002..63eb15b99 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -64,7 +64,7 @@ def eigenvectors(T_sym: _np.ndarray, associated eigenvalues. """ - (u,v) = _np.linalg.eigh(symmetric(T_sym)) + _,v = _np.linalg.eigh(symmetric(T_sym)) if RHS: v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 return v diff --git a/python/damask/util.py b/python/damask/util.py index c042e4dd4..0cf6606fb 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -7,7 +7,7 @@ import subprocess import shlex import re import fractions -import collections.abc as abc +from collections import abc from functools import reduce from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, Optional from pathlib import Path @@ -77,7 +77,7 @@ def srepr(msg, hasattr(msg, '__iter__'))): return glue.join(str(x) for x in msg) else: - return msg if isinstance(msg,str) else repr(msg) + return msg if isinstance(msg,str) else repr(msg) def emph(msg) -> str: @@ -230,15 +230,15 @@ def show_progress(iterable: Iterable, """ if isinstance(iterable,abc.Sequence): - if N_iter is None: - N = len(iterable) - else: - raise ValueError('N_iter given for 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_iter is None: + raise ValueError('N_iter not given') + + N = N_iter if N <= 1: for item in iterable: @@ -454,7 +454,7 @@ def shapeshifter(fro: Tuple[int, ...], """ - if not len(fro) and not len(to): return () + if len(fro) == 0 and len(to) == 0: return () beg = dict(left ='(^.*\\b)', right='(^.*?\\b)') @@ -462,8 +462,8 @@ def shapeshifter(fro: Tuple[int, ...], right='(.*?\\b)') end = dict(left ='(.*?$)', right='(.*$)') - fro = (1,) if not len(fro) else fro - to = (1,) if not len(to) else to + fro = (1,) if len(fro) == 0 else fro + to = (1,) if len(to) == 0 else to try: match = re.match(beg[mode] +f',{sep[mode]}'.join(map(lambda x: f'{x}' From 9ce4573b12660fcbcb7be092df4fe829ccfff3b8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 23:16:57 +0100 Subject: [PATCH 16/36] docstring polishing --- python/damask/_grid.py | 13 +++++-------- python/damask/util.py | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 0b3a067e2..b08f99757 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -786,9 +786,8 @@ class Grid: Parameters ---------- - directions : (sequence of) str + directions : (sequence of) {'x', 'y', 'z'} Direction(s) along which the grid is mirrored. - Valid entries are 'x', 'y', 'z'. reflect : bool, optional Reflect (include) outermost layers. Defaults to False. @@ -832,16 +831,14 @@ class Grid: def flip(self, - directions: Union[Literal['x', 'y', 'z'], - Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': + directions: Sequence[str]) -> 'Grid': """ Flip grid along given directions. Parameters ---------- - directions : (sequence of) str + directions : (sequence of) {'x', 'y', 'z'} Direction(s) along which the grid is flipped. - Valid entries are 'x', 'y', 'z'. Returns ------- @@ -1176,9 +1173,9 @@ class Grid: ---------- periodic : bool, optional Assume grid to be periodic. Defaults to True. - directions : (sequence of) string, optional + directions : (sequence of) {'x', 'y', 'z'}, optional Direction(s) along which the boundaries are determined. - Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'. + Defaults to 'xyz'. Returns ------- diff --git a/python/damask/util.py b/python/damask/util.py index 0cf6606fb..0bbc1e7b5 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -305,16 +305,20 @@ def project_equal_angle(vector: np.ndarray, normalize : bool Ensure unit length of input vector. Defaults to True. keepdims : bool - Maintain three-dimensional output coordinates. Defaults to False. - Two-dimensional output uses right-handed frame spanned by - the next and next-next axis relative to the projection direction, - e.g. x-y when projecting along z and z-x when projecting along y. + Maintain three-dimensional output coordinates. + Defaults to False. Returns ------- coordinates : numpy.ndarray, shape (...,2 | 3) Projected coordinates. + Notes + ----- + Two-dimensional output uses right-handed frame spanned by + the next and next-next axis relative to the projection direction, + e.g. x-y when projecting along z and z-x when projecting along y. + Examples -------- >>> import damask @@ -349,16 +353,21 @@ def project_equal_area(vector: np.ndarray, normalize : bool Ensure unit length of input vector. Defaults to True. keepdims : bool - Maintain three-dimensional output coordinates. Defaults to False. - Two-dimensional output uses right-handed frame spanned by - the next and next-next axis relative to the projection direction, - e.g. x-y when projecting along z and z-x when projecting along y. + Maintain three-dimensional output coordinates. + Defaults to False. Returns ------- coordinates : numpy.ndarray, shape (...,2 | 3) Projected coordinates. + Notes + ----- + Two-dimensional output uses right-handed frame spanned by + the next and next-next axis relative to the projection direction, + e.g. x-y when projecting along z and z-x when projecting along y. + + Examples -------- >>> import damask From a479c2971478325b2677c2000f40e6d7a30f5c5b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 30 Jan 2022 15:46:26 +0100 Subject: [PATCH 17/36] not used --- python/damask/_grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index b08f99757..f5c06df1b 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -4,7 +4,7 @@ import warnings import multiprocessing as mp from functools import partial import typing -from typing import Union, Optional, TextIO, List, Sequence, Literal +from typing import Union, Optional, TextIO, List, Sequence from pathlib import Path import numpy as np From 26cd8a46c2e10e6416705713a4ea273a4fd0eb30 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 30 Jan 2022 22:36:30 +0100 Subject: [PATCH 18/36] consistent style --- python/damask/grid_filters.py | 43 ++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index d9d658d0b..e2178a4b6 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -20,7 +20,9 @@ import numpy as _np from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence -def _ks(size: _FloatSequence, cells: _IntSequence, first_order: bool = False) -> _np.ndarray: +def _ks(size: _FloatSequence, + cells: _IntSequence, + first_order: bool = False) -> _np.ndarray: """ Get wave numbers operator. @@ -47,7 +49,8 @@ def _ks(size: _FloatSequence, cells: _IntSequence, first_order: bool = False) -> return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1) -def curl(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def curl(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate curl of a vector or tensor field in Fourier space. @@ -78,7 +81,8 @@ def curl(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3]) -def divergence(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def divergence(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate divergence of a vector or tensor field in Fourier space. @@ -105,7 +109,8 @@ def divergence(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3]) -def gradient(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def gradient(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate gradient of a scalar or vector field in Fourier space. @@ -163,7 +168,8 @@ def coordinates0_point(cells: _IntSequence, axis = -1) -def displacement_fluct_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_fluct_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from fluctuation part of the deformation gradient field. @@ -195,7 +201,8 @@ def displacement_fluct_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarra return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3]) -def displacement_avg_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_avg_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from average part of the deformation gradient field. @@ -216,7 +223,8 @@ def displacement_avg_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size)) -def displacement_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from deformation gradient field. @@ -236,7 +244,9 @@ def displacement_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return displacement_avg_point(size,F) + displacement_fluct_point(size,F) -def coordinates_point(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: +def coordinates_point(size: _FloatSequence, + F: _np.ndarray, + origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: """ Cell center positions. @@ -335,7 +345,8 @@ def coordinates0_node(cells: _IntSequence, axis = -1) -def displacement_fluct_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_fluct_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from fluctuation part of the deformation gradient field. @@ -355,7 +366,8 @@ def displacement_fluct_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray return point_to_node(displacement_fluct_point(size,F)) -def displacement_avg_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_avg_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from average part of the deformation gradient field. @@ -376,7 +388,8 @@ def displacement_avg_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size)) -def displacement_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from deformation gradient field. @@ -396,7 +409,9 @@ def displacement_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return displacement_avg_node(size,F) + displacement_fluct_node(size,F) -def coordinates_node(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: +def coordinates_node(size: _FloatSequence, + F: _np.ndarray, + origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: """ Nodal positions. @@ -526,7 +541,9 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool: return False -def regrid(size: _FloatSequence, F: _np.ndarray, cells: _IntSequence) -> _np.ndarray: +def regrid(size: _FloatSequence, + F: _np.ndarray, + cells: _IntSequence) -> _np.ndarray: """ Return mapping from coordinates in deformed configuration to a regular grid. From 3105b2c978548eb0965a8cd4b814c2927ddca1ec Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Mon, 31 Jan 2022 12:40:29 +0100 Subject: [PATCH 19/36] added missing return type to grid.get_grain_boundaries function --- python/damask/_grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index f5c06df1b..8a9a4bbd9 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -1165,7 +1165,7 @@ class Grid: def get_grain_boundaries(self, periodic: bool = True, - directions: Sequence[str] = 'xyz'): + directions: Sequence[str] = 'xyz') -> VTK: """ Create VTK unstructured grid containing grain boundaries. From 39aa24369547616fddca666b56fa9248ffe411e4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 31 Jan 2022 14:05:15 +0000 Subject: [PATCH 20/36] Polynomial Class --- src/CPFEM.f90 | 2 + src/CPFEM2.f90 | 2 + src/YAML_parse.f90 | 6 +- src/commercialFEM_fileList.f90 | 1 + src/material.f90 | 2 +- src/phase.f90 | 1 + src/phase_mechanical_elastic.f90 | 80 ++++---------- src/polynomials.f90 | 179 +++++++++++++++++++++++++++++++ 8 files changed, 211 insertions(+), 62 deletions(-) create mode 100644 src/polynomials.f90 diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index 8ee26ffe7..0f7590782 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -14,6 +14,7 @@ module CPFEM use config use math use rotations + use polynomials use lattice use material use phase @@ -83,6 +84,7 @@ subroutine CPFEM_initAll call config_init call math_init call rotations_init + call polynomials_init call lattice_init call discretization_marc_init call material_init(.false.) diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 647befd30..ed8fb611b 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -16,6 +16,7 @@ module CPFEM2 use config use math use rotations + use polynomials use lattice use material use phase @@ -57,6 +58,7 @@ subroutine CPFEM_initAll call config_init call math_init call rotations_init + call polynomials_init call lattice_init #if defined(MESH) call discretization_mesh_init(restart=interface_restartInc>0) diff --git a/src/YAML_parse.f90 b/src/YAML_parse.f90 index 9ebde963b..8a3264cff 100644 --- a/src/YAML_parse.f90 +++ b/src/YAML_parse.f90 @@ -191,8 +191,10 @@ logical function isScalar(line) character(len=*), intent(in) :: line - isScalar = (.not.isKeyValue(line) .and. .not.isKey(line) .and. .not.isListItem(line) & - .and. .not.isFlow(line)) + isScalar = (.not. isKeyValue(line) .and. & + .not. isKey(line) .and. & + .not. isListItem(line) .and. & + .not. isFlow(line)) end function isScalar diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index e67149dea..8dbbea706 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -14,6 +14,7 @@ #include "LAPACK_interface.f90" #include "math.f90" #include "rotations.f90" +#include "polynomials.f90" #include "lattice.f90" #include "element.f90" #include "geometry_plastic_nonlocal.f90" diff --git a/src/material.f90 b/src/material.f90 index 1e3a4b4ec..31eeef5e1 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -66,7 +66,7 @@ subroutine material_init(restart) print'(/,1x,a)', '<<<+- material init -+>>>'; flush(IO_STDOUT) - call parse + call parse() print'(/,1x,a)', 'parsed material.yaml' diff --git a/src/phase.f90 b/src/phase.f90 index 6035b4491..df7557a0b 100644 --- a/src/phase.f90 +++ b/src/phase.f90 @@ -8,6 +8,7 @@ module phase use constants use math use rotations + use polynomials use IO use config use material diff --git a/src/phase_mechanical_elastic.f90 b/src/phase_mechanical_elastic.f90 index 8972367d5..c57849b1f 100644 --- a/src/phase_mechanical_elastic.f90 +++ b/src/phase_mechanical_elastic.f90 @@ -1,15 +1,13 @@ submodule(phase:mechanical) elastic type :: tParameters - real(pReal),dimension(3) :: & - C_11 = 0.0_pReal, & - C_12 = 0.0_pReal, & - C_13 = 0.0_pReal, & - C_33 = 0.0_pReal, & - C_44 = 0.0_pReal, & - C_66 = 0.0_pReal - real(pReal) :: & - T_ref + type(tPolynomial) :: & + C_11, & + C_12, & + C_13, & + C_33, & + C_44, & + C_66 end type tParameters type(tParameters), allocatable, dimension(:) :: param @@ -47,35 +45,17 @@ module subroutine elastic_init(phases) associate(prm => param(ph)) - prm%T_ref = elastic%get_asFloat('T_ref', defaultVal=T_ROOM) - - prm%C_11(1) = elastic%get_asFloat('C_11') - prm%C_11(2) = elastic%get_asFloat('C_11,T', defaultVal=0.0_pReal) - prm%C_11(3) = elastic%get_asFloat('C_11,T^2',defaultVal=0.0_pReal) - - prm%C_12(1) = elastic%get_asFloat('C_12') - prm%C_12(2) = elastic%get_asFloat('C_12,T', defaultVal=0.0_pReal) - prm%C_12(3) = elastic%get_asFloat('C_12,T^2',defaultVal=0.0_pReal) - - prm%C_44(1) = elastic%get_asFloat('C_44') - prm%C_44(2) = elastic%get_asFloat('C_44,T', defaultVal=0.0_pReal) - prm%C_44(3) = elastic%get_asFloat('C_44,T^2',defaultVal=0.0_pReal) + prm%C_11 = polynomial(elastic%asDict(),'C_11','T') + prm%C_12 = polynomial(elastic%asDict(),'C_12','T') + prm%C_44 = polynomial(elastic%asDict(),'C_44','T') if (any(phase_lattice(ph) == ['hP','tI'])) then - prm%C_13(1) = elastic%get_asFloat('C_13') - prm%C_13(2) = elastic%get_asFloat('C_13,T', defaultVal=0.0_pReal) - prm%C_13(3) = elastic%get_asFloat('C_13,T^2',defaultVal=0.0_pReal) - - prm%C_33(1) = elastic%get_asFloat('C_33') - prm%C_33(2) = elastic%get_asFloat('C_33,T', defaultVal=0.0_pReal) - prm%C_33(3) = elastic%get_asFloat('C_33,T^2',defaultVal=0.0_pReal) + prm%C_13 = polynomial(elastic%asDict(),'C_13','T') + prm%C_33 = polynomial(elastic%asDict(),'C_33','T') end if - if (phase_lattice(ph) == 'tI') then - prm%C_66(1) = elastic%get_asFloat('C_66') - prm%C_66(2) = elastic%get_asFloat('C_66,T', defaultVal=0.0_pReal) - prm%C_66(3) = elastic%get_asFloat('C_66,T^2',defaultVal=0.0_pReal) - end if + if (phase_lattice(ph) == 'tI') & + prm%C_66 = polynomial(elastic%asDict(),'C_66','T') end associate end do @@ -97,38 +77,20 @@ pure module function elastic_C66(ph,en) result(C66) associate(prm => param(ph)) + C66 = 0.0_pReal T = thermal_T(ph,en) - C66(1,1) = prm%C_11(1) & - + prm%C_11(2)*(T - prm%T_ref) & - + prm%C_11(3)*(T - prm%T_ref)**2 - - C66(1,2) = prm%C_12(1) & - + prm%C_12(2)*(T - prm%T_ref) & - + prm%C_12(3)*(T - prm%T_ref)**2 - - C66(4,4) = prm%C_44(1) & - + prm%C_44(2)*(T - prm%T_ref) & - + prm%C_44(3)*(T - prm%T_ref)**2 - + C66(1,1) = prm%C_11%at(T) + C66(1,2) = prm%C_12%at(T) + C66(4,4) = prm%C_44%at(T) if (any(phase_lattice(ph) == ['hP','tI'])) then - C66(1,3) = prm%C_13(1) & - + prm%C_13(2)*(T - prm%T_ref) & - + prm%C_13(3)*(T - prm%T_ref)**2 - - C66(3,3) = prm%C_33(1) & - + prm%C_33(2)*(T - prm%T_ref) & - + prm%C_33(3)*(T - prm%T_ref)**2 - + C66(1,3) = prm%C_13%at(T) + C66(3,3) = prm%C_33%at(T) end if - if (phase_lattice(ph) == 'tI') then - C66(6,6) = prm%C_66(1) & - + prm%C_66(2)*(T - prm%T_ref) & - + prm%C_66(3)*(T - prm%T_ref)**2 - end if + if (phase_lattice(ph) == 'tI') C66(6,6) = prm%C_66%at(T) C66 = lattice_symmetrize_C66(C66,phase_lattice(ph)) diff --git a/src/polynomials.f90 b/src/polynomials.f90 new file mode 100644 index 000000000..49a46e2e4 --- /dev/null +++ b/src/polynomials.f90 @@ -0,0 +1,179 @@ +!-------------------------------------------------------------------------------------------------- +!> @author Martin Diehl, KU Leuven +!> @brief Polynomial representation for variable data +!-------------------------------------------------------------------------------------------------- +module polynomials + use prec + use IO + use YAML_parse + use YAML_types + + implicit none + private + + type, public :: tPolynomial + real(pReal), dimension(:), allocatable :: coef + real(pReal) :: x_ref + contains + procedure, public :: at => eval + procedure, public :: der1_at => eval_der1 + end type tPolynomial + + interface polynomial + module procedure polynomial_from_dict + module procedure polynomial_from_coef + end interface polynomial + + public :: & + polynomial, & + polynomials_init + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief Run self-test. +!-------------------------------------------------------------------------------------------------- +subroutine polynomials_init() + + print'(/,1x,a)', '<<<+- polynomials init -+>>>'; flush(IO_STDOUT) + + call selfTest() + +end subroutine polynomials_init + + +!-------------------------------------------------------------------------------------------------- +!> @brief Initialize a Polynomial from Coefficients. +!-------------------------------------------------------------------------------------------------- +function polynomial_from_coef(coef,x_ref) result(p) + + real(pReal), dimension(:), intent(in) :: coef + real(pReal), intent(in) :: x_ref + type(tPolynomial) :: p + + + allocate(p%coef(0:size(coef)-1),source=coef) ! should be zero based + p%x_ref = x_ref + +end function polynomial_from_coef + + +!-------------------------------------------------------------------------------------------------- +!> @brief Initialize a Polynomial from a Dictionary with Coefficients. +!-------------------------------------------------------------------------------------------------- +function polynomial_from_dict(dict,y,x) result(p) + + type(tDict), intent(in) :: dict + character(len=*), intent(in) :: y, x + type(tPolynomial) :: p + + real(pReal), dimension(:), allocatable :: coef + real(pReal) :: x_ref + + + allocate(coef(1),source=dict%get_asFloat(y)) + + if (dict%contains(y//','//x)) then + x_ref = dict%get_asFloat(x//'_ref') + coef = [coef,dict%get_asFloat(y//','//x)] + if (dict%contains(y//','//x//'^2')) then + coef = [coef,dict%get_asFloat(y//','//x//'^2')] + end if + else + x_ref = huge(0.0_pReal) ! Simplify debugging + end if + + p = Polynomial(coef,x_ref) + +end function polynomial_from_dict + + +!-------------------------------------------------------------------------------------------------- +!> @brief Evaluate a Polynomial. +!-------------------------------------------------------------------------------------------------- +pure function eval(self,x) result(y) + + class(tPolynomial), intent(in) :: self + real(pReal), intent(in) :: x + real(pReal) :: y + + integer :: i + + + y = self%coef(0) + do i = 1, ubound(self%coef,1) + y = y + self%coef(i) * (x-self%x_ref)**i + enddo + +end function eval + + +!-------------------------------------------------------------------------------------------------- +!> @brief Evaluate a first derivative of Polynomial. +!-------------------------------------------------------------------------------------------------- +pure function eval_der1(self,x) result(y) + + class(tPolynomial), intent(in) :: self + real(pReal), intent(in) :: x + real(pReal) :: y + + integer :: i + + + y = 0.0_pReal + do i = 1, ubound(self%coef,1) + y = y + real(i,pReal)*self%coef(i) * (x-self%x_ref)**(i-1) + enddo + +end function eval_der1 + + +!-------------------------------------------------------------------------------------------------- +!> @brief Check correctness of polynomical functionality. +!-------------------------------------------------------------------------------------------------- +subroutine selfTest + + type(tPolynomial) :: p1, p2 + real(pReal), dimension(3) :: coef + real(pReal) :: x_ref, x + class(tNode), pointer :: dict + character(len=pStringLen), dimension(3) :: coef_s + character(len=pStringLen) :: x_ref_s, x_s, YAML_s + + call random_number(coef) + call random_number(x_ref) + call random_number(x) + + coef = coef*10_pReal -0.5_pReal + x_ref = x_ref*10_pReal -0.5_pReal + x = x*10_pReal -0.5_pReal + + p1 = polynomial(coef,x_ref) + if (dNeq(p1%at(x_ref),coef(1))) error stop 'polynomial: @ref' + + write(coef_s(1),*) coef(1) + write(coef_s(2),*) coef(2) + write(coef_s(3),*) coef(3) + write(x_ref_s,*) x_ref + write(x_s,*) x + YAML_s = 'C: '//trim(adjustl(coef_s(1)))//IO_EOL//& + 'C,T: '//trim(adjustl(coef_s(2)))//IO_EOL//& + 'C,T^2: '//trim(adjustl(coef_s(3)))//IO_EOL//& + 'T_ref: '//trim(adjustl(x_ref_s))//IO_EOL + Dict => YAML_parse_str(trim(YAML_s)) + p2 = polynomial(dict%asDict(),'C','T') + if (dNeq(p1%at(x),p2%at(x),1.0e-12_pReal)) error stop 'polynomials: init' + + p1 = polynomial(coef*[0.0_pReal,1.0_pReal,0.0_pReal],x_ref) + if (dNeq(p1%at(x_ref+x),-p1%at(x_ref-x),1.0e-10_pReal)) error stop 'polynomials: eval(odd)' + if (dNeq(p1%der1_at(x),p1%der1_at(5.0_pReal*x),1.0e-10_pReal)) error stop 'polynomials: eval_der(odd)' + + p1 = polynomial(coef*[0.0_pReal,0.0_pReal,1.0_pReal],x_ref) + if (dNeq(p1%at(x_ref+x),p1%at(x_ref-x),1e-10_pReal)) error stop 'polynomials: eval(even)' + if (dNeq(p1%der1_at(x_ref+x),-p1%der1_at(x_ref-x),1e-10_pReal)) error stop 'polynomials: eval_der(even)' + + +end subroutine selfTest + +end module polynomials From 90b6b0e164a7cda9d5b27f82f672b9bc8dcebe2e Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 31 Jan 2022 17:16:01 +0100 Subject: [PATCH 21/36] [skip ci] updated version information after successful test of v3.0.0-alpha5-521-g30bf38641 --- python/damask/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/VERSION b/python/damask/VERSION index 750043c40..9c785bbbc 100644 --- a/python/damask/VERSION +++ b/python/damask/VERSION @@ -1 +1 @@ -v3.0.0-alpha5-518-g4fa97b9a3 +v3.0.0-alpha5-521-g30bf38641 From 98381bff2a1515e7a33a47c4977d65affb74a0ee Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 31 Jan 2022 20:14:24 +0100 Subject: [PATCH 22/36] [skip ci] updated version information after successful test of v3.0.0-alpha5-542-g225a5d908 --- python/damask/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/VERSION b/python/damask/VERSION index 9c785bbbc..92cb9dcb3 100644 --- a/python/damask/VERSION +++ b/python/damask/VERSION @@ -1 +1 @@ -v3.0.0-alpha5-521-g30bf38641 +v3.0.0-alpha5-542-g225a5d908 From 086ff42be58447056ed99480e2733029bf5f402a Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Tue, 1 Feb 2022 07:30:00 +0000 Subject: [PATCH 23/36] 05 Typehints config configmaterial --- python/damask/_config.py | 55 ++++++++++++++++++++++---------- python/damask/_configmaterial.py | 54 +++++++++++++++++++++---------- python/damask/util.py | 8 ++--- 3 files changed, 79 insertions(+), 38 deletions(-) diff --git a/python/damask/_config.py b/python/damask/_config.py index 2f5904cc6..5f7453b11 100644 --- a/python/damask/_config.py +++ b/python/damask/_config.py @@ -2,25 +2,34 @@ import copy from io import StringIO from collections.abc import Iterable import abc +from pathlib import Path +from typing import Union, Dict, Any, Type, TypeVar import numpy as np import yaml +from ._typehints import FileHandle from . import Rotation +MyType = TypeVar('MyType', bound='Config') + class NiceDumper(yaml.SafeDumper): """Make YAML readable for humans.""" - def write_line_break(self, data=None): + def write_line_break(self, + data: str = None): super().write_line_break(data) if len(self.indents) == 1: super().write_line_break() - def increase_indent(self, flow=False, indentless=False): + def increase_indent(self, + flow: bool = False, + indentless: bool = False): return super().increase_indent(flow, False) - def represent_data(self, data): + def represent_data(self, + data: Any): """Cast Config objects and its subclasses to dict.""" if isinstance(data, dict) and type(data) != dict: return self.represent_data(dict(data)) @@ -31,14 +40,17 @@ class NiceDumper(yaml.SafeDumper): else: return super().represent_data(data) - def ignore_aliases(self, data): + def ignore_aliases(self, + data: Any) -> bool: """Do not use references to existing objects.""" return True class Config(dict): """YAML-based configuration.""" - def __init__(self,yml=None,**kwargs): + def __init__(self, + yml: Union[str, Dict[str, Any]] = None, + **kwargs): """Initialize from YAML, dict, or key=value pairs.""" if isinstance(yml,str): kwargs.update(yaml.safe_load(yml)) @@ -47,7 +59,7 @@ class Config(dict): super().__init__(**kwargs) - def __repr__(self): + def __repr__(self) -> str: """Show as in file.""" output = StringIO() self.save(output) @@ -55,14 +67,15 @@ class Config(dict): return ''.join(output.readlines()) - def __copy__(self): + def __copy__(self: MyType) -> MyType: """Create deep copy.""" return copy.deepcopy(self) copy = __copy__ - def __or__(self,other): + def __or__(self: MyType, + other) -> MyType: """ Update configuration with contents of other. @@ -76,18 +89,24 @@ class Config(dict): updated : damask.Config Updated configuration. + Note + ---- + This functionality is a backport for Python 3.8 + """ duplicate = self.copy() duplicate.update(other) return duplicate - def __ior__(self,other): + def __ior__(self: MyType, + other) -> MyType: """Update configuration with contents of other.""" return self.__or__(other) - def delete(self,keys): + def delete(self: MyType, + keys: Union[Iterable, str]) -> MyType: """ Remove configuration keys. @@ -109,7 +128,8 @@ class Config(dict): @classmethod - def load(cls,fname): + def load(cls: Type[MyType], + fname: FileHandle) -> MyType: """ Load from yaml file. @@ -124,14 +144,15 @@ class Config(dict): Configuration from file. """ - try: + if isinstance(fname, (str, Path)): fhandle = open(fname) - except TypeError: + else: fhandle = fname return cls(yaml.safe_load(fhandle)) - - def save(self,fname,**kwargs): + def save(self, + fname: FileHandle, + **kwargs): """ Save to yaml file. @@ -143,9 +164,9 @@ class Config(dict): Keyword arguments parsed to yaml.dump. """ - try: + if isinstance(fname, (str, Path)): fhandle = open(fname,'w',newline='\n') - except TypeError: + else: fhandle = fname if 'width' not in kwargs: diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 1b4d4439c..01d85f6a4 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -1,10 +1,14 @@ import numpy as np import h5py +from typing import Sequence, Dict, Any, Collection +from ._typehints import FileHandle from . import Config from . import Rotation from . import Orientation from . import util +from . import Table + class ConfigMaterial(Config): """ @@ -17,7 +21,9 @@ class ConfigMaterial(Config): """ - def __init__(self,d=None,**kwargs): + def __init__(self, + d: Dict[str, Any] = None, + **kwargs): """ New material configuration. @@ -30,14 +36,17 @@ class ConfigMaterial(Config): Initial content specified as pairs of key=value. """ + default: Collection if d is None: - for section,default in {'material':[],'homogenization':{},'phase':{}}.items(): + for section, default in {'material':[],'homogenization':{},'phase':{}}.items(): if section not in kwargs: kwargs.update({section:default}) super().__init__(d,**kwargs) - def save(self,fname='material.yaml',**kwargs): + def save(self, + fname: FileHandle = 'material.yaml', + **kwargs): """ Save to yaml file. @@ -53,7 +62,8 @@ class ConfigMaterial(Config): @classmethod - def load(cls,fname='material.yaml'): + def load(cls, + fname: FileHandle = 'material.yaml') -> 'ConfigMaterial': """ Load from yaml file. @@ -72,10 +82,14 @@ class ConfigMaterial(Config): @staticmethod - def load_DREAM3D(fname, - grain_data=None,cell_data=None,cell_ensemble_data='CellEnsembleData', - phases='Phases',Euler_angles='EulerAngles',phase_names='PhaseName', - base_group=None): + def load_DREAM3D(fname: str, + grain_data: str = None, + cell_data: str = None, + cell_ensemble_data: str = 'CellEnsembleData', + phases: str = 'Phases', + Euler_angles: str = 'EulerAngles', + phase_names: str = 'PhaseName', + base_group: str = None) -> 'ConfigMaterial': """ Load DREAM.3D (HDF5) file. @@ -154,7 +168,8 @@ class ConfigMaterial(Config): @staticmethod - def from_table(table,**kwargs): + def from_table(table: Table, + **kwargs) -> 'ConfigMaterial': """ Generate from an ASCII table. @@ -207,7 +222,7 @@ class ConfigMaterial(Config): @property - def is_complete(self): + def is_complete(self) -> bool: """ Check for completeness. @@ -267,12 +282,11 @@ class ConfigMaterial(Config): if homogenization - set(self['homogenization']): print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing') ok = False - return ok @property - def is_valid(self): + def is_valid(self) -> bool: """ Check for valid content. @@ -316,7 +330,10 @@ class ConfigMaterial(Config): return ok - def material_rename_phase(self,mapping,ID=None,constituent=None): + def material_rename_phase(self, + mapping: Dict[str, str], + ID: Sequence[int] = None, + constituent: Sequence[int] = None) -> 'ConfigMaterial': """ Change phase name in material. @@ -347,7 +364,9 @@ class ConfigMaterial(Config): return dup - def material_rename_homogenization(self,mapping,ID=None): + def material_rename_homogenization(self, + mapping: Dict[str, str], + ID: Sequence[int] = None) -> 'ConfigMaterial': """ Change homogenization name in material. @@ -374,7 +393,8 @@ class ConfigMaterial(Config): return dup - def material_add(self,**kwargs): + def material_add(self, + **kwargs: Any) -> 'ConfigMaterial': """ Add material entries. @@ -453,7 +473,7 @@ class ConfigMaterial(Config): N = max(N,s[0]) if len(s)>0 else N n = max(n,s[1]) if len(s)>1 else n - mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)] + mat: Sequence[dict] = [{'constituents':[{} for _ in range(n)]} for _ in range(N)] if 'v' not in kwargs: shaped['v'] = np.broadcast_to(1/n,(N,n)) @@ -461,7 +481,7 @@ class ConfigMaterial(Config): map_shape = {'O':(N,n,4),'F_i':(N,n,3,3)} for k,v in shaped.items(): target = map_shape.get(k,(N,n)) - obj = np.broadcast_to(v.reshape(util.shapeshifter(v.shape,target,mode='right')),target) + obj = np.broadcast_to(v.reshape(util.shapeshifter(v.shape, target, mode = 'right')), target) for i in range(N): if k in ['phase','O','v','F_i']: for j in range(n): diff --git a/python/damask/util.py b/python/damask/util.py index 0bbc1e7b5..b4c287884 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -9,7 +9,7 @@ import re import fractions from collections import abc from functools import reduce -from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, Optional +from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, SupportsIndex, Sequence from pathlib import Path import numpy as np @@ -427,7 +427,7 @@ def hybrid_IA(dist: np.ndarray, def shapeshifter(fro: Tuple[int, ...], to: Tuple[int, ...], mode: Literal['left','right'] = 'left', - keep_ones: bool = False) -> Tuple[Optional[int], ...]: + keep_ones: bool = False) -> Sequence[SupportsIndex]: """ Return dimensions that reshape 'fro' to become broadcastable to 'to'. @@ -483,14 +483,14 @@ def shapeshifter(fro: Tuple[int, ...], grp = match.groups() except AssertionError: raise ValueError(f'Shapes can not be shifted {fro} --> {to}') - fill: Tuple[Optional[int], ...] = () + fill: Any = () for g,d in zip(grp,fro+(None,)): fill += (1,)*g.count(',')+(d,) return fill[:-1] def shapeblender(a: Tuple[int, ...], - b: Tuple[int, ...]) -> Tuple[int, ...]: + b: Tuple[int, ...]) -> Sequence[SupportsIndex]: """ Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'. From dc5ab9aee9f935e03e463fc13eb9d857f873c007 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 1 Feb 2022 11:55:34 +0100 Subject: [PATCH 24/36] [skip ci] updated version information after successful test of v3.0.0-alpha5-545-gad74f5dbe --- python/damask/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/VERSION b/python/damask/VERSION index 92cb9dcb3..8d2c8c56d 100644 --- a/python/damask/VERSION +++ b/python/damask/VERSION @@ -1 +1 @@ -v3.0.0-alpha5-542-g225a5d908 +v3.0.0-alpha5-545-gad74f5dbe From ad319efdd7049a3c81a495128c35987ab909d0b1 Mon Sep 17 00:00:00 2001 From: Sharan Date: Tue, 1 Feb 2022 22:11:02 +0100 Subject: [PATCH 25/36] updated PRIVATE repo --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index f3b0cfa68..88023f5ff 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit f3b0cfa68febbc90369e414c38733ccdc22258bb +Subproject commit 88023f5ff135b580c953e09c83e467dabba1bcd8 From 1bd654781b5931737ab113b1915e436974fe0e0c Mon Sep 17 00:00:00 2001 From: Sharan Date: Wed, 2 Feb 2022 00:02:03 +0100 Subject: [PATCH 26/36] tests updated --- PRIVATE | 2 +- python/damask/_result.py | 2 +- python/tests/test_Orientation.py | 2 +- python/tests/test_Result.py | 4 ++-- python/tests/test_Rotation.py | 2 +- python/tests/test_VTK.py | 8 ++++---- python/tests/test_grid_filters.py | 26 +++++++++++++------------- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/PRIVATE b/PRIVATE index 88023f5ff..a498ed64a 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 88023f5ff135b580c953e09c83e467dabba1bcd8 +Subproject commit a498ed64ac5d98d95fc6ba14f87ca16fadbb892a diff --git a/python/damask/_result.py b/python/damask/_result.py index 02d4174c9..de51eb611 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -5,7 +5,7 @@ import os import copy import datetime import warnings -import xml.etree.ElementTree as ET +import xml.etree.ElementTree as ET # noqa import xml.dom.minidom from pathlib import Path from functools import partial diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 2a32adea4..75f42da0f 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -287,7 +287,7 @@ class TestOrientation: @pytest.mark.parametrize('family',crystal_families) @pytest.mark.parametrize('proper',[True,False]) def test_in_SST(self,family,proper): - assert Orientation(family=family).in_SST(np.zeros(3),proper) + assert Orientation(family=family).in_SST(np.zeros(3),proper) # noqa @pytest.mark.parametrize('function',['in_SST','IPF_color']) def test_invalid_argument(self,function): diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index 1da56dedf..0af4353e0 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -367,7 +367,7 @@ class TestResult: @pytest.mark.parametrize('mode',['cell','node']) def test_coordinates(self,default,mode): - if mode == 'cell': + if mode == 'cell': # noqa a = grid_filters.coordinates0_point(default.cells,default.size,default.origin) b = default.coordinates0_point.reshape(tuple(default.cells)+(3,),order='F') elif mode == 'node': @@ -421,7 +421,7 @@ class TestResult: def test_XDMF_datatypes(self,tmp_path,single_phase,update,ref_path): for shape in [('scalar',()),('vector',(3,)),('tensor',(3,3)),('matrix',(12,))]: for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']: - single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')",f'{shape[0]}_{dtype}') + single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')",f'{shape[0]}_{dtype}') # noqa fname = os.path.splitext(os.path.basename(single_phase.fname))[0]+'.xdmf' os.chdir(tmp_path) single_phase.export_XDMF() diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index a431bc64b..9b603c3c3 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -1076,7 +1076,7 @@ class TestRotation: def test_from_fiber_component(self,N,sigma): p = [] for run in range(5): - alpha = np.random.random()*2*np.pi,np.arccos(np.random.random()) + alpha = np.random.random()*2*np.pi,np.arccos(np.random.random()) # noqa beta = np.random.random()*2*np.pi,np.arccos(np.random.random()) f_in_C = np.array([np.sin(alpha[0])*np.cos(alpha[1]), np.sin(alpha[0])*np.sin(alpha[1]), np.cos(alpha[0])]) diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index e59409a20..4a96fef1c 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -173,9 +173,9 @@ class TestVTK: polyData = VTK.from_poly_data(points) polyData.add(points,'coordinates') if update: - polyData.save(ref_path/'polyData') + polyData.save(ref_path/'polyData') # noqa else: - reference = VTK.load(ref_path/'polyData.vtp') + reference = VTK.load(ref_path/'polyData.vtp') # noqa assert polyData.__repr__() == reference.__repr__() and \ np.allclose(polyData.get('coordinates'),points) @@ -189,8 +189,8 @@ class TestVTK: rectilinearGrid.add(np.ascontiguousarray(c),'cell') rectilinearGrid.add(np.ascontiguousarray(n),'node') if update: - rectilinearGrid.save(ref_path/'rectilinearGrid') + rectilinearGrid.save(ref_path/'rectilinearGrid') # noqa else: - reference = VTK.load(ref_path/'rectilinearGrid.vtr') + reference = VTK.load(ref_path/'rectilinearGrid.vtr') # noqa assert rectilinearGrid.__repr__() == reference.__repr__() and \ np.allclose(rectilinearGrid.get('cell'),c) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index d5458f0eb..6b01ff44d 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -8,19 +8,19 @@ from damask import seeds class TestGridFilters: def test_coordinates0_point(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) coord = grid_filters.coordinates0_point(cells,size) assert np.allclose(coord[0,0,0],size/cells*.5) and coord.shape == tuple(cells) + (3,) def test_coordinates0_node(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) coord = grid_filters.coordinates0_node(cells,size) assert np.allclose(coord[-1,-1,-1],size) and coord.shape == tuple(cells+1) + (3,) def test_coord0(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) c = grid_filters.coordinates0_point(cells+1,size+size/cells) n = grid_filters.coordinates0_node(cells,size) + size/cells*.5 @@ -28,16 +28,16 @@ class TestGridFilters: @pytest.mark.parametrize('mode',['point','node']) def test_grid_DNA(self,mode): - """Ensure that cellsSizeOrigin_coordinates0_xx is the inverse of coordinates0_xx.""" + """Ensure that cellsSizeOrigin_coordinates0_xx is the inverse of coordinates0_xx.""" # noqa cells = np.random.randint(8,32,(3)) size = np.random.random(3) origin = np.random.random(3) - coord0 = eval(f'grid_filters.coordinates0_{mode}(cells,size,origin)') # noqa + coord0 = eval(f'grid_filters.coordinates0_{mode}(cells,size,origin)') # noqa _cells,_size,_origin = eval(f'grid_filters.cellsSizeOrigin_coordinates0_{mode}(coord0.reshape(-1,3,order="F"))') assert np.allclose(cells,_cells) and np.allclose(size,_size) and np.allclose(origin,_origin) def test_displacement_fluct_equivalence(self): - """Ensure that fluctuations are periodic.""" + """Ensure that fluctuations are periodic.""" # noqa size = np.random.random(3) cells = np.random.randint(8,32,(3)) F = np.random.random(tuple(cells)+(3,3)) @@ -45,14 +45,14 @@ class TestGridFilters: grid_filters.point_to_node(grid_filters.displacement_fluct_point(size,F))) def test_interpolation_to_node(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) F = np.random.random(tuple(cells)+(3,3)) assert np.allclose(grid_filters.coordinates_node(size,F) [1:-1,1:-1,1:-1], grid_filters.point_to_node(grid_filters.coordinates_point(size,F))[1:-1,1:-1,1:-1]) def test_interpolation_to_cell(self): - cells = np.random.randint(1,30,(3)) + cells = np.random.randint(1,30,(3)) # noqa coordinates_node_x = np.linspace(0,np.pi*2,num=cells[0]+1) node_field_x = np.cos(coordinates_node_x) @@ -66,7 +66,7 @@ class TestGridFilters: @pytest.mark.parametrize('mode',['point','node']) def test_coordinates0_origin(self,mode): - origin= np.random.random(3) + origin= np.random.random(3) # noqa size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) shifted = eval(f'grid_filters.coordinates0_{mode}(cells,size,origin)') @@ -79,7 +79,7 @@ class TestGridFilters: @pytest.mark.parametrize('function',[grid_filters.displacement_avg_point, grid_filters.displacement_avg_node]) def test_displacement_avg_vanishes(self,function): - """Ensure that random fluctuations in F do not result in average displacement.""" + """Ensure that random fluctuations in F do not result in average displacement.""" # noqa size = np.random.random(3) cells = np.random.randint(8,32,(3)) F = np.random.random(tuple(cells)+(3,3)) @@ -89,7 +89,7 @@ class TestGridFilters: @pytest.mark.parametrize('function',[grid_filters.displacement_fluct_point, grid_filters.displacement_fluct_node]) def test_displacement_fluct_vanishes(self,function): - """Ensure that constant F does not result in fluctuating displacement.""" + """Ensure that constant F does not result in fluctuating displacement.""" # noqa size = np.random.random(3) cells = np.random.randint(8,32,(3)) F = np.broadcast_to(np.random.random((3,3)), tuple(cells)+(3,3)) @@ -142,13 +142,13 @@ class TestGridFilters: function(unordered,mode) def test_regrid_identity(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) F = np.broadcast_to(np.eye(3), tuple(cells)+(3,3)) assert all(grid_filters.regrid(size,F,cells) == np.arange(cells.prod())) def test_regrid_double_cells(self): - size = np.random.random(3) + size = np.random.random(3) # noqa cells = np.random.randint(8,32,(3)) g = Grid.from_Voronoi_tessellation(cells,size,seeds.from_random(size,10)) F = np.broadcast_to(np.eye(3), tuple(cells)+(3,3)) From 6dcf6b972ccb06bcd0cb754e5d1a6705348b015e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Feb 2022 09:10:24 +0100 Subject: [PATCH 27/36] complaints from prospector (PEP8) --- python/tests/test_Orientation.py | 2 +- python/tests/test_Result.py | 16 ++++++++-------- python/tests/test_Rotation.py | 20 ++++++++++---------- python/tests/test_VTK.py | 16 ++++++++-------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 2a32adea4..bb4a14ed7 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -287,7 +287,7 @@ class TestOrientation: @pytest.mark.parametrize('family',crystal_families) @pytest.mark.parametrize('proper',[True,False]) def test_in_SST(self,family,proper): - assert Orientation(family=family).in_SST(np.zeros(3),proper) + assert Orientation(family=family).in_SST(np.zeros(3),proper) @pytest.mark.parametrize('function',['in_SST','IPF_color']) def test_invalid_argument(self,function): diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index 1da56dedf..71a4ce802 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -367,13 +367,13 @@ class TestResult: @pytest.mark.parametrize('mode',['cell','node']) def test_coordinates(self,default,mode): - if mode == 'cell': - a = grid_filters.coordinates0_point(default.cells,default.size,default.origin) - b = default.coordinates0_point.reshape(tuple(default.cells)+(3,),order='F') - elif mode == 'node': - a = grid_filters.coordinates0_node(default.cells,default.size,default.origin) - b = default.coordinates0_node.reshape(tuple(default.cells+1)+(3,),order='F') - assert np.allclose(a,b) + if mode == 'cell': + a = grid_filters.coordinates0_point(default.cells,default.size,default.origin) + b = default.coordinates0_point.reshape(tuple(default.cells)+(3,),order='F') + elif mode == 'node': + a = grid_filters.coordinates0_node(default.cells,default.size,default.origin) + b = default.coordinates0_node.reshape(tuple(default.cells+1)+(3,),order='F') + assert np.allclose(a,b) @pytest.mark.parametrize('output',['F','*',['P'],['P','F']],ids=range(4)) @pytest.mark.parametrize('fname',['12grains6x7x8_tensionY.hdf5'],ids=range(1)) @@ -421,7 +421,7 @@ class TestResult: def test_XDMF_datatypes(self,tmp_path,single_phase,update,ref_path): for shape in [('scalar',()),('vector',(3,)),('tensor',(3,3)),('matrix',(12,))]: for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']: - single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')",f'{shape[0]}_{dtype}') + single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape[1]},'{dtype}')",f'{shape[0]}_{dtype}') fname = os.path.splitext(os.path.basename(single_phase.fname))[0]+'.xdmf' os.chdir(tmp_path) single_phase.export_XDMF() diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index a431bc64b..fda986c2f 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -1076,19 +1076,19 @@ class TestRotation: def test_from_fiber_component(self,N,sigma): p = [] for run in range(5): - alpha = np.random.random()*2*np.pi,np.arccos(np.random.random()) - beta = np.random.random()*2*np.pi,np.arccos(np.random.random()) + alpha = np.random.random()*2*np.pi,np.arccos(np.random.random()) + beta = np.random.random()*2*np.pi,np.arccos(np.random.random()) - f_in_C = np.array([np.sin(alpha[0])*np.cos(alpha[1]), np.sin(alpha[0])*np.sin(alpha[1]), np.cos(alpha[0])]) - f_in_S = np.array([np.sin(beta[0] )*np.cos(beta[1] ), np.sin(beta[0] )*np.sin(beta[1] ), np.cos(beta[0] )]) - ax = np.append(np.cross(f_in_C,f_in_S), - np.arccos(np.dot(f_in_C,f_in_S))) - n = Rotation.from_axis_angle(ax if ax[3] > 0.0 else ax*-1.0 ,normalize=True) # rotation to align fiber axis in crystal and sample system + f_in_C = np.array([np.sin(alpha[0])*np.cos(alpha[1]), np.sin(alpha[0])*np.sin(alpha[1]), np.cos(alpha[0])]) + f_in_S = np.array([np.sin(beta[0] )*np.cos(beta[1] ), np.sin(beta[0] )*np.sin(beta[1] ), np.cos(beta[0] )]) + ax = np.append(np.cross(f_in_C,f_in_S), - np.arccos(np.dot(f_in_C,f_in_S))) + n = Rotation.from_axis_angle(ax if ax[3] > 0.0 else ax*-1.0 ,normalize=True) # rotation to align fiber axis in crystal and sample system - o = Rotation.from_fiber_component(alpha,beta,np.radians(sigma),N,False) - angles = np.arccos(np.clip(np.dot(o@np.broadcast_to(f_in_S,(N,3)),n@f_in_S),-1,1)) - dist = np.array(angles) * (np.random.randint(0,2,N)*2-1) + o = Rotation.from_fiber_component(alpha,beta,np.radians(sigma),N,False) + angles = np.arccos(np.clip(np.dot(o@np.broadcast_to(f_in_S,(N,3)),n@f_in_S),-1,1)) + dist = np.array(angles) * (np.random.randint(0,2,N)*2-1) - p.append(stats.normaltest(dist)[1]) + p.append(stats.normaltest(dist)[1]) sigma_out = np.degrees(np.std(dist)) p = np.average(p) diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index e59409a20..9f0dcc7cf 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -173,11 +173,11 @@ class TestVTK: polyData = VTK.from_poly_data(points) polyData.add(points,'coordinates') if update: - polyData.save(ref_path/'polyData') + polyData.save(ref_path/'polyData') else: - reference = VTK.load(ref_path/'polyData.vtp') - assert polyData.__repr__() == reference.__repr__() and \ - np.allclose(polyData.get('coordinates'),points) + reference = VTK.load(ref_path/'polyData.vtp') + assert polyData.__repr__() == reference.__repr__() and \ + np.allclose(polyData.get('coordinates'),points) @pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA') def test_compare_reference_rectilinearGrid(self,update,ref_path,tmp_path): @@ -189,8 +189,8 @@ class TestVTK: rectilinearGrid.add(np.ascontiguousarray(c),'cell') rectilinearGrid.add(np.ascontiguousarray(n),'node') if update: - rectilinearGrid.save(ref_path/'rectilinearGrid') + rectilinearGrid.save(ref_path/'rectilinearGrid') else: - reference = VTK.load(ref_path/'rectilinearGrid.vtr') - assert rectilinearGrid.__repr__() == reference.__repr__() and \ - np.allclose(rectilinearGrid.get('cell'),c) + reference = VTK.load(ref_path/'rectilinearGrid.vtr') + assert rectilinearGrid.__repr__() == reference.__repr__() and \ + np.allclose(rectilinearGrid.get('cell'),c) From 4b2e104f0303735ccf2a89bd5c5811d3eafcfb54 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 2 Feb 2022 12:52:59 +0100 Subject: [PATCH 28/36] added new type for rng_seed in _typehints module --- python/damask/_typehints.py | 2 ++ python/damask/seeds.py | 7 ++++--- python/damask/util.py | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python/damask/_typehints.py b/python/damask/_typehints.py index 67e920957..b8232a752 100644 --- a/python/damask/_typehints.py +++ b/python/damask/_typehints.py @@ -9,3 +9,5 @@ import numpy as np FloatSequence = Union[np.ndarray,Sequence[float]] IntSequence = Union[np.ndarray,Sequence[int]] FileHandle = Union[TextIO, str, Path] + +NumpyRngSeed = Union[int, IntSequence, np.random.SeedSequence, np.random.BitGenerator, np.random.Generator] diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 47e34d871..943d1bfd9 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -1,3 +1,4 @@ + """Functionality for generation of seed points for Voronoi or Laguerre tessellation.""" from typing import Tuple as _Tuple @@ -5,7 +6,7 @@ from typing import Tuple as _Tuple from scipy import spatial as _spatial import numpy as _np -from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence +from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence, NumpyRngSeed from . import util as _util from . import grid_filters as _grid_filters @@ -13,7 +14,7 @@ from . import grid_filters as _grid_filters def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None, - rng_seed=None) -> _np.ndarray: + rng_seed: NumpyRngSeed = None) -> _np.ndarray: """ Place seeds randomly in space. @@ -53,7 +54,7 @@ def from_Poisson_disc(size: _FloatSequence, N_candidates: int, distance: float, periodic: bool = True, - rng_seed=None) -> _np.ndarray: + rng_seed: NumpyRngSeed = None) -> _np.ndarray: """ Place seeds according to a Poisson disc distribution. diff --git a/python/damask/util.py b/python/damask/util.py index b4c287884..fc3f8ea8f 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -16,7 +16,7 @@ import numpy as np import h5py from . import version -from ._typehints import IntSequence, FloatSequence +from ._typehints import FloatSequence, NumpyRngSeed # limit visibility __all__=[ @@ -396,7 +396,7 @@ def execution_stamp(class_name: str, def hybrid_IA(dist: np.ndarray, N: int, - rng_seed: Union[int, IntSequence] = None) -> np.ndarray: + rng_seed: NumpyRngSeed = None) -> np.ndarray: """ Hybrid integer approximation. From 8fead8e306158ff8466fbd784e1d85ac4b8831d5 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Feb 2022 13:28:17 +0100 Subject: [PATCH 29/36] relaxed tolerances for optimized code, the last digit might differ --- src/polynomials.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polynomials.f90 b/src/polynomials.f90 index 49a46e2e4..155f54bf8 100644 --- a/src/polynomials.f90 +++ b/src/polynomials.f90 @@ -163,7 +163,7 @@ subroutine selfTest 'T_ref: '//trim(adjustl(x_ref_s))//IO_EOL Dict => YAML_parse_str(trim(YAML_s)) p2 = polynomial(dict%asDict(),'C','T') - if (dNeq(p1%at(x),p2%at(x),1.0e-12_pReal)) error stop 'polynomials: init' + if (dNeq(p1%at(x),p2%at(x),1.0e-10_pReal)) error stop 'polynomials: init' p1 = polynomial(coef*[0.0_pReal,1.0_pReal,0.0_pReal],x_ref) if (dNeq(p1%at(x_ref+x),-p1%at(x_ref-x),1.0e-10_pReal)) error stop 'polynomials: eval(odd)' From d868a240b242948a88f414b2b6a56d6c694ef49f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Feb 2022 16:45:13 +0000 Subject: [PATCH 30/36] bugix: change of behavior --- PRIVATE | 2 +- ...hase_mechanical_eigen_thermalexpansion.f90 | 45 +++++++------------ src/phase_mechanical_elastic.f90 | 4 +- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/PRIVATE b/PRIVATE index 5598ec489..419ba7b6f 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 5598ec4892b0921fccf63e8570f9fcd8e0365716 +Subproject commit 419ba7b6f6989a14e0c91c1f1f6621daf8215b71 diff --git a/src/phase_mechanical_eigen_thermalexpansion.f90 b/src/phase_mechanical_eigen_thermalexpansion.f90 index 70bf84cd8..a5d9868a8 100644 --- a/src/phase_mechanical_eigen_thermalexpansion.f90 +++ b/src/phase_mechanical_eigen_thermalexpansion.f90 @@ -8,10 +8,9 @@ submodule(phase:eigen) thermalexpansion integer, dimension(:), allocatable :: kinematics_thermal_expansion_instance type :: tParameters - real(pReal) :: & - T_ref - real(pReal), dimension(3,3,3) :: & - A = 0.0_pReal + type(tPolynomial) :: & + A_11, & + A_33 end type tParameters type(tParameters), dimension(:), allocatable :: param @@ -34,7 +33,7 @@ module function thermalexpansion_init(kinematics_length) result(myKinematics) phase, & mech, & kinematics, & - kinematic_type + myConfig print'(/,1x,a)', '<<<+- phase:mechanical:eigen:thermalexpansion init -+>>>' @@ -56,21 +55,13 @@ module function thermalexpansion_init(kinematics_length) result(myKinematics) do k = 1, kinematics%length if (myKinematics(k,p)) then associate(prm => param(kinematics_thermal_expansion_instance(p))) - kinematic_type => kinematics%get(k) - prm%T_ref = kinematic_type%get_asFloat('T_ref', defaultVal=T_ROOM) + myConfig => kinematics%get(k) + + prm%A_11 = polynomial(myConfig%asDict(),'A_11','T') + if (any(phase_lattice(p) == ['hP','tI'])) & + prm%A_33 = polynomial(myConfig%asDict(),'A_33','T') - prm%A(1,1,1) = kinematic_type%get_asFloat('A_11') - prm%A(1,1,2) = kinematic_type%get_asFloat('A_11,T', defaultVal=0.0_pReal) - prm%A(1,1,3) = kinematic_type%get_asFloat('A_11,T^2',defaultVal=0.0_pReal) - if (any(phase_lattice(p) == ['hP','tI'])) then - prm%A(3,3,1) = kinematic_type%get_asFloat('A_33') - prm%A(3,3,2) = kinematic_type%get_asFloat('A_33,T', defaultVal=0.0_pReal) - prm%A(3,3,3) = kinematic_type%get_asFloat('A_33,T^2',defaultVal=0.0_pReal) - end if - do i=1, size(prm%A,3) - prm%A(1:3,1:3,i) = lattice_symmetrize_33(prm%A(1:3,1:3,i),phase_lattice(p)) - end do end associate end if end do @@ -91,22 +82,20 @@ module subroutine thermalexpansion_LiAndItsTangent(Li, dLi_dTstar, ph,me) dLi_dTstar !< derivative of Li with respect to Tstar (4th-order tensor defined to be zero) real(pReal) :: T, dot_T + real(pReal), dimension(3,3) :: A T = thermal_T(ph,me) dot_T = thermal_dot_T(ph,me) associate(prm => param(kinematics_thermal_expansion_instance(ph))) - Li = dot_T * ( & - prm%A(1:3,1:3,1) & ! constant coefficient - + prm%A(1:3,1:3,2)*(T - prm%T_ref) & ! linear coefficient - + prm%A(1:3,1:3,3)*(T - prm%T_ref)**2 & ! quadratic coefficient - ) / & - (1.0_pReal & - + prm%A(1:3,1:3,1)*(T - prm%T_ref) / 1.0_pReal & - + prm%A(1:3,1:3,2)*(T - prm%T_ref)**2 / 2.0_pReal & - + prm%A(1:3,1:3,3)*(T - prm%T_ref)**3 / 3.0_pReal & - ) + + A = 0.0_pReal + A(1,1) = prm%A_11%at(T) + if (any(phase_lattice(ph) == ['hP','tI'])) A(3,3) = prm%A_33%at(T) + A = lattice_symmetrize_33(A,phase_lattice(ph)) + Li = dot_T * A + end associate dLi_dTstar = 0.0_pReal diff --git a/src/phase_mechanical_elastic.f90 b/src/phase_mechanical_elastic.f90 index c57849b1f..084cc75bc 100644 --- a/src/phase_mechanical_elastic.f90 +++ b/src/phase_mechanical_elastic.f90 @@ -48,7 +48,7 @@ module subroutine elastic_init(phases) prm%C_11 = polynomial(elastic%asDict(),'C_11','T') prm%C_12 = polynomial(elastic%asDict(),'C_12','T') prm%C_44 = polynomial(elastic%asDict(),'C_44','T') - + if (any(phase_lattice(ph) == ['hP','tI'])) then prm%C_13 = polynomial(elastic%asDict(),'C_13','T') prm%C_33 = polynomial(elastic%asDict(),'C_33','T') @@ -77,7 +77,7 @@ pure module function elastic_C66(ph,en) result(C66) associate(prm => param(ph)) - + C66 = 0.0_pReal T = thermal_T(ph,en) From 7078b5ec8709ad78dff64813d0e290c583c13979 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 2 Feb 2022 22:07:12 +0100 Subject: [PATCH 31/36] [skip ci] updated version information after successful test of v3.0.0-alpha5-552-ga6e78c5b6 --- python/damask/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/VERSION b/python/damask/VERSION index 8d2c8c56d..0f9864e69 100644 --- a/python/damask/VERSION +++ b/python/damask/VERSION @@ -1 +1 @@ -v3.0.0-alpha5-545-gad74f5dbe +v3.0.0-alpha5-552-ga6e78c5b6 From 2a45d2d48dff8aa9c4617a9064c10051ac5cd6bd Mon Sep 17 00:00:00 2001 From: Sharan Date: Wed, 2 Feb 2022 23:00:53 +0100 Subject: [PATCH 32/36] private updated --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index a498ed64a..ebb7f0ce7 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit a498ed64ac5d98d95fc6ba14f87ca16fadbb892a +Subproject commit ebb7f0ce78d11275020af0ba60f929f95b446932 From 038cdad85e196149c60d66746fffe8c1711b8ce8 Mon Sep 17 00:00:00 2001 From: Sharan Date: Wed, 2 Feb 2022 23:22:44 +0100 Subject: [PATCH 33/36] new naming --- src/homogenization.f90 | 4 ++-- src/phase_mechanical.f90 | 4 ++-- src/phase_thermal.f90 | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/homogenization.f90 b/src/homogenization.f90 index cc29ed619..3d96b007f 100644 --- a/src/homogenization.f90 +++ b/src/homogenization.f90 @@ -414,7 +414,7 @@ subroutine homogenization_restartWrite(fileHandle) groupHandle(2) = HDF5_addGroup(groupHandle(1),material_name_homogenization(ho)) - call HDF5_write(homogState(ho)%state,groupHandle(2),'omega') ! ToDo: should be done by mech + call HDF5_write(homogState(ho)%state,groupHandle(2),'omega_mechanical') ! ToDo: should be done by mech call HDF5_closeGroup(groupHandle(2)) @@ -441,7 +441,7 @@ subroutine homogenization_restartRead(fileHandle) groupHandle(2) = HDF5_openGroup(groupHandle(1),material_name_homogenization(ho)) - call HDF5_read(homogState(ho)%state0,groupHandle(2),'omega') ! ToDo: should be done by mech + call HDF5_read(homogState(ho)%state0,groupHandle(2),'omega_mechanical') ! ToDo: should be done by mech call HDF5_closeGroup(groupHandle(2)) diff --git a/src/phase_mechanical.f90 b/src/phase_mechanical.f90 index 1917d81c9..2252b941d 100644 --- a/src/phase_mechanical.f90 +++ b/src/phase_mechanical.f90 @@ -1248,7 +1248,7 @@ module subroutine mechanical_restartWrite(groupHandle,ph) integer, intent(in) :: ph - call HDF5_write(plasticState(ph)%state,groupHandle,'omega') + call HDF5_write(plasticState(ph)%state,groupHandle,'omega_plastic') call HDF5_write(phase_mechanical_Fi(ph)%data,groupHandle,'F_i') call HDF5_write(phase_mechanical_Li(ph)%data,groupHandle,'L_i') call HDF5_write(phase_mechanical_Lp(ph)%data,groupHandle,'L_p') @@ -1265,7 +1265,7 @@ module subroutine mechanical_restartRead(groupHandle,ph) integer, intent(in) :: ph - call HDF5_read(plasticState(ph)%state0,groupHandle,'omega') + call HDF5_read(plasticState(ph)%state0,groupHandle,'omega_plastic') call HDF5_read(phase_mechanical_Fi0(ph)%data,groupHandle,'F_i') call HDF5_read(phase_mechanical_Li0(ph)%data,groupHandle,'L_i') call HDF5_read(phase_mechanical_Lp0(ph)%data,groupHandle,'L_p') diff --git a/src/phase_thermal.f90 b/src/phase_thermal.f90 index fb98039fd..c7a9ea75a 100644 --- a/src/phase_thermal.f90 +++ b/src/phase_thermal.f90 @@ -263,8 +263,7 @@ module subroutine thermal_restartWrite(groupHandle,ph) integer :: so do so = 1,thermal_Nsources(ph) - !new_group = HDF5_addGroup(groupHandle, - call HDF5_write(thermalState(ph)%p(so)%state,groupHandle,'omega2') + call HDF5_write(thermalState(ph)%p(so)%state,groupHandle,'omega_thermal') enddo end subroutine thermal_restartWrite @@ -279,8 +278,7 @@ module subroutine thermal_restartRead(groupHandle,ph) integer :: so do so = 1,thermal_Nsources(ph) - !new_group = HDF5_addGroup(groupHandle, - call HDF5_read(thermalState(ph)%p(so)%state0,groupHandle,'omega2') + call HDF5_read(thermalState(ph)%p(so)%state0,groupHandle,'omega_thermal') enddo end subroutine thermal_restartRead From ef390ca916d53d5498ab3aacd81f493277413b2c Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 3 Feb 2022 03:49:37 +0100 Subject: [PATCH 34/36] [skip ci] updated version information after successful test of v3.0.0-alpha5-556-g97f849c09 --- python/damask/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/VERSION b/python/damask/VERSION index 0f9864e69..b4c8c4b3c 100644 --- a/python/damask/VERSION +++ b/python/damask/VERSION @@ -1 +1 @@ -v3.0.0-alpha5-552-ga6e78c5b6 +v3.0.0-alpha5-556-g97f849c09 From cf2b22b34a6bdeb80a4a0e658a6dd7c81a70cf50 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Feb 2022 23:04:54 +0100 Subject: [PATCH 35/36] does not exist for older numpy versions --- python/damask/_typehints.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/damask/_typehints.py b/python/damask/_typehints.py index 793e09bc6..0b4a56a69 100644 --- a/python/damask/_typehints.py +++ b/python/damask/_typehints.py @@ -9,4 +9,6 @@ import numpy as np FloatSequence = Union[np.ndarray,Sequence[float]] IntSequence = Union[np.ndarray,Sequence[int]] FileHandle = Union[TextIO, str, Path] -NumpyRngSeed = Union[int, IntSequence, np.random.SeedSequence, np.random.BitGenerator, np.random.Generator] +NumpyRngSeed = Union[int, IntSequence, np.random.SeedSequence, np.random.Generator] +# BitGenerator does not exists in older numpy versions +#NumpyRngSeed = Union[int, IntSequence, np.random.SeedSequence, np.random.BitGenerator, np.random.Generator] From 2cb3b2cc4540853ec1f0d9f8f9c1f2b8ec201692 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Feb 2022 07:58:51 +0100 Subject: [PATCH 36/36] not needed --- src/phase_thermal.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/phase_thermal.f90 b/src/phase_thermal.f90 index c7a9ea75a..bc464d35a 100644 --- a/src/phase_thermal.f90 +++ b/src/phase_thermal.f90 @@ -259,9 +259,9 @@ module subroutine thermal_restartWrite(groupHandle,ph) integer(HID_T), intent(in) :: groupHandle integer, intent(in) :: ph - integer(HID_T) :: new_group integer :: so + do so = 1,thermal_Nsources(ph) call HDF5_write(thermalState(ph)%p(so)%state,groupHandle,'omega_thermal') enddo @@ -274,9 +274,9 @@ module subroutine thermal_restartRead(groupHandle,ph) integer(HID_T), intent(in) :: groupHandle integer, intent(in) :: ph - integer(HID_T) :: new_group integer :: so + do so = 1,thermal_Nsources(ph) call HDF5_read(thermalState(ph)%p(so)%state0,groupHandle,'omega_thermal') enddo