From e419eea507019ae46f1705ae3706af7dffdf63da Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 12 Nov 2020 14:40:25 +0100 Subject: [PATCH 01/37] read vtr file only by process 1 --- src/grid/discretization_grid.f90 | 44 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index bb6c6210d..e869c0781 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -56,25 +56,33 @@ subroutine discretization_grid_init(restart) myGrid !< domain grid of this process integer, dimension(:), allocatable :: & - materialAt + materialAt, materialAt_global integer :: & j, & - debug_element, & - debug_ip + debug_element, debug_ip, & + ierr integer(C_INTPTR_T) :: & devNull, z, z_offset + integer, dimension(worldsize) :: & + displs, sendcounts print'(/,a)', ' <<<+- discretization_grid init -+>>>'; flush(IO_STDOUT) - call readVTR(grid,geomSize,origin,materialAt) + if(worldrank == 0) call readVTR(grid,geomSize,origin,materialAt_global) + + + call MPI_Bcast(grid,3,MPI_INTEGER,0,PETSC_COMM_WORLD, ierr) + if (ierr /= 0) error stop 'MPI error' + call MPI_Bcast(geomSize,3,MPI_DOUBLE,0,PETSC_COMM_WORLD, ierr) + if (ierr /= 0) error stop 'MPI error' + call MPI_Bcast(origin,3,MPI_DOUBLE,0,PETSC_COMM_WORLD, ierr) + if (ierr /= 0) error stop 'MPI error' print'(/,a,3(i12 ))', ' grid a b c: ', grid print'(a,3(es12.5))', ' size x y z: ', geomSize print'(a,3(es12.5))', ' origin x y z: ', origin -!-------------------------------------------------------------------------------------------------- -! grid solver specific quantities if(worldsize>grid(3)) call IO_error(894, ext_msg='number of processes exceeds grid(3)') call fftw_mpi_init @@ -93,14 +101,14 @@ subroutine discretization_grid_init(restart) myGrid = [grid(1:2),grid3] mySize = [geomSize(1:2),size3] -!------------------------------------------------------------------------------------------------- -! debug parameters - debug_element = config_debug%get_asInt('element',defaultVal=1) - debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1) + call MPI_Gather(product(grid(1:2))*grid3Offset,1,MPI_INTEGER,displs, 1,MPI_INTEGER,0,PETSC_COMM_WORLD,ierr) + if (ierr /= 0) error stop 'MPI error' + call MPI_Gather(product(myGrid), 1,MPI_INTEGER,sendcounts,1,MPI_INTEGER,0,PETSC_COMM_WORLD,ierr) + if (ierr /= 0) error stop 'MPI error' -!-------------------------------------------------------------------------------------------------- -! general discretization - materialAt = materialAt(product(grid(1:2))*grid3Offset+1:product(grid(1:2))*(grid3Offset+grid3)) ! reallocate/shrink in case of MPI + allocate(materialAt(product(myGrid))) + call MPI_scatterv(materialAt_global,sendcounts,displs,MPI_INTEGER,materialAt,size(materialAt),MPI_INTEGER,0,PETSC_COMM_WORLD,ierr) + if (ierr /= 0) error stop 'MPI error' call discretization_init(materialAt, & IPcoordinates0(myGrid,mySize,grid3Offset), & @@ -131,10 +139,12 @@ subroutine discretization_grid_init(restart) call geometry_plastic_nonlocal_setIPareaNormal (cellSurfaceNormal(product(myGrid))) call geometry_plastic_nonlocal_setIPneighborhood(IPneighborhood(myGrid)) -!-------------------------------------------------------------------------------------------------- -! sanity checks for debugging - if (debug_element < 1 .or. debug_element > product(myGrid)) call IO_error(602,ext_msg='element') ! selected element does not exist - if (debug_ip /= 1) call IO_error(602,ext_msg='IP') ! selected IP does not exist +!------------------------------------------------------------------------------------------------- +! debug parameters + debug_element = config_debug%get_asInt('element',defaultVal=1) + if (debug_element < 1 .or. debug_element > product(myGrid)) call IO_error(602,ext_msg='element') + debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1) + if (debug_ip /= 1) call IO_error(602,ext_msg='IP') end subroutine discretization_grid_init From e15678e7a40eec238862e1684da17f916cb4520f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 12 Nov 2020 21:31:09 +0100 Subject: [PATCH 02/37] consistent handling of comments --- python/damask/_table.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/damask/_table.py b/python/damask/_table.py index e90650eea..c05fa71a7 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -31,7 +31,7 @@ class Table: def __repr__(self): """Brief overview.""" - return util.srepr(self.comments)+'\n'+self.data.__repr__() + return '\n'.join(['# '+c for c in self.comments])+'\n'+self.data.__repr__() def __len__(self): """Number of rows.""" @@ -159,7 +159,7 @@ class Table: comments = [util.execution_stamp('Table','from_ang')] for line in content: if line.startswith('#'): - comments.append(line.strip()) + comments.append(line.split('#',1)[1].strip()) else: break @@ -222,6 +222,7 @@ class Table: dup.data[label] = data.reshape(dup.data[label].shape) return dup + def add(self,label,data,info=None): """ Add column data. From 42e52fad6626f353bb336e329f13bc469c644a1d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 12 Nov 2020 21:48:13 +0100 Subject: [PATCH 03/37] not needed anymore --- processing/pre/geom_fromMinimalSurface.py | 69 ----------------------- 1 file changed, 69 deletions(-) delete mode 100755 processing/pre/geom_fromMinimalSurface.py diff --git a/processing/pre/geom_fromMinimalSurface.py b/processing/pre/geom_fromMinimalSurface.py deleted file mode 100755 index eb0cdcc3b..000000000 --- a/processing/pre/geom_fromMinimalSurface.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from optparse import OptionParser - -import damask - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - - -minimal_surfaces = list(damask.Geom._minimal_surface.keys()) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [geomfile]', description = """ -Generate a bicontinuous structure of given type. - -""", version = scriptID) - - -parser.add_option('-t','--type', - dest = 'type', - choices = minimal_surfaces, metavar = 'string', - help = 'type of minimal surface [primitive] {%s}' %(','.join(minimal_surfaces))) -parser.add_option('-f','--threshold', - dest = 'threshold', - type = 'float', metavar = 'float', - help = 'threshold value defining minimal surface [%default]') -parser.add_option('-g', '--grid', - dest = 'grid', - type = 'int', nargs = 3, metavar = 'int int int', - help = 'a,b,c grid of hexahedral box [%default]') -parser.add_option('-s', '--size', - dest = 'size', - type = 'float', nargs = 3, metavar = 'float float float', - help = 'x,y,z size of hexahedral box [%default]') -parser.add_option('-p', '--periods', - dest = 'periods', - type = 'int', metavar = 'int', - help = 'number of repetitions of unit cell [%default]') -parser.add_option('--m', - dest = 'microstructure', - type = 'int', nargs = 2, metavar = 'int int', - help = 'two microstructure indices to be used [%default]') - -parser.set_defaults(type = minimal_surfaces[0], - threshold = 0.0, - periods = 1, - grid = (16,16,16), - size = (1.0,1.0,1.0), - microstructure = (1,2), - ) - -(options,filename) = parser.parse_args() - - -name = None if filename == [] else filename[0] -damask.util.report(scriptName,name) - -geom=damask.Geom.from_minimal_surface(options.grid,options.size,options.type,options.threshold, - options.periods,options.microstructure) -damask.util.croak(geom) - -geom.save_ASCII(sys.stdout if name is None else name) From 65f41b3de39676a9442505c400c8b793ef22e8cc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 12 Nov 2020 21:48:48 +0100 Subject: [PATCH 04/37] new pytest-based tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 281e7eb84..3bac05107 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 281e7eb84f76a2974a50eb54faf35ea25ec89b20 +Subproject commit 3bac05107a8b436eddc61645e01efa17ccb72332 From 1d3ec769115225c3694237bbc5ec69b945de3bcb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 12 Nov 2020 22:31:02 +0100 Subject: [PATCH 05/37] updated tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 3bac05107..7b2dcb193 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 3bac05107a8b436eddc61645e01efa17ccb72332 +Subproject commit 7b2dcb193c7e47ddec7ea9e77c018c5c0086c543 From 69263ea59fb7024c94a002a0fd29619c5e74adbf Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 13 Nov 2020 08:32:58 +0100 Subject: [PATCH 06/37] thorough testing in pytest-based restart test --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 7b2dcb193..eb35bb0a5 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 7b2dcb193c7e47ddec7ea9e77c018c5c0086c543 +Subproject commit eb35bb0a5704c6c0b2191b9423864b5ff9859049 From a333f94bac2017750c5eb7a0ad7e6b29fce91951 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 13 Nov 2020 23:12:40 +0100 Subject: [PATCH 07/37] restart tests are now in pytest --- .gitlab-ci.yml | 16 ---------------- PRIVATE | 2 +- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c6d1d6f6..71f1d6652 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -274,22 +274,6 @@ Nonlocal_Damage_DetectChanges: - master - release -grid_all_restart: - stage: grid - script: grid_all_restart/test.py - except: - - master - - release - -grid_all_restartMPI: - stage: grid - script: - - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - - grid_all_restartMPI/test.py - except: - - master - - release - Plasticity_DetectChanges: stage: grid script: Plasticity_DetectChanges/test.py diff --git a/PRIVATE b/PRIVATE index eb35bb0a5..bc60d4065 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit eb35bb0a5704c6c0b2191b9423864b5ff9859049 +Subproject commit bc60d4065df425d00dbdeb22cad24ab01ffc4d8a From 167f1626552ab7ce60c05337b90cf59c44c334bf Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 11:13:51 +0100 Subject: [PATCH 08/37] fix for compile_grid test --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index bc60d4065..75aa46a4a 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit bc60d4065df425d00dbdeb22cad24ab01ffc4d8a +Subproject commit 75aa46a4a1c27f3d2c8d7c7eff393dcf069ff41c From 5a28a5b4dbc51b7a7099b5b5eeb4dbaae3ae070c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 14:36:10 +0100 Subject: [PATCH 09/37] correct handling of C strings cleaning and improving the C code for system routines and the interface to Fortran Reporting PETSc version --- src/C_routines.c | 36 +++++++---- src/DAMASK_interface.f90 | 25 ++++--- src/system_routines.f90 | 136 +++++++++++++++++++-------------------- 3 files changed, 101 insertions(+), 96 deletions(-) diff --git a/src/C_routines.c b/src/C_routines.c index 98dc25e45..4b07c0ee0 100644 --- a/src/C_routines.c +++ b/src/C_routines.c @@ -4,25 +4,24 @@ #include #include #include +#include #include #include #include "zlib.h" -/* http://stackoverflow.com/questions/30279228/is-there-an-alternative-to-getcwd-in-fortran-2003-2008 */ +#define PATHLEN 4096 +#define STRLEN 256 -int isdirectory_c(const char *dir){ - struct stat statbuf; - if(stat(dir, &statbuf) != 0) /* error */ - return 0; /* return "NO, this is not a directory" */ - return S_ISDIR(statbuf.st_mode); /* 1 => is directory, 0 => this is NOT a directory */ +int setcwd_c(const char *cwd){ + return chdir(cwd); } -void getcurrentworkdir_c(char cwd[], int *stat ){ - char cwd_tmp[4096]; - if(getcwd(cwd_tmp, sizeof(cwd_tmp)) == cwd_tmp){ - strcpy(cwd,cwd_tmp); +void getcwd_c(char cwd[], int *stat ){ + char cwd_tmp[PATHLEN+1]; + if(getcwd(cwd_tmp, sizeof(cwd_tmp))){ + strcpy(cwd,cwd_tmp); // getcwd guarantees a NULL-terminated string *stat = 0; } else{ @@ -32,9 +31,9 @@ void getcurrentworkdir_c(char cwd[], int *stat ){ void gethostname_c(char hostname[], int *stat){ - char hostname_tmp[4096]; + char hostname_tmp[STRLEN]; if(gethostname(hostname_tmp, sizeof(hostname_tmp)) == 0){ - strcpy(hostname,hostname_tmp); + strncpy(hostname,hostname_tmp,sizeof(hostname_tmp)+1); // gethostname does not guarantee a NULL-terminated string *stat = 0; } else{ @@ -43,10 +42,18 @@ void gethostname_c(char hostname[], int *stat){ } -int chdir_c(const char *dir){ - return chdir(dir); +void getusername_c(char username[], int *stat){ + struct passwd *pw = getpwuid(geteuid()); + if(pw && strlen(pw->pw_name) <= STRLEN){ + strncpy(username,pw->pw_name,STRLEN+1); + *stat = 0; + } + else{ + *stat = 1; + } } + void signalterm_c(void (*handler)(int)){ signal(SIGTERM, handler); } @@ -59,6 +66,7 @@ void signalusr2_c(void (*handler)(int)){ signal(SIGUSR2, handler); } + void inflate_c(const uLong *s_deflated, const uLong *s_inflated, const Byte deflated[], Byte inflated[]){ /* make writable copy, uncompress will write to it */ uLong s_inflated_,i; diff --git a/src/DAMASK_interface.f90 b/src/DAMASK_interface.f90 index 52971ae06..3e3f981e2 100644 --- a/src/DAMASK_interface.f90 +++ b/src/DAMASK_interface.f90 @@ -69,8 +69,6 @@ subroutine DAMASK_interface_init loadCaseArg = '', & !< -l argument given to the executable geometryArg = '', & !< -g argument given to the executable workingDirArg = '' !< -w argument given to the executable - character(len=pStringLen) :: & - userName !< name of user calling the executable integer :: & stat, & i @@ -117,6 +115,9 @@ subroutine DAMASK_interface_init print'(/,a)', ' Compiled on: '//__DATE__//' at '//__TIME__ + print'(/,a,i0,a,i0,a,i0)', & + ' PETSc version: ',PETSC_VERSION_MAJOR,'.',PETSC_VERSION_MINOR,'.',PETSC_VERSION_SUBMINOR + call date_and_time(values = dateAndTime) print'(/,a,2(i2.2,a),i4.4)', ' Date: ',dateAndTime(3),'/',dateAndTime(2),'/', dateAndTime(1) print'(a,2(i2.2,a),i2.2)', ' Time: ',dateAndTime(5),':', dateAndTime(6),':', dateAndTime(7) @@ -189,17 +190,15 @@ subroutine DAMASK_interface_init interface_loadFile = getLoadCaseFile(loadCaseArg) call get_command(commandLine) - call get_environment_variable('USER',userName) - ! ToDo: https://stackoverflow.com/questions/8953424/how-to-get-the-username-in-c-c-in-linux - print'(a)', ' Host name: '//trim(getHostName()) - print'(a)', ' User name: '//trim(userName) + print'(/,a)', ' Host name: '//getHostName() + print'(a)', ' User name: '//getUserName() print'(/a)', ' Command line call: '//trim(commandLine) if (len_trim(workingDirArg) > 0) & print'(a)', ' Working dir argument: '//trim(workingDirArg) print'(a)', ' Geometry argument: '//trim(geometryArg) - print'(a)', ' Load case argument: '//trim(loadcaseArg) - print'(a)', ' Working directory: '//getCWD() + print'(a)', ' Loadcase argument: '//trim(loadcaseArg) + print'(/,a)', ' Working directory: '//getCWD() print'(a)', ' Geometry file: '//interface_geomFile print'(a)', ' Loadcase file: '//interface_loadFile print'(a)', ' Solver job name: '//getSolverJobName() @@ -222,8 +221,8 @@ end subroutine DAMASK_interface_init !-------------------------------------------------------------------------------------------------- subroutine setWorkingDirectory(workingDirectoryArg) - character(len=*), intent(in) :: workingDirectoryArg !< working directory argument - character(len=pPathLen) :: workingDirectory + character(len=*), intent(in) :: workingDirectoryArg !< working directory argument + character(len=:), allocatable :: workingDirectory logical :: error external :: quit @@ -359,12 +358,12 @@ end function rectifyPath !-------------------------------------------------------------------------------------------------- -!> @brief relative path from absolute a to absolute b +!> @brief Determine relative path from absolute a to absolute b !-------------------------------------------------------------------------------------------------- function makeRelativePath(a,b) - character (len=*), intent(in) :: a,b - character (len=pPathLen) :: a_cleaned,b_cleaned + character(len=*), intent(in) :: a,b + character(len=pPathLen) :: a_cleaned,b_cleaned character(len=:), allocatable :: makeRelativePath integer :: i,posLastCommonSlash,remainingSlashes diff --git a/src/system_routines.f90 b/src/system_routines.f90 index 9a2442163..309b96b7e 100644 --- a/src/system_routines.f90 +++ b/src/system_routines.f90 @@ -8,79 +8,65 @@ module system_routines use prec implicit none + private public :: & - signalterm_C, & - signalusr1_C, & - signalusr2_C, & - isDirectory, & + setCWD, & getCWD, & getHostName, & - setCWD + getUserName, & + signalterm_C, & + signalusr1_C, & + signalusr2_C + interface - function isDirectory_C(path) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_INT, & - C_CHAR + function setCWD_C(cwd) bind(C) + use, intrinsic :: ISO_C_Binding, only: C_INT, C_CHAR + + integer(C_INT) :: setCWD_C + character(kind=C_CHAR), dimension(*), intent(in) :: cwd + end function setCWD_C + subroutine getCWD_C(cwd, stat) bind(C) + use, intrinsic :: ISO_C_Binding, only: C_INT, C_CHAR use prec - integer(C_INT) :: isDirectory_C - character(kind=C_CHAR), dimension(pPathLen), intent(in) :: path ! C string is an array - end function isDirectory_C - - subroutine getCurrentWorkDir_C(path, stat) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_INT, & - C_CHAR - - use prec - - character(kind=C_CHAR), dimension(pPathLen), intent(out) :: path ! C string is an array - integer(C_INT), intent(out) :: stat - end subroutine getCurrentWorkDir_C - - subroutine getHostName_C(str, stat) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_INT, & - C_CHAR - - use prec - - character(kind=C_CHAR), dimension(pStringLen), intent(out) :: str ! C string is an array + character(kind=C_CHAR), dimension(pPathLen+1), intent(out) :: cwd ! NULL-terminated array integer(C_INT), intent(out) :: stat + end subroutine getCWD_C + + subroutine getHostName_C(hostname, stat) bind(C) + use, intrinsic :: ISO_C_Binding, only: C_INT, C_CHAR + use prec + + character(kind=C_CHAR), dimension(pStringLen+1), intent(out) :: hostname ! NULL-terminated array + integer(C_INT), intent(out) :: stat end subroutine getHostName_C - function chdir_C(path) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_INT, & - C_CHAR - + subroutine getUserName_C(username, stat) bind(C) + use, intrinsic :: ISO_C_Binding, only: C_INT, C_CHAR use prec - integer(C_INT) :: chdir_C - character(kind=C_CHAR), dimension(pPathLen), intent(in) :: path ! C string is an array - end function chdir_C + character(kind=C_CHAR), dimension(pStringLen+1), intent(out) :: username ! NULL-terminated array + integer(C_INT), intent(out) :: stat + end subroutine getUserName_C subroutine signalterm_C(handler) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_FUNPTR + use, intrinsic :: ISO_C_Binding, only: C_FUNPTR type(C_FUNPTR), intent(in), value :: handler end subroutine signalterm_C subroutine signalusr1_C(handler) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_FUNPTR + use, intrinsic :: ISO_C_Binding, only: C_FUNPTR type(C_FUNPTR), intent(in), value :: handler end subroutine signalusr1_C subroutine signalusr2_C(handler) bind(C) - use, intrinsic :: ISO_C_Binding, only: & - C_FUNPTR + use, intrinsic :: ISO_C_Binding, only: C_FUNPTR type(C_FUNPTR), intent(in), value :: handler end subroutine signalusr2_C @@ -89,45 +75,48 @@ module system_routines contains + !-------------------------------------------------------------------------------------------------- -!> @brief figures out if a given path is a directory (and not an ordinary file) +!> @brief set the current working directory !-------------------------------------------------------------------------------------------------- -logical function isDirectory(path) +logical function setCWD(path) character(len=*), intent(in) :: path - - isDirectory=merge(.True.,.False.,isDirectory_C(f_c_string(path)) /= 0_C_INT) -end function isDirectory + setCWD=merge(.True.,.False.,setCWD_C(f_c_string(path)) /= 0_C_INT) + +end function setCWD !-------------------------------------------------------------------------------------------------- -!> @brief gets the current working directory +!> @brief get the current working directory !-------------------------------------------------------------------------------------------------- function getCWD() - character(kind=C_CHAR), dimension(pPathLen) :: getCWD_Cstring - character(len=:), allocatable :: getCWD + character(len=:), allocatable :: getCWD + + character(kind=C_CHAR), dimension(pPathLen+1) :: getCWD_Cstring integer(C_INT) :: stat - call getCurrentWorkDir_C(getCWD_Cstring,stat) + call getCWD_C(getCWD_Cstring,stat) if(stat == 0) then getCWD = c_f_string(getCWD_Cstring) else - getCWD = 'Error occured when getting currend working directory' + error stop 'invalid working directory' endif end function getCWD !-------------------------------------------------------------------------------------------------- -!> @brief gets the current host name +!> @brief get the host name !-------------------------------------------------------------------------------------------------- function getHostName() - character(kind=C_CHAR), dimension(pPathLen) :: getHostName_Cstring - character(len=:), allocatable :: getHostName + character(len=:), allocatable :: getHostName + + character(kind=C_CHAR), dimension(pStringLen+1) :: getHostName_Cstring integer(C_INT) :: stat call getHostName_C(getHostName_Cstring,stat) @@ -135,22 +124,31 @@ function getHostName() if(stat == 0) then getHostName = c_f_string(getHostName_Cstring) else - getHostName = 'Error occured when getting host name' + getHostName = 'n/a (Error!)' endif end function getHostName !-------------------------------------------------------------------------------------------------- -!> @brief changes the current working directory +!> @brief get the user name !-------------------------------------------------------------------------------------------------- -logical function setCWD(path) +function getUserName() - character(len=*), intent(in) :: path + character(len=:), allocatable :: getUserName - setCWD=merge(.True.,.False.,chdir_C(f_c_string(path)) /= 0_C_INT) + character(kind=C_CHAR), dimension(pStringLen+1) :: getUserName_Cstring + integer(C_INT) :: stat -end function setCWD + call getUserName_C(getUserName_Cstring,stat) + + if(stat == 0) then + getUserName = c_f_string(getUserName_Cstring) + else + getUserName = 'n/a (Error!)' + endif + +end function getUserName !-------------------------------------------------------------------------------------------------- @@ -182,14 +180,14 @@ end function c_f_string !-------------------------------------------------------------------------------------------------- pure function f_c_string(f_string) result(c_string) - character(len=*), intent(in) :: f_string - character(kind=C_CHAR), dimension(len(f_string)+1) :: c_string + character(len=*), intent(in) :: f_string + character(kind=C_CHAR), dimension(len_trim(f_string)+1) :: c_string integer :: i - do i=1,len(f_string) + do i=1,len_trim(f_string) c_string(i)=f_string(i:i) enddo - c_string(i) = C_NULL_CHAR + c_string(len_trim(f_string)+1) = C_NULL_CHAR end function f_c_string From 9eb4e2d0de764825c33b55640550a0a8db3c684b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 17:13:38 +0100 Subject: [PATCH 10/37] corrected handling of scalar/array arguments + more tests + corrected handling of numpy types --- python/damask/_configmaterial.py | 27 +++++++++++++++------ python/tests/test_ConfigMaterial.py | 37 +++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 4f3eba816..6de2283f4 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -226,13 +226,13 @@ class ConfigMaterial(Config): return dup - def material_add(self,constituents,**kwargs): + def material_add(self,constituents=None,**kwargs): """ Add material entries. Parameters ---------- - constituents : dict + constituents : dict, optional Entries for 'constituents' as key-value pair. **kwargs Key-value pairs. @@ -263,13 +263,26 @@ class ConfigMaterial(Config): homogenization: SX """ - c = [{'constituents':u} for u in ConfigMaterial._constituents(**constituents)] + length = -1 + for v in kwargs.values(): + if hasattr(v,'__len__') and not isinstance(v,str): + if length != -1 and len(v) != length: + raise ValueError('Cannot add entries of different length') + else: + length = len(v) + length = max(1,length) + + c = [{} for _ in range(length)] if constituents is None else \ + [{'constituents':u} for u in ConfigMaterial._constituents(**constituents)] + if len(c) == 1: c = [copy.deepcopy(c[0]) for _ in range(length)] + + if length != 1 and length != len(c): + raise ValueError('Cannot add entries of different length') + for k,v in kwargs.items(): if hasattr(v,'__len__') and not isinstance(v,str): - if len(v) != len(c): - raise ValueError('Cannot add entries of different length') for i,vv in enumerate(v): - c[i][k] = [w.item() for w in vv] if isinstance(vv,np.ndarray) else vv.item() + c[i][k] = vv.item() if isinstance(vv,np.generic) else vv else: for i in range(len(c)): c[i][k] = v @@ -293,7 +306,7 @@ class ConfigMaterial(Config): if len(v) != N_material: raise ValueError('Cannot add entries of different length') for i,vv in enumerate(np.array(v)): - m[i][0][k] = [w.item() for w in vv] if isinstance(vv,np.ndarray) else vv.item() + m[i][0][k] = vv.item() if isinstance(vv,np.generic) else vv else: for i in range(N_material): m[i][0][k] = v diff --git a/python/tests/test_ConfigMaterial.py b/python/tests/test_ConfigMaterial.py index 0f2b6a90c..25c05d711 100644 --- a/python/tests/test_ConfigMaterial.py +++ b/python/tests/test_ConfigMaterial.py @@ -62,6 +62,12 @@ class TestConfigMaterial: del material_config['material'][0]['homogenization'] assert not material_config.is_complete + def test_incomplete_homogenization_N_constituents(self,reference_dir): + material_config = ConfigMaterial.load(reference_dir/'material.yaml') + for h in material_config['homogenization'].keys(): + del material_config['homogenization'][h]['N_constituents'] + assert not material_config.is_complete + def test_incomplete_phase_lattice(self,reference_dir): material_config = ConfigMaterial.load(reference_dir/'material.yaml') del material_config['phase']['Aluminum']['lattice'] @@ -85,9 +91,36 @@ class TestConfigMaterial: assert len(c['material']) == N for i,m in enumerate(c['material']): c = m['constituents'][0] - assert m['c'] == 1 and c['b'] == 0 and c['a'] == [i,1] + assert m['c'] == 1 and c['b'] == 0 and (c['a'] == [i,1]).all() - def test__constituents(self): + def test_constituents(self): c = ConfigMaterial._constituents(c=1,v=[2,3]) assert c[0][0]['c'] == c[1][0]['c'] == 1 assert c[0][0]['v'] == c[1][0]['v'] -1 ==2 + + @pytest.mark.parametrize('constituents',[{'W':1,'X':[2,3]},{'Y':4},{'Z':[5,6]}]) + @pytest.mark.parametrize('a',[[7.,8.],9.]) + @pytest.mark.parametrize('b',['bd',['efg','hi']]) + def test_material_add(self,tmp_path,constituents,a,b): + len_c = len(ConfigMaterial()._constituents(1,**constituents)) + len_a = len(a) if isinstance(a,list) else 1 + len_b = len(b) if isinstance(b,list) else 1 + m = ConfigMaterial().material_add(constituents,a=a,b=b) + m.save() + assert len(m['material']) == np.max([len_a,len_b,len_c]) + + @pytest.mark.parametrize('constituents',[{'W':1,'X':np.array([2,3])},{'Y':4},{'Z':np.array([5,6])}]) + @pytest.mark.parametrize('a',[np.array([7,8]),9]) + def test_material_add_np(self,tmp_path,constituents,a): + len_c = len(ConfigMaterial()._constituents(1,**constituents)) + len_a = len(a) if isinstance(a,np.ndarray) else 1 + m = ConfigMaterial().material_add(constituents,ld=a) + m.save() + assert len(m['material']) == np.max([len_a,len_c]) + + @pytest.mark.parametrize('constituents',[{'X':np.array([2,3,4,5])},{'Y':4}]) + @pytest.mark.parametrize('a',[np.array([1,2,3]),[4,5,6]]) + @pytest.mark.parametrize('b',[np.array([6.,7.]),[8.,9.]]) + def test_material_add_invalid(self,constituents,a,b): + with pytest.raises(ValueError): + ConfigMaterial().material_add(constituents,a=a,u=b) From 764aacf2a10c686a031bc4bfa5e0c047d8981a99 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 17:54:47 +0100 Subject: [PATCH 11/37] increasing test coverage --- python/damask/_environment.py | 6 +++--- python/damask/_geom.py | 10 +++++++++- python/tests/test_Geom.py | 5 +++++ python/tests/test_VTK.py | 9 +++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/python/damask/_environment.py b/python/damask/_environment.py index 9983a91aa..b040920c2 100644 --- a/python/damask/_environment.py +++ b/python/damask/_environment.py @@ -9,8 +9,6 @@ class Environment: @property def screen_size(self): - width = 1024 - height = 768 try: import wx _ = wx.App(False) # noqa @@ -23,7 +21,9 @@ class Environment: height = tk.winfo_screenheight() tk.destroy() except Exception as e: - pass + width = 1024 + height = 768 + return (width,height) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 3d73861ad..798bad0f8 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -2,6 +2,7 @@ import copy import multiprocessing as mp from functools import partial from os import path +import warnings import numpy as np import pandas as pd @@ -188,12 +189,16 @@ class Geom: """ Read a geom file. + Storing geometry files in ASCII format is deprecated. + This function will be removed in a future version of DAMASK. + Parameters ---------- fname : str, pathlib.Path, or file handle Geometry file to read. """ + warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning) try: f = open(fname) except TypeError: @@ -247,7 +252,6 @@ class Geom: return Geom(material.reshape(grid,order='F'),size,origin,comments) - @staticmethod def load_DREAM3D(fname,base_group,point_data=None,material='FeatureIds'): """ @@ -523,6 +527,9 @@ class Geom: """ Write a geom file. + Storing geometry files in ASCII format is deprecated. + This function will be removed in a future version of DAMASK. + Parameters ---------- fname : str or file handle @@ -531,6 +538,7 @@ class Geom: Compress geometry with 'x of y' and 'a to b'. """ + warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning) header = [f'{len(self.comments)+4} header'] + self.comments \ + ['grid a {} b {} c {}'.format(*self.grid), 'size x {} y {} z {}'.format(*self.size), diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index a9b9c91b5..09c43fe7e 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -45,6 +45,8 @@ class TestGeom: new = Geom(default.material[1:,1:,1:]+1,default.size*.9,np.ones(3)-default.origin,comments=['modified']) assert str(default.diff(new)) != '' + def test_repr(self,default): + print(default) def test_read_write_vtr(self,default,tmp_path): default.save(tmp_path/'default') @@ -70,6 +72,9 @@ class TestGeom: Geom(default.material[1:,1:,1:], size=np.ones(2)) + def test_save_load_ASCII(self,default,tmp_path): + default.save_ASCII(tmp_path/'ASCII') + assert geom_equal(Geom.load_ASCII(tmp_path/'ASCII'),default) def test_invalid_origin(self,default): with pytest.raises(ValueError): diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index bab6051b0..3b14981ae 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -84,6 +84,15 @@ class TestVTK: time.sleep(.5) assert(False) + def test_compress(self,tmp_path): + points = np.random.rand(102,3) + v = VTK.from_poly_data(points) + fname_c = tmp_path/'compreesed.vtp' + fname_p = tmp_path/'plain.vtp' + v.save(fname_c,parallel=False,compress=False) + v.save(fname_p,parallel=False,compress=True) + assert(VTK.load(fname_c).__repr__() == VTK.load(fname_p).__repr__()) + @pytest.mark.parametrize('fname',['a','a.vtp','a.b','a.b.vtp']) def test_filename_variations(self,tmp_path,fname): From 9160677ff330541e6c96fd0b2d6d4ca9933a07e3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 19:00:51 +0100 Subject: [PATCH 12/37] no need for special damask class (no action=extend) --- processing/post/addCompatibilityMismatch.py | 2 +- processing/post/addDisplacement.py | 2 +- processing/post/addSchmidfactors.py | 2 +- processing/pre/geom_fromDREAM3D.py | 2 +- processing/pre/geom_fromMinimalSurface.py | 2 +- processing/pre/geom_fromOsteonGeometry.py | 2 +- processing/pre/mentat_pbcOnBoxMesh.py | 38 ++++++++++----------- processing/pre/mentat_spectralBox.py | 2 +- processing/pre/seeds_fromDistribution.py | 2 +- processing/pre/seeds_fromPokes.py | 2 +- 10 files changed, 28 insertions(+), 28 deletions(-) diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index 0e7d3ea42..9a2bd1a5b 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -136,7 +136,7 @@ def shapeMismatch(size,F,nodes,centres): # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ +parser = OptionParser(usage='%prog options [ASCIItable(s)]', description = """ Add column(s) containing the shape and volume mismatch resulting from given deformation gradient. Operates on periodic three-dimensional x,y,z-ordered data sets. diff --git a/processing/post/addDisplacement.py b/processing/post/addDisplacement.py index a6cff86ab..069d923e8 100755 --- a/processing/post/addDisplacement.py +++ b/processing/post/addDisplacement.py @@ -16,7 +16,7 @@ scriptID = ' '.join([scriptName,damask.version]) # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ +parser = OptionParser(usage='%prog options [ASCIItable(s)]', description = """ Add displacments resulting from deformation gradient field. Operates on periodic three-dimensional x,y,z-ordered data sets. Outputs at cell centers or cell nodes (into separate file). diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 8f43308cb..10f2443be 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -98,7 +98,7 @@ slipSystems = { # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ +parser = OptionParser(usage='%prog options [ASCIItable(s)]', description = """ Add columns listing Schmid factors (and optional trace vector of selected system) for given Euler angles. """, version = scriptID) diff --git a/processing/pre/geom_fromDREAM3D.py b/processing/pre/geom_fromDREAM3D.py index eca837455..eb4fe443e 100755 --- a/processing/pre/geom_fromDREAM3D.py +++ b/processing/pre/geom_fromDREAM3D.py @@ -14,7 +14,7 @@ scriptID = ' '.join([scriptName,damask.version]) # MAIN #-------------------------------------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [DREAM.3Dfile(s)]', description = """ +parser = OptionParser(usage='%prog options [DREAM.3Dfile(s)]', description = """ Converts DREAM.3D file. Input can be cell data (direct pointwise takeover) or grain data (individual grains are segmented). Requires orientation data as quaternion. diff --git a/processing/pre/geom_fromMinimalSurface.py b/processing/pre/geom_fromMinimalSurface.py index eb0cdcc3b..5f58d960c 100755 --- a/processing/pre/geom_fromMinimalSurface.py +++ b/processing/pre/geom_fromMinimalSurface.py @@ -17,7 +17,7 @@ minimal_surfaces = list(damask.Geom._minimal_surface.keys()) # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [geomfile]', description = """ +parser = OptionParser(usage='%prog options [geomfile]', description = """ Generate a bicontinuous structure of given type. """, version = scriptID) diff --git a/processing/pre/geom_fromOsteonGeometry.py b/processing/pre/geom_fromOsteonGeometry.py index 0b6d48001..51aca3056 100755 --- a/processing/pre/geom_fromOsteonGeometry.py +++ b/processing/pre/geom_fromOsteonGeometry.py @@ -17,7 +17,7 @@ scriptID = ' '.join([scriptName,damask.version]) # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [geomfile]', description = """ +parser = OptionParser(usage='%prog options [geomfile]', description = """ Generate description of an osteon enclosing the Harvesian canal and separated by interstitial tissue. The osteon phase is lamellar with a twisted plywood structure. Its fiber orientation is oscillating by +/- amplitude within one period. diff --git a/processing/pre/mentat_pbcOnBoxMesh.py b/processing/pre/mentat_pbcOnBoxMesh.py index 3677a5efa..e03a4e5c5 100755 --- a/processing/pre/mentat_pbcOnBoxMesh.py +++ b/processing/pre/mentat_pbcOnBoxMesh.py @@ -30,11 +30,11 @@ def parseMFD(dat): # lines that start with a space are numerical data if line[0] == ' ': formatted[section]['els'].append([]) - + # grab numbers nums = re.split(r'\s+', line.strip()) - - for num in nums: + + for num in nums: # floating point has format ' -x.xxxxxxxxxxxxe+yy' # scientific notation is used for float if (len(num) >= 4) and (num[-4] == 'e'): @@ -47,7 +47,7 @@ def parseMFD(dat): else: formatted[section]['els'].append([]) formatted[section]['els'][-1] = line - + else: # Not in a section, we are looking for a =beg= now search = re.search(r'=beg=\s+(\d+)\s\((.*?)\)', line) if search is not None: # found start of a new section @@ -60,7 +60,7 @@ def parseMFD(dat): section += 1 formatted.append({'label': '', 'uid': -2, 'els': []}) # make dummy section to store unrecognized data formatted[section]['els'].append(line) - + return formatted def asMFD(mfd_data): @@ -93,14 +93,14 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to 'max': np.zeros(3,dtype='d'), 'delta': np.zeros(3,dtype='d'), } - + mfd_dict = {} for i in range(len(mfd_data)): mfd_dict[mfd_data[i]['label']] = i NodeCoords = np.array(mfd_data[mfd_dict['nodes']]['els'][1::4])[:,1:4] - Nnodes = NodeCoords.shape[0] - + Nnodes = NodeCoords.shape[0] + box['min'] = NodeCoords.min(axis=0) # find the bounding box box['max'] = NodeCoords.max(axis=0) box['delta'] = box['max']-box['min'] @@ -131,7 +131,7 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to elif (key[base[coord]] == "%.8e"%box['max'][coord]): # compare to max of bounding box (i.e. is on outer face?) Nmax += 1 # count outer (front) face membership maxFlag[coord] = True # remember face membership (for linked nodes) - + if Nmin > 0: # node is on a back face # prepare for any non-existing entries in the data structure if key['x'] not in baseNode.keys(): @@ -140,17 +140,17 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to baseNode[key['x']][key['y']] = {} if key['z'] not in baseNode[key['x']][key['y']].keys(): baseNode[key['x']][key['y']][key['z']] = 0 - + baseNode[key['x']][key['y']][key['z']] = node+1 # remember the base node id if Nmax > 0 and Nmax >= Nmin: # node is on at least as many front than back faces if any([maxFlag[i] and active[i] for i in range(3)]): linkNodes.append({'id': node+1,'coord': NodeCoords[node], 'faceMember': [maxFlag[i] and active[i] for i in range(3)]}) - + mfd_data[mfd_dict['entities']]['els'][0][0] += len(linkNodes) * 3 - + baseCorner = baseNode["%.8e"%box['min'][0]]["%.8e"%box['min'][1]]["%.8e"%box['min'][2]] # detect ultimate base node - + links = {'uid': 1705, 'label': 'links', 'els': [[7,0],[9,0]]} linkID = 0 for node in linkNodes: # loop over all linked nodes @@ -165,7 +165,7 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to for dof in [1,2,3]: tied_node = node['id'] nterms = 1 + nLinks - + linkID += 1 # Link header links['els'].append('link{0}\n'.format(linkID)) @@ -173,10 +173,10 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to links['els'].append([0]) links['els'].append([0]) links['els'].append([0, 0, 0, tied_node]) - + # these need to be put in groups of four link_payload = [dof, 0, nterms] - + # Individual node contributions (node, dof, coef.) for i in range(nterms): if i == nLinks: @@ -190,7 +190,7 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to link_payload.append(1.0 - nLinks) else: link_payload.append(1.0) - + # Needs to be formatted 4 data points per row, character width of 20, so 80 total for j in range(0, len(link_payload), 4): links['els'].append(link_payload[j:j+4]) @@ -206,9 +206,9 @@ def add_servoLinks(mfd_data,active=[True,True,True]): # directions on which to #-------------------------------------------------------------------------------------------------- # MAIN -#-------------------------------------------------------------------------------------------------- +#-------------------------------------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(usage='%prog options [file[s]]', description = """ Set up servo linking to achieve periodic boundary conditions for a regular hexahedral mesh. Use *py_connection to operate on model presently opened in MSC.Mentat. """, version = scriptID) diff --git a/processing/pre/mentat_spectralBox.py b/processing/pre/mentat_spectralBox.py index 7d78cb973..57c2644c2 100755 --- a/processing/pre/mentat_spectralBox.py +++ b/processing/pre/mentat_spectralBox.py @@ -168,7 +168,7 @@ def initial_conditions(material): # MAIN #-------------------------------------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(usage='%prog options [file[s]]', description = """ Generate MSC.Marc FE hexahedral mesh from geom file. """, version = scriptID) diff --git a/processing/pre/seeds_fromDistribution.py b/processing/pre/seeds_fromDistribution.py index 375f33ad3..1f20db995 100755 --- a/processing/pre/seeds_fromDistribution.py +++ b/processing/pre/seeds_fromDistribution.py @@ -164,7 +164,7 @@ class myThread (threading.Thread): # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(usage='%prog options [file[s]]', description = """ Monte Carlo simulation to produce seed file that gives same size distribution like given geometry file. """, version = scriptID) diff --git a/processing/pre/seeds_fromPokes.py b/processing/pre/seeds_fromPokes.py index 887d76392..67acf0f6b 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -16,7 +16,7 @@ scriptID = ' '.join([scriptName,damask.version]) # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(usage='%prog options [file[s]]', description = """ Create seeds file by poking at 45 degree through given geom file. Mimics APS Beamline 34-ID-E DAXM poking. From 149fce0a7eb8c5149ab1e5302bea2816034b0cf5 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 19:24:31 +0100 Subject: [PATCH 13/37] increase test coverage --- python/damask/util.py | 13 ++----------- python/tests/test_Table.py | 6 ++++++ python/tests/test_util.py | 8 ++++++++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index d02877f8f..fa983d64e 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -56,6 +56,8 @@ def croak(what, newline = True): """ Write formated to stderr. + DEPRECATED + Parameters ---------- what : str or iterable @@ -393,17 +395,6 @@ class bcolors: UNDERLINE = '\033[4m' CROSSOUT = '\033[9m' - def disable(self): - self.HEADER = '' - self.OKBLUE = '' - self.OKGREEN = '' - self.WARNING = '' - self.FAIL = '' - self.ENDC = '' - self.BOLD = '' - self.UNDERLINE = '' - self.CROSSOUT = '' - class return_message: """Object with formatted return message.""" diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index 9dad681bd..8c4465dc1 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -17,6 +17,12 @@ def reference_dir(reference_dir_base): class TestTable: + def test_repr(self,default): + print(default) + + def test_len(self): + len(Table(np.random.rand(7,3),{'X':3})) == 7 + def test_get_scalar(self,default): d = default.get('s') assert np.allclose(d,1.0) and d.shape[1:] == (1,) diff --git a/python/tests/test_util.py b/python/tests/test_util.py index 19b6377f6..9906689e9 100644 --- a/python/tests/test_util.py +++ b/python/tests/test_util.py @@ -15,6 +15,10 @@ class TestUtil: out,err = util.execute('sh -c "echo $test_for_execute"',env={'test_for_execute':'test'}) assert out=='test\n' and err=='' + def test_execute_invalid(self): + with pytest.raises(RuntimeError): + util.execute('/bin/false') + def test_croak(self): util.croak('Burp!') @@ -93,3 +97,7 @@ class TestUtil: ]) def test_shapeblender(self,a,b,answer): assert util.shapeblender(a,b) == answer + + @pytest.mark.parametrize('style',[util.emph,util.deemph,util.delete,util.strikeout]) + def test_decorate(self,style): + assert 'DAMASK' in style('DAMASK') From 1eb9d494c79bc560fbd126cbe9e52f8f6f7772c5 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 19:51:15 +0100 Subject: [PATCH 14/37] not specific to Orientation class --- python/damask/_orientation.py | 44 +++++++++++------------------------ python/damask/util.py | 20 ++++++++++++++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index e0a00e0a0..c849b0d89 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -4,7 +4,7 @@ from . import Rotation from . import util from . import mechanics -__parameter_doc__ = \ +_parameter_doc = \ """lattice : str Either a crystal family out of [triclinic, monoclinic, orthorhombic, tetragonal, hexagonal, cubic] or a Bravais lattice out of [aP, mP, mS, oP, oS, oI, oF, tP, tI, hP, cP, cI, cF]. @@ -27,22 +27,6 @@ __parameter_doc__ = \ """ -def extend_docstring(): - """Decorator: Append Orientation parameter documentation to function's docstring.""" - def _decorator(func): - func.__doc__ += __parameter_doc__ - return func - return _decorator - - -def extended_docstring(f): - """Decorator: Combine Orientation parameter documentation with another function's docstring.""" - def _decorator(func): - func.__doc__ = f.__doc__ + __parameter_doc__ - return func - return _decorator - - class Orientation(Rotation): """ Representation of crystallographic orientation as combination of rotation and either crystal family or Bravais lattice. @@ -128,7 +112,7 @@ class Orientation(Rotation): } - @extend_docstring() + @util.extend_docstring(_parameter_doc) def __init__(self, rotation = None, lattice = None, @@ -279,73 +263,73 @@ class Orientation(Rotation): @classmethod - @extended_docstring(Rotation.from_random) + @util.extended_docstring(Rotation.from_random,_parameter_doc) def from_random(cls,**kwargs): return cls(rotation=Rotation.from_random(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_quaternion) + @util.extended_docstring(Rotation.from_quaternion,_parameter_doc) def from_quaternion(cls,**kwargs): return cls(rotation=Rotation.from_quaternion(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_Eulers) + @util.extended_docstring(Rotation.from_Eulers,_parameter_doc) def from_Eulers(cls,**kwargs): return cls(rotation=Rotation.from_Eulers(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_axis_angle) + @util.extended_docstring(Rotation.from_axis_angle,_parameter_doc) def from_axis_angle(cls,**kwargs): return cls(rotation=Rotation.from_axis_angle(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_basis) + @util.extended_docstring(Rotation.from_basis,_parameter_doc) def from_basis(cls,**kwargs): return cls(rotation=Rotation.from_basis(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_matrix) + @util.extended_docstring(Rotation.from_matrix,_parameter_doc) def from_matrix(cls,**kwargs): return cls(rotation=Rotation.from_matrix(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_Rodrigues) + @util.extended_docstring(Rotation.from_Rodrigues,_parameter_doc) def from_Rodrigues(cls,**kwargs): return cls(rotation=Rotation.from_Rodrigues(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_homochoric) + @util.extended_docstring(Rotation.from_homochoric,_parameter_doc) def from_homochoric(cls,**kwargs): return cls(rotation=Rotation.from_homochoric(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_cubochoric) + @util.extended_docstring(Rotation.from_cubochoric,_parameter_doc) def from_cubochoric(cls,**kwargs): return cls(rotation=Rotation.from_cubochoric(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_spherical_component) + @util.extended_docstring(Rotation.from_spherical_component,_parameter_doc) def from_spherical_component(cls,**kwargs): return cls(rotation=Rotation.from_spherical_component(**kwargs),**kwargs) @classmethod - @extended_docstring(Rotation.from_fiber_component) + @util.extended_docstring(Rotation.from_fiber_component,_parameter_doc) def from_fiber_component(cls,**kwargs): return cls(rotation=Rotation.from_fiber_component(**kwargs),**kwargs) @classmethod - @extend_docstring() + @util.extend_docstring(_parameter_doc) def from_directions(cls,uvw,hkl,**kwargs): """ Initialize orientation object from two crystallographic directions. diff --git a/python/damask/util.py b/python/damask/util.py index fa983d64e..d1b3ed842 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -26,8 +26,8 @@ __all__=[ 'return_message', 'extendableOption', 'execution_stamp', - 'shapeshifter', - 'shapeblender', + 'shapeshifter', 'shapeblender', + 'extend_docstring', 'extended_docstring' ] #################################################################################################### @@ -302,6 +302,22 @@ def shapeblender(a,b): return a + b[i:] +def extend_docstring(general): + """Decorator: Append Orientation parameter documentation to function's docstring.""" + def _decorator(func): + func.__doc__ += general + return func + return _decorator + + +def extended_docstring(f,general): + """Decorator: Combine Orientation parameter documentation with another function's docstring.""" + def _decorator(func): + func.__doc__ = f.__doc__ + general + return func + return _decorator + + #################################################################################################### # Classes #################################################################################################### From 6aa013d8314c23339813d436652826ae887dba85 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 14 Nov 2020 22:29:18 +0100 Subject: [PATCH 15/37] new tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 75aa46a4a..583c6c2b8 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 75aa46a4a1c27f3d2c8d7c7eff393dcf069ff41c +Subproject commit 583c6c2b89980259df1cf8ced4e998c5910cc831 From 05c1007addfae8ade0ba6462e0c123db978ccc28 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 10:22:01 +0100 Subject: [PATCH 16/37] documentation improvments + acceptance of lists example code at respective function, no space in 'or' variable names (sphinx cannot handle this) --- python/damask/_orientation.py | 85 ++++++++++++++++++++++------------- python/damask/_rotation.py | 2 +- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index c849b0d89..aa15879bf 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -69,18 +69,6 @@ class Orientation(Rotation): An array of 3 x 5 random orientations reduced to the fundamental zone of tetragonal symmetry: >>> damask.Orientation.from_random(shape=(3,5),lattice='tetragonal').reduced - Disorientation between two specific orientations of hexagonal symmetry: - >>> a = damask.Orientation.from_Eulers(phi=[123,32,21],degrees=True,lattice='hexagonal') - >>> b = damask.Orientation.from_Eulers(phi=[104,11,87],degrees=True,lattice='hexagonal') - >>> a.disorientation(b) - - Inverse pole figure color of the e_3 direction for a crystal in "Cube" orientation with cubic symmetry: - >>> o = damask.Orientation(lattice='cubic') - >>> o.IPF_color(o.to_SST(np.array([0,0,1]))) - - Schmid matrix (in lab frame) of slip systems of a face-centered cubic crystal in "Goss" orientation: - >>> damask.Orientation.from_Eulers(phi=[0,45,0],degrees=True,lattice='cF').Schmid('slip') - """ crystal_families = ['triclinic', @@ -831,6 +819,14 @@ class Orientation(Rotation): rgb : numpy.ndarray of shape (...,3) RGB array of IPF colors. + Examples + -------- + Inverse pole figure color of the e_3 direction for a crystal in "Cube" orientation with cubic symmetry: + + >>> o = damask.Orientation(lattice='cubic') + >>> o.IPF_color(o.to_SST([0,0,1])) + array([1., 0., 0.]) + References ---------- Bases are computed from @@ -851,7 +847,8 @@ class Orientation(Rotation): ... } """ - if vector.shape[-1] != 3: + vector_ = np.array(vector) + if vector_.shape[-1] != 3: raise ValueError('Input is not a field of three-dimensional vectors.') if self.family == 'cubic': @@ -887,23 +884,23 @@ class Orientation(Rotation): [ 0., 1., 0.] ]), } else: # direct exit for unspecified symmetry - return np.zeros_like(vector) + return np.zeros_like(vector_) if proper: components_proper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['proper'], vector.shape+(3,)), - vector), 12) + np.broadcast_to(basis['proper'], vector_.shape+(3,)), + vector_), 12) components_improper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector.shape+(3,)), - vector), 12) + np.broadcast_to(basis['improper'], vector_.shape+(3,)), + vector_), 12) in_SST = np.all(components_proper >= 0.0,axis=-1) \ | np.all(components_improper >= 0.0,axis=-1) components = np.where((in_SST & np.all(components_proper >= 0.0,axis=-1))[...,np.newaxis], components_proper,components_improper) else: components = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector.shape+(3,)), - np.block([vector[...,:2],np.abs(vector[...,2:3])])), 12) + np.broadcast_to(basis['improper'], vector_.shape+(3,)), + np.block([vector_[...,:2],np.abs(vector_[...,2:3])])), 12) in_SST = np.all(components >= 0.0,axis=-1) @@ -941,6 +938,22 @@ class Orientation(Rotation): Currently requires same crystal family for both orientations. For extension to cases with differing symmetry see A. Heinz and P. Neumann 1991 and 10.1107/S0021889808016373. + Examples + -------- + Disorientation between two specific orientations of hexagonal symmetry: + + >>> import damask + >>> a = damask.Orientation.from_Eulers(phi=[123,32,21],degrees=True,lattice='hexagonal') + >>> b = damask.Orientation.from_Eulers(phi=[104,11,87],degrees=True,lattice='hexagonal') + >>> a.disorientation(b) + Crystal family hexagonal + Quaternion: (real=0.976, imag=<+0.189, +0.018, +0.103>) + Matrix: + [[ 0.97831006 0.20710935 0.00389135] + [-0.19363288 0.90765544 0.37238141] + [ 0.07359167 -0.36505797 0.92807163]] + Bunge Eulers / deg: (11.40, 21.86, 0.60) + """ if self.family is None or other.family is None: raise ValueError('Missing crystal symmetry') @@ -1049,8 +1062,8 @@ class Orientation(Rotation): raise ValueError('Missing crystal symmetry') eq = self.equivalent - blend = util.shapeblender(eq.shape,vector.shape[:-1]) - poles = eq.broadcast_to(blend,mode='right') @ np.broadcast_to(vector,blend+(3,)) + blend = util.shapeblender(eq.shape,np.array(vector).shape[:-1]) + poles = eq.broadcast_to(blend,mode='right') @ np.broadcast_to(np.array(vector),blend+(3,)) ok = self.in_SST(poles,proper=proper) ok &= np.cumsum(ok,axis=0) == 1 loc = np.where(ok) @@ -1069,12 +1082,12 @@ class Orientation(Rotation): Parameters ---------- - uvtw | hkil : numpy.ndarray of shape (...,4) + uvtw|hkil : numpy.ndarray of shape (...,4) Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil). Returns ------- - uvw | hkl : numpy.ndarray of shape (...,3) + uvw|hkl : numpy.ndarray of shape (...,3) Miller indices of [uvw] direction or (hkl) plane normal. """ @@ -1097,12 +1110,12 @@ class Orientation(Rotation): Parameters ---------- - uvw | hkl : numpy.ndarray of shape (...,3) + uvw|hkl : numpy.ndarray of shape (...,3) Miller indices of crystallographic direction [uvw] or plane normal (hkl). Returns ------- - uvtw | hkil : numpy.ndarray of shape (...,4) + uvtw|hkil : numpy.ndarray of shape (...,4) Miller–Bravais indices of [uvtw] direction or (hkil) plane normal. """ @@ -1126,7 +1139,7 @@ class Orientation(Rotation): Parameters ---------- - direction | normal : numpy.ndarray of shape (...,3) + direction|normal : numpy.ndarray of shape (...,3) Vector along direction or plane normal. Returns @@ -1150,7 +1163,7 @@ class Orientation(Rotation): Parameters ---------- - uvw | hkl : numpy.ndarray of shape (...,3) + uvw|hkl : numpy.ndarray of shape (...,3) Miller indices of crystallographic direction or plane normal. with_symmetry : bool, optional Calculate all N symmetrically equivalent vectors. @@ -1178,7 +1191,7 @@ class Orientation(Rotation): Parameters ---------- - uvw | hkl : numpy.ndarray of shape (...,3) + uvw|hkl : numpy.ndarray of shape (...,3) Miller indices of crystallographic direction or plane normal. with_symmetry : bool, optional Calculate all N symmetrically equivalent vectors. @@ -1201,13 +1214,25 @@ class Orientation(Rotation): Parameters ---------- mode : str - Type of kinematics, e.g. 'slip' or 'twin'. + Type of kinematics, i.e. 'slip' or 'twin'. Returns ------- P : numpy.ndarray of shape (...,N,3,3) Schmid matrix for each of the N deformation systems. + Examples + -------- + Schmid matrix (in lab frame) of slip systems of a face-centered + cubic crystal in "Goss" orientation. + + >>> import damask + >>> import numpy as np + >>> np.set_printoptions(3,suppress=True,floatmode='fixed') + >>> damask.Orientation.from_Eulers(phi=[0,45,0],degrees=True,lattice='cF').Schmid('slip')[0] + array([[ 0.000, 0.000, 0.000], + [ 0.577, -0.000, 0.816], + [ 0.000, 0.000, 0.000]]) """ d = self.to_frame(uvw=self.kinematics[mode]['direction'],with_symmetry=False) p = self.to_frame(hkl=self.kinematics[mode]['plane'] ,with_symmetry=False) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index deae8b6ac..145b27884 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -404,7 +404,7 @@ class Rotation: Returns ------- h : numpy.ndarray of shape (...,3) - Homochoric vector: (h_1, h_2, h_3), ǀhǀ < 1/2*π^(2/3). + Homochoric vector: (h_1, h_2, h_3), ǀhǀ < (3/4*π)^(1/3). """ return Rotation._qu2ho(self.quaternion) From 51e5dda702fda11c157fd53dc8f3a0b8d8bd6927 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 10:53:23 +0100 Subject: [PATCH 17/37] documentation + consistent string formatting --- python/damask/_geom.py | 10 +++---- python/damask/_result.py | 4 +-- python/damask/util.py | 55 ++++++++++++++++++++++------------- python/tests/test_Rotation.py | 6 ++-- python/tests/test_util.py | 2 +- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 798bad0f8..d364ad6e8 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -74,23 +74,23 @@ class Geom: """ message = [] if np.any(other.grid != self.grid): - message.append(util.delete(f'grid a b c: {util.srepr(other.grid," x ")}')) + message.append(util.deemph(f'grid a b c: {util.srepr(other.grid," x ")}')) message.append(util.emph( f'grid a b c: {util.srepr( self.grid," x ")}')) if not np.allclose(other.size,self.size): - message.append(util.delete(f'size x y z: {util.srepr(other.size," x ")}')) + message.append(util.deemph(f'size x y z: {util.srepr(other.size," x ")}')) message.append(util.emph( f'size x y z: {util.srepr( self.size," x ")}')) if not np.allclose(other.origin,self.origin): - message.append(util.delete(f'origin x y z: {util.srepr(other.origin," ")}')) + message.append(util.deemph(f'origin x y z: {util.srepr(other.origin," ")}')) message.append(util.emph( f'origin x y z: {util.srepr( self.origin," ")}')) if other.N_materials != self.N_materials: - message.append(util.delete(f'# materials: {other.N_materials}')) + message.append(util.deemph(f'# materials: {other.N_materials}')) message.append(util.emph( f'# materials: { self.N_materials}')) if np.nanmax(other.material) != np.nanmax(self.material): - message.append(util.delete(f'max material: {np.nanmax(other.material)}')) + message.append(util.deemph(f'max material: {np.nanmax(other.material)}')) message.append(util.emph( f'max material: {np.nanmax( self.material)}')) return util.return_message(message) diff --git a/python/damask/_result.py b/python/damask/_result.py index 5bed4347f..45a7fafc6 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -167,9 +167,7 @@ class Result: def allow_modification(self): - print(util.bcolors().WARNING+util.bcolors().BOLD+ - 'Warning: Modification of existing datasets allowed!'+ - util.bcolors().ENDC) + print(util.warn('Warning: Modification of existing datasets allowed!')) self._allow_modification = True def disallow_modification(self): diff --git a/python/damask/util.py b/python/damask/util.py index d1b3ed842..49e85c9f5 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -17,7 +17,7 @@ __all__=[ 'srepr', 'croak', 'report', - 'emph','deemph','delete','strikeout', + 'emph','deemph','warn','strikeout', 'execute', 'show_progress', 'scale_to_coprime', @@ -74,7 +74,7 @@ def croak(what, newline = True): def report(who = None, what = None): """ - Reports script and file name. + Report script and file name. DEPRECATED @@ -86,16 +86,13 @@ def emph(what): """Formats string with emphasis.""" return bcolors.BOLD+srepr(what)+bcolors.ENDC - def deemph(what): """Formats string with deemphasis.""" return bcolors.DIM+srepr(what)+bcolors.ENDC - -def delete(what): - """Formats string as deleted.""" - return bcolors.DIM+srepr(what)+bcolors.ENDC - +def warn(what): + """Formats string for warning.""" + return bcolors.WARNING+emph(what)+bcolors.ENDC def strikeout(what): """Formats string as strikeout.""" @@ -302,20 +299,38 @@ def shapeblender(a,b): return a + b[i:] -def extend_docstring(general): - """Decorator: Append Orientation parameter documentation to function's docstring.""" - def _decorator(func): - func.__doc__ += general - return func - return _decorator +def extend_docstring(extra_docstring): + """ + Decorator: Append to function's docstring. + + Parameters + ---------- + extra_docstring : str + Docstring to append. + + """ + def _decorator(func): + func.__doc__ += extra_docstring + return func + return _decorator -def extended_docstring(f,general): - """Decorator: Combine Orientation parameter documentation with another function's docstring.""" - def _decorator(func): - func.__doc__ = f.__doc__ + general - return func - return _decorator +def extended_docstring(f,extra_docstring): + """ + Decorator: Combine another function's docstring with a given docstring. + + Parameters + ---------- + f : function + Function of which the docstring is taken. + extra_docstring : str + Docstring to append. + + """ + def _decorator(func): + func.__doc__ = f.__doc__ + extra_docstring + return func + return _decorator #################################################################################################### diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index 9361008e5..20eb49b7e 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -772,15 +772,15 @@ class TestRotation: Rotation.from_random(shape) def test_equal(self): - r = Rotation.from_random(seed=0) + r = Rotation.from_random() assert r == r def test_unequal(self): - r = Rotation.from_random(seed=0) + r = Rotation.from_random() assert not (r != r) def test_inversion(self): - r = Rotation.from_random(seed=0) + r = Rotation.from_random() assert r == ~~r @pytest.mark.parametrize('shape',[None,1,(1,),(4,2),(1,1,1)]) diff --git a/python/tests/test_util.py b/python/tests/test_util.py index 9906689e9..eb1084b09 100644 --- a/python/tests/test_util.py +++ b/python/tests/test_util.py @@ -98,6 +98,6 @@ class TestUtil: def test_shapeblender(self,a,b,answer): assert util.shapeblender(a,b) == answer - @pytest.mark.parametrize('style',[util.emph,util.deemph,util.delete,util.strikeout]) + @pytest.mark.parametrize('style',[util.emph,util.deemph,util.warn,util.strikeout]) def test_decorate(self,style): assert 'DAMASK' in style('DAMASK') From 15af12bbb4c3696b344415b6d75aca2cbf51b3b6 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 11:38:26 +0100 Subject: [PATCH 18/37] __ne__ is automatically set to !__eq__, __neq__ has no special meaning --- python/damask/_rotation.py | 16 ---------------- python/tests/test_Rotation.py | 15 ++++++++------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 145b27884..a77c40ca5 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -107,22 +107,6 @@ class Rotation: and np.allclose(self.quaternion,other.quaternion) - def __neq__(self,other): - """ - Not Equal to other. - - Equality is determined taking limited floating point precision into - account. See numpy.allclose for details. - - Parameters - ---------- - other : Rotation - Rotation to check for inequality. - - """ - return not self.__eq__(other) - - @property def shape(self): return self.quaternion.shape[:-1] diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index 20eb49b7e..fe30726e3 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -769,15 +769,16 @@ class TestRotation: @pytest.mark.parametrize('shape',[None,1,(4,4)]) def test_random(self,shape): - Rotation.from_random(shape) + r = Rotation.from_random(shape) + if shape is None: + assert r.shape == () + elif shape == 1: + assert r.shape == (1,) + else: + assert r.shape == shape def test_equal(self): - r = Rotation.from_random() - assert r == r - - def test_unequal(self): - r = Rotation.from_random() - assert not (r != r) + assert Rotation.from_random(seed=1) == Rotation.from_random(seed=1) def test_inversion(self): r = Rotation.from_random() From 01d84c1477b93e3de7a52c674b67027d4a027e9d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 11:49:52 +0100 Subject: [PATCH 19/37] testing also functions with graphical output --- python/tests/conftest.py | 2 +- python/tests/test_Colormap.py | 2 +- python/tests/test_Geom.py | 2 +- python/tests/test_VTK.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 9c58eedd9..5f5de52ba 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -26,7 +26,7 @@ def patch_datetime_now(monkeypatch): monkeypatch.setattr(datetime, 'datetime', mydatetime) @pytest.fixture -def execution_stamp(monkeypatch): +def patch_execution_stamp(monkeypatch): """Set damask.util.execution_stamp for reproducible tests results.""" def execution_stamp(class_name,function_name=None): _function_name = '' if function_name is None else f'.{function_name}' diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 71d896016..9b317b451 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -17,7 +17,7 @@ def reference_dir(reference_dir_base): class TestColormap: @pytest.fixture(autouse=True) - def _execution_stamp(self, execution_stamp): + def _patch_execution_stamp(self, patch_execution_stamp): print('patched damask.util.execution_stamp') def test_conversion(self): diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index 09c43fe7e..5fd4d3b1c 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -34,7 +34,7 @@ def reference_dir(reference_dir_base): class TestGeom: @pytest.fixture(autouse=True) - def _execution_stamp(self, execution_stamp): + def _patch_execution_stamp(self, patch_execution_stamp): print('patched damask.util.execution_stamp') def test_diff_equal(self,default): diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index 3b14981ae..53fbaa2f4 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -23,7 +23,7 @@ def default(): class TestVTK: @pytest.fixture(autouse=True) - def _execution_stamp(self, execution_stamp): + def _patch_execution_stamp(self, patch_execution_stamp): print('patched damask.util.execution_stamp') def test_rectilinearGrid(self,tmp_path): From 1541ac0add6f58cb229ad8804d2c437c38778a6a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 12:00:26 +0100 Subject: [PATCH 20/37] more intuitive use --- python/damask/_colormap.py | 23 +++++++++++------------ python/damask/_geom.py | 3 +-- python/tests/conftest.py | 12 +++++++++++- python/tests/test_Colormap.py | 3 +++ 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 6803f4c60..87135caf9 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -36,6 +36,17 @@ class Colormap(mpl.colors.ListedColormap): """Return inverted colormap.""" return self.reversed() + def __repr__(self): + """Show colormap as matplotlib figure.""" + fig = plt.figure(figsize=(5,.5)) + ax1 = fig.add_axes([0, 0, 1, 1]) + ax1.set_axis_off() + ax1.imshow(np.linspace(0,1,self.N).reshape(1,-1), + aspect='auto', cmap=self, interpolation='nearest') + plt.show(block = False) + return self.name + + @staticmethod def from_range(low,high,name='DAMASK colormap',N=256,model='rgb'): """ @@ -203,18 +214,6 @@ class Colormap(mpl.colors.ListedColormap): mode='RGBA') - def show(self,aspect=10,vertical=False): - """Show colormap as matplotlib figure.""" - fig = plt.figure(figsize=(5/aspect,5) if vertical else (5,5/aspect)) - ax1 = fig.add_axes([0, 0, 1, 1]) - ax1.set_axis_off() - ax1.imshow(np.linspace(1 if vertical else 0, - 0 if vertical else 1, - self.N).reshape((-1,1) if vertical else (1,-1)), - aspect='auto', cmap=self, interpolation='nearest') - plt.show() - - def reversed(self,name=None): """ Make a reversed instance of the colormap. diff --git a/python/damask/_geom.py b/python/damask/_geom.py index d364ad6e8..f75a48fff 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -555,8 +555,7 @@ class Geom: def show(self): """Show on screen.""" - v = VTK.from_rectilinear_grid(self.grid,self.size,self.origin) - v.show() + VTK.from_rectilinear_grid(self.grid,self.size,self.origin).show() def add_primitive(self,dimension,center,exponent, diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 5f5de52ba..f402c4614 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -1,8 +1,13 @@ from pathlib import Path import datetime +import os import numpy as np import pytest +import matplotlib as mpl +if os.name == 'posix' and 'DISPLAY' not in os.environ: + mpl.use('Agg') +import matplotlib.pyplot as plt import damask @@ -13,7 +18,6 @@ def patch_damask_version(monkeypatch): """Set damask.version for reproducible tests results.""" monkeypatch.setattr(damask, 'version', patched_version) - patched_date = datetime.datetime(2019, 11, 2, 11, 58, 0) @pytest.fixture def patch_datetime_now(monkeypatch): @@ -34,6 +38,12 @@ def patch_execution_stamp(monkeypatch): monkeypatch.setattr(damask.util, 'execution_stamp', execution_stamp) +@pytest.fixture +def patch_plt_show(monkeypatch): + def _None(block=None): + pass + monkeypatch.setattr(plt, 'show', _None, raising=True) + def pytest_addoption(parser): parser.addoption("--update", diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 9b317b451..279f7eea9 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -20,6 +20,9 @@ class TestColormap: def _patch_execution_stamp(self, patch_execution_stamp): print('patched damask.util.execution_stamp') + def test_repr(self,patch_plt_show): + print(Colormap.from_predefined('stress')) + def test_conversion(self): specials = np.array([[0.,0.,0.], [1.,0.,0.], From fd8743af5e2d9d457f68b037b32c3df0a4b3a51a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 13:06:26 +0100 Subject: [PATCH 21/37] clearly distinguish seeds for tessellation and seeds for RNG --- python/damask/_orientation.py | 1 + python/damask/_rotation.py | 24 ++++++++++++------------ python/damask/seeds.py | 12 ++++++------ python/damask/util.py | 30 ++++++++++++++++++++++++++---- python/tests/conftest.py | 6 ++++++ python/tests/test_Orientation.py | 20 ++++++++++---------- python/tests/test_Rotation.py | 2 +- 7 files changed, 62 insertions(+), 33 deletions(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index aa15879bf..e60459489 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -1233,6 +1233,7 @@ class Orientation(Rotation): array([[ 0.000, 0.000, 0.000], [ 0.577, -0.000, 0.816], [ 0.000, 0.000, 0.000]]) + """ d = self.to_frame(uvw=self.kinematics[mode]['direction'],with_symmetry=False) p = self.to_frame(hkl=self.kinematics[mode]['plane'] ,with_symmetry=False) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index a77c40ca5..60dd055c6 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -682,7 +682,7 @@ class Rotation: @staticmethod def from_random(shape = None, - seed = None, + rng_seed = None, **kwargs): """ Draw random rotation. @@ -694,12 +694,12 @@ class Rotation: shape : tuple of ints, optional Shape of the sample. Defaults to None which gives a single rotation - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) r = rng.random(3 if shape is None else tuple(shape)+(3,) if hasattr(shape, '__iter__') else (shape,3)) A = np.sqrt(r[...,2]) @@ -718,7 +718,7 @@ class Rotation: N = 500, degrees = True, fractions = True, - seed = None, + rng_seed = None, **kwargs): """ Sample discrete values from a binned ODF. @@ -737,7 +737,7 @@ class Rotation: fractions : boolean, optional ODF values correspond to volume fractions, not probability density. Defaults to True. - seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. @@ -768,7 +768,7 @@ class Rotation: dg = 1.0 if fractions else _dg(Eulers,degrees) dV_V = dg * np.maximum(0.0,weights.squeeze()) - return Rotation.from_Eulers(Eulers[util.hybrid_IA(dV_V,N,seed)],degrees) + return Rotation.from_Eulers(Eulers[util.hybrid_IA(dV_V,N,rng_seed)],degrees) @staticmethod @@ -776,7 +776,7 @@ class Rotation: sigma, N = 500, degrees = True, - seed = None, + rng_seed = None, **kwargs): """ Calculate set of rotations with Gaussian distribution around center. @@ -791,12 +791,12 @@ class Rotation: Number of samples, defaults to 500. degrees : boolean, optional sigma is given in degrees. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) sigma = np.radians(sigma) if degrees else sigma u,Theta = (rng.random((N,2)) * 2.0 * np.array([1,np.pi]) - np.array([1.0, 0])).T omega = abs(rng.normal(scale=sigma,size=N)) @@ -813,7 +813,7 @@ class Rotation: sigma = 0.0, N = 500, degrees = True, - seed = None, + rng_seed = None, **kwargs): """ Calculate set of rotations with Gaussian distribution around direction. @@ -831,12 +831,12 @@ class Rotation: Number of samples, defaults to 500. degrees : boolean, optional sigma, alpha, and beta are given in degrees. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) sigma_,alpha_,beta_ = map(np.radians,(sigma,alpha,beta)) if degrees else (sigma,alpha,beta) d_cr = 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/damask/seeds.py b/python/damask/seeds.py index 9aab953d0..717fc620b 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -5,7 +5,7 @@ from . import util from . import grid_filters -def from_random(size,N_seeds,grid=None,seed=None): +def from_random(size,N_seeds,grid=None,rng_seed=None): """ Random seeding in space. @@ -18,12 +18,12 @@ def from_random(size,N_seeds,grid=None,seed=None): grid : numpy.ndarray of shape (3), optional. If given, ensures that all seeds initiate one grain if using a standard Voronoi tessellation. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = _np.random.default_rng(seed) + rng = _np.random.default_rng(rng_seed) if grid is None: coords = rng.random((N_seeds,3)) * size else: @@ -34,7 +34,7 @@ def from_random(size,N_seeds,grid=None,seed=None): return coords -def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,seed=None): +def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,rng_seed=None): """ Seeding in space according to a Poisson disc distribution. @@ -50,12 +50,12 @@ def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,seed=None Minimum acceptable distance to other seeds. periodic : boolean, optional Calculate minimum distance for periodically repeated grid. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = _np.random.default_rng(seed) + rng = _np.random.default_rng(rng_seed) coords = _np.empty((N_seeds,3)) coords[0] = rng.random(3) * size diff --git a/python/damask/util.py b/python/damask/util.py index 49e85c9f5..fb122bd11 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -42,7 +42,7 @@ def srepr(arg,glue = '\n'): arg : iterable Items to join. glue : str, optional - Defaults to \n. + Glue used for joining operation. Defaults to \n. """ if (not hasattr(arg, "strip") and @@ -163,7 +163,15 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50): def scale_to_coprime(v): - """Scale vector to co-prime (relatively prime) integers.""" + """ + Scale vector to co-prime (relatively prime) integers. + + Parameters + ---------- + v : numpy.ndarray of shape (:) + Vector to scale. + + """ MAX_DENOMINATOR = 1000000 def get_square_denominator(x): @@ -214,7 +222,21 @@ def execution_stamp(class_name,function_name=None): return f'damask.{class_name}{_function_name} v{version} ({now})' -def hybrid_IA(dist,N,seed=None): +def hybrid_IA(dist,N,rng_seed=None): + """ + Hybrid integer approximation. + + Parameters + ---------- + dist : numpy.ndarray + Distribution to be approximated + N : int + Number of samples to draw. + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + A seed to initialize the BitGenerator. Defaults to None. + If None, then fresh, unpredictable entropy will be pulled from the OS. + + """ N_opt_samples,N_inv_samples = (max(np.count_nonzero(dist),N),0) # random subsampling if too little samples requested scale_,scale,inc_factor = (0.0,float(N_opt_samples),1.0) @@ -225,7 +247,7 @@ def hybrid_IA(dist,N,seed=None): if N_inv_samples < N_opt_samples else \ (scale_,0.5*(scale_ + scale), 1.0) - return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(seed).permutation(N_inv_samples)[:N]] + return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]] def shapeshifter(fro,to,mode='left',keep_ones=False): diff --git a/python/tests/conftest.py b/python/tests/conftest.py index f402c4614..9410ba15a 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -18,6 +18,7 @@ def patch_damask_version(monkeypatch): """Set damask.version for reproducible tests results.""" monkeypatch.setattr(damask, 'version', patched_version) + patched_date = datetime.datetime(2019, 11, 2, 11, 58, 0) @pytest.fixture def patch_datetime_now(monkeypatch): @@ -29,6 +30,7 @@ def patch_datetime_now(monkeypatch): monkeypatch.setattr(datetime, 'datetime', mydatetime) + @pytest.fixture def patch_execution_stamp(monkeypatch): """Set damask.util.execution_stamp for reproducible tests results.""" @@ -38,6 +40,7 @@ def patch_execution_stamp(monkeypatch): monkeypatch.setattr(damask.util, 'execution_stamp', execution_stamp) + @pytest.fixture def patch_plt_show(monkeypatch): def _None(block=None): @@ -50,16 +53,19 @@ def pytest_addoption(parser): action="store_true", default=False) + @pytest.fixture def update(request): """Store current results as new reference results.""" return request.config.getoption("--update") + @pytest.fixture def reference_dir_base(): """Directory containing reference results.""" return Path(__file__).parent/'reference' + @pytest.fixture def set_of_quaternions(): """A set of n random rotations.""" diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index fe35bda14..3e6aad134 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -125,9 +125,9 @@ class TestOrientation: def test_from_fiber_component(self): r = Rotation.from_fiber_component(alpha=np.zeros(2),beta=np.zeros(2), - sigma=0.0,N=1,seed=0) + sigma=0.0,N=1,rng_seed=0) assert np.all(Orientation.from_fiber_component(alpha=np.zeros(2),beta=np.zeros(2), - sigma=0.0,N=1,seed=0,lattice='triclinic').quaternion + sigma=0.0,N=1,rng_seed=0,lattice='triclinic').quaternion == r.quaternion) @pytest.mark.parametrize('kwargs',[ @@ -175,8 +175,8 @@ class TestOrientation: @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('N',[1,8,32]) def test_disorientation(self,lattice,N): - o = Orientation.from_random(lattice=lattice,shape=N,seed=0) - p = Orientation.from_random(lattice=lattice,shape=N,seed=1) + o = Orientation.from_random(lattice=lattice,shape=N) + p = Orientation.from_random(lattice=lattice,shape=N) d,ops = o.disorientation(p,return_operators=True) @@ -198,8 +198,8 @@ class TestOrientation: (None,None), ]) def test_disorientation_blending(self,lattice,a,b): - o = Orientation.from_random(lattice=lattice,shape=a,seed=0) - p = Orientation.from_random(lattice=lattice,shape=b,seed=1) + o = Orientation.from_random(lattice=lattice,shape=a) + p = Orientation.from_random(lattice=lattice,shape=b) blend = util.shapeblender(o.shape,p.shape) for loc in np.random.randint(0,blend,(10,len(blend))): assert o[tuple(loc[:len(o.shape)])].disorientation(p[tuple(loc[-len(p.shape):])]) \ @@ -214,7 +214,7 @@ class TestOrientation: @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)]) def test_reduced_vectorization(self,lattice,shape): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) for r, theO in zip(o.reduced.flatten(),o.flatten()): assert r == theO.reduced @@ -223,7 +223,7 @@ class TestOrientation: @pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]])) @pytest.mark.parametrize('proper',[True,False]) def test_to_SST_vectorization(self,lattice,shape,vector,proper): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) for r, theO in zip(o.to_SST(vector=vector,proper=proper).reshape((-1,3)),o.flatten()): assert np.allclose(r,theO.to_SST(vector=vector,proper=proper)) @@ -232,7 +232,7 @@ class TestOrientation: @pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]])) @pytest.mark.parametrize('proper',[True,False]) def test_IPF_color_vectorization(self,lattice,shape,vector,proper): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) poles = o.to_SST(vector=vector,proper=proper) for r, theO in zip(o.IPF_color(poles,proper=proper).reshape((-1,3)),o.flatten()): assert np.allclose(r,theO.IPF_color(theO.to_SST(vector=vector,proper=proper),proper=proper)) @@ -245,7 +245,7 @@ class TestOrientation: (None,(3,)), ]) def test_to_SST_blending(self,lattice,a,b): - o = Orientation.from_random(lattice=lattice,shape=a,seed=0) + o = Orientation.from_random(lattice=lattice,shape=a) v = np.random.random(b+(3,)) blend = util.shapeblender(o.shape,b) for loc in np.random.randint(0,blend,(10,len(blend))): diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index fe30726e3..fe90e2aea 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -778,7 +778,7 @@ class TestRotation: assert r.shape == shape def test_equal(self): - assert Rotation.from_random(seed=1) == Rotation.from_random(seed=1) + assert Rotation.from_random(rng_seed=1) == Rotation.from_random(rng_seed=1) def test_inversion(self): r = Rotation.from_random() From c9356fd44794b8b1bb1eb042a8ee66c7a8b217c8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 15:39:54 +0100 Subject: [PATCH 22/37] error checking, making readable with damask.Result --- src/mesh/DAMASK_mesh.f90 | 69 ++++++++++++++++---------------- src/mesh/discretization_mesh.f90 | 5 +++ 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/mesh/DAMASK_mesh.f90 b/src/mesh/DAMASK_mesh.f90 index bfa8d22ce..1e353892c 100644 --- a/src/mesh/DAMASK_mesh.f90 +++ b/src/mesh/DAMASK_mesh.f90 @@ -20,7 +20,7 @@ program DAMASK_mesh use discretization_mesh use FEM_Utilities use mesh_mech_FEM - + implicit none !-------------------------------------------------------------------------------------------------- @@ -56,7 +56,7 @@ program DAMASK_mesh totalIncsCounter = 0, & !< total # of increments statUnit = 0, & !< file unit for statistics output stagIter, & - component + component class(tNode), pointer :: & num_mesh character(len=pStringLen), dimension(:), allocatable :: fileContent @@ -80,7 +80,7 @@ program DAMASK_mesh call CPFEM_initAll print'(/,a)', ' <<<+- DAMASK_mesh init -+>>>'; flush(IO_STDOUT) -!--------------------------------------------------------------------- +!--------------------------------------------------------------------- ! reading field information from numerics file and do sanity checks num_mesh => config_numerics%get('mesh', defaultVal=emptyDict) stagItMax = num_mesh%get_asInt('maxStaggeredIter',defaultVal=10) @@ -100,7 +100,7 @@ program DAMASK_mesh do l = 1, size(fileContent) line = fileContent(l) if (IO_isBlank(line)) cycle ! skip empty lines - + chunkPos = IO_stringPos(line) do i = 1, chunkPos(1) ! reading compulsory parameters for loadcase select case (IO_lc(IO_stringValue(line,chunkPos,i))) @@ -109,15 +109,16 @@ program DAMASK_mesh end select enddo ! count all identifiers to allocate memory and do sanity check enddo - - allocate (loadCases(N_def)) - + + if(N_def < 1) call IO_error(error_ID = 837) + allocate(loadCases(N_def)) + do i = 1, size(loadCases) allocate(loadCases(i)%fieldBC(nActiveFields)) field = 1 loadCases(i)%fieldBC(field)%ID = FIELD_MECH_ID enddo - + do i = 1, size(loadCases) do field = 1, nActiveFields select case (loadCases(i)%fieldBC(field)%ID) @@ -133,21 +134,21 @@ program DAMASK_mesh case (3) loadCases(i)%fieldBC(field)%componentBC(component)%ID = COMPONENT_MECH_Z_ID end select - enddo + enddo end select do component = 1, loadCases(i)%fieldBC(field)%nComponents allocate(loadCases(i)%fieldBC(field)%componentBC(component)%Value(mesh_Nboundaries), source = 0.0_pReal) allocate(loadCases(i)%fieldBC(field)%componentBC(component)%Mask (mesh_Nboundaries), source = .false.) enddo - enddo - enddo + enddo + enddo !-------------------------------------------------------------------------------------------------- ! reading the load case and assign values to the allocated data structure do l = 1, size(fileContent) line = fileContent(l) if (IO_isBlank(line)) cycle ! skip empty lines - + chunkPos = IO_stringPos(line) do i = 1, chunkPos(1) select case (IO_lc(IO_stringValue(line,chunkPos,i))) @@ -161,7 +162,7 @@ program DAMASK_mesh do faceSet = 1, mesh_Nboundaries if (mesh_boundaries(faceSet) == currentFace) currentFaceSet = faceSet enddo - if (currentFaceSet < 0) call IO_error(error_ID = errorID, ext_msg = 'invalid BC') + if (currentFaceSet < 0) call IO_error(error_ID = 837, ext_msg = 'invalid BC') case('t','time','delta') ! increment time loadCases(currentLoadCase)%time = IO_floatValue(line,chunkPos,i+1) case('n','incs','increments','steps') ! number of increments @@ -170,7 +171,7 @@ program DAMASK_mesh loadCases(currentLoadCase)%incs = IO_intValue(line,chunkPos,i+1) loadCases(currentLoadCase)%logscale = 1 case('freq','frequency','outputfreq') ! frequency of result writings - loadCases(currentLoadCase)%outputfrequency = IO_intValue(line,chunkPos,i+1) + loadCases(currentLoadCase)%outputfrequency = IO_intValue(line,chunkPos,i+1) case('guessreset','dropguessing') loadCases(currentLoadCase)%followFormerTrajectory = .false. ! do not continue to predict deformation along former trajectory @@ -185,7 +186,7 @@ program DAMASK_mesh case('z') ID = COMPONENT_MECH_Z_ID end select - + do field = 1, nActiveFields if (loadCases(currentLoadCase)%fieldBC(field)%ID == FIELD_MECH_ID) then do component = 1, loadcases(currentLoadCase)%fieldBC(field)%nComponents @@ -197,11 +198,11 @@ program DAMASK_mesh endif enddo endif - enddo + enddo end select enddo enddo - + !-------------------------------------------------------------------------------------------------- ! consistency checks and output of load case loadCases(1)%followFormerTrajectory = .false. ! cannot guess along trajectory for first inc of first currentLoadCase @@ -215,17 +216,17 @@ program DAMASK_mesh select case (loadCases(currentLoadCase)%fieldBC(field)%ID) case(FIELD_MECH_ID) print'(a)', ' Field '//trim(FIELD_MECH_label) - + end select do faceSet = 1, mesh_Nboundaries do component = 1, loadCases(currentLoadCase)%fieldBC(field)%nComponents if (loadCases(currentLoadCase)%fieldBC(field)%componentBC(component)%Mask(faceSet)) & print'(a,i2,a,i2,a,f12.7)', ' Face ', mesh_boundaries(faceSet), & - ' Component ', component, & + ' Component ', component, & ' Value ', loadCases(currentLoadCase)%fieldBC(field)% & componentBC(component)%Value(faceSet) enddo - enddo + enddo enddo print'(a,f12.6)', ' time: ', loadCases(currentLoadCase)%time if (loadCases(currentLoadCase)%incs < 1) errorID = 835 ! non-positive incs count @@ -244,7 +245,7 @@ program DAMASK_mesh case(FIELD_MECH_ID) call FEM_mech_init(loadCases(1)%fieldBC(field)) end select - enddo + enddo if (worldrank == 0) then open(newunit=statUnit,file=trim(getSolverJobName())//'.sta',form='FORMATTED',status='REPLACE') @@ -254,9 +255,9 @@ program DAMASK_mesh loadCaseLooping: do currentLoadCase = 1, size(loadCases) time0 = time ! load case start time guess = loadCases(currentLoadCase)%followFormerTrajectory ! change of load case? homogeneous guess for the first inc - + incLooping: do inc = 1, loadCases(currentLoadCase)%incs - totalIncsCounter = totalIncsCounter + 1 + totalIncsCounter = totalIncsCounter + 1 !-------------------------------------------------------------------------------------------------- ! forwarding time @@ -266,7 +267,7 @@ program DAMASK_mesh else if (currentLoadCase == 1) then ! 1st load case of logarithmic scale if (inc == 1) then ! 1st inc of 1st load case of logarithmic scale - timeinc = loadCases(1)%time*(2.0_pReal**real( 1-loadCases(1)%incs ,pReal)) ! assume 1st inc is equal to 2nd + timeinc = loadCases(1)%time*(2.0_pReal**real( 1-loadCases(1)%incs ,pReal)) ! assume 1st inc is equal to 2nd else ! not-1st inc of 1st load case of logarithmic scale timeinc = loadCases(1)%time*(2.0_pReal**real(inc-1-loadCases(1)%incs ,pReal)) endif @@ -287,7 +288,7 @@ program DAMASK_mesh remainingLoadCaseTime = loadCases(currentLoadCase)%time+time0 - time time = time + timeinc ! forward target time stepFraction = stepFraction + 1 ! count step - + !-------------------------------------------------------------------------------------------------- ! report begin of new step print'(/,a)', ' ###########################################################################' @@ -310,8 +311,8 @@ program DAMASK_mesh guess,timeinc,timeIncOld,loadCases(currentLoadCase)%fieldBC(field)) end select - enddo - + enddo + !-------------------------------------------------------------------------------------------------- ! solve fields stagIter = 0 @@ -332,10 +333,10 @@ program DAMASK_mesh stagIterate = stagIter < stagItMax & .and. all(solres(:)%converged) & .and. .not. all(solres(:)%stagConverged) ! stationary with respect to staggered iteration - enddo - -! check solution - cutBack = .False. + enddo + +! check solution + cutBack = .False. if(.not. all(solres(:)%converged .and. solres(:)%stagConverged)) then ! no solution found if (cutBackLevel < maxCutBack) then ! do cut back print'(/,a)', ' cut back detected' @@ -344,7 +345,7 @@ program DAMASK_mesh cutBackLevel = cutBackLevel + 1 time = time - timeinc ! rewind time timeinc = timeinc/2.0_pReal - else ! default behavior, exit if spectral solver does not converge + else ! default behavior, exit if spectral solver does not converge call IO_warning(850) call quit(1) ! quit endif @@ -374,8 +375,8 @@ program DAMASK_mesh enddo incLooping enddo loadCaseLooping - - + + !-------------------------------------------------------------------------------------------------- ! report summary of whole calculation print'(/,a)', ' ###########################################################################' diff --git a/src/mesh/discretization_mesh.f90 b/src/mesh/discretization_mesh.f90 index bc96951a1..7dbd05e46 100644 --- a/src/mesh/discretization_mesh.f90 +++ b/src/mesh/discretization_mesh.f90 @@ -17,6 +17,7 @@ module discretization_mesh use IO use config use discretization + use results use FEsolving use FEM_quadrature use YAML_types @@ -182,6 +183,10 @@ subroutine discretization_mesh_init(restart) reshape(mesh_ipCoordinates,[3,mesh_maxNips*mesh_NcpElems]), & mesh_node0) + call results_openJobFile + call results_closeGroup(results_addGroup('geometry')) + call results_closeJobFile + end subroutine discretization_mesh_init From 5220bd4416dfbafa3a5ce0049af8d06b95059f06 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 16:51:57 +0100 Subject: [PATCH 23/37] includes improved(working) compilation tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 583c6c2b8..9f453aa6d 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 583c6c2b89980259df1cf8ced4e998c5910cc831 +Subproject commit 9f453aa6d2ec2fe1ff192e422a7f596fc46cc778 From b3955573f635c8ad39e57fa7e3d4ae562bfcdb7f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 15 Nov 2020 22:16:44 +0100 Subject: [PATCH 24/37] using new tests --- .gitlab-ci.yml | 8 -------- PRIVATE | 2 +- python/damask/_environment.py | 9 --------- src/DAMASK_interface.f90 | 4 ++-- 4 files changed, 3 insertions(+), 20 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 71f1d6652..a33a5a078 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -187,8 +187,6 @@ grid_mech_compile_Intel: stage: compilePETSc script: - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - - cp -r grid_mech_compile grid_mech_compile_Intel - - grid_mech_compile_Intel/test.py - cd pytest - pytest -k 'compile and grid' --basetemp=${TESTROOT}/compile_grid_Intel except: @@ -199,8 +197,6 @@ Compile_FEM_Intel: stage: compilePETSc script: - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel - - cp -r FEM_compile FEM_compile_Intel - - FEM_compile_Intel/test.py - cd pytest - pytest -k 'compile and mesh' --basetemp=${TESTROOT}/compile_mesh_Intel except: @@ -211,8 +207,6 @@ grid_mech_compile_GNU: stage: compilePETSc script: - module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU - - cp -r grid_mech_compile grid_mech_compile_GNU - - grid_mech_compile_GNU/test.py - cd pytest - pytest -k 'compile and grid' --basetemp=${TESTROOT}/compile_grid_GNU except: @@ -223,8 +217,6 @@ Compile_FEM_GNU: stage: compilePETSc script: - module load $GNUCompiler $MPICH_GNU $PETSc_MPICH_GNU - - cp -r FEM_compile FEM_compile_GNU - - FEM_compile_GNU/test.py - cd pytest - pytest -k 'compile and mesh' --basetemp=${TESTROOT}/compile_mesh_GNU except: diff --git a/PRIVATE b/PRIVATE index 9f453aa6d..34c896194 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 9f453aa6d2ec2fe1ff192e422a7f596fc46cc778 +Subproject commit 34c89619411e2a0e84f3efc122589d41e270b640 diff --git a/python/damask/_environment.py b/python/damask/_environment.py index 9983a91aa..1aa5e8384 100644 --- a/python/damask/_environment.py +++ b/python/damask/_environment.py @@ -3,10 +3,6 @@ from pathlib import Path class Environment: - def __init__(self): - """Do Nothing.""" - pass - @property def screen_size(self): width = 1024 @@ -43,8 +39,3 @@ class Environment: def root_dir(self): """Return DAMASK root path.""" return Path(__file__).parents[2] - - - # for compatibility - def rootDir(self): - return str(self.root_dir) diff --git a/src/DAMASK_interface.f90 b/src/DAMASK_interface.f90 index 52971ae06..70f343a15 100644 --- a/src/DAMASK_interface.f90 +++ b/src/DAMASK_interface.f90 @@ -126,9 +126,9 @@ subroutine DAMASK_interface_init if (err /= 0) call quit(1) select case(trim(arg)) ! extract key case ('-h','--help') - print'(a)', ' #######################################################################' + print'(/,a)',' #######################################################################' print'(a)', ' DAMASK Command Line Interface:' - print'(a)', ' For PETSc-based solvers for the Düsseldorf Advanced Material Simulation Kit' + print'(a)', ' Düsseldorf Advanced Material Simulation Kit with PETSc-based solvers' print'(a,/)',' #######################################################################' print'(a,/)',' Valid command line switches:' print'(a)', ' --geom (-g, --geometry)' From 0bd8a410ad61a4b156de573036492ef5dcd69948 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 16 Nov 2020 09:22:55 +0100 Subject: [PATCH 25/37] check all errors, avoid intermediate wait --- src/grid/spectral_utilities.f90 | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/grid/spectral_utilities.f90 b/src/grid/spectral_utilities.f90 index 36ab99e2c..f66b78488 100644 --- a/src/grid/spectral_utilities.f90 +++ b/src/grid/spectral_utilities.f90 @@ -993,12 +993,11 @@ subroutine utilities_updateCoords(F) real(pReal), dimension(3, grid(1)+1,grid(2)+1,grid3+1) :: nodeCoords integer :: & i,j,k,n, & - rank_t, & - rank_b, & - c, r, & + rank_t, rank_b, & + c, & ierr - integer, dimension(MPI_STATUS_SIZE) :: & - s + integer, dimension(4) :: request + integer, dimension(MPI_STATUS_SIZE,4) :: status real(pReal), dimension(3) :: step real(pReal), dimension(3,3) :: Favg integer, dimension(3) :: me @@ -1044,20 +1043,20 @@ subroutine utilities_updateCoords(F) rank_b = modulo(worldrank-1,worldsize) ! send bottom layer to process below - call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0,PETSC_COMM_WORLD,r,ierr) + call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0,PETSC_COMM_WORLD,request(1),ierr) if(ierr /=0) error stop 'MPI error' - call MPI_Irecv(IPfluct_padded(:,:,:,grid3+2),c,MPI_DOUBLE,rank_t,0,PETSC_COMM_WORLD,r,ierr) - if(ierr /=0) error stop 'MPI error' - call MPI_Wait(r,s,ierr) + call MPI_Irecv(IPfluct_padded(:,:,:,grid3+2),c,MPI_DOUBLE,rank_t,0,PETSC_COMM_WORLD,request(2),ierr) if(ierr /=0) error stop 'MPI error' ! send top layer to process above - call MPI_Isend(IPfluct_padded(:,:,:,grid3+1),c,MPI_DOUBLE,rank_t,0,PETSC_COMM_WORLD,r,ierr) + call MPI_Isend(IPfluct_padded(:,:,:,grid3+1),c,MPI_DOUBLE,rank_t,1,PETSC_COMM_WORLD,request(3),ierr) if(ierr /=0) error stop 'MPI error' - call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,0,PETSC_COMM_WORLD,r,ierr) + call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,1,PETSC_COMM_WORLD,request(4),ierr) if(ierr /=0) error stop 'MPI error' - call MPI_Wait(r,s,ierr) + + call MPI_Waitall(4,request,status,ierr) if(ierr /=0) error stop 'MPI error' + if(any(status(MPI_ERROR,:) /= 0)) error stop 'MPI error' !-------------------------------------------------------------------------------------------------- ! calculate nodal displacements From de20e6b35dbdbc6e2d9fc4bb9696ddb795f58559 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 16 Nov 2020 10:23:01 -0500 Subject: [PATCH 26/37] code shortening; list_predefined() --> property "predefined" --- python/damask/_colormap.py | 142 ++++++++++++++-------------------- python/tests/test_Colormap.py | 4 +- 2 files changed, 61 insertions(+), 85 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 87135caf9..b148b8b2e 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -22,6 +22,16 @@ _ref_white = np.array([.95047, 1.00000, 1.08883]) # - support NaN color (paraview) class Colormap(mpl.colors.ListedColormap): + """ + References + ---------- + [1] DAMASK colormap theory + https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf + [2] DAMASK colormaps first use + https://doi.org/10.1016/j.ijplas.2012.09.012 + [3] Matplotlib colormaps overview + https://matplotlib.org/tutorials/colors/colormaps.html + """ def __add__(self,other): """Concatenate colormaps.""" @@ -137,40 +147,16 @@ class Colormap(mpl.colors.ListedColormap): """ # matplotlib presets - for cat in Colormap._predefined_mpl: - for n in cat[1]: - if n == name: - colormap = cm.__dict__[name] - if isinstance(colormap,mpl.colors.LinearSegmentedColormap): - return Colormap(np.array(list(map(colormap,np.linspace(0,1,N)))),name=name) - else: - return Colormap(np.array(colormap.colors),name=name) - - # DAMASK presets - definition = Colormap._predefined_DAMASK[name] - return Colormap.from_range(definition['low'],definition['high'],name,N) - - - @staticmethod - def list_predefined(): - """ - List predefined colormaps by category. - - References - ---------- - [1] DAMASK colormap theory - https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf - [2] DAMASK colormaps first use - https://doi.org/10.1016/j.ijplas.2012.09.012 - [3] Matplotlib colormaps overview - https://matplotlib.org/tutorials/colors/colormaps.html - - """ - print('DAMASK colormaps') - print(' '+', '.join(Colormap._predefined_DAMASK.keys())) - for cat in Colormap._predefined_mpl: - print(f'{cat[0]}') - print(' '+', '.join(cat[1])) + try: + colormap = cm.__dict__[name] + return Colormap(np.array(list(map(colormap,np.linspace(0,1,N))) + if isinstance(colormap,mpl.colors.LinearSegmentedColormap) else + colormap.colors), + name=name) + except: + # DAMASK presets + definition = Colormap._predefined_DAMASK[name] + return Colormap.from_range(definition['low'],definition['high'],name,N) def shade(self,field,bounds=None,gap=None): @@ -179,9 +165,9 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- - field : numpy.array of shape(:,:) + field : numpy.array of shape (:,:) Data to be shaded. - bounds : iterable of len(2), optional + bounds : iterable of len (2), optional Colormap value range (low,high). gap : field.dtype, optional Transparent value. NaN will always be rendered transparent. @@ -234,7 +220,6 @@ class Colormap(mpl.colors.ListedColormap): return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name) - def save_paraview(self,fname=None): """ Write colormap to JSON file for Paraview. @@ -246,13 +231,13 @@ class Colormap(mpl.colors.ListedColormap): consist of the name of the colormap and extension '.json'. """ - if fname is not None: + if fname is None: + fhandle = None + else: try: fhandle = open(fname,'w') except TypeError: fhandle = fname - else: - fhandle = None colors = [] for i,c in enumerate(np.round(self.colors,6).tolist()): @@ -265,11 +250,9 @@ class Colormap(mpl.colors.ListedColormap): 'DefaultMap':True, 'RGBPoints':colors }] - if fhandle is None: - with open(self.name.replace(' ','_')+'.json', 'w') as f: - json.dump(out, f,indent=4) - else: - json.dump(out,fhandle,indent=4) + + with open(self.name.replace(' ','_')+'.json', 'w') if fhandle is None else fhandle as f: + json.dump(out, f,indent=4) def save_ASCII(self,fname=None): @@ -283,22 +266,19 @@ class Colormap(mpl.colors.ListedColormap): consist of the name of the colormap and extension '.txt'. """ - if fname is not None: + if fname is None: + fhandle = None + else: try: fhandle = open(fname,'w') except TypeError: fhandle = fname - else: - fhandle = None labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3} t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}') - if fhandle is None: - with open(self.name.replace(' ','_')+'.txt', 'w') as f: - t.save(f) - else: - t.save(fhandle) + with open(self.name.replace(' ','_')+'.txt', 'w') if fhandle is None else fhandle as f: + t.save(f) def save_GOM(self,fname=None): @@ -312,24 +292,21 @@ class Colormap(mpl.colors.ListedColormap): consist of the name of the colormap and extension '.legend'. """ - if fname is not None: + if fname is None: + fhandle = None + else: try: fhandle = open(fname,'w') except TypeError: fhandle = fname - else: - fhandle = None # ToDo: test in GOM GOM_str = '1 1 {name} 9 {name} '.format(name=self.name.replace(" ","_")) \ + '0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' \ + f'30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 {len(self.colors)}' \ + ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((self.colors*255).astype(int))]) \ + '\n' - if fhandle is None: - with open(self.name.replace(' ','_')+'.legend', 'w') as f: - f.write(GOM_str) - else: - fhandle.write(GOM_str) + with open(self.name.replace(' ','_')+'.legend', 'w') if fhandle is None else fhandle as f: + f.write(GOM_str) def save_gmsh(self,fname=None): @@ -343,22 +320,19 @@ class Colormap(mpl.colors.ListedColormap): consist of the name of the colormap and extension '.msh'. """ - if fname is not None: + if fname is None: + fhandle = None + else: try: fhandle = open(fname,'w') except TypeError: fhandle = fname - else: - fhandle = None # ToDo: test in gmsh gmsh_str = 'View.ColorTable = {\n' \ +'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \ +'\n}\n' - if fhandle is None: - with open(self.name.replace(' ','_')+'.msh', 'w') as f: - f.write(gmsh_str) - else: - fhandle.write(gmsh_str) + with open(self.name.replace(' ','_')+'.msh', 'w') if fhandle is None else fhandle as f: + f.write(gmsh_str) @staticmethod @@ -386,7 +360,6 @@ class Colormap(mpl.colors.ListedColormap): if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0 return msh_sat[2] + hSpin - lo = np.array(low) hi = np.array(high) @@ -406,28 +379,28 @@ class Colormap(mpl.colors.ListedColormap): return (1.0 - frac) * lo + frac * hi - _predefined_mpl= [('Perceptually Uniform Sequential', [ - 'viridis', 'plasma', 'inferno', 'magma', 'cividis']), - ('Sequential', [ + _predefined_mpl= {'Perceptually Uniform Sequential': [ + 'viridis', 'plasma', 'inferno', 'magma', 'cividis'], + 'Sequential': [ 'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', - 'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']), - ('Sequential (2)', [ + 'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn'], + 'Sequential (2)': [ 'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink', 'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia', - 'hot', 'afmhot', 'gist_heat', 'copper']), - ('Diverging', [ + 'hot', 'afmhot', 'gist_heat', 'copper'], + 'Diverging': [ 'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', - 'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']), - ('Cyclic', ['twilight', 'twilight_shifted', 'hsv']), - ('Qualitative', [ + 'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic'], + 'Cyclic': ['twilight', 'twilight_shifted', 'hsv'], + 'Qualitative': [ 'Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', - 'tab10', 'tab20', 'tab20b', 'tab20c']), - ('Miscellaneous', [ + 'tab10', 'tab20', 'tab20b', 'tab20c'], + 'Miscellaneous': [ 'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', - 'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])] + 'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']} _predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], 'high': [0.250980,0.007843,0.000000]}, @@ -436,6 +409,9 @@ class Colormap(mpl.colors.ListedColormap): 'stress': {'low': [0.878432,0.874511,0.949019], 'high': [0.000002,0.000000,0.286275]}} + predefined = dict(**{'DAMASK':list(_predefined_DAMASK)},**_predefined_mpl) + + @staticmethod def _hsv2rgb(hsv): """ diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 279f7eea9..054158c22 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -141,8 +141,8 @@ class TestColormap: diff = ImageChops.difference(img_reference.convert('RGB'),img_current.convert('RGB')) assert not diff.getbbox() - def test_list(self): - Colormap.list_predefined() + def test_predefined(self): + assert (isinstance(Colormap.predefined,dict)) @pytest.mark.parametrize('format,ext',[('ASCII','.txt'), ('paraview','.json'), From fa25a1326488eac57664fb27c6b6ca19a8f2dc9f Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 16 Nov 2020 10:34:49 -0500 Subject: [PATCH 27/37] fixed typo --- python/tests/test_VTK.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index 53fbaa2f4..48dce4707 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -87,7 +87,7 @@ class TestVTK: def test_compress(self,tmp_path): points = np.random.rand(102,3) v = VTK.from_poly_data(points) - fname_c = tmp_path/'compreesed.vtp' + fname_c = tmp_path/'compressed.vtp' fname_p = tmp_path/'plain.vtp' v.save(fname_c,parallel=False,compress=False) v.save(fname_p,parallel=False,compress=True) From cf3a28952a6fb550e8afa797f2e50e9498c4df4a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 16 Nov 2020 16:38:17 +0100 Subject: [PATCH 28/37] fixed tests --- PRIVATE | 2 +- src/grid/grid_mech_spectral_polarisation.f90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PRIVATE b/PRIVATE index 34c896194..2105ed1c6 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 34c89619411e2a0e84f3efc122589d41e270b640 +Subproject commit 2105ed1c6e4800050010ca4d73b1882022f81551 diff --git a/src/grid/grid_mech_spectral_polarisation.f90 b/src/grid/grid_mech_spectral_polarisation.f90 index 8f9ea81b3..cdd7e1e2b 100644 --- a/src/grid/grid_mech_spectral_polarisation.f90 +++ b/src/grid/grid_mech_spectral_polarisation.f90 @@ -497,7 +497,7 @@ subroutine converged(snes_local,PETScIter,devNull1,devNull2,devNull3,reason,dumm err_div/divTol, ' (',err_div, ' / m, tol = ',divTol,')' print '(a,f12.2,a,es8.2,a,es9.2,a)', ' error curl = ', & err_curl/curlTol,' (',err_curl,' -, tol = ',curlTol,')' - print '(a,f12.2,a,es8.2,a,es9.2,a)', ' error stress BC = ', & + print '(a,f12.2,a,es8.2,a,es9.2,a)', ' error stress BC = ', & err_BC/BCTol, ' (',err_BC, ' Pa, tol = ',BCTol,')' print'(/,a)', ' ===========================================================================' flush(IO_STDOUT) From 5a53f8743b64d01b658d6f67fa6827f0335c4ab2 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 16 Nov 2020 10:39:43 -0500 Subject: [PATCH 29/37] added to docstring --- python/damask/_colormap.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index b148b8b2e..8cd8a6aa9 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -23,6 +23,8 @@ _ref_white = np.array([.95047, 1.00000, 1.08883]) class Colormap(mpl.colors.ListedColormap): """ + Enhance matplotlib colormap functionality to be used within DAMASK. + References ---------- [1] DAMASK colormap theory @@ -31,6 +33,7 @@ class Colormap(mpl.colors.ListedColormap): https://doi.org/10.1016/j.ijplas.2012.09.012 [3] Matplotlib colormaps overview https://matplotlib.org/tutorials/colors/colormaps.html + """ def __add__(self,other): @@ -153,7 +156,7 @@ class Colormap(mpl.colors.ListedColormap): if isinstance(colormap,mpl.colors.LinearSegmentedColormap) else colormap.colors), name=name) - except: + except KeyError: # DAMASK presets definition = Colormap._predefined_DAMASK[name] return Colormap.from_range(definition['low'],definition['high'],name,N) From a8fec922d5a643d1ea205479434cd8368f300b56 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 16 Nov 2020 17:25:13 +0100 Subject: [PATCH 30/37] show name in title --- python/damask/_colormap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 8cd8a6aa9..aaa3fdc4a 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -51,7 +51,7 @@ class Colormap(mpl.colors.ListedColormap): def __repr__(self): """Show colormap as matplotlib figure.""" - fig = plt.figure(figsize=(5,.5)) + fig = plt.figure(self.name,figsize=(5,.5)) ax1 = fig.add_axes([0, 0, 1, 1]) ax1.set_axis_off() ax1.imshow(np.linspace(0,1,self.N).reshape(1,-1), From ab0012a868a3786f67da839d7deb766c055d1735 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 17 Nov 2020 01:18:53 +0100 Subject: [PATCH 31/37] [skip ci] updated version information after successful test of v3.0.0-alpha-738-gc430b571f --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3f1edac2f..9c1c49d4d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-726-g1f59f6301 +v3.0.0-alpha-738-gc430b571f From 24b71931d2de2f8ad872f01cd406f7364247e98d Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 17 Nov 2020 04:11:44 +0100 Subject: [PATCH 32/37] [skip ci] updated version information after successful test of v3.0.0-alpha-751-gc16ad845b --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3f1edac2f..c1db5f258 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-726-g1f59f6301 +v3.0.0-alpha-751-gc16ad845b From c193c71a6540074fd1ade4edfd383d4fee9e3910 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 17 Nov 2020 09:54:10 +0100 Subject: [PATCH 33/37] [skip ci] updated version information after successful test of v3.0.0-alpha-773-ga13a9d0e9 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9c1c49d4d..bbf941738 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-738-gc430b571f +v3.0.0-alpha-773-ga13a9d0e9 From 2157bf50cd3021ca8cf2583d1b6edde87d1345e3 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Tue, 17 Nov 2020 21:24:40 +0100 Subject: [PATCH 34/37] mech --> mechanics --- PRIVATE | 2 +- examples/SpectralMethod/Polycrystal/material.yaml | 4 ++-- examples/SpectralMethod/Polycrystal/shearXY.yaml | 2 +- examples/SpectralMethod/Polycrystal/shearZX.yaml | 2 +- examples/SpectralMethod/Polycrystal/tensionX.yaml | 4 ++-- src/constitutive_mech.f90 | 6 +++--- src/constitutive_plastic_disloTungsten.f90 | 2 +- src/constitutive_plastic_dislotwin.f90 | 2 +- src/constitutive_plastic_isotropic.f90 | 2 +- src/constitutive_plastic_kinehardening.f90 | 2 +- src/constitutive_plastic_none.f90 | 2 +- src/constitutive_plastic_nonlocal.f90 | 2 +- src/constitutive_plastic_phenopowerlaw.f90 | 2 +- src/crystallite.f90 | 4 ++-- src/grid/DAMASK_grid.f90 | 2 +- src/homogenization_mech_RGC.f90 | 2 +- src/homogenization_mech_isostrain.f90 | 2 +- src/kinematics_slipplane_opening.f90 | 2 +- src/lattice.f90 | 2 +- src/material.f90 | 2 +- src/source_damage_anisoDuctile.f90 | 2 +- 21 files changed, 26 insertions(+), 26 deletions(-) diff --git a/PRIVATE b/PRIVATE index 2105ed1c6..3af7a36cc 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 2105ed1c6e4800050010ca4d73b1882022f81551 +Subproject commit 3af7a36cc6b34f24aa6ce5b1e055631d8459a7f7 diff --git a/examples/SpectralMethod/Polycrystal/material.yaml b/examples/SpectralMethod/Polycrystal/material.yaml index 9bfc97ca3..366fce151 100644 --- a/examples/SpectralMethod/Polycrystal/material.yaml +++ b/examples/SpectralMethod/Polycrystal/material.yaml @@ -2,7 +2,7 @@ homogenization: SX: N_constituents: 1 - mech: {type: none} + mechanics: {type: none} material: - homogenization: SX @@ -109,7 +109,7 @@ material: phase: Aluminum: lattice: fcc - mech: + mechanics: output: [F, P, F_e, F_p, L_p, O] elasticity: {C_11: 106.75e9, C_12: 60.41e9, C_44: 28.34e9, type: hooke} plasticity: diff --git a/examples/SpectralMethod/Polycrystal/shearXY.yaml b/examples/SpectralMethod/Polycrystal/shearXY.yaml index 39966d181..559bdfe56 100644 --- a/examples/SpectralMethod/Polycrystal/shearXY.yaml +++ b/examples/SpectralMethod/Polycrystal/shearXY.yaml @@ -1,5 +1,5 @@ step: - - mech: + - mechanics: dot_F: [0, 0, 0, 1e-3, 0, 0, 0, 0, 0] diff --git a/examples/SpectralMethod/Polycrystal/shearZX.yaml b/examples/SpectralMethod/Polycrystal/shearZX.yaml index 4395ecf17..df7b887e5 100644 --- a/examples/SpectralMethod/Polycrystal/shearZX.yaml +++ b/examples/SpectralMethod/Polycrystal/shearZX.yaml @@ -1,6 +1,6 @@ --- step: - - mech: + - mechanics: dot_F: [0, 0, 1e-3, 0, 0, 0, 0, 0, 0] diff --git a/examples/SpectralMethod/Polycrystal/tensionX.yaml b/examples/SpectralMethod/Polycrystal/tensionX.yaml index 6e86fdcf2..2f1d11f91 100644 --- a/examples/SpectralMethod/Polycrystal/tensionX.yaml +++ b/examples/SpectralMethod/Polycrystal/tensionX.yaml @@ -1,7 +1,7 @@ --- step: - - mech: + - mechanics: dot_F: [1.0e-3, 0, 0, 0, x, 0, 0, 0, x] @@ -12,7 +12,7 @@ step: t: 10 N: 40 f_out: 4 - - mech: + - mechanics: dot_F: [1.0e-3, 0, 0, 0, x, 0, 0, 0, x] diff --git a/src/constitutive_mech.f90 b/src/constitutive_mech.f90 index 074ef88fe..98b3f63de 100644 --- a/src/constitutive_mech.f90 +++ b/src/constitutive_mech.f90 @@ -217,7 +217,7 @@ module subroutine mech_init do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') elastic => mech%get('elasticity') if(elastic%get_asString('type') == 'hooke') then phase_elasticity(p) = ELASTICITY_HOOKE_ID @@ -234,7 +234,7 @@ module subroutine mech_init if(maxVal(phase_NstiffnessDegradations)/=0) then do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') stiffDegradation => mech%get('stiffness_degradation',defaultVal=emptyList) do stiffDegradationCtr = 1, stiffDegradation%length if(stiffDegradation%get_asString(stiffDegradationCtr) == 'damage') & @@ -285,7 +285,7 @@ module function plastic_active(plastic_label) result(active_plastic) allocate(active_plastic(phases%length), source = .false. ) do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') pl => mech%get('plasticity') if(pl%get_asString('type') == plastic_label) active_plastic(p) = .true. enddo diff --git a/src/constitutive_plastic_disloTungsten.f90 b/src/constitutive_plastic_disloTungsten.f90 index adaa36ee7..dfabc610d 100644 --- a/src/constitutive_plastic_disloTungsten.f90 +++ b/src/constitutive_plastic_disloTungsten.f90 @@ -116,7 +116,7 @@ module function plastic_disloTungsten_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/constitutive_plastic_dislotwin.f90 b/src/constitutive_plastic_dislotwin.f90 index 2bc2b1176..e9273334b 100644 --- a/src/constitutive_plastic_dislotwin.f90 +++ b/src/constitutive_plastic_dislotwin.f90 @@ -169,7 +169,7 @@ module function plastic_dislotwin_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/constitutive_plastic_isotropic.f90 b/src/constitutive_plastic_isotropic.f90 index 4bbd5187e..b7c5f67c1 100644 --- a/src/constitutive_plastic_isotropic.f90 +++ b/src/constitutive_plastic_isotropic.f90 @@ -86,7 +86,7 @@ module function plastic_isotropic_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/constitutive_plastic_kinehardening.f90 b/src/constitutive_plastic_kinehardening.f90 index 7dbd51597..02fa9312d 100644 --- a/src/constitutive_plastic_kinehardening.f90 +++ b/src/constitutive_plastic_kinehardening.f90 @@ -96,7 +96,7 @@ module function plastic_kinehardening_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/constitutive_plastic_none.f90 b/src/constitutive_plastic_none.f90 index 6164ab29f..27a01fb93 100644 --- a/src/constitutive_plastic_none.f90 +++ b/src/constitutive_plastic_none.f90 @@ -31,7 +31,7 @@ module function plastic_none_init() result(myPlasticity) allocate(myPlasticity(phases%length), source = .false.) do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') pl => mech%get ('plasticity') if(pl%get_asString('type') == 'none') myPlasticity(p) = .true. enddo diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 8aab40fc8..732958f0a 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -213,7 +213,7 @@ module function plastic_nonlocal_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/constitutive_plastic_phenopowerlaw.f90 b/src/constitutive_plastic_phenopowerlaw.f90 index 747dd6615..00925e4ed 100644 --- a/src/constitutive_plastic_phenopowerlaw.f90 +++ b/src/constitutive_plastic_phenopowerlaw.f90 @@ -104,7 +104,7 @@ module function plastic_phenopowerlaw_init() result(myPlasticity) i = 0 do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') if(.not. myPlasticity(p)) cycle i = i + 1 associate(prm => param(i), & diff --git a/src/crystallite.f90 b/src/crystallite.f90 index 2315fcd77..c6ccd6f08 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -240,7 +240,7 @@ subroutine crystallite_init allocate(output_constituent(phases%length)) do c = 1, phases%length phase => phases%get(c) - mech => phase%get('mech',defaultVal = emptyDict) + mech => phase%get('mechanics',defaultVal = emptyDict) #if defined(__GFORTRAN__) output_constituent(c)%label = output_asStrings(mech) #else @@ -739,7 +739,7 @@ subroutine crystallite_results character(len=:), allocatable :: group,structureLabel do p=1,size(material_name_phase) - group = trim('current/constituent')//'/'//trim(material_name_phase(p))//'/generic' + group = trim('current/constituent')//'/'//trim(material_name_phase(p))//'/mechanics' call results_closeGroup(results_addGroup(group)) diff --git a/src/grid/DAMASK_grid.f90 b/src/grid/DAMASK_grid.f90 index 1cb3acf16..577c9d1a7 100644 --- a/src/grid/DAMASK_grid.f90 +++ b/src/grid/DAMASK_grid.f90 @@ -176,7 +176,7 @@ program DAMASK_grid load_step => load_steps%get(l) - step_mech => load_step%get('mech') + step_mech => load_step%get('mechanics') loadCases(l)%stress%myType='P' readMech: do m = 1, step_mech%length select case (step_mech%getKey(m)) diff --git a/src/homogenization_mech_RGC.f90 b/src/homogenization_mech_RGC.f90 index 5fcea1f8d..585752469 100644 --- a/src/homogenization_mech_RGC.f90 +++ b/src/homogenization_mech_RGC.f90 @@ -145,7 +145,7 @@ module subroutine mech_RGC_init(num_homogMech) do h = 1, size(homogenization_type) if (homogenization_type(h) /= HOMOGENIZATION_RGC_ID) cycle homog => material_homogenization%get(h) - homogMech => homog%get('mech') + homogMech => homog%get('mechanics') associate(prm => param(homogenization_typeInstance(h)), & stt => state(homogenization_typeInstance(h)), & st0 => state0(homogenization_typeInstance(h)), & diff --git a/src/homogenization_mech_isostrain.f90 b/src/homogenization_mech_isostrain.f90 index 994c1b410..751518e09 100644 --- a/src/homogenization_mech_isostrain.f90 +++ b/src/homogenization_mech_isostrain.f90 @@ -48,7 +48,7 @@ module subroutine mech_isostrain_init do h = 1, size(homogenization_type) if (homogenization_type(h) /= HOMOGENIZATION_ISOSTRAIN_ID) cycle homog => material_homogenization%get(h) - homogMech => homog%get('mech') + homogMech => homog%get('mechanics') associate(prm => param(homogenization_typeInstance(h))) prm%N_constituents = homogenization_Nconstituents(h) diff --git a/src/kinematics_slipplane_opening.f90 b/src/kinematics_slipplane_opening.f90 index 7e45a7a05..aa0bdfbde 100644 --- a/src/kinematics_slipplane_opening.f90 +++ b/src/kinematics_slipplane_opening.f90 @@ -63,7 +63,7 @@ module function kinematics_slipplane_opening_init(kinematics_length) result(myKi do p = 1, phases%length if(any(myKinematics(:,p))) kinematics_slipplane_opening_instance(p) = count(myKinematics(:,1:p)) phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') pl => mech%get('plasticity') if(count(myKinematics(:,p)) == 0) cycle kinematics => phase%get('kinematics') diff --git a/src/lattice.f90 b/src/lattice.f90 index 08385eac7..19c6b5f2c 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -476,7 +476,7 @@ subroutine lattice_init do p = 1, phases%length phase => phases%get(p) - mech => phase%get('mech') + mech => phase%get('mechanics') elasticity => mech%get('elasticity') lattice_C66(1,1,p) = elasticity%get_asFloat('C_11') lattice_C66(1,2,p) = elasticity%get_asFloat('C_12') diff --git a/src/material.f90 b/src/material.f90 index a0c81a519..8603c77d2 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -226,7 +226,7 @@ subroutine material_parseHomogenization do h=1, size(material_name_homogenization) homog => material_homogenization%get(h) - homogMech => homog%get('mech') + homogMech => homog%get('mechanics') select case (homogMech%get_asString('type')) case('none') homogenization_type(h) = HOMOGENIZATION_NONE_ID diff --git a/src/source_damage_anisoDuctile.f90 b/src/source_damage_anisoDuctile.f90 index ffbb38d2a..601ec2531 100644 --- a/src/source_damage_anisoDuctile.f90 +++ b/src/source_damage_anisoDuctile.f90 @@ -60,7 +60,7 @@ module function source_damage_anisoDuctile_init(source_length) result(mySources) phase => phases%get(p) if(any(mySources(:,p))) source_damage_anisoDuctile_instance(p) = count(mySources(:,1:p)) if(count(mySources(:,p)) == 0) cycle - mech => phase%get('mech') + mech => phase%get('mechanics') pl => mech%get('plasticity') sources => phase%get('source') do sourceOffset = 1, sources%length From 746941638131a87298fa626c83c1ea52144cea12 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 17 Nov 2020 22:34:50 +0100 Subject: [PATCH 35/37] [skip ci] updated version information after successful test of v3.0.0-alpha-777-g523a0979e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bbf941738..fe2e304cb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-773-ga13a9d0e9 +v3.0.0-alpha-777-g523a0979e From 99c8b161d15c8a911bd01637f8142768c4f80681 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 18 Nov 2020 01:54:50 +0100 Subject: [PATCH 36/37] typo --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 3af7a36cc..21074e659 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 3af7a36cc6b34f24aa6ce5b1e055631d8459a7f7 +Subproject commit 21074e659c561b3c4ce7c220e8660c6319c5a12c From 8895d53ba607e412453fd87b3189dd7eb7403627 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 18 Nov 2020 03:25:40 +0100 Subject: [PATCH 37/37] fixed test --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 21074e659..163bf7aea 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 21074e659c561b3c4ce7c220e8660c6319c5a12c +Subproject commit 163bf7aeae1412dcec3de064411993f8203140ea