From 54207760db9c78a8fd37ed8b9b284cdcc0ae9d59 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Sep 2020 17:36:05 +0200 Subject: [PATCH 01/42] conversion byte -> float/int with 4/8 byte length --- src/prec.f90 | 81 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/src/prec.f90 b/src/prec.f90 index 73649f76b..6f0a2ab3d 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -8,6 +8,7 @@ !-------------------------------------------------------------------------------------------------- module prec use, intrinsic :: IEEE_arithmetic + use, intrinsic :: ISO_C_Binding implicit none public @@ -81,7 +82,7 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief reporting precision +!> @brief report precision and do self test !-------------------------------------------------------------------------------------------------- subroutine prec_init @@ -230,24 +231,96 @@ logical elemental pure function cNeq(a,b,tol) end function cNeq +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_FLOAT (4 byte float) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_FLOAT(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_FLOAT array + real(C_FLOAT), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_FLOAT,pLongInt)/8_pLongInt)) :: & + bytes_to_C_FLOAT + + bytes_to_C_FLOAT = transfer(bytes,bytes_to_C_FLOAT,size(bytes_to_C_FLOAT)) + +end function bytes_to_C_FLOAT + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_DOUBLE (8 byte float) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_DOUBLE(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_DOUBLE array + real(C_DOUBLE), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_DOUBLE,pLongInt)/8_pLongInt)) :: & + bytes_to_C_DOUBLE + + bytes_to_C_DOUBLE = transfer(bytes,bytes_to_C_DOUBLE,size(bytes_to_C_DOUBLE)) + +end function bytes_to_C_DOUBLE + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT32_T (4 byte signed integer) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_INT32_T(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT32_T array + integer(C_INT32_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT32_T,pLongInt)/8_pLongInt)) :: & + bytes_to_C_INT32_T + + bytes_to_C_INT32_T = transfer(bytes,bytes_to_C_INT32_T,size(bytes_to_C_INT32_T)) + +end function bytes_to_C_INT32_T + + +!-------------------------------------------------------------------------------------------------- +!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT64_T (8 byte signed integer) +!-------------------------------------------------------------------------------------------------- +pure function bytes_to_C_INT64_T(bytes) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT64_T array + integer(C_INT64_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT64_T,pLongInt)/8_pLongInt)) :: & + bytes_to_C_INT64_T + + bytes_to_C_INT64_T = transfer(bytes,bytes_to_C_INT64_T,size(bytes_to_C_INT64_T)) + +end function bytes_to_C_INT64_T + + !-------------------------------------------------------------------------------------------------- !> @brief check correctness of some prec functions !-------------------------------------------------------------------------------------------------- subroutine selfTest integer, allocatable, dimension(:) :: realloc_lhs_test - real(pReal), dimension(2) :: r + real(pReal), dimension(1) :: f + integer(pInt), dimension(1) :: i + real(pReal), dimension(2) :: r external :: & quit + realloc_lhs_test = [1,2] + if (any(realloc_lhs_test/=[1,2])) call quit(9000) + call random_number(r) r = r/minval(r) if(.not. all(dEq(r,r+PREAL_EPSILON))) call quit(9000) if(dEq(r(1),r(2)) .and. dNeq(r(1),r(2))) call quit(9000) if(.not. all(dEq0(r-(r+PREAL_MIN)))) call quit(9000) - realloc_lhs_test = [1,2] - if (any(realloc_lhs_test/=[1,2])) call quit(9000) + ! https://www.binaryconvert.com + ! https://www.rapidtables.com/convert/number/binary-to-decimal.html + f = real(bytes_to_C_FLOAT(int([-65,+11,-102,+75],C_SIGNED_CHAR)),pReal) + if(dNeq(f(1),20191102.0_pReal,0.0_pReal)) call quit(9000) + + f = real(bytes_to_C_DOUBLE(int([0,0,0,-32,+119,+65,+115,65],C_SIGNED_CHAR)),pReal) + if(dNeq(f(1),20191102.0_pReal,0.0_pReal)) call quit(9000) + + i = int(bytes_to_C_INT32_T(int([+126,+23,+52,+1],C_SIGNED_CHAR)),pInt) + if(i(1) /= 20191102_pInt) call quit(9000) + + i = int(bytes_to_C_INT64_T(int([+126,+23,+52,+1,0,0,0,0],C_SIGNED_CHAR)),pInt) + if(i(1) /= 20191102_pInt) call quit(9000) end subroutine selfTest From a931625be06e1ca4de372ca1a10da08da657d46a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Sep 2020 17:38:30 +0200 Subject: [PATCH 02/42] functionality to decode base64 strings into bytes --- src/CPFEM2.f90 | 2 + src/base64.f90 | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 src/base64.f90 diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index b26ad65fd..adeb00955 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -14,6 +14,7 @@ module CPFEM2 use material use lattice use IO + use base64 use DAMASK_interface use results use discretization @@ -42,6 +43,7 @@ subroutine CPFEM_initAll call DAMASK_interface_init ! Spectral and FEM interface to commandline call prec_init call IO_init + call base64_init #ifdef Mesh call FEM_quadrature_init #endif diff --git a/src/base64.f90 b/src/base64.f90 new file mode 100644 index 000000000..32ead69cd --- /dev/null +++ b/src/base64.f90 @@ -0,0 +1,180 @@ +!-------------------------------------------------------------------------------------------------- +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Decode Base64 strings +!-------------------------------------------------------------------------------------------------- +module base64 + use prec + use IO + + implicit none + private + + public :: & + base64_init, & + base64_to_bytes, & + base64_nBase64, & + base64_nByte + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief do self test +!-------------------------------------------------------------------------------------------------- +subroutine base64_init + + write(6,'(/,a)') ' <<<+- base64 init -+>>>'; flush(6) + + call selfTest + +end subroutine base64_init + + +!-------------------------------------------------------------------------------------------------- +!> @brief calculate number of Base64 characters required for storage of N bytes +!-------------------------------------------------------------------------------------------------- +pure function base64_nBase64(nByte) + + integer(pLongInt), intent(in) :: nByte + integer(pLongInt) :: base64_nBase64 + + base64_nBase64 = 4_pLongInt * (nByte/3_pLongInt + merge(1_pLongInt,0_pLongInt,mod(nByte,3_pLongInt) /= 0_pLongInt)) + +end function base64_nBase64 + + +!-------------------------------------------------------------------------------------------------- +!> @brief calculate number of bytes required for storage of N Base64 characters +!-------------------------------------------------------------------------------------------------- +pure function base64_nByte(nBase64) + + integer(pLongInt), intent(in) :: nBase64 + integer(pLongInt) :: base64_nByte + + base64_nByte = 3_pLongInt * (nBase64/4_pLongInt) + +end function base64_nByte + + +!-------------------------------------------------------------------------------------------------- +!> @brief return byte-wise binary representation of a (part of a) Base64 ASCII string +!-------------------------------------------------------------------------------------------------- +pure function base64_to_bytes(base64_str,s,e) result(bytes) + + character(len=*), intent(in) :: base64_str !< Base64 string representation + integer(pLongInt), intent(in), optional :: & + s, & !< start (in bytes) + e !< end (in bytes) + + integer(pLongInt) :: s_, e_ + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes, bytes_raw + + allocate(bytes_raw(base64_nByte(len_trim(base64_str,pLongInt)))) + + if(present(s)) then + s_ = s + else + s_ = 1 + endif + + if(present(e)) then + e_ = e + else + e_ = size(bytes_raw,kind=pLongInt) + endif + + ! ToDo: inefficient for s_>>1 or e_< @brief convert a Base64 ASCII string into its byte-wise binary representation +!> @details https://en.wikipedia.org/wiki/Base64 +!-------------------------------------------------------------------------------------------------- +pure subroutine decode_base64(bytes,base64_str) + + integer(C_SIGNED_CHAR), intent(out),dimension(:) :: bytes !< byte-wise representation + character(len=*), intent(in) :: base64_str !< Base64 string representation + + integer(C_SIGNED_CHAR), dimension(0:3) :: charPos + integer(pLongInt) :: c, b, bytesLen,base64Len, p + character(len=*), parameter :: encoding='ABCDEFGHIJKLMNOPQRSTUVWXYZ& + &abcdefghijklmnopqrstuvwxyz0123456789+/' + + bytes = 0_C_SIGNED_CHAR + + bytesLen = size(bytes,kind=pLongInt) + base64Len = len_trim(base64_str,kind=pLongInt) + + c = 1_pLongInt + b = 1_pLongInt + + do while(.True.) + do p=0_pLongInt,3_pLongInt + if(c+p<=len(base64_str,kind=pLongInt)) then + charPos(p) = int(merge(index(encoding,base64_str(c+p:c+p))-1, 0, base64_str(c+p:c+p) /= '='),C_SIGNED_CHAR) + else + charPos(p) = 0_C_SIGNED_CHAR + endif + enddo + + if (b+0<=bytesLen) then + call mvbits(charPos(0),0,6,bytes(b+0),2) + call mvbits(charPos(1),4,2,bytes(b+0),0) + endif + if (b+1<=bytesLen) then + call mvbits(charPos(1),0,4,bytes(b+1),4) + call mvbits(charPos(2),2,4,bytes(b+1),0) + endif + if (b+2<=bytesLen) then + call mvbits(charPos(2),0,2,bytes(b+2),6) + call mvbits(charPos(3),0,6,bytes(b+2),0) + endif + b = b+3_pLongInt + c = c+4_pLongInt + if(b>bytesLen+3_pLongInt .or. c > base64Len+4_pLongInt) exit + enddo + +end subroutine decode_base64 + + +!-------------------------------------------------------------------------------------------------- +!> @brief check correctness of base64 functions +!-------------------------------------------------------------------------------------------------- +subroutine selfTest + + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes + character(len=*), parameter :: zero_to_three = 'AAECAw==' + + allocate(bytes(7), source = -1_C_SIGNED_CHAR) + call decode_base64(bytes,zero_to_three) + if(any(bytes /= int([0,1,2,3,0,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 7) call IO_error(0,ext_msg='base64_decode') + + bytes = base64_to_bytes(zero_to_three) + if(any(bytes /= int([0,1,2,3,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 6) call IO_error(0,ext_msg='base64_to_bytes') + + bytes = base64_to_bytes(zero_to_three,s=2_pLongInt) + if(any(bytes /= int([1,2,3,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 5) call IO_error(0,ext_msg='base64_to_bytes/s') + + bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=3_pLongInt) + if(any(bytes /= int([1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/s/e') + + bytes = base64_to_bytes(zero_to_three,e=2_pLongInt) + if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/e') + + ! https://en.wikipedia.org/wiki/Base64#Output_padding + if(base64_nBase64(20_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nBase64/20/28') + if(base64_nBase64(19_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nBase64/19/28') + if(base64_nBase64(18_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/18/24') + if(base64_nBase64(17_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/17/24') + if(base64_nBase64(16_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/16/24') + + if(base64_nByte(4_pLongInt) /= 3_pLongInt) call IO_error(0,ext_msg='base64_nByte/4/3') + if(base64_nByte(8_pLongInt) /= 6_pLongInt) call IO_error(0,ext_msg='base64_nByte/8/6') + +end subroutine selfTest + +end module base64 From 9ce406ed11919c25a24c040041e5d46a775af360 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Sep 2020 17:49:00 +0200 Subject: [PATCH 03/42] wrapper for zlib library assume that zlib is available for linking. This is usually the case (zlib is a stable standard library), but there is currently no check that gives a nice error message or the possibility to use zlib from a non-standard location --- CMakeLists.txt | 2 +- src/C_routines.c | 15 +++++++++++++++ src/zlib.f90 | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/zlib.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 708d8aa3c..dd2348fd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,7 +184,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "DEBUG") endif () set (CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}} ${PETSC_INCLUDES} ${BUILDCMD_POST}") -set (CMAKE_Fortran_LINK_EXECUTABLE "${CMAKE_Fortran_LINK_EXECUTABLE} -o ${PETSC_EXTERNAL_LIB} ${BUILDCMD_POST}") +set (CMAKE_Fortran_LINK_EXECUTABLE "${CMAKE_Fortran_LINK_EXECUTABLE} -o ${PETSC_EXTERNAL_LIB} -lz ${BUILDCMD_POST}") message ("Fortran Compiler Flags:\n${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}}\n") message ("C Compiler Flags:\n${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}}\n") diff --git a/src/C_routines.c b/src/C_routines.c index 723c2978d..927b26412 100644 --- a/src/C_routines.c +++ b/src/C_routines.c @@ -6,6 +6,7 @@ #include #include #include +#include "zlib.h" /* http://stackoverflow.com/questions/30279228/is-there-an-alternative-to-getcwd-in-fortran-2003-2008 */ @@ -57,3 +58,17 @@ void signalusr1_c(void (*handler)(int)){ 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_; + s_inflated_ = *s_inflated; + + if(uncompress((Bytef *)inflated, &s_inflated_, (Bytef *)deflated, *s_deflated) == Z_OK) + return; + else{ + for(uLong i=0;i<*s_inflated;i++){ + inflated[i] = 0; + } + } +} diff --git a/src/zlib.f90 b/src/zlib.f90 new file mode 100644 index 000000000..670131334 --- /dev/null +++ b/src/zlib.f90 @@ -0,0 +1,44 @@ +!-------------------------------------------------------------------------------------------------- +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Inflate zlib compressed data +!-------------------------------------------------------------------------------------------------- +module zlib + use prec + + implicit none + private + + public :: & + zlib_inflate + + interface + + subroutine inflate_C(s_deflated,s_inflated,deflated,inflated) bind(C) + use, intrinsic :: ISO_C_Binding, only: & + C_SIGNED_CHAR, C_INT64_T + + integer(C_INT64_T), intent(in) :: s_deflated,s_inflated + integer(C_SIGNED_CHAR), dimension(s_deflated), intent(in) :: deflated + integer(C_SIGNED_CHAR), dimension(s_inflated), intent(out) :: inflated + + end subroutine inflate_C + + end interface + +contains + +!-------------------------------------------------------------------------------------------------- +!> @brief Inflate byte-wise representation +!-------------------------------------------------------------------------------------------------- +function zlib_inflate(deflated,size_inflated) + + integer(C_SIGNED_CHAR), dimension(:), intent(in) :: deflated + integer(pLongInt), intent(in) :: size_inflated + + integer(C_SIGNED_CHAR), dimension(size_inflated) :: zlib_inflate + + call inflate_C(size(deflated,kind=C_INT64_T),int(size_inflated,C_INT64_T),deflated,zlib_inflate) + +end function zlib_inflate + +end module zlib From 3fdcebc0a08b247f80ff9e7593563fd32656a4d7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 6 Sep 2020 17:50:32 +0200 Subject: [PATCH 04/42] following python recommendation functions have "active" docstring --- src/IO.f90 | 3 ++- src/rotations.f90 | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/IO.f90 b/src/IO.f90 index d4533f47c..5dbbf8563 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -10,6 +10,7 @@ module IO implicit none private + character(len=*), parameter, public :: & IO_WHITESPACE = achar(44)//achar(32)//achar(9)//achar(10)//achar(13) !< whitespace characters character, parameter, public :: & @@ -50,7 +51,7 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief does nothing. +!> @brief do self test !-------------------------------------------------------------------------------------------------- subroutine IO_init diff --git a/src/rotations.f90 b/src/rotations.f90 index fc523e813..ee1cf6b96 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -99,7 +99,7 @@ module rotations contains !-------------------------------------------------------------------------------------------------- -!> @brief doing self test +!> @brief do self test !-------------------------------------------------------------------------------------------------- subroutine rotations_init From cfad4a71f653a87a930ff70a646b96ad5ac4e63e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 05:56:01 +0200 Subject: [PATCH 05/42] clearer logic --- src/base64.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index 32ead69cd..3a02e9491 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -112,7 +112,7 @@ pure subroutine decode_base64(bytes,base64_str) c = 1_pLongInt b = 1_pLongInt - do while(.True.) + do while(b <= bytesLen+3_pLongInt .and. c <= base64Len+4_pLongInt) do p=0_pLongInt,3_pLongInt if(c+p<=len(base64_str,kind=pLongInt)) then charPos(p) = int(merge(index(encoding,base64_str(c+p:c+p))-1, 0, base64_str(c+p:c+p) /= '='),C_SIGNED_CHAR) @@ -135,7 +135,6 @@ pure subroutine decode_base64(bytes,base64_str) endif b = b+3_pLongInt c = c+4_pLongInt - if(b>bytesLen+3_pLongInt .or. c > base64Len+4_pLongInt) exit enddo end subroutine decode_base64 From 43e9ea352aa0b096e30aeab8717c38c265f36254 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 05:56:10 +0200 Subject: [PATCH 06/42] typo --- src/prec.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/prec.f90 b/src/prec.f90 index 6f0a2ab3d..8fe38b5ef 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -232,7 +232,7 @@ end function cNeq !-------------------------------------------------------------------------------------------------- -!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_FLOAT (4 byte float) +!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_FLOAT (4 byte float) !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_FLOAT(bytes) @@ -246,7 +246,7 @@ end function bytes_to_C_FLOAT !-------------------------------------------------------------------------------------------------- -!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_DOUBLE (8 byte float) +!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_DOUBLE (8 byte float) !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_DOUBLE(bytes) @@ -260,7 +260,7 @@ end function bytes_to_C_DOUBLE !-------------------------------------------------------------------------------------------------- -!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT32_T (4 byte signed integer) +!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_INT32_T (4 byte signed integer) !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_INT32_T(bytes) @@ -274,7 +274,7 @@ end function bytes_to_C_INT32_T !-------------------------------------------------------------------------------------------------- -!> @brief interprete array of bytes (C_SIGNED_CHAR) as C_INT64_T (8 byte signed integer) +!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_INT64_T (8 byte signed integer) !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_INT64_T(bytes) From 1f28592fcdbbccef98d133ab431bfb83b51b76fe Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 06:55:04 +0200 Subject: [PATCH 07/42] improved documentation Python/numpy style: Active description, start with capital, end with full stop --- src/prec.f90 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/prec.f90 b/src/prec.f90 index 8fe38b5ef..8bb3332f3 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -101,7 +101,7 @@ end subroutine prec_init !-------------------------------------------------------------------------------------------------- -!> @brief equality comparison for float with double precision +!> @brief Test floating point numbers with double precision for equality. ! replaces "==" but for certain (relative) tolerance. Counterpart to dNeq ! https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ ! AlmostEqualRelative @@ -124,7 +124,7 @@ end function dEq !-------------------------------------------------------------------------------------------------- -!> @brief inequality comparison for float with double precision +!> @brief Test floating point numbers with double precision for inequality. ! replaces "!=" but for certain (relative) tolerance. Counterpart to dEq ! https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ ! AlmostEqualRelative NOT @@ -144,7 +144,7 @@ end function dNeq !-------------------------------------------------------------------------------------------------- -!> @brief equality to 0 comparison for float with double precision +!> @brief Test floating point number with double precision for equality to 0. ! replaces "==0" but everything not representable as a normal number is treated as 0. Counterpart to dNeq0 ! https://de.mathworks.com/help/matlab/ref/realmin.html ! https://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html @@ -167,7 +167,7 @@ end function dEq0 !-------------------------------------------------------------------------------------------------- -!> @brief inequality to 0 comparison for float with double precision +!> @brief Test floating point number with double precision for inequality to 0. ! replaces "!=0" but everything not representable as a normal number is treated as 0. Counterpart to dEq0 ! https://de.mathworks.com/help/matlab/ref/realmin.html ! https://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html @@ -187,7 +187,7 @@ end function dNeq0 !-------------------------------------------------------------------------------------------------- -!> @brief equality comparison for complex with double precision +!> @brief Test complex floating point numbers with double precision for equality. ! replaces "==" but for certain (relative) tolerance. Counterpart to cNeq ! https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ ! probably a component wise comparison would be more accurate than the comparsion of the absolute @@ -211,7 +211,7 @@ end function cEq !-------------------------------------------------------------------------------------------------- -!> @brief inequality comparison for complex with double precision +!> @brief Test complex floating point numbers with double precision for inequality. ! replaces "!=" but for certain (relative) tolerance. Counterpart to cEq ! https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ ! probably a component wise comparison would be more accurate than the comparsion of the absolute @@ -232,7 +232,7 @@ end function cNeq !-------------------------------------------------------------------------------------------------- -!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_FLOAT (4 byte float) +!> @brief Decode byte array (C_SIGNED_CHAR) as C_FLOAT array (4 byte float). !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_FLOAT(bytes) @@ -246,7 +246,7 @@ end function bytes_to_C_FLOAT !-------------------------------------------------------------------------------------------------- -!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_DOUBLE (8 byte float) +!> @brief Decode byte array (C_SIGNED_CHAR) as C_DOUBLE array (8 byte float). !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_DOUBLE(bytes) @@ -260,7 +260,7 @@ end function bytes_to_C_DOUBLE !-------------------------------------------------------------------------------------------------- -!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_INT32_T (4 byte signed integer) +!> @brief Decode byte array (C_SIGNED_CHAR) as C_INT32_T array (4 byte signed integer). !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_INT32_T(bytes) @@ -274,7 +274,7 @@ end function bytes_to_C_INT32_T !-------------------------------------------------------------------------------------------------- -!> @brief interpret array of bytes (C_SIGNED_CHAR) as C_INT64_T (8 byte signed integer) +!> @brief Decode byte array (C_SIGNED_CHAR) as C_INT64_T array (8 byte signed integer). !-------------------------------------------------------------------------------------------------- pure function bytes_to_C_INT64_T(bytes) @@ -288,7 +288,7 @@ end function bytes_to_C_INT64_T !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of some prec functions +!> @brief Check correctness of some prec functions. !-------------------------------------------------------------------------------------------------- subroutine selfTest From 049ad4e202989401095400141c981339ac2b5880 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 06:34:21 +0200 Subject: [PATCH 08/42] simplify base64 handling require valid base64 string, which allows to calculate output size automatically --- src/base64.f90 | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index 3a02e9491..a93f64340 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -84,7 +84,7 @@ pure function base64_to_bytes(base64_str,s,e) result(bytes) endif ! ToDo: inefficient for s_>>1 or e_< @brief convert a Base64 ASCII string into its byte-wise binary representation -!> @details https://en.wikipedia.org/wiki/Base64 +!> @details see https://en.wikipedia.org/wiki/Base64. Input string must be properly padded. !-------------------------------------------------------------------------------------------------- -pure subroutine decode_base64(bytes,base64_str) +pure function decode_base64(base64_str) result(bytes) - integer(C_SIGNED_CHAR), intent(out),dimension(:) :: bytes !< byte-wise representation - character(len=*), intent(in) :: base64_str !< Base64 string representation + character(len=*), intent(in) :: base64_str !< Base64 string representation + + integer(C_SIGNED_CHAR), dimension(base64_nByte(len_trim(base64_str,pLongInt))) :: bytes integer(C_SIGNED_CHAR), dimension(0:3) :: charPos - integer(pLongInt) :: c, b, bytesLen,base64Len, p + integer(pLongInt) :: c, b, p character(len=*), parameter :: encoding='ABCDEFGHIJKLMNOPQRSTUVWXYZ& &abcdefghijklmnopqrstuvwxyz0123456789+/' - bytes = 0_C_SIGNED_CHAR - - bytesLen = size(bytes,kind=pLongInt) - base64Len = len_trim(base64_str,kind=pLongInt) - c = 1_pLongInt b = 1_pLongInt - do while(b <= bytesLen+3_pLongInt .and. c <= base64Len+4_pLongInt) + do while(c + 3_pInt <= len_trim(base64_str,kind=pLongInt)) !ToDo: Confusing + 3 do p=0_pLongInt,3_pLongInt if(c+p<=len(base64_str,kind=pLongInt)) then charPos(p) = int(merge(index(encoding,base64_str(c+p:c+p))-1, 0, base64_str(c+p:c+p) /= '='),C_SIGNED_CHAR) @@ -121,23 +117,17 @@ pure subroutine decode_base64(bytes,base64_str) endif enddo - if (b+0<=bytesLen) then - call mvbits(charPos(0),0,6,bytes(b+0),2) - call mvbits(charPos(1),4,2,bytes(b+0),0) - endif - if (b+1<=bytesLen) then - call mvbits(charPos(1),0,4,bytes(b+1),4) - call mvbits(charPos(2),2,4,bytes(b+1),0) - endif - if (b+2<=bytesLen) then - call mvbits(charPos(2),0,2,bytes(b+2),6) - call mvbits(charPos(3),0,6,bytes(b+2),0) - endif + call mvbits(charPos(0),0,6,bytes(b+0),2) + call mvbits(charPos(1),4,2,bytes(b+0),0) + call mvbits(charPos(1),0,4,bytes(b+1),4) + call mvbits(charPos(2),2,4,bytes(b+1),0) + call mvbits(charPos(2),0,2,bytes(b+2),6) + call mvbits(charPos(3),0,6,bytes(b+2),0) b = b+3_pLongInt c = c+4_pLongInt enddo -end subroutine decode_base64 +end function decode_base64 !-------------------------------------------------------------------------------------------------- @@ -148,10 +138,6 @@ subroutine selfTest integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes character(len=*), parameter :: zero_to_three = 'AAECAw==' - allocate(bytes(7), source = -1_C_SIGNED_CHAR) - call decode_base64(bytes,zero_to_three) - if(any(bytes /= int([0,1,2,3,0,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 7) call IO_error(0,ext_msg='base64_decode') - bytes = base64_to_bytes(zero_to_three) if(any(bytes /= int([0,1,2,3,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 6) call IO_error(0,ext_msg='base64_to_bytes') From a70819e4585379a00b9f3eb870b1d0994f6543ba Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 10:36:22 +0200 Subject: [PATCH 09/42] simplified base64 encoding - ensure valid Base64 string (needs to be padded correctly) - background routine expects proper Base64 string (length = N*4) - user routine ensures correct length of byte representation --- src/base64.f90 | 77 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index a93f64340..743afb5a7 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -1,6 +1,7 @@ !-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief Decode Base64 strings +!> @brief Decode Base64 strings. +!> @details See https://en.wikipedia.org/wiki/Base64. !-------------------------------------------------------------------------------------------------- module base64 use prec @@ -9,6 +10,9 @@ module base64 implicit none private + character(len=*), parameter :: & + base64_encoding='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + public :: & base64_init, & base64_to_bytes, & @@ -19,7 +23,7 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief do self test +!> @brief Do self test. !-------------------------------------------------------------------------------------------------- subroutine base64_init @@ -31,7 +35,7 @@ end subroutine base64_init !-------------------------------------------------------------------------------------------------- -!> @brief calculate number of Base64 characters required for storage of N bytes +!> @brief Calculate number of Base64 characters required for storage of N bytes. !-------------------------------------------------------------------------------------------------- pure function base64_nBase64(nByte) @@ -44,7 +48,7 @@ end function base64_nBase64 !-------------------------------------------------------------------------------------------------- -!> @brief calculate number of bytes required for storage of N Base64 characters +!> @brief Calculate number of bytes required for storage of N Base64 characters. !-------------------------------------------------------------------------------------------------- pure function base64_nByte(nBase64) @@ -57,61 +61,64 @@ end function base64_nByte !-------------------------------------------------------------------------------------------------- -!> @brief return byte-wise binary representation of a (part of a) Base64 ASCII string +!> @brief Decode Base64 ASCII string into byte-wise binary representation. !-------------------------------------------------------------------------------------------------- -pure function base64_to_bytes(base64_str,s,e) result(bytes) +function base64_to_bytes(base64_str,s,e) result(bytes) character(len=*), intent(in) :: base64_str !< Base64 string representation integer(pLongInt), intent(in), optional :: & s, & !< start (in bytes) e !< end (in bytes) - integer(pLongInt) :: s_, e_ + integer(pLongInt) :: s_bytes, e_bytes integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes, bytes_raw - allocate(bytes_raw(base64_nByte(len_trim(base64_str,pLongInt)))) + if(.not. valid_base64(base64_str)) error stop 'invalid base64' if(present(s)) then - s_ = s + if(s<1_pLongInt) error stop 'invalid s' + s_bytes = s else - s_ = 1 + s_bytes = 1 endif if(present(e)) then - e_ = e + if(e>base64_nByte(len(base64_str,kind=pLongInt))) error stop 'invalid e' + e_bytes = e else - e_ = size(bytes_raw,kind=pLongInt) + e_bytes = base64_nByte(len(base64_str,kind=pLongInt)) + if(base64_str(len(base64_str)-0_pLongInt:len(base64_str)-0_pLongInt) == '=') & + e_bytes = e_bytes -1_pLongInt + if(base64_str(len(base64_str)-1_pLongInt:len(base64_str)-1_pLongInt) == '=') & + e_bytes = e_bytes -1_pLongInt endif ! ToDo: inefficient for s_>>1 or e_< @brief convert a Base64 ASCII string into its byte-wise binary representation -!> @details see https://en.wikipedia.org/wiki/Base64. Input string must be properly padded. +!> @brief Convert a Base64 ASCII string into its byte-wise binary representation. !-------------------------------------------------------------------------------------------------- pure function decode_base64(base64_str) result(bytes) character(len=*), intent(in) :: base64_str !< Base64 string representation - integer(C_SIGNED_CHAR), dimension(base64_nByte(len_trim(base64_str,pLongInt))) :: bytes + integer(C_SIGNED_CHAR), dimension(base64_nByte(len(base64_str,pLongInt))) :: bytes integer(C_SIGNED_CHAR), dimension(0:3) :: charPos integer(pLongInt) :: c, b, p - character(len=*), parameter :: encoding='ABCDEFGHIJKLMNOPQRSTUVWXYZ& - &abcdefghijklmnopqrstuvwxyz0123456789+/' c = 1_pLongInt b = 1_pLongInt - do while(c + 3_pInt <= len_trim(base64_str,kind=pLongInt)) !ToDo: Confusing + 3 + do while(c < len(base64_str,kind=pLongInt)) do p=0_pLongInt,3_pLongInt if(c+p<=len(base64_str,kind=pLongInt)) then - charPos(p) = int(merge(index(encoding,base64_str(c+p:c+p))-1, 0, base64_str(c+p:c+p) /= '='),C_SIGNED_CHAR) + charPos(p) = int(index(base64_encoding,base64_str(c+p:c+p))-1,C_SIGNED_CHAR) else charPos(p) = 0_C_SIGNED_CHAR endif @@ -131,7 +138,27 @@ end function decode_base64 !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of base64 functions +!> @brief Test for valid Base64 encoded string. +!> @details Input string must be properly padded. +!-------------------------------------------------------------------------------------------------- +pure logical function valid_base64(base64_str) + + character(len=*), intent(in) :: base64_str !< Base64 string representation + + integer(pLongInt) :: l + + l = len(base64_str,pLongInt) + valid_base64 = .true. + + if(mod(l,4_pLongInt)/=0_pLongInt .or. l < 4_pInt) valid_base64 = .false. + if(verify(base64_str(:l-2_pLongInt),base64_encoding, kind=pLongInt) /= 0_pLongInt) valid_base64 = .false. + if(verify(base64_str(l-1_pLongInt:),base64_encoding//'=',kind=pLongInt) /= 0_pLongInt) valid_base64 = .false. + +end function valid_base64 + + +!-------------------------------------------------------------------------------------------------- +!> @brief Check correctness of base64 functions. !-------------------------------------------------------------------------------------------------- subroutine selfTest @@ -139,16 +166,16 @@ subroutine selfTest character(len=*), parameter :: zero_to_three = 'AAECAw==' bytes = base64_to_bytes(zero_to_three) - if(any(bytes /= int([0,1,2,3,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 6) call IO_error(0,ext_msg='base64_to_bytes') + if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes') bytes = base64_to_bytes(zero_to_three,s=2_pLongInt) - if(any(bytes /= int([1,2,3,0,0],C_SIGNED_CHAR)) .or. size(bytes) /= 5) call IO_error(0,ext_msg='base64_to_bytes/s') + if(any(bytes /= int([1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/s') bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=3_pLongInt) - if(any(bytes /= int([1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/s/e') + if(any(bytes /= int([1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/s/e') bytes = base64_to_bytes(zero_to_three,e=2_pLongInt) - if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/e') + if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/e') ! https://en.wikipedia.org/wiki/Base64#Output_padding if(base64_nBase64(20_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nBase64/20/28') From fb68d430ec7a975401741a559e7c6f6c3547c4a3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 8 Sep 2020 22:44:01 +0200 Subject: [PATCH 10/42] decode only relevant part of the base64 string --- src/IO.f90 | 3 +++ src/base64.f90 | 68 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/IO.f90 b/src/IO.f90 index 5dbbf8563..2884eab33 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -448,6 +448,9 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg) msg = 'invalid character for float:' case (113) msg = 'invalid character for logical:' + case (114) + msg = 'cannot decode base64 string:' + !-------------------------------------------------------------------------------------------------- ! lattice error messages case (130) diff --git a/src/base64.f90 b/src/base64.f90 index 743afb5a7..2d2d4d010 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -70,22 +70,26 @@ function base64_to_bytes(base64_str,s,e) result(bytes) s, & !< start (in bytes) e !< end (in bytes) - integer(pLongInt) :: s_bytes, e_bytes - integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes, bytes_raw + integer(pLongInt) :: s_bytes, e_bytes, s_str, e_str + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes - if(.not. valid_base64(base64_str)) error stop 'invalid base64' + if(.not. valid_base64(base64_str)) call IO_error(114,'invalid character') if(present(s)) then - if(s<1_pLongInt) error stop 'invalid s' - s_bytes = s + if(s<1_pLongInt) call IO_error(114, 's out of range') + s_str = ((s-1_pLongInt)/3_pLongInt)*4_pLongInt + 1_pLongInt + s_bytes = mod(s-1_pLongInt,3_pLongInt) + 1_pLongInt else - s_bytes = 1 + s_str = 1_pLongInt + s_bytes = 1_pLongInt endif if(present(e)) then - if(e>base64_nByte(len(base64_str,kind=pLongInt))) error stop 'invalid e' + if(e>base64_nByte(len(base64_str,kind=pLongInt))) call IO_error(114, 'e out of range') + e_str = ((e-1_pLongInt)/3_pLongInt)*4_pLongInt + 4_pLongInt e_bytes = e else + e_str = len(base64_str,kind=pLongInt) e_bytes = base64_nByte(len(base64_str,kind=pLongInt)) if(base64_str(len(base64_str)-0_pLongInt:len(base64_str)-0_pLongInt) == '=') & e_bytes = e_bytes -1_pLongInt @@ -93,9 +97,10 @@ function base64_to_bytes(base64_str,s,e) result(bytes) e_bytes = e_bytes -1_pLongInt endif - ! ToDo: inefficient for s_>>1 or e_< Date: Tue, 8 Sep 2020 23:21:45 +0200 Subject: [PATCH 11/42] keyword was missing --- src/base64.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index 2d2d4d010..735a19a34 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -73,10 +73,10 @@ function base64_to_bytes(base64_str,s,e) result(bytes) integer(pLongInt) :: s_bytes, e_bytes, s_str, e_str integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes - if(.not. valid_base64(base64_str)) call IO_error(114,'invalid character') + if(.not. valid_base64(base64_str)) call IO_error(114,ext_msg='invalid character') if(present(s)) then - if(s<1_pLongInt) call IO_error(114, 's out of range') + if(s<1_pLongInt) call IO_error(114, ext_msg='s out of range') s_str = ((s-1_pLongInt)/3_pLongInt)*4_pLongInt + 1_pLongInt s_bytes = mod(s-1_pLongInt,3_pLongInt) + 1_pLongInt else @@ -85,7 +85,7 @@ function base64_to_bytes(base64_str,s,e) result(bytes) endif if(present(e)) then - if(e>base64_nByte(len(base64_str,kind=pLongInt))) call IO_error(114, 'e out of range') + if(e>base64_nByte(len(base64_str,kind=pLongInt))) call IO_error(114, ext_msg='e out of range') e_str = ((e-1_pLongInt)/3_pLongInt)*4_pLongInt + 4_pLongInt e_bytes = e else From 0f9fb7e68356ff0cb23c23e6b6fdc928dcb22853 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 8 Sep 2020 23:53:27 +0200 Subject: [PATCH 12/42] [skip ci] updated version information after successful test of v3.0.0-alpha-105-gf57cb8b7 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a76c23653..ec915dcad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-92-g751bf786 +v3.0.0-alpha-105-gf57cb8b7 From 85d9e843f02d933a2dafa21cc2b072aead518c9e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 9 Sep 2020 07:50:12 +0200 Subject: [PATCH 13/42] better readable --- src/base64.f90 | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index 735a19a34..fac08f80e 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -87,18 +87,14 @@ function base64_to_bytes(base64_str,s,e) result(bytes) if(present(e)) then if(e>base64_nByte(len(base64_str,kind=pLongInt))) call IO_error(114, ext_msg='e out of range') e_str = ((e-1_pLongInt)/3_pLongInt)*4_pLongInt + 4_pLongInt - e_bytes = e + e_bytes = e - base64_nByte(s_str) else e_str = len(base64_str,kind=pLongInt) - e_bytes = base64_nByte(len(base64_str,kind=pLongInt)) - if(base64_str(len(base64_str)-0_pLongInt:len(base64_str)-0_pLongInt) == '=') & - e_bytes = e_bytes -1_pLongInt - if(base64_str(len(base64_str)-1_pLongInt:len(base64_str)-1_pLongInt) == '=') & - e_bytes = e_bytes -1_pLongInt + e_bytes = base64_nByte(len(base64_str,kind=pLongInt)) - base64_nByte(s_str) + if(base64_str(e_str-0_pLongInt:e_str-0_pLongInt) == '=') e_bytes = e_bytes - 1_pLongInt + if(base64_str(e_str-1_pLongInt:e_str-1_pLongInt) == '=') e_bytes = e_bytes - 1_pLongInt endif - e_bytes = e_bytes - base64_nByte(s_str) - bytes = decode_base64(base64_str(s_str:e_str)) bytes = bytes(s_bytes:e_bytes) From edf16de7b6255e9d402a256f4f0084a11a551fbc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 9 Sep 2020 11:53:25 +0200 Subject: [PATCH 14/42] include pytest-based state integration test --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 1b82ac397..3bc603489 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 1b82ac39703fdea70962aea47a0381d50bd1d44e +Subproject commit 3bc60348981a68bc22a5ebaafe4173b7513ac264 From a5f9ef118a6e162cfe2133fc90a10e57c3c9535b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 9 Sep 2020 12:38:02 +0200 Subject: [PATCH 15/42] feature complete test --- src/base64.f90 | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index fac08f80e..eb2a1e929 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -178,7 +178,7 @@ subroutine selfTest bytes = base64_to_bytes(zero_to_three) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes//') - + bytes = base64_to_bytes(zero_to_three,e=1_pLongInt) if(any(bytes /= int([0],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes//1') bytes = base64_to_bytes(zero_to_three,e=2_pLongInt) @@ -187,7 +187,7 @@ subroutine selfTest if(any(bytes /= int([0,1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes//3') bytes = base64_to_bytes(zero_to_three,e=4_pLongInt) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes//4') - + bytes = base64_to_bytes(zero_to_three,s=1_pLongInt) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes/1/') bytes = base64_to_bytes(zero_to_three,s=2_pLongInt) @@ -196,7 +196,7 @@ subroutine selfTest if(any(bytes /= int([2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/3/') bytes = base64_to_bytes(zero_to_three,s=4_pLongInt) if(any(bytes /= int([3],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/4/') - + bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=1_pLongInt) if(any(bytes /= int([0],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/1/1') bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=2_pLongInt) @@ -205,7 +205,21 @@ subroutine selfTest if(any(bytes /= int([2],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/3/3') bytes = base64_to_bytes(zero_to_three,s=4_pLongInt,e=4_pLongInt) if(any(bytes /= int([3],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/4/4') - + + bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=2_pLongInt) + if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/1/2') + bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=3_pLongInt) + if(any(bytes /= int([1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/2/3') + bytes = base64_to_bytes(zero_to_three,s=3_pLongInt,e=4_pLongInt) + if(any(bytes /= int([2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/3/4') + + bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=3_pLongInt) + if(any(bytes /= int([0,1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/1/3') + bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=4_pLongInt) + if(any(bytes /= int([1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/2/4') + + bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=4_pLongInt) + if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes/1/4') end subroutine selfTest From c189d35df6fd5ffddb0f299e1d1f6781c0e714a2 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 9 Sep 2020 13:08:31 +0200 Subject: [PATCH 16/42] [skip ci] updated version information after successful test of v3.0.0-alpha-113-g3352a5a1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ec915dcad..22da2ccfb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-105-gf57cb8b7 +v3.0.0-alpha-113-g3352a5a1 From e0b4bc6d1ecedf374bd4d438f900d0c945fe6742 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 9 Sep 2020 21:09:23 +0200 Subject: [PATCH 17/42] [skip ci] updated version information after successful test of v3.0.0-alpha-129-gd7932aea --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 22da2ccfb..72f7156f8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-113-g3352a5a1 +v3.0.0-alpha-129-gd7932aea From 7d9a4c08ce083a6ac0ecdee315ab4c89849ea475 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 10 Sep 2020 00:59:40 +0200 Subject: [PATCH 18/42] Do not strictly require np.ndarrays for grid, size, or origin when not essential for functionality. --- python/damask/_vtk.py | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 2fd374f7c..4a2f7540a 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -40,20 +40,20 @@ class VTK: """ Create VTK of type vtk.vtkRectilinearGrid. - This is the common type for results from the grid solver. + This is the common type for grid solver results. Parameters ---------- - grid : numpy.ndarray of shape (3) of np.dtype = int - Number of cells. - size : numpy.ndarray of shape (3) - Physical length. - origin : numpy.ndarray of shape (3), optional - Spatial origin. + grid : iterable of int, len (3) + Number of cells along each dimension. + size : iterable of float, len (3) + Physical lengths along each dimension. + origin : iterable of float, len (3), optional + Spatial origin coordinates. """ vtk_data = vtk.vtkRectilinearGrid() - vtk_data.SetDimensions(*(grid+1)) + vtk_data.SetDimensions(*(np.array(grid)+1)) coord = [np_to_vtk(np.linspace(origin[i],origin[i]+size[i],grid[i]+1),deep=True) for i in [0,1,2]] [coord[i].SetName(n) for i,n in enumerate(['x','y','z'])] vtk_data.SetXCoordinates(coord[0]) @@ -68,7 +68,7 @@ class VTK: """ Create VTK of type vtk.vtkUnstructuredGrid. - This is the common type for results from FEM solvers. + This is the common type for FEM solver results. Parameters ---------- @@ -127,7 +127,7 @@ class VTK: fname : str or pathlib.Path Filename for reading. Valid extensions are .vtr, .vtu, .vtp, and .vtk. dataset_type : str, optional - Name of the vtk.vtkDataSet subclass when opening an .vtk file. Valid types are vtkRectilinearGrid, + Name of the vtk.vtkDataSet subclass when opening a .vtk file. Valid types are vtkRectilinearGrid, vtkUnstructuredGrid, and vtkPolyData. """ @@ -215,31 +215,30 @@ class VTK: Parameters ---------- data : numpy.ndarray - Data to add. First dimension need to match either - number of cells or number of points + Data to add. First dimension needs to match either + number of cells or number of points. label : str Data label. """ + N_data = data.shape[0] N_points = self.vtk_data.GetNumberOfPoints() N_cells = self.vtk_data.GetNumberOfCells() - if isinstance(data,np.ndarray): + if isinstance(data,np.ndarray): if label is None: raise ValueError('No label defined for numpy.ndarray') - if data.dtype in [np.float64, np.float128]: # avoid large files - d = np_to_vtk(num_array=data.astype(np.float32).reshape(data.shape[0],-1),deep=True) - else: - d = np_to_vtk(num_array=data.reshape(data.shape[0],-1),deep=True) + d = np_to_vtk((data.astype(np.float32) if data.dtype in [np.float64, np.float128] + else data).reshape(N_data,-1),deep=True) # avoid large files d.SetName(label) - if data.shape[0] == N_cells: + if N_data == N_cells: self.vtk_data.GetCellData().AddArray(d) - elif data.shape[0] == N_points: + elif N_data == N_points: self.vtk_data.GetPointData().AddArray(d) else: - raise ValueError(f'Invalid shape {data.shape[0]}') + raise ValueError(f'Cell / point count ({N_cells} / {N_points}) differs from data ({N_data}).') elif isinstance(data,pd.DataFrame): raise NotImplementedError('pd.DataFrame') elif isinstance(data,Table): @@ -272,7 +271,7 @@ class VTK: if point_data.GetArrayName(a) == label: return vtk_to_np(point_data.GetArray(a)) - raise ValueError(f'array "{label}" not found') + raise ValueError(f'Array "{label}" not found.') def get_comments(self): From 865c90d00bfc8e2f2cc83f3a11f8d9f891131467 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 9 Sep 2020 19:10:03 -0400 Subject: [PATCH 19/42] first check data type, then determine length of data... --- python/damask/_vtk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 4a2f7540a..7f3e64aef 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -221,7 +221,6 @@ class VTK: Data label. """ - N_data = data.shape[0] N_points = self.vtk_data.GetNumberOfPoints() N_cells = self.vtk_data.GetNumberOfCells() @@ -229,7 +228,8 @@ class VTK: if label is None: raise ValueError('No label defined for numpy.ndarray') - d = np_to_vtk((data.astype(np.float32) if data.dtype in [np.float64, np.float128] + N_data = data.shape[0] + d = np_to_vtk((data.astype(np.float32) if data.dtype in [np.float64, np.float128] else data).reshape(N_data,-1),deep=True) # avoid large files d.SetName(label) From f4f67cb403765c24d81655563bf2a6ddc0245bd9 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 10 Sep 2020 08:43:59 +0200 Subject: [PATCH 20/42] [skip ci] updated version information after successful test of v3.0.0-alpha-133-ga70150c6 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 72f7156f8..c14a5099b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-129-gd7932aea +v3.0.0-alpha-133-ga70150c6 From 062d9986fe04b90e8266b7239e710dda9c816732 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 10 Sep 2020 14:08:36 +0200 Subject: [PATCH 21/42] [skip ci] updated version information after successful test of v3.0.0-alpha-136-gc0ea8e3f --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c14a5099b..5dac27a44 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-133-ga70150c6 +v3.0.0-alpha-136-gc0ea8e3f From 7a6ada9ad74412ee196dc3e5e7ea9e16f0dc666b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 08:47:46 +0200 Subject: [PATCH 22/42] clearer name --- src/base64.f90 | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index eb2a1e929..89696f53d 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -16,7 +16,7 @@ module base64 public :: & base64_init, & base64_to_bytes, & - base64_nBase64, & + base64_nChar, & base64_nByte contains @@ -37,14 +37,14 @@ end subroutine base64_init !-------------------------------------------------------------------------------------------------- !> @brief Calculate number of Base64 characters required for storage of N bytes. !-------------------------------------------------------------------------------------------------- -pure function base64_nBase64(nByte) +pure function base64_nChar(nByte) integer(pLongInt), intent(in) :: nByte - integer(pLongInt) :: base64_nBase64 + integer(pLongInt) :: base64_nChar - base64_nBase64 = 4_pLongInt * (nByte/3_pLongInt + merge(1_pLongInt,0_pLongInt,mod(nByte,3_pLongInt) /= 0_pLongInt)) + base64_nChar = 4_pLongInt * (nByte/3_pLongInt + merge(1_pLongInt,0_pLongInt,mod(nByte,3_pLongInt) /= 0_pLongInt)) -end function base64_nBase64 +end function base64_nChar !-------------------------------------------------------------------------------------------------- @@ -167,14 +167,14 @@ subroutine selfTest character(len=*), parameter :: zero_to_three = 'AAECAw==' ! https://en.wikipedia.org/wiki/Base64#Output_padding - if(base64_nBase64(20_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nBase64/20/28') - if(base64_nBase64(19_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nBase64/19/28') - if(base64_nBase64(18_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/18/24') - if(base64_nBase64(17_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/17/24') - if(base64_nBase64(16_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nBase64/16/24') + if(base64_nChar(20_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nChar/20/28') + if(base64_nChar(19_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nChar/19/28') + if(base64_nChar(18_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/18/24') + if(base64_nChar(17_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/17/24') + if(base64_nChar(16_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/16/24') - if(base64_nByte(4_pLongInt) /= 3_pLongInt) call IO_error(0,ext_msg='base64_nByte/4/3') - if(base64_nByte(8_pLongInt) /= 6_pLongInt) call IO_error(0,ext_msg='base64_nByte/8/6') + if(base64_nByte(4_pLongInt) /= 3_pLongInt) call IO_error(0,ext_msg='base64_nByte/4/3') + if(base64_nByte(8_pLongInt) /= 6_pLongInt) call IO_error(0,ext_msg='base64_nByte/8/6') bytes = base64_to_bytes(zero_to_three) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes//') From a6ac875db8be547aa77ba0fe0c41c008050eafb9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 09:14:33 +0200 Subject: [PATCH 23/42] short and clear names for integer precision --- src/base64.f90 | 130 ++++++++++++++++++++++++------------------------- src/prec.f90 | 15 +++--- src/zlib.f90 | 2 +- 3 files changed, 74 insertions(+), 73 deletions(-) diff --git a/src/base64.f90 b/src/base64.f90 index 89696f53d..3d7a51987 100644 --- a/src/base64.f90 +++ b/src/base64.f90 @@ -39,10 +39,10 @@ end subroutine base64_init !-------------------------------------------------------------------------------------------------- pure function base64_nChar(nByte) - integer(pLongInt), intent(in) :: nByte - integer(pLongInt) :: base64_nChar + integer(pI64), intent(in) :: nByte + integer(pI64) :: base64_nChar - base64_nChar = 4_pLongInt * (nByte/3_pLongInt + merge(1_pLongInt,0_pLongInt,mod(nByte,3_pLongInt) /= 0_pLongInt)) + base64_nChar = 4_pI64 * (nByte/3_pI64 + merge(1_pI64,0_pI64,mod(nByte,3_pI64) /= 0_pI64)) end function base64_nChar @@ -52,10 +52,10 @@ end function base64_nChar !-------------------------------------------------------------------------------------------------- pure function base64_nByte(nBase64) - integer(pLongInt), intent(in) :: nBase64 - integer(pLongInt) :: base64_nByte + integer(pI64), intent(in) :: nBase64 + integer(pI64) :: base64_nByte - base64_nByte = 3_pLongInt * (nBase64/4_pLongInt) + base64_nByte = 3_pI64 * (nBase64/4_pI64) end function base64_nByte @@ -66,36 +66,36 @@ end function base64_nByte function base64_to_bytes(base64_str,s,e) result(bytes) character(len=*), intent(in) :: base64_str !< Base64 string representation - integer(pLongInt), intent(in), optional :: & + integer(pI64), intent(in), optional :: & s, & !< start (in bytes) e !< end (in bytes) - integer(pLongInt) :: s_bytes, e_bytes, s_str, e_str + integer(pI64) :: s_bytes, e_bytes, s_str, e_str integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes - if(.not. valid_base64(base64_str)) call IO_error(114,ext_msg='invalid character') + if(.not. validBase64(base64_str)) call IO_error(114,ext_msg='invalid character') if(present(s)) then - if(s<1_pLongInt) call IO_error(114, ext_msg='s out of range') - s_str = ((s-1_pLongInt)/3_pLongInt)*4_pLongInt + 1_pLongInt - s_bytes = mod(s-1_pLongInt,3_pLongInt) + 1_pLongInt + if(s<1_pI64) call IO_error(114, ext_msg='s out of range') + s_str = ((s-1_pI64)/3_pI64)*4_pI64 + 1_pI64 + s_bytes = mod(s-1_pI64,3_pI64) + 1_pI64 else - s_str = 1_pLongInt - s_bytes = 1_pLongInt + s_str = 1_pI64 + s_bytes = 1_pI64 endif if(present(e)) then - if(e>base64_nByte(len(base64_str,kind=pLongInt))) call IO_error(114, ext_msg='e out of range') - e_str = ((e-1_pLongInt)/3_pLongInt)*4_pLongInt + 4_pLongInt + if(e>base64_nByte(len(base64_str,kind=pI64))) call IO_error(114, ext_msg='e out of range') + e_str = ((e-1_pI64)/3_pI64)*4_pI64 + 4_pI64 e_bytes = e - base64_nByte(s_str) else - e_str = len(base64_str,kind=pLongInt) - e_bytes = base64_nByte(len(base64_str,kind=pLongInt)) - base64_nByte(s_str) - if(base64_str(e_str-0_pLongInt:e_str-0_pLongInt) == '=') e_bytes = e_bytes - 1_pLongInt - if(base64_str(e_str-1_pLongInt:e_str-1_pLongInt) == '=') e_bytes = e_bytes - 1_pLongInt + e_str = len(base64_str,kind=pI64) + e_bytes = base64_nByte(len(base64_str,kind=pI64)) - base64_nByte(s_str) + if(base64_str(e_str-0_pI64:e_str-0_pI64) == '=') e_bytes = e_bytes - 1_pI64 + if(base64_str(e_str-1_pI64:e_str-1_pI64) == '=') e_bytes = e_bytes - 1_pI64 endif - bytes = decode_base64(base64_str(s_str:e_str)) + bytes = decodeBase64(base64_str(s_str:e_str)) bytes = bytes(s_bytes:e_bytes) end function base64_to_bytes @@ -104,21 +104,21 @@ end function base64_to_bytes !-------------------------------------------------------------------------------------------------- !> @brief Convert a Base64 ASCII string into its byte-wise binary representation. !-------------------------------------------------------------------------------------------------- -pure function decode_base64(base64_str) result(bytes) +pure function decodeBase64(base64_str) result(bytes) character(len=*), intent(in) :: base64_str !< Base64 string representation - integer(C_SIGNED_CHAR), dimension(base64_nByte(len(base64_str,pLongInt))) :: bytes + integer(C_SIGNED_CHAR), dimension(base64_nByte(len(base64_str,pI64))) :: bytes integer(C_SIGNED_CHAR), dimension(0:3) :: charPos - integer(pLongInt) :: c, b, p + integer(pI64) :: c, b, p - c = 1_pLongInt - b = 1_pLongInt + c = 1_pI64 + b = 1_pI64 - do while(c < len(base64_str,kind=pLongInt)) - do p=0_pLongInt,3_pLongInt - if(c+p<=len(base64_str,kind=pLongInt)) then + do while(c < len(base64_str,kind=pI64)) + do p=0_pI64,3_pI64 + if(c+p<=len(base64_str,kind=pI64)) then charPos(p) = int(index(base64_encoding,base64_str(c+p:c+p))-1,C_SIGNED_CHAR) else charPos(p) = 0_C_SIGNED_CHAR @@ -131,31 +131,31 @@ pure function decode_base64(base64_str) result(bytes) call mvbits(charPos(2),2,4,bytes(b+1),0) call mvbits(charPos(2),0,2,bytes(b+2),6) call mvbits(charPos(3),0,6,bytes(b+2),0) - b = b+3_pLongInt - c = c+4_pLongInt + b = b+3_pI64 + c = c+4_pI64 enddo -end function decode_base64 +end function decodeBase64 !-------------------------------------------------------------------------------------------------- !> @brief Test for valid Base64 encoded string. !> @details Input string must be properly padded. !-------------------------------------------------------------------------------------------------- -pure logical function valid_base64(base64_str) +pure logical function validBase64(base64_str) character(len=*), intent(in) :: base64_str !< Base64 string representation - integer(pLongInt) :: l + integer(pI64) :: l - l = len(base64_str,pLongInt) - valid_base64 = .true. + l = len(base64_str,pI64) + validBase64 = .true. - if(mod(l,4_pLongInt)/=0_pLongInt .or. l < 4_pInt) valid_base64 = .false. - if(verify(base64_str(:l-2_pLongInt),base64_encoding, kind=pLongInt) /= 0_pLongInt) valid_base64 = .false. - if(verify(base64_str(l-1_pLongInt:),base64_encoding//'=',kind=pLongInt) /= 0_pLongInt) valid_base64 = .false. + if(mod(l,4_pI64)/=0_pI64 .or. l < 4_pInt) validBase64 = .false. + if(verify(base64_str(:l-2_pI64),base64_encoding, kind=pI64) /= 0_pI64) validBase64 = .false. + if(verify(base64_str(l-1_pI64:),base64_encoding//'=',kind=pI64) /= 0_pI64) validBase64 = .false. -end function valid_base64 +end function validBase64 !-------------------------------------------------------------------------------------------------- @@ -167,58 +167,58 @@ subroutine selfTest character(len=*), parameter :: zero_to_three = 'AAECAw==' ! https://en.wikipedia.org/wiki/Base64#Output_padding - if(base64_nChar(20_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nChar/20/28') - if(base64_nChar(19_pLongInt) /= 28_pLongInt) call IO_error(0,ext_msg='base64_nChar/19/28') - if(base64_nChar(18_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/18/24') - if(base64_nChar(17_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/17/24') - if(base64_nChar(16_pLongInt) /= 24_pLongInt) call IO_error(0,ext_msg='base64_nChar/16/24') + if(base64_nChar(20_pI64) /= 28_pI64) call IO_error(0,ext_msg='base64_nChar/20/28') + if(base64_nChar(19_pI64) /= 28_pI64) call IO_error(0,ext_msg='base64_nChar/19/28') + if(base64_nChar(18_pI64) /= 24_pI64) call IO_error(0,ext_msg='base64_nChar/18/24') + if(base64_nChar(17_pI64) /= 24_pI64) call IO_error(0,ext_msg='base64_nChar/17/24') + if(base64_nChar(16_pI64) /= 24_pI64) call IO_error(0,ext_msg='base64_nChar/16/24') - if(base64_nByte(4_pLongInt) /= 3_pLongInt) call IO_error(0,ext_msg='base64_nByte/4/3') - if(base64_nByte(8_pLongInt) /= 6_pLongInt) call IO_error(0,ext_msg='base64_nByte/8/6') + if(base64_nByte(4_pI64) /= 3_pI64) call IO_error(0,ext_msg='base64_nByte/4/3') + if(base64_nByte(8_pI64) /= 6_pI64) call IO_error(0,ext_msg='base64_nByte/8/6') bytes = base64_to_bytes(zero_to_three) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes//') - bytes = base64_to_bytes(zero_to_three,e=1_pLongInt) + bytes = base64_to_bytes(zero_to_three,e=1_pI64) if(any(bytes /= int([0],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes//1') - bytes = base64_to_bytes(zero_to_three,e=2_pLongInt) + bytes = base64_to_bytes(zero_to_three,e=2_pI64) if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes//2') - bytes = base64_to_bytes(zero_to_three,e=3_pLongInt) + bytes = base64_to_bytes(zero_to_three,e=3_pI64) if(any(bytes /= int([0,1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes//3') - bytes = base64_to_bytes(zero_to_three,e=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,e=4_pI64) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes//4') - bytes = base64_to_bytes(zero_to_three,s=1_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=1_pI64) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes/1/') - bytes = base64_to_bytes(zero_to_three,s=2_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=2_pI64) if(any(bytes /= int([1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/2/') - bytes = base64_to_bytes(zero_to_three,s=3_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=3_pI64) if(any(bytes /= int([2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/3/') - bytes = base64_to_bytes(zero_to_three,s=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=4_pI64) if(any(bytes /= int([3],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/4/') - bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=1_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=1_pI64,e=1_pI64) if(any(bytes /= int([0],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/1/1') - bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=2_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=2_pI64,e=2_pI64) if(any(bytes /= int([1],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/2/2') - bytes = base64_to_bytes(zero_to_three,s=3_pLongInt,e=3_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=3_pI64,e=3_pI64) if(any(bytes /= int([2],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/3/3') - bytes = base64_to_bytes(zero_to_three,s=4_pLongInt,e=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=4_pI64,e=4_pI64) if(any(bytes /= int([3],C_SIGNED_CHAR)) .or. size(bytes) /= 1) call IO_error(0,ext_msg='base64_to_bytes/4/4') - bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=2_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=1_pI64,e=2_pI64) if(any(bytes /= int([0,1],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/1/2') - bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=3_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=2_pI64,e=3_pI64) if(any(bytes /= int([1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/2/3') - bytes = base64_to_bytes(zero_to_three,s=3_pLongInt,e=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=3_pI64,e=4_pI64) if(any(bytes /= int([2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 2) call IO_error(0,ext_msg='base64_to_bytes/3/4') - bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=3_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=1_pI64,e=3_pI64) if(any(bytes /= int([0,1,2],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/1/3') - bytes = base64_to_bytes(zero_to_three,s=2_pLongInt,e=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=2_pI64,e=4_pI64) if(any(bytes /= int([1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 3) call IO_error(0,ext_msg='base64_to_bytes/2/4') - bytes = base64_to_bytes(zero_to_three,s=1_pLongInt,e=4_pLongInt) + bytes = base64_to_bytes(zero_to_three,s=1_pI64,e=4_pI64) if(any(bytes /= int([0,1,2,3],C_SIGNED_CHAR)) .or. size(bytes) /= 4) call IO_error(0,ext_msg='base64_to_bytes/1/4') end subroutine selfTest diff --git a/src/prec.f90 b/src/prec.f90 index 8bb3332f3..d3ec108fe 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -15,12 +15,13 @@ module prec ! https://software.intel.com/en-us/blogs/2017/03/27/doctor-fortran-in-it-takes-all-kinds integer, parameter :: pReal = IEEE_selected_real_kind(15,307) !< number with 15 significant digits, up to 1e+-307 (typically 64 bit) + integer, parameter :: pI32 = selected_int_kind(9) !< number with at least up to +-1e9 (typically 32 bit) + integer, parameter :: pI64 = selected_int_kind(18) !< number with at least up to +-1e18 (typically 64 bit) #if(INT==8) - integer, parameter :: pInt = selected_int_kind(18) !< number with at least up to +-1e18 (typically 64 bit) + integer, parameter :: pInt = pI64 #else - integer, parameter :: pInt = selected_int_kind(9) !< number with at least up to +-1e9 (typically 32 bit) + integer, parameter :: pInt = pI32 #endif - integer, parameter :: pLongInt = selected_int_kind(18) !< number with at least up to +-1e18 (typically 64 bit) integer, parameter :: pStringLen = 256 !< default string length integer, parameter :: pPathLen = 4096 !< maximum length of a path name on linux @@ -237,7 +238,7 @@ end function cNeq pure function bytes_to_C_FLOAT(bytes) integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_FLOAT array - real(C_FLOAT), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_FLOAT,pLongInt)/8_pLongInt)) :: & + real(C_FLOAT), dimension(size(bytes,kind=pI64)/(storage_size(0._C_FLOAT,pI64)/8_pI64)) :: & bytes_to_C_FLOAT bytes_to_C_FLOAT = transfer(bytes,bytes_to_C_FLOAT,size(bytes_to_C_FLOAT)) @@ -251,7 +252,7 @@ end function bytes_to_C_FLOAT pure function bytes_to_C_DOUBLE(bytes) integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_DOUBLE array - real(C_DOUBLE), dimension(size(bytes,kind=pLongInt)/(storage_size(0._C_DOUBLE,pLongInt)/8_pLongInt)) :: & + real(C_DOUBLE), dimension(size(bytes,kind=pI64)/(storage_size(0._C_DOUBLE,pI64)/8_pI64)) :: & bytes_to_C_DOUBLE bytes_to_C_DOUBLE = transfer(bytes,bytes_to_C_DOUBLE,size(bytes_to_C_DOUBLE)) @@ -265,7 +266,7 @@ end function bytes_to_C_DOUBLE pure function bytes_to_C_INT32_T(bytes) integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT32_T array - integer(C_INT32_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT32_T,pLongInt)/8_pLongInt)) :: & + integer(C_INT32_T), dimension(size(bytes,kind=pI64)/(storage_size(0_C_INT32_T,pI64)/8_pI64)) :: & bytes_to_C_INT32_T bytes_to_C_INT32_T = transfer(bytes,bytes_to_C_INT32_T,size(bytes_to_C_INT32_T)) @@ -279,7 +280,7 @@ end function bytes_to_C_INT32_T pure function bytes_to_C_INT64_T(bytes) integer(C_SIGNED_CHAR), dimension(:), intent(in) :: bytes !< byte-wise representation of a C_INT64_T array - integer(C_INT64_T), dimension(size(bytes,kind=pLongInt)/(storage_size(0_C_INT64_T,pLongInt)/8_pLongInt)) :: & + integer(C_INT64_T), dimension(size(bytes,kind=pI64)/(storage_size(0_C_INT64_T,pI64)/8_pI64)) :: & bytes_to_C_INT64_T bytes_to_C_INT64_T = transfer(bytes,bytes_to_C_INT64_T,size(bytes_to_C_INT64_T)) diff --git a/src/zlib.f90 b/src/zlib.f90 index 670131334..21428255c 100644 --- a/src/zlib.f90 +++ b/src/zlib.f90 @@ -33,7 +33,7 @@ contains function zlib_inflate(deflated,size_inflated) integer(C_SIGNED_CHAR), dimension(:), intent(in) :: deflated - integer(pLongInt), intent(in) :: size_inflated + integer(pI64), intent(in) :: size_inflated integer(C_SIGNED_CHAR), dimension(size_inflated) :: zlib_inflate From a5d5638e4afb8339f11322bc1e28a50e4c1c0588 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 13:46:55 +0200 Subject: [PATCH 24/42] allow uncompressed files --- python/damask/_vtk.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 7f3e64aef..d23bfd22e 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -168,7 +168,7 @@ class VTK: def _write(writer): """Wrapper for parallel writing.""" writer.Write() - def to_file(self,fname,parallel=True): + def to_file(self,fname,parallel=True,compress=True): """ Write to file. @@ -192,7 +192,10 @@ class VTK: if ext and ext != '.'+default_ext: raise ValueError(f'Given extension {ext} does not match default .{default_ext}') writer.SetFileName(str(Path(fname).with_suffix('.'+default_ext))) - writer.SetCompressorTypeToZLib() + if compress: + writer.SetCompressorTypeToZLib() + else: + writer.SetCompressorTypeToNone() writer.SetDataModeToBinary() writer.SetInputData(self.vtk_data) From 566ab7e7d9ddcc3a2bcef129e140bd6003e396b1 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 14:43:04 +0200 Subject: [PATCH 25/42] reading in VTR files will replace geom file in the near future --- PRIVATE | 2 +- src/IO.f90 | 2 + src/grid/discretization_grid.f90 | 375 ++++++++++++++++++++++++++++++- 3 files changed, 376 insertions(+), 3 deletions(-) diff --git a/PRIVATE b/PRIVATE index 3bc603489..92ca3e83b 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 3bc60348981a68bc22a5ebaafe4173b7513ac264 +Subproject commit 92ca3e83b6093c1af277cfc06a504e4bb09fe8bc diff --git a/src/IO.f90 b/src/IO.f90 index 23f70eb8c..f434539b0 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -585,6 +585,8 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg) msg = 'incomplete information in grid mesh header' case (843) msg = 'microstructure count mismatch' + case (844) + msg = 'invalid VTR file' case (846) msg = 'rotation for load case rotation ill-defined (R:RT != I)' case (891) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index 995f9e104..1fdb6c922 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -10,6 +10,8 @@ module discretization_grid use prec use system_routines + use base64 + use zlib use DAMASK_interface use IO use config @@ -64,7 +66,11 @@ subroutine discretization_grid_init(restart) write(6,'(/,a)') ' <<<+- discretization_grid init -+>>>'; flush(6) - call readGeom(grid,geomSize,origin,microstructureAt) + if(index(geometryFile,'.vtr') /= 0) then + call readVTR(grid,geomSize,origin,microstructureAt) + else + call readGeom(grid,geomSize,origin,microstructureAt) + endif !-------------------------------------------------------------------------------------------------- ! grid solver specific quantities @@ -150,7 +156,6 @@ subroutine readGeom(grid,geomSize,origin,microstructure) character(len=65536) :: line integer, allocatable, dimension(:) :: chunkPos integer :: & - h =- 1, & headerLength = -1, & !< length of header (in lines) fileLength, & !< length of the geom file (in characters) fileUnit, & @@ -294,6 +299,372 @@ subroutine readGeom(grid,geomSize,origin,microstructure) end subroutine readGeom +!-------------------------------------------------------------------------------------------------- +!> @brief Parse vtk rectilinear grid (.vtr) +!> @details https://vtk.org/Wiki/VTK_XML_Formats +!-------------------------------------------------------------------------------------------------- +subroutine readVTR(grid,geomSize,origin,microstructure) + + integer, dimension(3), intent(out) :: & + grid ! grid (for all processes!) + real(pReal), dimension(3), intent(out) :: & + geomSize, & ! size (for all processes!) + origin ! origin (for all processes!) + integer, dimension(:), intent(out), allocatable :: & + microstructure + + character(len=:), allocatable :: fileContent, data_type, header_type + logical :: inFile,inGrid,readCoordinates,readCellData,compressed + integer :: fileUnit, myStat, coord + integer(pI64) :: & + fileLength, & !< length of the geom file (in characters) + startPos, endPos, & + s + + grid = -1 + geomSize = -1.0_pReal + +!-------------------------------------------------------------------------------------------------- +! read raw data as stream + inquire(file = trim(geometryFile), size=fileLength) + open(newunit=fileUnit, file=trim(geometryFile), access='stream',& + status='old', position='rewind', action='read',iostat=myStat) + if(myStat /= 0) call IO_error(100,ext_msg=trim(geometryFile)) + allocate(character(len=fileLength)::fileContent) + read(fileUnit) fileContent + close(fileUnit) + + inFile = .false. + inGrid = .false. + readCoordinates = .false. + readCelldata = .false. + +!-------------------------------------------------------------------------------------------------- +! interprete XML file + startPos = 1_pI64 + do while (startPos < len(fileContent,kind=pI64)) + endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 + if (endPos < startPos) endPos = len(fileContent,kind=pI64) ! end of file without new line + + if(.not. inFile) then + if(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) then + readCellData = .true. + startPos = endPos + 2_pI64 + do while (index(fileContent(startPos:endPos),'',kind=pI64) == 0_pI64) + endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 + if(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) then + readCoordinates = .true. + startPos = endPos + 2_pI64 + + coord = 0 + do while (startPos',kind=pI64) /= 0_pI64) exit + startPos = endPos + 2_pI64 + enddo + endif + endif + endif + + if(readCellData .and. readCoordinates) exit + startPos = endPos + 2_pI64 + + end do + + if(.not. allocated(microstructure)) call IO_error(error_ID = 844, ext_msg='materialpoint not found') + if(size(microstructure) /= product(grid)) call IO_error(error_ID = 844, ext_msg='size(materialpoint)') + if(any(geomSize<=0)) call IO_error(error_ID = 844, ext_msg='size') + if(any(grid<1)) call IO_error(error_ID = 844, ext_msg='grid') + + contains + + !------------------------------------------------------------------------------------------------ + !> @brief determine size and origin from coordinates + !------------------------------------------------------------------------------------------------ + !ToDo: check for regular spacing + subroutine origin_and_size(base64_str,header_type,compressed,data_type,direction) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string of 1D coordinates + header_type, & ! header type (UInt32 or Uint64) + data_type ! data type (Int32, Int64, Float32, Float64) + logical, intent(in) :: compressed ! indicate whether data is zlib compressed + integer, intent(in) :: direction ! direction (1=x,2=y,3=z) + + real(pReal), dimension(:), allocatable :: coords + + coords = as_pReal(base64_str,header_type,compressed,data_type) + + origin(direction) = coords(1) + geomSize(direction) = coords(size(coords)) - coords(1) + + end subroutine + + + !------------------------------------------------------------------------------------------------ + !> @brief Interpret Base64 string in vtk XML file as integer of default kind + !------------------------------------------------------------------------------------------------ + function as_Int(base64_str,header_type,compressed,data_type) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string + header_type, & ! header type (UInt32 or Uint64) + data_type ! data type (Int32, Int64, Float32, Float64) + logical, intent(in) :: compressed ! indicate whether data is zlib compressed + + integer, dimension(:), allocatable :: as_Int + + select case(data_type) + case('Int32') + as_Int = int(bytes_to_C_INT32_T(asBytes(base64_str,header_type,compressed))) + case('Int64') + as_Int = int(bytes_to_C_INT64_T(asBytes(base64_str,header_type,compressed))) + case('Float32') + as_Int = int(bytes_to_C_FLOAT (asBytes(base64_str,header_type,compressed))) + case('Float64') + as_Int = int(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed))) + case default + allocate(as_Int(0)) + end select + + end function as_Int + + + !------------------------------------------------------------------------------------------------ + !> @brief Interpret Base64 string in vtk XML file as integer of pReal kind + !------------------------------------------------------------------------------------------------ + function as_pReal(base64_str,header_type,compressed,data_type) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string + header_type, & ! header type (UInt32 or Uint64) + data_type ! data type (Int32, Int64, Float32, Float64) + logical, intent(in) :: compressed ! indicate whether data is zlib compressed + + real(pReal), dimension(:), allocatable :: as_pReal + + select case(data_type) + case('Int32') + as_pReal = real(bytes_to_C_INT32_T(asBytes(base64_str,header_type,compressed)),pReal) + case('Int64') + as_pReal = real(bytes_to_C_INT64_T(asBytes(base64_str,header_type,compressed)),pReal) + case('Float32') + as_pReal = real(bytes_to_C_FLOAT (asBytes(base64_str,header_type,compressed)),pReal) + case('Float64') + as_pReal = real(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed)),pReal) + case default + allocate(as_pReal(0)) + end select + + end function as_pReal + + + !------------------------------------------------------------------------------------------------ + !> @brief Interpret Base64 string in vtk XML file as bytes + !------------------------------------------------------------------------------------------------ + function asBytes(base64_str,header_type,compressed) result(bytes) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string + header_type ! header type (UInt32 or Uint64) + logical, intent(in) :: compressed ! indicate whether data is zlib compressed + + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes + + if(compressed) then + bytes = asBytes_compressed(base64_str,header_type) + else + bytes = asBytes_uncompressed(base64_str,header_type) + endif + + end function asBytes + + !------------------------------------------------------------------------------------------------ + !> @brief Interpret compressed Base64 string in vtk XML file as bytes + !> @details A compressed Base64 string consists of a header block and a data block + ! [#blocks/#u-size/#p-size/#c-size-1/#c-size-2/.../#c-size-#blocks][DATA-1/DATA-2...] + ! #blocks = Number of blocks + ! #u-size = Block size before compression + ! #p-size = Size of last partial block (zero if it not needed) + ! #c-size-i = Size in bytes of block i after compression + !------------------------------------------------------------------------------------------------ + function asBytes_compressed(base64_str,header_type) result(bytes) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string + header_type ! header type (UInt32 or Uint64) + + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes + + integer(pI64), dimension(:), allocatable :: temp, size_inflated, size_deflated + integer(pI64) :: header_len, N_blocks, b,s,e + + if (header_type == 'UInt32') then + temp = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(:base64_nChar(4_pI64)))),pI64) + N_blocks = int(temp(1),pI64) + header_len = 4_pI64 * (3_pI64 + N_blocks) + temp = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(:base64_nChar(header_len)))),pI64) + elseif(header_type == 'UInt64') then + temp = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(:base64_nChar(8_pI64)))),pI64) + N_blocks = int(temp(1),pI64) + header_len = 8_pI64 * (3_pI64 + N_blocks) + temp = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(:base64_nChar(header_len)))),pI64) + endif + + allocate(size_inflated(N_blocks),source=temp(2)) + size_inflated(N_blocks) = merge(temp(3),temp(2),temp(3)/=0_pI64) + size_deflated = temp(4:) + allocate(bytes(0)) + + e = 0_pI64 + do b = 1, N_blocks + s = e + 1_pI64 + e = s + size_deflated(b) - 1_pI64 + bytes = [bytes,zlib_inflate(base64_to_bytes(base64_str(base64_nChar(header_len)+1:),s,e),size_inflated(b))] + enddo + + end function asBytes_compressed + + + !------------------------------------------------------------------------------------------------ + !> @brief Interprete uncompressed Base64 string in vtk XML file as bytes + !> @details An uncompressed Base64 string consists of N headers blocks and a N data blocks + ![#bytes-1/DATA-1][#bytes-2/DATA-2]... + !------------------------------------------------------------------------------------------------ + function asBytes_uncompressed(base64_str,header_type) result(bytes) + + character(len=*), intent(in) :: base64_str, & ! base64 encoded string + header_type ! header type (UInt32 or Uint64) + + integer(pI64) :: s + integer(pI64), dimension(1) :: N_bytes + + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes + allocate(bytes(0)) + + s=0_pI64 + if (header_type == 'UInt32') then + do while(s+base64_nChar(4_pI64)<(len(base64_str,pI64))) + N_bytes = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64)))),pI64) + bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64+N_bytes(1))),5_pI64)] + s = s + base64_nChar(4_pI64+N_bytes(1)) + enddo + elseif(header_type == 'UInt64') then + do while(s+base64_nChar(8_pI64)<(len(base64_str,pI64))) + N_bytes = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64)))),pI64) + bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64+N_bytes(1))),9_pI64)] + s = s + base64_nChar(8_pI64+N_bytes(1)) + enddo + endif + + end function asBytes_uncompressed + + !------------------------------------------------------------------------------------------------ + !> @brief Get XML string value for given key + !------------------------------------------------------------------------------------------------ + ! ToDo: check if "=" is between key and value + pure function getXMLValue(line,key) + + character(len=*), intent(in) :: line, key + + character(len=:), allocatable :: getXMLValue + + integer :: s,e +#ifdef __INTEL_COMPILER + character :: q +#endif + + s = index(line," "//key,back=.true.) + if(s==0) then + getXMLValue = '' + else + s = s + 1 + scan(line(s+1:),"'"//'"') +#ifdef __INTEL_COMPILER + q = str(s-1:s-1) + e = s + index(line(s:),q) - 1 +#else + e = s + index(line(s:),merge("'",'"',line(s-1:s-1)=="'")) - 1 +#endif + getXMLValue = line(s:e-1) + endif + + end function + + + !------------------------------------------------------------------------------------------------ + !> @brief figure out if file format is understandable + !------------------------------------------------------------------------------------------------ + pure function fileOk(line) + + character(len=*),intent(in) :: line + logical :: fileOk + + fileOk = getXMLValue(line,'type') == 'RectilinearGrid' .and. & + getXMLValue(line,'byte_order') == 'LittleEndian' .and. & + getXMLValue(line,'compressor') /= 'vtkLZ4DataCompressor' .and. & + getXMLValue(line,'compressor') /= 'vtkLZMADataCompressor' + + end function fileOk + + + !------------------------------------------------------------------------------------------------ + !> @brief get grid information from '' + !------------------------------------------------------------------------------------------------ + function getGrid(line) + + character(len=*),intent(in) :: line + + integer,dimension(3) :: getGrid + + integer :: s,e,i + + s=scan(line,'"'//"'",back=.False.) + e=scan(line,'"'//"'",back=.True.) + + getGrid = [(IO_intValue(line(s+1:e-1),IO_stringPos(line(s+1:e-1)),i*2),i=1,3)] + + end function getGrid + +end subroutine readVTR + + !--------------------------------------------------------------------------------------------------- !> @brief Calculate undeformed position of IPs/cell centers (pretend to be an element) !--------------------------------------------------------------------------------------------------- From faac9883a5392eac02a89514c863e20e44ae959b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 15:25:37 +0200 Subject: [PATCH 26/42] more verbose GitLab CI --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4c33f83e7..03aee2abe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -499,7 +499,7 @@ mergeIntoMaster: removeData: stage: clean before_script: - - echo 'Do nothing' + - echo "Removing data and lock of pipeline $CI_PIPELINE_ID" script: - rm -rf $TESTROOT/GitLabCI_Pipeline_$CI_PIPELINE_ID - sed -i "/$CI_PIPELINE_ID/d" $TESTROOT/GitLabCI.queue # in case pipeline was manually (web GUI) restarted and releaseLock was performed already @@ -511,7 +511,7 @@ removeData: removeLock: stage: releaseLock before_script: - - echo 'Do nothing' + - echo "Removing lock of pipeline $CI_PIPELINE_ID" when: always script: sed -i "/$CI_PIPELINE_ID/d" $TESTROOT/GitLabCI.queue except: From 307b1b20cc5de287ebb23dcd815efebcdef55616 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 15:26:16 +0200 Subject: [PATCH 27/42] forgotten rename for ifort workaround --- src/grid/discretization_grid.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index 1fdb6c922..fb6e7f1aa 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -617,7 +617,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) else s = s + 1 + scan(line(s+1:),"'"//'"') #ifdef __INTEL_COMPILER - q = str(s-1:s-1) + q = line(s-1:s-1) e = s + index(line(s:),q) - 1 #else e = s + index(line(s:),merge("'",'"',line(s-1:s-1)=="'")) - 1 From 81063046c485c4cdd8ae37acaae64e4a7c3161a7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 12 Sep 2020 22:55:30 +0200 Subject: [PATCH 28/42] improved error handling, potentially faster algorithm --- src/grid/discretization_grid.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index fb6e7f1aa..3f36ff4f8 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -435,7 +435,6 @@ subroutine readVTR(grid,geomSize,origin,microstructure) real(pReal), dimension(:), allocatable :: coords coords = as_pReal(base64_str,header_type,compressed,data_type) - origin(direction) = coords(1) geomSize(direction) = coords(size(coords)) - coords(1) @@ -464,7 +463,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) case('Float64') as_Int = int(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed))) case default - allocate(as_Int(0)) + call IO_error(844_pInt,ext_msg='unknown data type: '//trim(data_type)) end select end function as_Int @@ -492,7 +491,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) case('Float64') as_pReal = real(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed)),pReal) case default - allocate(as_pReal(0)) + call IO_error(844_pInt,ext_msg='unknown data type: '//trim(data_type)) end select end function as_pReal @@ -531,7 +530,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) character(len=*), intent(in) :: base64_str, & ! base64 encoded string header_type ! header type (UInt32 or Uint64) - integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes + integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes, bytes_inflated integer(pI64), dimension(:), allocatable :: temp, size_inflated, size_deflated integer(pI64) :: header_len, N_blocks, b,s,e @@ -551,13 +550,14 @@ subroutine readVTR(grid,geomSize,origin,microstructure) allocate(size_inflated(N_blocks),source=temp(2)) size_inflated(N_blocks) = merge(temp(3),temp(2),temp(3)/=0_pI64) size_deflated = temp(4:) - allocate(bytes(0)) + bytes_inflated = base64_to_bytes(base64_str(base64_nChar(header_len)+1_pI64:)) + allocate(bytes(0)) e = 0_pI64 do b = 1, N_blocks s = e + 1_pI64 e = s + size_deflated(b) - 1_pI64 - bytes = [bytes,zlib_inflate(base64_to_bytes(base64_str(base64_nChar(header_len)+1:),s,e),size_inflated(b))] + bytes = [bytes,zlib_inflate(bytes_inflated(s:e),size_inflated(b))] enddo end function asBytes_compressed From e2ded43636585690e04a61408c2a4f92ec541289 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 13 Sep 2020 06:58:34 +0200 Subject: [PATCH 29/42] polishing - unified style (CamelCase) - more sanity checks - simplified determination of grid --- src/grid/discretization_grid.f90 | 168 ++++++++++++++----------------- 1 file changed, 78 insertions(+), 90 deletions(-) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index 3f36ff4f8..e440042dc 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -313,7 +313,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) integer, dimension(:), intent(out), allocatable :: & microstructure - character(len=:), allocatable :: fileContent, data_type, header_type + character(len=:), allocatable :: fileContent, dataType, headerType logical :: inFile,inGrid,readCoordinates,readCellData,compressed integer :: fileUnit, myStat, coord integer(pI64) :: & @@ -350,15 +350,12 @@ subroutine readVTR(grid,geomSize,origin,microstructure) if(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) then readCellData = .true. @@ -370,12 +367,12 @@ subroutine readVTR(grid,geomSize,origin,microstructure) if(getXMLValue(fileContent(startPos:endPos),'format') /= 'binary') & call IO_error(error_ID = 844, ext_msg='format (materialpoint)') - data_type = getXMLValue(fileContent(startPos:endPos),'type') + dataType = getXMLValue(fileContent(startPos:endPos),'type') startPos = endPos + 2_pI64 endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 s = startPos + verify(fileContent(startPos:endPos),IO_WHITESPACE,kind=pI64) -1_pI64 ! start (no leading whitespace) - microstructure = as_Int(fileContent(s:endPos),header_type,compressed,data_type) + microstructure = as_Int(fileContent(s:endPos),headerType,compressed,dataType) exit endif startPos = endPos + 2_pI64 @@ -391,7 +388,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) if(getXMLValue(fileContent(startPos:endPos),'format') /= 'binary') & call IO_error(error_ID = 844, ext_msg='format (coordinates)') - data_type = getXMLValue(fileContent(startPos:endPos),'type') + dataType = getXMLValue(fileContent(startPos:endPos),'type') startPos = endPos + 2_pI64 endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 @@ -399,7 +396,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) coord = coord + 1 - call origin_and_size(fileContent(s:endPos),header_type,compressed,data_type,coord) + call gridSizeOrigin(fileContent(s:endPos),headerType,compressed,dataType,coord) endif if(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) exit startPos = endPos + 2_pI64 @@ -423,19 +420,24 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ !> @brief determine size and origin from coordinates !------------------------------------------------------------------------------------------------ - !ToDo: check for regular spacing - subroutine origin_and_size(base64_str,header_type,compressed,data_type,direction) + subroutine gridSizeOrigin(base64_str,headerType,compressed,dataType,direction) character(len=*), intent(in) :: base64_str, & ! base64 encoded string of 1D coordinates - header_type, & ! header type (UInt32 or Uint64) - data_type ! data type (Int32, Int64, Float32, Float64) + headerType, & ! header type (UInt32 or Uint64) + dataType ! data type (Int32, Int64, Float32, Float64) logical, intent(in) :: compressed ! indicate whether data is zlib compressed integer, intent(in) :: direction ! direction (1=x,2=y,3=z) - real(pReal), dimension(:), allocatable :: coords + real(pReal), dimension(:), allocatable :: coords,delta - coords = as_pReal(base64_str,header_type,compressed,data_type) - origin(direction) = coords(1) + coords = as_pReal(base64_str,headerType,compressed,dataType) + + delta = coords(2:) - coords(:size(coords)-1) + if(any(delta<0.0_pReal) .or. dNeq(maxval(delta),minval(delta))) & + call IO_error(error_ID = 844, ext_msg = 'grid spacing') + + grid(direction) = size(coords)-1 + origin(direction) = coords(1) geomSize(direction) = coords(size(coords)) - coords(1) end subroutine @@ -444,26 +446,26 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ !> @brief Interpret Base64 string in vtk XML file as integer of default kind !------------------------------------------------------------------------------------------------ - function as_Int(base64_str,header_type,compressed,data_type) + function as_Int(base64_str,headerType,compressed,dataType) character(len=*), intent(in) :: base64_str, & ! base64 encoded string - header_type, & ! header type (UInt32 or Uint64) - data_type ! data type (Int32, Int64, Float32, Float64) + headerType, & ! header type (UInt32 or Uint64) + dataType ! data type (Int32, Int64, Float32, Float64) logical, intent(in) :: compressed ! indicate whether data is zlib compressed integer, dimension(:), allocatable :: as_Int - select case(data_type) + select case(dataType) case('Int32') - as_Int = int(bytes_to_C_INT32_T(asBytes(base64_str,header_type,compressed))) + as_Int = int(bytes_to_C_INT32_T(asBytes(base64_str,headerType,compressed))) case('Int64') - as_Int = int(bytes_to_C_INT64_T(asBytes(base64_str,header_type,compressed))) + as_Int = int(bytes_to_C_INT64_T(asBytes(base64_str,headerType,compressed))) case('Float32') - as_Int = int(bytes_to_C_FLOAT (asBytes(base64_str,header_type,compressed))) + as_Int = int(bytes_to_C_FLOAT (asBytes(base64_str,headerType,compressed))) case('Float64') - as_Int = int(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed))) + as_Int = int(bytes_to_C_DOUBLE (asBytes(base64_str,headerType,compressed))) case default - call IO_error(844_pInt,ext_msg='unknown data type: '//trim(data_type)) + call IO_error(844_pInt,ext_msg='unknown data type: '//trim(dataType)) end select end function as_Int @@ -472,26 +474,26 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ !> @brief Interpret Base64 string in vtk XML file as integer of pReal kind !------------------------------------------------------------------------------------------------ - function as_pReal(base64_str,header_type,compressed,data_type) + function as_pReal(base64_str,headerType,compressed,dataType) character(len=*), intent(in) :: base64_str, & ! base64 encoded string - header_type, & ! header type (UInt32 or Uint64) - data_type ! data type (Int32, Int64, Float32, Float64) + headerType, & ! header type (UInt32 or Uint64) + dataType ! data type (Int32, Int64, Float32, Float64) logical, intent(in) :: compressed ! indicate whether data is zlib compressed real(pReal), dimension(:), allocatable :: as_pReal - select case(data_type) + select case(dataType) case('Int32') - as_pReal = real(bytes_to_C_INT32_T(asBytes(base64_str,header_type,compressed)),pReal) + as_pReal = real(bytes_to_C_INT32_T(asBytes(base64_str,headerType,compressed)),pReal) case('Int64') - as_pReal = real(bytes_to_C_INT64_T(asBytes(base64_str,header_type,compressed)),pReal) + as_pReal = real(bytes_to_C_INT64_T(asBytes(base64_str,headerType,compressed)),pReal) case('Float32') - as_pReal = real(bytes_to_C_FLOAT (asBytes(base64_str,header_type,compressed)),pReal) + as_pReal = real(bytes_to_C_FLOAT (asBytes(base64_str,headerType,compressed)),pReal) case('Float64') - as_pReal = real(bytes_to_C_DOUBLE (asBytes(base64_str,header_type,compressed)),pReal) + as_pReal = real(bytes_to_C_DOUBLE (asBytes(base64_str,headerType,compressed)),pReal) case default - call IO_error(844_pInt,ext_msg='unknown data type: '//trim(data_type)) + call IO_error(844_pInt,ext_msg='unknown data type: '//trim(dataType)) end select end function as_pReal @@ -500,18 +502,18 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ !> @brief Interpret Base64 string in vtk XML file as bytes !------------------------------------------------------------------------------------------------ - function asBytes(base64_str,header_type,compressed) result(bytes) + function asBytes(base64_str,headerType,compressed) result(bytes) character(len=*), intent(in) :: base64_str, & ! base64 encoded string - header_type ! header type (UInt32 or Uint64) + headerType ! header type (UInt32 or Uint64) logical, intent(in) :: compressed ! indicate whether data is zlib compressed integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes if(compressed) then - bytes = asBytes_compressed(base64_str,header_type) + bytes = asBytes_compressed(base64_str,headerType) else - bytes = asBytes_uncompressed(base64_str,header_type) + bytes = asBytes_uncompressed(base64_str,headerType) endif end function asBytes @@ -525,36 +527,36 @@ subroutine readVTR(grid,geomSize,origin,microstructure) ! #p-size = Size of last partial block (zero if it not needed) ! #c-size-i = Size in bytes of block i after compression !------------------------------------------------------------------------------------------------ - function asBytes_compressed(base64_str,header_type) result(bytes) + function asBytes_compressed(base64_str,headerType) result(bytes) character(len=*), intent(in) :: base64_str, & ! base64 encoded string - header_type ! header type (UInt32 or Uint64) + headerType ! header type (UInt32 or Uint64) integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes, bytes_inflated integer(pI64), dimension(:), allocatable :: temp, size_inflated, size_deflated - integer(pI64) :: header_len, N_blocks, b,s,e + integer(pI64) :: headerLen, nBlock, b,s,e - if (header_type == 'UInt32') then + if (headerType == 'UInt32') then temp = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(:base64_nChar(4_pI64)))),pI64) - N_blocks = int(temp(1),pI64) - header_len = 4_pI64 * (3_pI64 + N_blocks) - temp = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(:base64_nChar(header_len)))),pI64) - elseif(header_type == 'UInt64') then + nBlock = int(temp(1),pI64) + headerLen = 4_pI64 * (3_pI64 + nBlock) + temp = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(:base64_nChar(headerLen)))),pI64) + elseif(headerType == 'UInt64') then temp = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(:base64_nChar(8_pI64)))),pI64) - N_blocks = int(temp(1),pI64) - header_len = 8_pI64 * (3_pI64 + N_blocks) - temp = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(:base64_nChar(header_len)))),pI64) + nBlock = int(temp(1),pI64) + headerLen = 8_pI64 * (3_pI64 + nBlock) + temp = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(:base64_nChar(headerLen)))),pI64) endif - allocate(size_inflated(N_blocks),source=temp(2)) - size_inflated(N_blocks) = merge(temp(3),temp(2),temp(3)/=0_pI64) + allocate(size_inflated(nBlock),source=temp(2)) + size_inflated(nBlock) = merge(temp(3),temp(2),temp(3)/=0_pI64) size_deflated = temp(4:) - bytes_inflated = base64_to_bytes(base64_str(base64_nChar(header_len)+1_pI64:)) + bytes_inflated = base64_to_bytes(base64_str(base64_nChar(headerLen)+1_pI64:)) allocate(bytes(0)) e = 0_pI64 - do b = 1, N_blocks + do b = 1, nBlock s = e + 1_pI64 e = s + size_deflated(b) - 1_pI64 bytes = [bytes,zlib_inflate(bytes_inflated(s:e),size_inflated(b))] @@ -568,29 +570,29 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !> @details An uncompressed Base64 string consists of N headers blocks and a N data blocks ![#bytes-1/DATA-1][#bytes-2/DATA-2]... !------------------------------------------------------------------------------------------------ - function asBytes_uncompressed(base64_str,header_type) result(bytes) + function asBytes_uncompressed(base64_str,headerType) result(bytes) character(len=*), intent(in) :: base64_str, & ! base64 encoded string - header_type ! header type (UInt32 or Uint64) + headerType ! header type (UInt32 or Uint64) integer(pI64) :: s - integer(pI64), dimension(1) :: N_bytes + integer(pI64), dimension(1) :: nByte integer(C_SIGNED_CHAR), dimension(:), allocatable :: bytes allocate(bytes(0)) s=0_pI64 - if (header_type == 'UInt32') then + if (headerType == 'UInt32') then do while(s+base64_nChar(4_pI64)<(len(base64_str,pI64))) - N_bytes = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64)))),pI64) - bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64+N_bytes(1))),5_pI64)] - s = s + base64_nChar(4_pI64+N_bytes(1)) + nByte = int(bytes_to_C_INT32_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64)))),pI64) + bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(4_pI64+nByte(1))),5_pI64)] + s = s + base64_nChar(4_pI64+nByte(1)) enddo - elseif(header_type == 'UInt64') then + elseif(headerType == 'UInt64') then do while(s+base64_nChar(8_pI64)<(len(base64_str,pI64))) - N_bytes = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64)))),pI64) - bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64+N_bytes(1))),9_pI64)] - s = s + base64_nChar(8_pI64+N_bytes(1)) + nByte = int(bytes_to_C_INT64_T(base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64)))),pI64) + bytes = [bytes,base64_to_bytes(base64_str(s+1_pI64:s+base64_nChar(8_pI64+nByte(1))),9_pI64)] + s = s + base64_nChar(8_pI64+nByte(1)) enddo endif @@ -599,7 +601,6 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ !> @brief Get XML string value for given key !------------------------------------------------------------------------------------------------ - ! ToDo: check if "=" is between key and value pure function getXMLValue(line,key) character(len=*), intent(in) :: line, key @@ -615,14 +616,20 @@ subroutine readVTR(grid,geomSize,origin,microstructure) if(s==0) then getXMLValue = '' else - s = s + 1 + scan(line(s+1:),"'"//'"') + e = s + 1 + scan(line(s+1:),"'"//'"') + if(scan(line(s:e-2),'=') == 0) then + getXMLValue = '' + else + s = e +! https://community.intel.com/t5/Intel-Fortran-Compiler/ICE-for-merge-with-strings/m-p/1207204#M151657 #ifdef __INTEL_COMPILER - q = line(s-1:s-1) - e = s + index(line(s:),q) - 1 + q = line(s-1:s-1) + e = s + index(line(s:),q) - 1 #else - e = s + index(line(s:),merge("'",'"',line(s-1:s-1)=="'")) - 1 + e = s + index(line(s:),merge("'",'"',line(s-1:s-1)=="'")) - 1 #endif - getXMLValue = line(s:e-1) + getXMLValue = line(s:e-1) + endif endif end function @@ -643,25 +650,6 @@ subroutine readVTR(grid,geomSize,origin,microstructure) end function fileOk - - !------------------------------------------------------------------------------------------------ - !> @brief get grid information from '' - !------------------------------------------------------------------------------------------------ - function getGrid(line) - - character(len=*),intent(in) :: line - - integer,dimension(3) :: getGrid - - integer :: s,e,i - - s=scan(line,'"'//"'",back=.False.) - e=scan(line,'"'//"'",back=.True.) - - getGrid = [(IO_intValue(line(s+1:e-1),IO_stringPos(line(s+1:e-1)),i*2),i=1,3)] - - end function getGrid - end subroutine readVTR From 507910ffcda8d4cecad79e707100fbb018eb8af2 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 13 Sep 2020 18:32:49 +0200 Subject: [PATCH 30/42] improved language/descriptions --- src/grid/discretization_grid.f90 | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index e440042dc..7c089cc88 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -145,10 +145,10 @@ end subroutine discretization_grid_init subroutine readGeom(grid,geomSize,origin,microstructure) integer, dimension(3), intent(out) :: & - grid ! grid (for all processes!) + grid ! grid (across all processes!) real(pReal), dimension(3), intent(out) :: & - geomSize, & ! size (for all processes!) - origin ! origin (for all processes!) + geomSize, & ! size (across all processes!) + origin ! origin (across all processes!) integer, dimension(:), intent(out), allocatable :: & microstructure @@ -194,7 +194,7 @@ subroutine readGeom(grid,geomSize,origin,microstructure) endif !-------------------------------------------------------------------------------------------------- -! read and interprete header +! read and interpret header origin = 0.0_pReal l = 0 do while (l < headerLength .and. startPos < len(rawData)) @@ -306,15 +306,15 @@ end subroutine readGeom subroutine readVTR(grid,geomSize,origin,microstructure) integer, dimension(3), intent(out) :: & - grid ! grid (for all processes!) + grid ! grid (across all processes!) real(pReal), dimension(3), intent(out) :: & - geomSize, & ! size (for all processes!) - origin ! origin (for all processes!) + geomSize, & ! size (across all processes!) + origin ! origin (across all processes!) integer, dimension(:), intent(out), allocatable :: & microstructure character(len=:), allocatable :: fileContent, dataType, headerType - logical :: inFile,inGrid,readCoordinates,readCellData,compressed + logical :: inFile,inGrid,gotCoordinates,gotCellData,compressed integer :: fileUnit, myStat, coord integer(pI64) :: & fileLength, & !< length of the geom file (in characters) @@ -334,13 +334,13 @@ subroutine readVTR(grid,geomSize,origin,microstructure) read(fileUnit) fileContent close(fileUnit) - inFile = .false. - inGrid = .false. - readCoordinates = .false. - readCelldata = .false. + inFile = .false. + inGrid = .false. + gotCoordinates = .false. + gotCelldata = .false. !-------------------------------------------------------------------------------------------------- -! interprete XML file +! interpret XML file startPos = 1_pI64 do while (startPos < len(fileContent,kind=pI64)) endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 @@ -349,7 +349,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) if(.not. inFile) then if(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) then - readCellData = .true. + gotCellData = .true. startPos = endPos + 2_pI64 do while (index(fileContent(startPos:endPos),'',kind=pI64) == 0_pI64) endPos = startPos + index(fileContent(startPos:),IO_EOL,kind=pI64) - 2_pI64 @@ -378,7 +378,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) startPos = endPos + 2_pI64 enddo elseif(index(fileContent(startPos:endPos),'',kind=pI64) /= 0_pI64) then - readCoordinates = .true. + gotCoordinates = .true. startPos = endPos + 2_pI64 coord = 0 @@ -405,7 +405,7 @@ subroutine readVTR(grid,geomSize,origin,microstructure) endif endif - if(readCellData .and. readCoordinates) exit + if(gotCellData .and. gotCoordinates) exit startPos = endPos + 2_pI64 end do @@ -636,19 +636,19 @@ subroutine readVTR(grid,geomSize,origin,microstructure) !------------------------------------------------------------------------------------------------ - !> @brief figure out if file format is understandable + !> @brief check for supported file format !------------------------------------------------------------------------------------------------ - pure function fileOk(line) + pure function fileFormatOk(line) character(len=*),intent(in) :: line - logical :: fileOk + logical :: fileFormatOk - fileOk = getXMLValue(line,'type') == 'RectilinearGrid' .and. & - getXMLValue(line,'byte_order') == 'LittleEndian' .and. & - getXMLValue(line,'compressor') /= 'vtkLZ4DataCompressor' .and. & - getXMLValue(line,'compressor') /= 'vtkLZMADataCompressor' + fileFormatOk = getXMLValue(line,'type') == 'RectilinearGrid' .and. & + getXMLValue(line,'byte_order') == 'LittleEndian' .and. & + getXMLValue(line,'compressor') /= 'vtkLZ4DataCompressor' .and. & + getXMLValue(line,'compressor') /= 'vtkLZMADataCompressor' - end function fileOk + end function fileFormatOk end subroutine readVTR From c6907bfa4b7442289618ef46009e766c578173df Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 14 Sep 2020 06:13:58 +0200 Subject: [PATCH 31/42] [skip ci] updated version information after successful test of v3.0.0-alpha-147-gf0806a9e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5dac27a44..2d2d2952b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-136-gc0ea8e3f +v3.0.0-alpha-147-gf0806a9e From f6758ecc283a3d71e9144c967c13c32dbad119e9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 07:04:01 +0200 Subject: [PATCH 32/42] table class operates out of place --- .gitlab-ci.yml | 7 - processing/post/DADF5_postResults.py | 4 +- processing/post/addCompatibilityMismatch.py | 12 +- processing/post/addCurl.py | 6 +- processing/post/addDerivative.py | 6 +- processing/post/addDisplacement.py | 20 +-- processing/post/addDivergence.py | 6 +- processing/post/addEuclideanDistance.py | 6 +- processing/post/addGaussian.py | 10 +- processing/post/addGradient.py | 6 +- processing/post/addIndexed.py | 64 --------- processing/post/addLinked.py | 118 ---------------- processing/post/addOrientations.py | 10 +- processing/post/addSchmidfactors.py | 2 +- processing/post/groupTable.py | 142 -------------------- processing/post/permuteData.py | 2 +- processing/pre/seeds_fromGeom.py | 5 +- processing/pre/seeds_fromRandom.py | 4 +- python/damask/_table.py | 77 +++++++---- python/tests/test_Orientation.py | 2 +- python/tests/test_Table.py | 47 +++---- 21 files changed, 121 insertions(+), 435 deletions(-) delete mode 100755 processing/post/addIndexed.py delete mode 100755 processing/post/addLinked.py delete mode 100755 processing/post/groupTable.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4c33f83e7..9407ffc7c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -141,13 +141,6 @@ Pre_General: - release ################################################################################################### -Post_ASCIItable: - stage: postprocessing - script: ASCIItable/test.py - except: - - master - - release - Post_General: stage: postprocessing script: PostProcessing/test.py diff --git a/processing/post/DADF5_postResults.py b/processing/post/DADF5_postResults.py index 08c8c7070..9c520ac33 100755 --- a/processing/post/DADF5_postResults.py +++ b/processing/post/DADF5_postResults.py @@ -39,7 +39,7 @@ for filename in options.filenames: N_digits = 5 # hack to keep test intact for inc in damask.util.show_progress(results.iterate('increments'),len(results.increments)): table = damask.Table(np.ones(np.product(results.grid),dtype=int)*int(inc[3:]),{'inc':(1,)}) - table.add('pos',coords.reshape(-1,3)) + table = table.add('pos',coords.reshape(-1,3)) results.pick('materialpoints',False) results.pick('constituents', True) @@ -53,7 +53,7 @@ for filename in options.filenames: for label in options.mat: x = results.get_dataset_location(label) if len(x) != 0: - table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1)) + table = table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1)) dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) if not os.path.isdir(dirname): diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index bd55ab66a..5009d44a0 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -181,14 +181,14 @@ for name in filenames: if options.shape: centers = damask.grid_filters.cell_coord(size,F) shapeMismatch = shapeMismatch(size,F,nodes,centers) - table.add('shapeMismatch(({}))'.format(options.defgrad), - shapeMismatch.reshape(-1,1,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('shapeMismatch(({}))'.format(options.defgrad), + shapeMismatch.reshape(-1,1,order='F'), + scriptID+' '+' '.join(sys.argv[1:])) if options.volume: volumeMismatch = volumeMismatch(size,F,nodes) - table.add('volMismatch(({}))'.format(options.defgrad), - volumeMismatch.reshape(-1,1,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('volMismatch(({}))'.format(options.defgrad), + volumeMismatch.reshape(-1,1,order='F'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index a9ddc8ae8..1033e3303 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -51,8 +51,8 @@ for name in filenames: shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor field = field.reshape(tuple(grid)+(-1,),order='F').reshape(tuple(grid)+shape) curl = damask.grid_filters.curl(size,field) - table.add('curlFFT({})'.format(label), - curl.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape),order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('curlFFT({})'.format(label), + curl.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape),order='F'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addDerivative.py b/processing/post/addDerivative.py index 9030ae83b..b6b19c98a 100755 --- a/processing/post/addDerivative.py +++ b/processing/post/addDerivative.py @@ -67,8 +67,8 @@ for name in filenames: table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) for label in options.labels: - table.add('d({})/d({})'.format(label,options.coordinates), - derivative(table.get(options.coordinates),table.get(label)), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('d({})/d({})'.format(label,options.coordinates), + derivative(table.get(options.coordinates),table.get(label)), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addDisplacement.py b/processing/post/addDisplacement.py index 80725410d..f1ab565b0 100755 --- a/processing/post/addDisplacement.py +++ b/processing/post/addDisplacement.py @@ -53,19 +53,19 @@ for name in filenames: F = table.get(options.f).reshape(tuple(grid)+(-1,),order='F').reshape(tuple(grid)+(3,3)) if options.nodal: table = damask.Table(damask.grid_filters.node_coord0(grid,size).reshape(-1,3,order='F'), - {'pos':(3,)}) - table.add('avg({}).{}'.format(options.f,options.pos), - damask.grid_filters.node_displacement_avg(size,F).reshape(-1,3,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) - table.add('fluct({}).{}'.format(options.f,options.pos), - damask.grid_filters.node_displacement_fluct(size,F).reshape(-1,3,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + {'pos':(3,)})\ + .add('avg({}).{}'.format(options.f,options.pos), + damask.grid_filters.node_displacement_avg(size,F).reshape(-1,3,order='F'), + scriptID+' '+' '.join(sys.argv[1:]))\ + .add('fluct({}).{}'.format(options.f,options.pos), + damask.grid_filters.node_displacement_fluct(size,F).reshape(-1,3,order='F'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'_nodal.txt') else: - table.add('avg({}).{}'.format(options.f,options.pos), + table = table.add('avg({}).{}'.format(options.f,options.pos), damask.grid_filters.cell_displacement_avg(size,F).reshape(-1,3,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) - table.add('fluct({}).{}'.format(options.f,options.pos), + scriptID+' '+' '.join(sys.argv[1:]))\ + .add('fluct({}).{}'.format(options.f,options.pos), damask.grid_filters.cell_displacement_fluct(size,F).reshape(-1,3,order='F'), scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index 9abe1e2c6..6495793cf 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -51,8 +51,8 @@ for name in filenames: shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor field = field.reshape(tuple(grid)+(-1,),order='F').reshape(tuple(grid)+shape) div = damask.grid_filters.divergence(size,field) - table.add('divFFT({})'.format(label), - div.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape)//3,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('divFFT({})'.format(label), + div.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape)//3,order='F'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addEuclideanDistance.py b/processing/post/addEuclideanDistance.py index 921afc826..f5cf58ab3 100755 --- a/processing/post/addEuclideanDistance.py +++ b/processing/post/addEuclideanDistance.py @@ -180,8 +180,8 @@ for name in filenames: for i,feature in enumerate(feature_list): - table.add('ED_{}({})'.format(features[feature]['names'][0],options.id), - distance[i,:], - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('ED_{}({})'.format(features[feature]['names'][0],options.id), + distance[i,:], + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addGaussian.py b/processing/post/addGaussian.py index 93397e215..8e58da884 100755 --- a/processing/post/addGaussian.py +++ b/processing/post/addGaussian.py @@ -67,10 +67,10 @@ for name in filenames: damask.grid_filters.coord0_check(table.get(options.pos)) for label in options.labels: - table.add('Gauss{}({})'.format(options.sigma,label), - ndimage.filters.gaussian_filter(table.get(label).reshape(-1), - options.sigma,options.order, - mode = 'wrap' if options.periodic else 'nearest'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('Gauss{}({})'.format(options.sigma,label), + ndimage.filters.gaussian_filter(table.get(label).reshape(-1), + options.sigma,options.order, + mode = 'wrap' if options.periodic else 'nearest'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py index 3aee29374..718a972f3 100755 --- a/processing/post/addGradient.py +++ b/processing/post/addGradient.py @@ -51,8 +51,8 @@ for name in filenames: shape = (1,) if np.prod(field.shape)//np.prod(grid) == 1 else (3,) # scalar or vector field = field.reshape(tuple(grid)+(-1,),order='F') grad = damask.grid_filters.gradient(size,field) - table.add('gradFFT({})'.format(label), - grad.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape)*3,order='F'), - scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('gradFFT({})'.format(label), + grad.reshape(tuple(grid)+(-1,)).reshape(-1,np.prod(shape)*3,order='F'), + scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addIndexed.py b/processing/post/addIndexed.py deleted file mode 100755 index 50db36c20..000000000 --- a/processing/post/addIndexed.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from io import StringIO -from optparse import OptionParser - -import numpy as np - -import damask - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ -Add data in column(s) of mapped ASCIItable selected from the row indexed by the value in a mapping column. -Row numbers start at 1. - -""", version = scriptID) - -parser.add_option('--index', - dest = 'index', - type = 'string', metavar = 'string', - help = 'column label containing row index') -parser.add_option('-o','--offset', - dest = 'offset', - type = 'int', metavar = 'int', - help = 'constant offset for index column value [%default]') -parser.add_option('-l','--label', - dest = 'label', - action = 'extend', metavar = '', - help = 'column label(s) to be appended') -parser.add_option('-a','--asciitable', - dest = 'asciitable', - type = 'string', metavar = 'string', - help = 'indexed ASCIItable') - -parser.set_defaults(offset = 0, - ) - -(options,filenames) = parser.parse_args() -if filenames == []: filenames = [None] - -if options.label is None: - parser.error('no data columns specified.') -if options.index is None: - parser.error('no index column given.') - -for name in filenames: - damask.util.report(scriptName,name) - - table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - indexedTable = damask.Table.from_ASCII(options.asciitable) - idx = np.reshape(table.get(options.index).astype(int) + options.offset,(-1))-1 - - for data in options.label: - table.add(data+'_addIndexed',indexedTable.get(data)[idx],scriptID+' '+' '.join(sys.argv[1:])) - - table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addLinked.py b/processing/post/addLinked.py deleted file mode 100755 index 9b09cb7c7..000000000 --- a/processing/post/addLinked.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from optparse import OptionParser - -import numpy as np - -import damask - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ -Add data of selected column(s) from (first) row of linked ASCIItable that shares the linking column value. - -""", version = scriptID) - -parser.add_option('--link', - dest = 'link', nargs = 2, - type = 'string', metavar = 'string string', - help = 'column labels of table and linked table containing linking values') -parser.add_option('-l','--label', - dest = 'label', - action = 'extend', metavar = '', - help = 'column label(s) to add from linked ASCIItable') -parser.add_option('-a','--asciitable', - dest = 'asciitable', - type = 'string', metavar = 'string', - help = 'linked ASCIItable') - -parser.set_defaults() - -(options,filenames) = parser.parse_args() - -if options.label is None: - parser.error('no data columns specified.') -if options.link is None: - parser.error('no linking columns given.') - -# -------------------------------------- process linked ASCIItable -------------------------------- - -if options.asciitable is not None and os.path.isfile(options.asciitable): - - linkedTable = damask.ASCIItable(name = options.asciitable, readonly = True) - linkedTable.head_read() # read ASCII header info of linked table - linkDim = linkedTable.label_dimension(options.link[1]) # dimension of linking column - - missing_labels = linkedTable.data_readArray([options.link[1]]+options.label) # try reading linked ASCII table - linkedTable.close() # close linked ASCII table - - if len(missing_labels) > 0: - damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) - if len(missing_labels) >= len(options.label): - damask.util.croak('aborting...') - sys.exit() - - index = linkedTable.data[:,:linkDim] - data = linkedTable.data[:,linkDim:] -else: - parser.error('no linked ASCIItable given.') - -# --- loop over input files ----------------------------------------------------------------------- - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name) - except IOError: - continue - damask.util.report(scriptName,"{} {} <== {} {}".format(name,damask.util.deemph('@ '+options.link[0]), - options.asciitable,damask.util.deemph('@ '+options.link[1]))) - -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - - myLink = table.label_index (options.link[0]) - myLinkDim = table.label_dimension(options.link[0]) - if myLink < 0: errors.append('linking column {} not found.'.format(options.link[0])) - if myLinkDim != linkDim: errors.append('dimension mismatch for column {}.'.format(options.link[0])) - - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(linkedTable.labels(raw = True)[linkDim:]) # extend with new labels (except for linked column) - - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - try: - table.data_append(data[np.argwhere(np.all((list(map(float,table.data[myLink:myLink+myLinkDim])) - index)==0, - axis=1))[0]]) # add data of first matching line - except IndexError: - table.data_append(np.nan*np.ones_like(data[0])) # or add NaNs - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 51d668eb9..dddc14193 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -137,14 +137,14 @@ for name in filenames: if 'rodrigues' in options.output: - table.add('ro({})'.format(label),o.as_Rodrigues(), scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('ro({})'.format(label),o.as_Rodrigues(), scriptID+' '+' '.join(sys.argv[1:])) if 'eulers' in options.output: - table.add('eu({})'.format(label),o.as_Eulers(options.degrees), scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('eu({})'.format(label),o.as_Eulers(options.degrees), scriptID+' '+' '.join(sys.argv[1:])) if 'quaternion' in options.output: - table.add('qu({})'.format(label),o.as_quaternion(), scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('qu({})'.format(label),o.as_quaternion(), scriptID+' '+' '.join(sys.argv[1:])) if 'matrix' in options.output: - table.add('om({})'.format(label),o.as_matrix(), scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('om({})'.format(label),o.as_matrix(), scriptID+' '+' '.join(sys.argv[1:])) if 'axisangle' in options.output: - table.add('om({})'.format(label),o.as_axisangle(options.degrees), scriptID+' '+' '.join(sys.argv[1:])) + table = table.add('om({})'.format(label),o.as_axisangle(options.degrees), scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 26a0c5c93..dc4117d78 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -187,6 +187,6 @@ for name in filenames: np.einsum('ijk,ik->ij',slip_normal, (o@normal))) for i,label in enumerate(labels): - table.add(label,S[:,i],scriptID+' '+' '.join(sys.argv[1:])) + table = table.add(label,S[:,i],scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/post/groupTable.py b/processing/post/groupTable.py deleted file mode 100755 index a73e7d505..000000000 --- a/processing/post/groupTable.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from optparse import OptionParser, OptionGroup -import math # noqa - -import numpy as np - -import damask - - -def periodicAverage(coords, limits): - """Centroid in periodic domain, see https://en.wikipedia.org/wiki/Center_of_mass#Systems_with_periodic_boundary_conditions.""" - theta = 2.0*np.pi * (coords - limits[0])/(limits[1] - limits[0]) - theta_avg = np.pi + np.arctan2(-np.sin(theta).mean(axis=0), -np.cos(theta).mean(axis=0)) - return limits[0] + theta_avg * (limits[1] - limits[0])/2.0/np.pi - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ -Apply a user-specified function to condense into a single row all those rows for which columns 'label' have identical values. -Output table will contain as many rows as there are different (unique) values in the grouping column(s). -Periodic domain averaging of coordinate values is supported. - -Examples: -For grain averaged values, replace all rows of particular 'texture' with a single row containing their average. -{name} --label texture --function np.average data.txt -""".format(name = scriptName), version = scriptID) - -parser.add_option('-l','--label', - dest = 'label', - action = 'extend', metavar = '', - help = 'column label(s) for grouping rows') -parser.add_option('-f','--function', - dest = 'function', - type = 'string', metavar = 'string', - help = 'mapping function [%default]') -parser.add_option('-a','--all', - dest = 'all', - action = 'store_true', - help = 'apply mapping function also to grouping column(s)') - -group = OptionGroup(parser, "periodic averaging", "") - -group.add_option ('-p','--periodic', - dest = 'periodic', - action = 'extend', metavar = '', - help = 'coordinate label(s) to average across periodic domain') -group.add_option ('--limits', - dest = 'boundary', - type = 'float', metavar = 'float float', nargs = 2, - help = 'min and max of periodic domain %default') - -parser.add_option_group(group) - -parser.set_defaults(function = 'np.average', - all = False, - label = [], - boundary = [0.0, 1.0]) - -(options,filenames) = parser.parse_args() - -funcModule,funcName = options.function.split('.') - -try: - mapFunction = getattr(locals().get(funcModule) or - globals().get(funcModule) or - __import__(funcModule), - funcName) -except Exception: - mapFunction = None - -if options.label is []: - parser.error('no grouping column specified.') -if not hasattr(mapFunction,'__call__'): - parser.error('function "{}" is not callable.'.format(options.function)) - - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name) - except IOError: - continue - damask.util.report(scriptName,name) - -# ------------------------------------------ sanity checks --------------------------------------- - - remarks = [] - errors = [] - - table.head_read() - grpColumns = table.label_index(options.label)[::-1] - grpColumns = grpColumns[np.where(grpColumns>=0)] - - if len(grpColumns) == 0: errors.append('no valid grouping column present.') - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue - -# ------------------------------------------ assemble info --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data -------------------------------- - - table.data_readArray() - indexrange = table.label_indexrange(options.periodic) if options.periodic is not None else [] - rows,cols = table.data.shape - - table.data = table.data[np.lexsort(table.data[:,grpColumns].T)] # sort data by grpColumn(s) - values,index = np.unique(table.data[:,grpColumns], axis=0, return_index=True) # unique grpColumn values and their positions - index = sorted(np.append(index,rows)) # add termination position - grpTable = np.empty((len(values), cols)) # initialize output - - for i in range(len(values)): # iterate over groups (unique values in grpColumn) - grpTable[i] = np.apply_along_axis(mapFunction,0,table.data[index[i]:index[i+1]]) # apply (general) mapping function - grpTable[i,indexrange] = \ - periodicAverage(table.data[index[i]:index[i+1],indexrange],options.boundary) # apply periodicAverage mapping function - - if not options.all: grpTable[i,grpColumns] = table.data[index[i],grpColumns] # restore grouping column value - - table.data = grpTable - -# ------------------------------------------ output result ------------------------------- - - table.data_writeArray() - table.close() # close ASCII table diff --git a/processing/post/permuteData.py b/processing/post/permuteData.py index 766558216..316fdd3da 100755 --- a/processing/post/permuteData.py +++ b/processing/post/permuteData.py @@ -56,6 +56,6 @@ for name in filenames: data = table.get(label) uniques,inverse = np.unique(data,return_inverse=True,axis=0) if options.unique else (data,np.arange(len(data))) rng.shuffle(uniques) - table.set(label,uniques[inverse], scriptID+' '+' '.join(sys.argv[1:])) + table = table.set(label,uniques[inverse], scriptID+' '+' '.join(sys.argv[1:])) table.to_file(sys.stdout if name is None else name) diff --git a/processing/pre/seeds_fromGeom.py b/processing/pre/seeds_fromGeom.py index ab64c6b1e..97550ce13 100755 --- a/processing/pre/seeds_fromGeom.py +++ b/processing/pre/seeds_fromGeom.py @@ -64,6 +64,5 @@ for name in filenames: 'homogenization\t{}'.format(geom.homogenization)] table = damask.Table(seeds[mask],{'pos':(3,)},comments) - table.add('microstructure',microstructure[mask]) - table.to_file(sys.stdout if name is None else \ - os.path.splitext(name)[0]+'.seeds') + table = table.add('microstructure',microstructure[mask]) + table.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'.seeds') diff --git a/processing/pre/seeds_fromRandom.py b/processing/pre/seeds_fromRandom.py index b9e419391..a544528cf 100755 --- a/processing/pre/seeds_fromRandom.py +++ b/processing/pre/seeds_fromRandom.py @@ -155,11 +155,11 @@ for name in filenames: ] table = damask.Table(np.hstack((seeds,eulers)),{'pos':(3,),'euler':(3,)},comments) - table.add('microstructure',np.arange(options.microstructure,options.microstructure + options.N,dtype=int)) + table = table.add('microstructure',np.arange(options.microstructure,options.microstructure + options.N,dtype=int)) if options.weights: weights = np.random.uniform(low = 0, high = options.max, size = options.N) if options.max > 0.0 \ else np.random.normal(loc = options.mean, scale = options.sigma, size = options.N) - table.add('weight',weights) + table = table.add('weight',weights) table.to_file(sys.stdout if name is None else name) diff --git a/python/damask/_table.py b/python/damask/_table.py index 180c51f6f..b4fd2975a 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -1,4 +1,5 @@ import re +import copy import pandas as pd import numpy as np @@ -29,6 +30,15 @@ class Table: self._label_condensed() + def __copy__(self): + """Copy Table.""" + return copy.deepcopy(self) + + def copy(self): + """Copy Table.""" + return self.__copy__() + + def _label_flat(self): """Label data individually, e.g. v v v ==> 1_v 2_v 3_v.""" labels = [] @@ -191,15 +201,16 @@ class Table: Human-readable information about the new data. """ - self._add_comment(label,data.shape[1:],info) + dup = self.copy() + dup._add_comment(label,data.shape[1:],info) if re.match(r'[0-9]*?_',label): idx,key = label.split('_',1) - iloc = self.data.columns.get_loc(key).tolist().index(True) + int(idx) -1 - self.data.iloc[:,iloc] = data + iloc = dup.data.columns.get_loc(key).tolist().index(True) + int(idx) -1 + dup.data.iloc[:,iloc] = data else: - self.data[label] = data.reshape(self.data[label].shape) - + dup.data[label] = data.reshape(dup.data[label].shape) + return dup def add(self,label,data,info=None): """ @@ -215,15 +226,17 @@ class Table: Human-readable information about the modified data. """ - self._add_comment(label,data.shape[1:],info) + dup = self.copy() + dup._add_comment(label,data.shape[1:],info) - self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,) + dup.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,) size = np.prod(data.shape[1:],dtype=int) new = pd.DataFrame(data=data.reshape(-1,size), columns=[label]*size, ) - new.index = self.data.index - self.data = pd.concat([self.data,new],axis=1) + new.index = dup.data.index + dup.data = pd.concat([dup.data,new],axis=1) + return dup def delete(self,label): @@ -236,25 +249,31 @@ class Table: Column label. """ - self.data.drop(columns=label,inplace=True) - del self.shapes[label] + dup = self.copy() + dup.data.drop(columns=label,inplace=True) + del dup.shapes[label] + return dup - def rename(self,label_old,label_new,info=None): + def rename(self,old,new,info=None): """ Rename column data. Parameters ---------- - label_old : str - Old column label. - label_new : str - New column label. + label_old : str or iterable of str + Old column label(s). + label_new : str or iterable of str + New column label(s). """ - self.data.rename(columns={label_old:label_new},inplace=True) - self.comments.append(f'{label_old} => {label_new}'+('' if info is None else f': {info}')) - self.shapes = {(label if label != label_old else label_new):self.shapes[label] for label in self.shapes} + dup = self.copy() + columns = dict(zip([old] if isinstance(old,str) else old, + [new] if isinstance(new,str) else new)) + dup.data.rename(columns=columns,inplace=True) + dup.comments.append(f'{old} => {new}'+('' if info is None else f': {info}')) + dup.shapes = {(label if label not in columns else columns[label]):dup.shapes[label] for label in dup.shapes} + return dup def sort_by(self,labels,ascending=True): @@ -269,10 +288,12 @@ class Table: Set sort order. """ - self._label_flat() - self.data.sort_values(labels,axis=0,inplace=True,ascending=ascending) - self._label_condensed() - self.comments.append(f'sorted by [{", ".join(labels)}]') + dup = self.copy() + dup._label_flat() + dup.data.sort_values(labels,axis=0,inplace=True,ascending=ascending) + dup._label_condensed() + dup.comments.append(f'sorted {"ascending" if ascending else "descending"} by {labels}') + return dup def append(self,other): @@ -290,7 +311,9 @@ class Table: if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns): raise KeyError('Labels or shapes or order do not match') else: - self.data = self.data.append(other.data,ignore_index=True) + dup = self.copy() + dup.data = dup.data.append(other.data,ignore_index=True) + return dup def join(self,other): @@ -308,9 +331,11 @@ class Table: if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]: raise KeyError('Dublicated keys or row count mismatch') else: - self.data = self.data.join(other.data) + dup = self.copy() + dup.data = dup.data.join(other.data) for key in other.shapes: - self.shapes[key] = other.shapes[key] + dup.shapes[key] = other.shapes[key] + return dup def to_file(self,fname,format='ASCII',new_style=False): diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 636eeb0c4..9a23dc0ed 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -105,7 +105,7 @@ class TestOrientation: if update: coords = np.array([(1,i+1) for i,x in enumerate(eu)]) table = Table(eu,{'Eulers':(3,)}) - table.add('pos',coords) + table = table.add('pos',coords) table.to_ASCII(reference) assert np.allclose(eu,Table.from_ASCII(reference).get('Eulers')) diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index 6f9eca2d5..1763e27ef 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -81,13 +81,11 @@ class TestTable: Table.from_ASCII(f) def test_set(self,default): - default.set('F',np.zeros((5,3,3)),'set to zero') - d=default.get('F') + d = default.set('F',np.zeros((5,3,3)),'set to zero').get('F') assert np.allclose(d,0.0) and d.shape[1:] == (3,3) def test_set_component(self,default): - default.set('1_F',np.zeros((5)),'set to zero') - d=default.get('F') + d = default.set('1_F',np.zeros((5)),'set to zero').get('F') assert np.allclose(d[...,0,0],0.0) and d.shape[1:] == (3,3) def test_labels(self,default): @@ -95,36 +93,34 @@ class TestTable: def test_add(self,default): d = np.random.random((5,9)) - default.add('nine',d,'random data') - assert np.allclose(d,default.get('nine')) + assert np.allclose(d,default.add('nine',d,'random data').get('nine')) def test_rename_equivalent(self): x = np.random.random((5,13)) t = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) s = t.get('s') - t.rename('s','u') - u = t.get('u') + u = t.rename('s','u').get('u') assert np.all(s == u) def test_rename_gone(self,default): - default.rename('v','V') - assert 'v' not in default.shapes and 'v' not in default.data.columns + gone = default.rename('v','V') + assert 'v' not in gone.shapes and 'v' not in gone.data.columns with pytest.raises(KeyError): - default.get('v') + gone.get('v') def test_delete(self,default): - default.delete('v') - assert 'v' not in default.shapes and 'v' not in default.data.columns + delete = default.delete('v') + assert 'v' not in delete.shapes and 'v' not in delete.data.columns with pytest.raises(KeyError): - default.get('v') + delete.get('v') def test_join(self): x = np.random.random((5,13)) a = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) y = np.random.random((5,3)) b = Table(y,{'u':(3,)},['random test data']) - a.join(b) - assert np.array_equal(a.get('u'), b.get('u')) + c = a.join(b) + assert np.array_equal(c.get('u'), b.get('u')) def test_join_invalid(self): x = np.random.random((5,13)) @@ -135,8 +131,8 @@ class TestTable: def test_append(self): x = np.random.random((5,13)) a = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) - a.append(a) - assert np.array_equal(a.data[:5].to_numpy(),a.data[5:].to_numpy()) + b = a.append(a) + assert np.array_equal(b.data[:5].to_numpy(),b.data[5:].to_numpy()) def test_append_invalid(self): x = np.random.random((5,13)) @@ -163,29 +159,26 @@ class TestTable: x = np.random.random((5,13)) t = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) unsort = t.get('s') - t.sort_by('s') - sort = t.get('s') + sort = t.sort_by('s').get('s') assert np.all(np.sort(unsort,0)==sort) def test_sort_component(self): x = np.random.random((5,12)) t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) unsort = t.get('4_F') - t.sort_by('4_F') - sort = t.get('4_F') + sort = t.sort_by('4_F').get('4_F') assert np.all(np.sort(unsort,0)==sort) def test_sort_revert(self): x = np.random.random((5,12)) t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) - t.sort_by('4_F',ascending=False) - sort = t.get('4_F') + sort = t.sort_by('4_F',ascending=False).get('4_F') assert np.all(np.sort(sort,0)==sort[::-1,:]) def test_sort(self): t = Table(np.array([[0,1,],[2,1,]]), {'v':(2,)}, - ['test data']) - t.add('s',np.array(['b','a'])) - t.sort_by('s') + ['test data'])\ + .add('s',np.array(['b','a']))\ + .sort_by('s') assert np.all(t.get('1_v') == np.array([2,0]).reshape(2,1)) From e0375ef5ddcfaba9043c2dcbde94af18da5aa8ac Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 08:09:49 +0200 Subject: [PATCH 33/42] testset without tests for old shell scripts --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 92ca3e83b..1e398d1e3 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 92ca3e83b6093c1af277cfc06a504e4bb09fe8bc +Subproject commit 1e398d1e3a4cd627d1902285159c7711a4a4e9d4 From 1da0c64fd41e0f746a7497aef9d8ae70d31435a6 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 10:52:59 +0200 Subject: [PATCH 34/42] fixed tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 1e398d1e3..dc3aa7b20 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 1e398d1e3a4cd627d1902285159c7711a4a4e9d4 +Subproject commit dc3aa7b20590f9f72afc6a3d2c4cbee0424208a6 From 7d6a1dc58373672b8ae08e0934c488e606cac732 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 11:52:54 +0200 Subject: [PATCH 35/42] 'fixed' broken test actually, old pandas version was broken. Now (after an update) it should work --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index dc3aa7b20..8e3ca0385 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit dc3aa7b20590f9f72afc6a3d2c4cbee0424208a6 +Subproject commit 8e3ca03857b569ffa73baf78ac0cffd288e4eec2 From 8a32a1529929399a1c26f9ef3ca3fa01a02b43ca Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 12:17:43 +0200 Subject: [PATCH 36/42] changed to out-of-place mode --- PRIVATE | 2 +- processing/post/DADF5_postResults.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PRIVATE b/PRIVATE index 8e3ca0385..3a43b550b 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 8e3ca03857b569ffa73baf78ac0cffd288e4eec2 +Subproject commit 3a43b550b5a0054c708e7cc5b70af9dd6a41d141 diff --git a/processing/post/DADF5_postResults.py b/processing/post/DADF5_postResults.py index 9c520ac33..e81330581 100755 --- a/processing/post/DADF5_postResults.py +++ b/processing/post/DADF5_postResults.py @@ -46,7 +46,7 @@ for filename in options.filenames: for label in options.con: x = results.get_dataset_location(label) if len(x) != 0: - table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1)) + table = table.add(label,results.read_dataset(x,0,plain=True).reshape(results.grid.prod(),-1)) results.pick('constituents', False) results.pick('materialpoints',True) From 4738ab6a5997263aaf0ca5d3fb4f54098135584b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Sep 2020 14:15:55 +0200 Subject: [PATCH 37/42] out-of place example test --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 3a43b550b..6abc9c275 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 3a43b550b5a0054c708e7cc5b70af9dd6a41d141 +Subproject commit 6abc9c2757794b345bcf81d7c966de312b8fb93d From df548e95fc70894b7b11a4ea0eee0e859d826a81 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 14 Sep 2020 15:11:48 +0200 Subject: [PATCH 38/42] [skip ci] added reference to explain Fp_0 = O_0 --- src/crystallite.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crystallite.f90 b/src/crystallite.f90 index 9d2d534d7..018293f63 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -255,7 +255,7 @@ subroutine crystallite_init do e = FEsolving_execElem(1),FEsolving_execElem(2) myNcomponents = homogenization_Ngrains(material_homogenizationAt(e)) do i = FEsolving_execIP(1), FEsolving_execIP(2); do c = 1, myNcomponents - crystallite_Fp0(1:3,1:3,c,i,e) = material_orientation0(c,i,e)%asMatrix() ! plastic def gradient reflects init orientation + crystallite_Fp0(1:3,1:3,c,i,e) = material_orientation0(c,i,e)%asMatrix() ! Fp reflects initial orientation (see 10.1016/j.actamat.2006.01.005) crystallite_Fp0(1:3,1:3,c,i,e) = crystallite_Fp0(1:3,1:3,c,i,e) & / math_det33(crystallite_Fp0(1:3,1:3,c,i,e))**(1.0_pReal/3.0_pReal) crystallite_Fi0(1:3,1:3,c,i,e) = constitutive_initialFi(c,i,e) From 89875c900d84203ea264f6ee592868088e9ef6df Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 14 Sep 2020 13:19:49 -0400 Subject: [PATCH 39/42] adopted fixed runtime/memory plotting in tests --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 6abc9c275..8d5e08a8a 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 6abc9c2757794b345bcf81d7c966de312b8fb93d +Subproject commit 8d5e08a8a4dab7ed61f50ee37efb3fd115483437 From 2cb9b86353071a13b2ff5c162d131c5cbf7c3740 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 14 Sep 2020 15:59:49 -0400 Subject: [PATCH 40/42] use corrected testing --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 8d5e08a8a..313467be7 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 8d5e08a8a4dab7ed61f50ee37efb3fd115483437 +Subproject commit 313467be79a420a03985e0a04ecd72283380725f From 117f85ecd9be067c360447f45b76b93d73dd44ce Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 15 Sep 2020 01:02:04 +0200 Subject: [PATCH 41/42] missing from merge of 'table-out-of-place-only' server side problems with plotting are hopefully fixed now --- PRIVATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVATE b/PRIVATE index 313467be7..65ec74c07 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 313467be79a420a03985e0a04ecd72283380725f +Subproject commit 65ec74c07052e77f35a4b5e80bf110aff1f5ae61 From 77026e5d53dbcffc2a9935844e049ced4ff36a4c Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 15 Sep 2020 03:43:40 +0200 Subject: [PATCH 42/42] [skip ci] updated version information after successful test of v3.0.0-alpha-160-g117f85ec --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2d2d2952b..6f2aeecd0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-147-gf0806a9e +v3.0.0-alpha-160-g117f85ec