From 3fb5194c17556941779148917a105928658da38d Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 2 Feb 2016 16:24:09 +0100 Subject: [PATCH 001/134] updated version information after successful test of revision3813-992-g15e1c7e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6e8120049..4e86a1b4a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-984-gf13bddd +revision3813-992-g15e1c7e From fc1a21eb784dc577a75bdeefb1fc8067d3cb59be Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 4 Feb 2016 19:55:44 +0100 Subject: [PATCH 002/134] ignore marc aliases --- code/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 code/.gitignore diff --git a/code/.gitignore b/code/.gitignore new file mode 100644 index 000000000..9467b3147 --- /dev/null +++ b/code/.gitignore @@ -0,0 +1 @@ +DAMASK_marc*.f90 From 283bcd269c7b108da4bbf36a77a6f0af691e4190 Mon Sep 17 00:00:00 2001 From: Test User Date: Fri, 5 Feb 2016 10:50:25 +0100 Subject: [PATCH 003/134] updated version information after successful test of revision3813-1002-gfc1a21e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6e8120049..b4b4acd04 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-984-gf13bddd +revision3813-1002-gfc1a21e From 2bfc07079736f34912ab1053efbfc686cccf7024 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 8 Feb 2016 17:33:17 +0100 Subject: [PATCH 004/134] clarified function description --- code/spectral_utilities.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/spectral_utilities.f90 b/code/spectral_utilities.f90 index bde088ccb..f547a98aa 100644 --- a/code/spectral_utilities.f90 +++ b/code/spectral_utilities.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH @@ -1132,6 +1130,8 @@ end function utilities_forwardField !-------------------------------------------------------------------------------------------------- !> @brief calculates filter for fourier convolution depending on type given in numerics.config +!> @details this is the full operator to calculate derivatives, i.e. 2 \pi i k for the +! standard approach !-------------------------------------------------------------------------------------------------- pure function utilities_getFreqDerivative(k_s) use math, only: & @@ -1141,7 +1141,7 @@ pure function utilities_getFreqDerivative(k_s) grid implicit none - integer(pInt), intent(in), dimension(3) :: k_s !< indices of frequency + integer(pInt), intent(in), dimension(3) :: k_s !< indices of frequency complex(pReal), dimension(3) :: utilities_getFreqDerivative select case (spectral_derivative_ID) From c87625b30c166328654aa20936ca171cedffbb54 Mon Sep 17 00:00:00 2001 From: Chuanlai Liu Date: Mon, 22 Feb 2016 15:45:18 +0100 Subject: [PATCH 005/134] wrong state handling --- code/plastic_dislotwin.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/plastic_dislotwin.f90 b/code/plastic_dislotwin.f90 index 532312bfd..7e6164afc 100644 --- a/code/plastic_dislotwin.f90 +++ b/code/plastic_dislotwin.f90 @@ -2007,7 +2007,7 @@ subroutine plastic_dislotwin_dotState(Tstar_v,Temperature,ipc,ip,el) !* Total twin volume fraction sumf = sum(state(instance)%twinFraction(1_pInt:nt,of)) ! safe for nt == 0 - plasticState(instance)%dotState(:,of) = 0.0_pReal + plasticState(ph)%dotState(:,of) = 0.0_pReal !* Total transformed volume fraction sumftr = sum(state(instance)%stressTransFraction(1_pInt:nr,of)) + & From 5d0900ee2e7bd50316e7de4bd2ce2025f19b466a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 26 Feb 2016 15:36:24 +0100 Subject: [PATCH 006/134] plasticity test (phenoplus) working again with changed polar decomposition --- code/math.f90 | 160 ++++++++++++++++++++++--------------- code/plastic_dislotwin.f90 | 12 +-- 2 files changed, 101 insertions(+), 71 deletions(-) diff --git a/code/math.f90 b/code/math.f90 index 47c7da175..918035c9e 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -152,6 +152,8 @@ module math math_symmetricEulers, & math_spectralDecompositionSym33, & math_spectralDecompositionSym, & + math_eigenValuesVectorsSym33, & + math_eigenValuesVectorsSym, & math_rotationalPart33, & math_invariantsSym33, & math_eigenvaluesSym33, & @@ -472,7 +474,23 @@ end function math_crossproduct !-------------------------------------------------------------------------------------------------- -!> @brief tensor product a \otimes b +!> @brief tensor product A \otimes B of arbitrary sized vectors A and B +!-------------------------------------------------------------------------------------------------- +pure function math_tensorproduct(A,B) + + implicit none + real(pReal), dimension(:), intent(in) :: A,B + real(pReal), dimension(size(A,1),size(B,1)) :: math_tensorproduct + + integer(pInt) :: i,j + + forall (i=1_pInt:size(A,1),j=1_pInt:size(B,1)) math_tensorproduct(i,j) = A(i)*B(j) + +end function math_tensorproduct + + +!-------------------------------------------------------------------------------------------------- +!> @brief tensor product A \otimes B of leght-3 vectors A and B !-------------------------------------------------------------------------------------------------- pure function math_tensorproduct33(A,B) @@ -682,7 +700,7 @@ pure function math_exp33(A,n) math_exp33 = B ! A^0 = eye2 do i = 1_pInt,n - invfac = invfac/real(i) ! invfac = 1/i! + invfac = invfac/real(i,pReal) ! invfac = 1/i! B = math_mul33x33(B,A) math_exp33 = math_exp33 + invfac*B ! exp = SUM (A^i)/i! enddo @@ -761,6 +779,7 @@ pure subroutine math_invert33(A, InvA, DetA, error) DetA = A(1,1) * InvA(1,1) + A(1,2) * InvA(2,1) + A(1,3) * InvA(3,1) if (abs(DetA) <= tiny(DetA)) then + InvA = 0.0_pReal error = .true. else InvA(1,2) = -A(1,2) * A(3,3) + A(1,3) * A(3,2) @@ -1913,7 +1932,7 @@ end function math_symmetricEulers !-------------------------------------------------------------------------------------------------- !> @brief eigenvalues and eigenvectors of symmetric matrix m !-------------------------------------------------------------------------------------------------- -subroutine math_spectralDecompositionSym(m,values,vectors,error) +subroutine math_eigenValuesVectorsSym(m,values,vectors,error) implicit none real(pReal), dimension(:,:), intent(in) :: m @@ -1924,7 +1943,7 @@ subroutine math_spectralDecompositionSym(m,values,vectors,error) integer(pInt) :: info real(pReal), dimension((64+2)*size(m,1)) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f - vectors = M ! copy matrix to input (doubles as output) array + vectors = m ! copy matrix to input (doubles as output) array #if(FLOAT==8) call dsyev('V','U',size(m,1),vectors,size(m,1),values,work,(64+2)*size(m,1),info) #elif(FLOAT==4) @@ -1932,68 +1951,85 @@ subroutine math_spectralDecompositionSym(m,values,vectors,error) #endif error = (info == 0_pInt) -end subroutine math_spectralDecompositionSym +end subroutine math_eigenValuesVectorsSym !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m using an analytical expression -!> and the general LAPACK powered version for arbritrary sized matrices as fallback -!> @author Joachim Kopp, Max–Planck–Institut für Kernphysik, Heidelberg (Copyright (C) 2006) -!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @details See http://arxiv.org/abs/physics/0610206 (DSYEVH3) +!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m !-------------------------------------------------------------------------------------------------- -subroutine math_spectralDecompositionSym33(m,values,vectors) - +subroutine math_eigenValuesVectorsSym33(m,values,vectors) + implicit none - real(pReal), dimension(3,3),intent(in) :: m - real(pReal), dimension(3), intent(out) :: values - real(pReal), dimension(3,3),intent(out) :: vectors - real(pReal) :: T, U, norm, threshold + real(pReal), dimension(3,3), intent(in) :: m + real(pReal), dimension(3), intent(out) :: values + real(pReal), dimension(3,3), intent(out) :: vectors logical :: error + integer(pInt) :: info + real(pReal), dimension((64+2)*3) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f - values = math_eigenvaluesSym33(m) + vectors = m ! copy matrix to input (doubles as output) array +#if(FLOAT==8) + call dsyev('V','U',3,vectors,3,values,work,(64+2)*3,info) +#elif(FLOAT==4) + call ssyev('V','U',3,vectors,3,values,work,(64+2)*3,info) +#endif + error = (info == 0_pInt) - vectors(1:3,2) = [ m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2), & - m(1, 3) * m(1, 2) - m(2, 3) * m(1, 1), & - m(1, 2)**2_pInt] - - T = maxval(abs(values)) - U = max(T, T**2_pInt) - threshold = sqrt(5.0e-14_pReal * U**2_pInt) - -! Calculate first eigenvector by the formula v[0] = (m - lambda[0]).e1 x (m - lambda[0]).e2 - vectors(1:3,1) = [ vectors(1,2) + m(1, 3) * values(1), & - vectors(2,2) + m(2, 3) * values(1), & - (m(1,1) - values(1)) * (m(2,2) - values(1)) - vectors(3,2)] - norm = norm2(vectors(1:3, 1)) - - fallback1: if(norm < threshold) then - call math_spectralDecompositionSym(m,values,vectors,error) - return - endif fallback1 - - vectors(1:3,1) = vectors(1:3, 1) / norm - -! Calculate second eigenvector by the formula v[1] = (m - lambda[1]).e1 x (m - lambda[1]).e2 - vectors(1:3,2) = [ vectors(1,2) + m(1, 3) * values(2), & - vectors(2,2) + m(2, 3) * values(2), & - (m(1,1) - values(2)) * (m(2,2) - values(2)) - vectors(3,2)] - norm = norm2(vectors(1:3, 2)) - - fallback2: if(norm < threshold) then - call math_spectralDecompositionSym(m,values,vectors,error) - return - endif fallback2 - vectors(1:3,2) = vectors(1:3, 2) / norm - -! Calculate third eigenvector according to v[2] = v[0] x v[1] - vectors(1:3,3) = math_crossproduct(vectors(1:3,1),vectors(1:3,2)) - -end subroutine math_spectralDecompositionSym33 +end subroutine math_eigenValuesVectorsSym33 !-------------------------------------------------------------------------------------------------- -!> @brief rotational part from polar decomposition of tensor m +!> @brief eigenvalues and eigenvectors of symmetric matrix m +!-------------------------------------------------------------------------------------------------- +function math_spectralDecompositionSym(m) + + implicit none + real(pReal), dimension(:,:), intent(in) :: m + real(pReal), dimension(size(m,1)) :: values + real(pReal), dimension(size(m,1),size(m,1)) :: vectors + real(pReal), dimension(size(m,1),size(m,1)) :: math_spectralDecompositionSym + logical :: error + integer(pInt) :: i + + math_spectralDecompositionSym = 0.0_pReal + call math_eigenValuesVectorsSym(m,values,vectors,error) + if(error) return + + do i=1_pInt, size(m,1) + math_spectralDecompositionSym = math_spectralDecompositionSym & + + sqrt(values(i)) * math_tensorproduct(vectors(:,i),vectors(:,i)) + enddo + +end function math_spectralDecompositionSym + + +!-------------------------------------------------------------------------------------------------- +!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m +!-------------------------------------------------------------------------------------------------- +function math_spectralDecompositionSym33(m) + + implicit none + real(pReal), dimension(3,3), intent(in) :: m + real(pReal), dimension(3,3) :: math_spectralDecompositionSym33 + real(pReal), dimension(3) :: values + real(pReal), dimension(3,3) :: vectors + logical :: error + integer(pInt) :: i + + math_spectralDecompositionSym33 = 0.0_pReal + call math_eigenValuesVectorsSym33(m,values,vectors) + if(error) return + + do i=1_pInt, 3_pInt + math_spectralDecompositionSym33 = math_spectralDecompositionSym33 & + + sqrt(values(i)) * math_tensorproduct(vectors(:,i),vectors(:,i)) + enddo + +end function math_spectralDecompositionSym33 + + +!-------------------------------------------------------------------------------------------------- +!> @brief rotational part from polar decomposition of 33 tensor m !-------------------------------------------------------------------------------------------------- function math_rotationalPart33(m) use IO, only: & @@ -2002,17 +2038,11 @@ function math_rotationalPart33(m) implicit none real(pReal), intent(in), dimension(3,3) :: m real(pReal), dimension(3,3) :: math_rotationalPart33 - real(pReal), dimension(3,3) :: U, mTm , Uinv, EB - real(pReal), dimension(3) :: EV - - mTm = math_mul33x33(math_transpose33(m),m) - call math_spectralDecompositionSym33(mTm,EV,EB) - - U = sqrt(EV(1)) * math_tensorproduct33(EB(1:3,1),EB(1:3,1)) & - + sqrt(EV(2)) * math_tensorproduct33(EB(1:3,2),EB(1:3,2)) & - + sqrt(EV(3)) * math_tensorproduct33(EB(1:3,3),EB(1:3,3)) + real(pReal), dimension(3,3) :: U , Uinv + U = math_spectralDecompositionSym33(math_mul33x33(transpose(m),m)) Uinv = math_inv33(U) + if (all(abs(Uinv) <= tiny(Uinv))) then ! math_inv33 returns zero when failed, avoid floating point equality comparison math_rotationalPart33 = math_I3 call IO_warning(650_pInt) @@ -2675,4 +2705,4 @@ real(pReal) pure function math_limit(a, left, right) end function math_limit -end module math +end module math \ No newline at end of file diff --git a/code/plastic_dislotwin.f90 b/code/plastic_dislotwin.f90 index 532312bfd..e84321dee 100644 --- a/code/plastic_dislotwin.f90 +++ b/code/plastic_dislotwin.f90 @@ -1637,7 +1637,7 @@ subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dTstar99,Tstar_v,Temperature math_Plain3333to99, & math_Mandel6to33, & math_Mandel33to6, & - math_spectralDecompositionSym, & + math_eigenValuesVectorsSym, & math_tensorproduct33, & math_symmetric33, & math_mul33x3 @@ -1783,7 +1783,7 @@ subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dTstar99,Tstar_v,Temperature abs(plastic_dislotwin_sbResistance(instance)) > tiny(0.0_pReal)) then gdot_sb = 0.0_pReal dgdot_dtausb = 0.0_pReal - call math_spectralDecompositionSym(math_Mandel6to33(Tstar_v),eigValues,eigVectors,error) + call math_eigenValuesVectorsSym(math_Mandel6to33(Tstar_v),eigValues,eigVectors,error) do j = 1_pInt,6_pInt sb_s = 0.5_pReal*sqrt(2.0_pReal)*math_mul33x3(eigVectors,sb_sComposition(1:3,j)) sb_m = 0.5_pReal*sqrt(2.0_pReal)*math_mul33x3(eigVectors,sb_mComposition(1:3,j)) @@ -2197,8 +2197,8 @@ function plastic_dislotwin_postResults(Tstar_v,Temperature,ipc,ip,el) use math, only: & pi, & math_Mandel6to33, & - math_eigenvaluesSym33, & - math_spectralDecompositionSym33 + math_eigenValuesSym33, & + math_eigenValuesVectorsSym33 use material, only: & material_phase, & phase_plasticityInstance,& @@ -2519,7 +2519,7 @@ function plastic_dislotwin_postResults(Tstar_v,Temperature,ipc,ip,el) plastic_dislotwin_postResults(c+1_pInt:c+3_pInt) = math_eigenvaluesSym33(math_Mandel6to33(Tstar_v)) c = c + 3_pInt case (sb_eigenvectors_ID) - call math_spectralDecompositionSym33(math_Mandel6to33(Tstar_v),eigValues,eigVectors) + call math_eigenValuesVectorsSym33(math_Mandel6to33(Tstar_v),eigValues,eigVectors) plastic_dislotwin_postResults(c+1_pInt:c+9_pInt) = reshape(eigVectors,[9]) c = c + 9_pInt case (stress_trans_fraction_ID) @@ -2539,4 +2539,4 @@ function plastic_dislotwin_postResults(Tstar_v,Temperature,ipc,ip,el) enddo end function plastic_dislotwin_postResults -end module plastic_dislotwin \ No newline at end of file +end module plastic_dislotwin From 76b67e88eb8a1939e25b0195df7210ee7a73d4de Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 26 Feb 2016 16:35:55 +0100 Subject: [PATCH 007/134] re-indroduced special spectral decomposition for 33 tensors --- code/math.f90 | 97 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/code/math.f90 b/code/math.f90 index 918035c9e..e81781e53 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -2009,21 +2009,90 @@ end function math_spectralDecompositionSym function math_spectralDecompositionSym33(m) implicit none - real(pReal), dimension(3,3), intent(in) :: m real(pReal), dimension(3,3) :: math_spectralDecompositionSym33 - real(pReal), dimension(3) :: values - real(pReal), dimension(3,3) :: vectors - logical :: error - integer(pInt) :: i + real(pReal), dimension(3) :: invariants, values + real(pReal), dimension(3,3), intent(in) :: m + real(pReal) :: EW1,EW2,EW3 + real(pReal) :: P, Q, RHO, PHI, Y1, Y2, Y3, D1, D2, D3 + real(pReal), parameter :: TOL=1.e-14_pReal + real(pReal), dimension(3,3) :: M1, M2, M3,EB1, EB2, EB3 + real(pReal) C1,C2,C3 - math_spectralDecompositionSym33 = 0.0_pReal - call math_eigenValuesVectorsSym33(m,values,vectors) - if(error) return - - do i=1_pInt, 3_pInt - math_spectralDecompositionSym33 = math_spectralDecompositionSym33 & - + sqrt(values(i)) * math_tensorproduct(vectors(:,i),vectors(:,i)) - enddo + invariants = math_invariantsSym33(m) + + P=invariants(2)-invariants(1)**2.0_pReal/3.0_pReal + Q=-2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+invariants(1)*invariants(2)/3.0_pReal-invariants(3) + + EB1=0.0_pReal + EB2=0.0_pReal + EB3=0.0_pReal + if((ABS(P) < TOL).AND.(ABS(Q) < TOL)) then +! DREI GLEICHE EIGENWERTE + values = invariants(1)/3.0_pReal +! this is not really correct, but this way U is calculated +! correctly in PDECOMPOSITION (correct is EB?=I) + EB1(1,1)=1.0_pReal + EB2(2,2)=1.0_pReal + EB3(3,3)=1.0_pReal + else + rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal + phi=acos(math_limit(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) + Y1=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal) + Y2=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal+2.0_pReal/3.0_pReal*PI) + Y3=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal+4.0_pReal/3.0_pReal*PI) + EW1=Y1+invariants(1)/3.0_pReal + EW2=Y2+invariants(1)/3.0_pReal + EW3=Y3+invariants(1)/3.0_pReal + C1=ABS(EW1-EW2) + C2=ABS(EW2-EW3) + C3=ABS(EW3-EW1) + + if (C1 < TOL) then +! EW1 is equal to EW2 + D3=1.0_pReal/(EW3-EW1)/(EW3-EW2) + M1=M-EW1*math_I3 + M2=M-EW2*math_I3 + EB3=math_mul33x33(M1,M2)*D3 + + EB1=math_I3-EB3 +! both EB2 and EW2 are set to zero so that they do not +! contribute to U in PDECOMPOSITION + EW2=0.0_pReal + elseif (C2 < TOL) then +! EW2 is equal to EW3 + D1=1.0_pReal/(EW1-EW2)/(EW1-EW3) + M2=M-math_I3*EW2 + M3=M-math_I3*EW3 + EB1=math_mul33x33(M2,M3)*D1 + EB2=math_I3-EB1 +! both EB3 and EW3 are set to zero so that they do not +! contribute to U in PDECOMPOSITION + EW3=0.0_pReal + elseif(C3 < TOL) then +! EW1 is equal to EW3 + D2=1.0_pReal/(EW2-EW1)/(EW2-EW3) + M1=M-math_I3*EW1 + M3=M-math_I3*EW3 + EB2=math_mul33x33(M1,M3)*D2 + EB1=math_I3-EB2 +! both EB3 and EW3 are set to zero so that they do not +! contribute to U in PDECOMPOSITION + EW3=0.0_pReal + else +! all three eigenvectors are different + D1=1.0_pReal/(EW1-EW2)/(EW1-EW3) + D2=1.0_pReal/(EW2-EW1)/(EW2-EW3) + D3=1.0_pReal/(EW3-EW1)/(EW3-EW2) + M1=M-EW1*math_I3 + M2=M-EW2*math_I3 + M3=M-EW3*math_I3 + EB1=math_mul33x33(M2,M3)*D1 + EB2=math_mul33x33(M1,M3)*D2 + EB3=math_mul33x33(M1,M2)*D3 + endif + endif + + math_spectralDecompositionSym33 = sqrt(EW1) * EB1 + sqrt(EW2) * EB2 + sqrt(EW3) * EB3 end function math_spectralDecompositionSym33 @@ -2705,4 +2774,4 @@ real(pReal) pure function math_limit(a, left, right) end function math_limit -end module math \ No newline at end of file +end module math From 17e75a1e0b6c5af1e5cf0c697781a09e3e9d2081 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 26 Feb 2016 17:51:34 +0100 Subject: [PATCH 008/134] some more simplifications --- code/math.f90 | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/code/math.f90 b/code/math.f90 index e81781e53..76c93aaa3 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -2012,8 +2012,7 @@ function math_spectralDecompositionSym33(m) real(pReal), dimension(3,3) :: math_spectralDecompositionSym33 real(pReal), dimension(3) :: invariants, values real(pReal), dimension(3,3), intent(in) :: m - real(pReal) :: EW1,EW2,EW3 - real(pReal) :: P, Q, RHO, PHI, Y1, Y2, Y3, D1, D2, D3 + real(pReal) :: P, Q, rho, phi, D1, D2, D3 real(pReal), parameter :: TOL=1.e-14_pReal real(pReal), dimension(3,3) :: M1, M2, M3,EB1, EB2, EB3 real(pReal) C1,C2,C3 @@ -2037,62 +2036,61 @@ function math_spectralDecompositionSym33(m) else rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal phi=acos(math_limit(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) - Y1=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal) - Y2=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal+2.0_pReal/3.0_pReal*PI) - Y3=2.0_pReal*RHO**(1.0_pReal/3.0_pReal)*cos(PHI/3.0_pReal+4.0_pReal/3.0_pReal*PI) - EW1=Y1+invariants(1)/3.0_pReal - EW2=Y2+invariants(1)/3.0_pReal - EW3=Y3+invariants(1)/3.0_pReal - C1=ABS(EW1-EW2) - C2=ABS(EW2-EW3) - C3=ABS(EW3-EW1) + values = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & + [cos(phi/3.0_pReal), & + cos((phi+2.0_pReal*PI)/3.0_pReal), & + cos((phi+4.0_pReal*PI)/3.0_pReal) & + ] + invariants(1)/3.0_pReal + C1=ABS(values(1)-values(2)) + C2=ABS(values(2)-values(3)) + C3=ABS(values(3)-values(1)) if (C1 < TOL) then -! EW1 is equal to EW2 - D3=1.0_pReal/(EW3-EW1)/(EW3-EW2) - M1=M-EW1*math_I3 - M2=M-EW2*math_I3 +! values(1) is equal to values(2) + D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) + M1=M-values(1)*math_I3 + M2=M-values(2)*math_I3 EB3=math_mul33x33(M1,M2)*D3 EB1=math_I3-EB3 -! both EB2 and EW2 are set to zero so that they do not +! both EB2 and values(2) are set to zero so that they do not ! contribute to U in PDECOMPOSITION - EW2=0.0_pReal + values(2)=0.0_pReal elseif (C2 < TOL) then -! EW2 is equal to EW3 - D1=1.0_pReal/(EW1-EW2)/(EW1-EW3) - M2=M-math_I3*EW2 - M3=M-math_I3*EW3 +! values(2) is equal to values(3) + D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) + M2=M-math_I3*values(2) + M3=M-math_I3*values(3) EB1=math_mul33x33(M2,M3)*D1 EB2=math_I3-EB1 -! both EB3 and EW3 are set to zero so that they do not +! both EB3 and values(3) are set to zero so that they do not ! contribute to U in PDECOMPOSITION - EW3=0.0_pReal + values(3)=0.0_pReal elseif(C3 < TOL) then -! EW1 is equal to EW3 - D2=1.0_pReal/(EW2-EW1)/(EW2-EW3) - M1=M-math_I3*EW1 - M3=M-math_I3*EW3 +! values(1) is equal to values(3) + D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) + M1=M-math_I3*values(1) + M3=M-math_I3*values(3) EB2=math_mul33x33(M1,M3)*D2 EB1=math_I3-EB2 -! both EB3 and EW3 are set to zero so that they do not +! both EB3 and values(3) are set to zero so that they do not ! contribute to U in PDECOMPOSITION - EW3=0.0_pReal + values(3)=0.0_pReal else ! all three eigenvectors are different - D1=1.0_pReal/(EW1-EW2)/(EW1-EW3) - D2=1.0_pReal/(EW2-EW1)/(EW2-EW3) - D3=1.0_pReal/(EW3-EW1)/(EW3-EW2) - M1=M-EW1*math_I3 - M2=M-EW2*math_I3 - M3=M-EW3*math_I3 + D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) + D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) + D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) + M1=M-values(1)*math_I3 + M2=M-values(2)*math_I3 + M3=M-values(3)*math_I3 EB1=math_mul33x33(M2,M3)*D1 EB2=math_mul33x33(M1,M3)*D2 EB3=math_mul33x33(M1,M2)*D3 endif endif - math_spectralDecompositionSym33 = sqrt(EW1) * EB1 + sqrt(EW2) * EB2 + sqrt(EW3) * EB3 + math_spectralDecompositionSym33 = sqrt(values(1)) * EB1 + sqrt(values(2)) * EB2 + sqrt(values(3)) * EB3 end function math_spectralDecompositionSym33 From ca3e1f0da055aa7991b4f841774af3cd2b8cd4ef Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 26 Feb 2016 19:37:10 +0100 Subject: [PATCH 009/134] further simpilifcations --- code/math.f90 | 48 ++++++++++---------------------------- code/plastic_dislotwin.f90 | 2 -- 2 files changed, 12 insertions(+), 38 deletions(-) diff --git a/code/math.f90 b/code/math.f90 index 76c93aaa3..a3ef37ce5 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -2010,12 +2010,12 @@ function math_spectralDecompositionSym33(m) implicit none real(pReal), dimension(3,3) :: math_spectralDecompositionSym33 - real(pReal), dimension(3) :: invariants, values + real(pReal), dimension(3) :: invariants, values,C real(pReal), dimension(3,3), intent(in) :: m - real(pReal) :: P, Q, rho, phi, D1, D2, D3 + real(pReal) :: P, Q, rho, phi real(pReal), parameter :: TOL=1.e-14_pReal real(pReal), dimension(3,3) :: M1, M2, M3,EB1, EB2, EB3 - real(pReal) C1,C2,C3 + real(pReal) :: D1, D2, D3 invariants = math_invariantsSym33(m) @@ -2025,8 +2025,7 @@ function math_spectralDecompositionSym33(m) EB1=0.0_pReal EB2=0.0_pReal EB3=0.0_pReal - if((ABS(P) < TOL).AND.(ABS(Q) < TOL)) then -! DREI GLEICHE EIGENWERTE + if((ABS(P) < TOL).AND.(ABS(Q) < TOL)) then ! EV_2 = EV_1 = EV_3 values = invariants(1)/3.0_pReal ! this is not really correct, but this way U is calculated ! correctly in PDECOMPOSITION (correct is EB?=I) @@ -2041,49 +2040,26 @@ function math_spectralDecompositionSym33(m) cos((phi+2.0_pReal*PI)/3.0_pReal), & cos((phi+4.0_pReal*PI)/3.0_pReal) & ] + invariants(1)/3.0_pReal - C1=ABS(values(1)-values(2)) - C2=ABS(values(2)-values(3)) - C3=ABS(values(3)-values(1)) - - if (C1 < TOL) then -! values(1) is equal to values(2) + C = abs([values(1)-values(2),values(2)-values(3),values(3)-values(1)]) + M1=M-values(1)*math_I3 + M2=M-values(2)*math_I3 + M3=M-values(3)*math_I3 + if (C(1) < TOL) then ! EV_2 = EV_1, no contribution from EV_2 D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) - M1=M-values(1)*math_I3 - M2=M-values(2)*math_I3 EB3=math_mul33x33(M1,M2)*D3 - EB1=math_I3-EB3 -! both EB2 and values(2) are set to zero so that they do not -! contribute to U in PDECOMPOSITION - values(2)=0.0_pReal - elseif (C2 < TOL) then -! values(2) is equal to values(3) + elseif (C(2) < TOL) then ! EV_2 = EV_3, no contribution from EV_3 D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) - M2=M-math_I3*values(2) - M3=M-math_I3*values(3) EB1=math_mul33x33(M2,M3)*D1 EB2=math_I3-EB1 -! both EB3 and values(3) are set to zero so that they do not -! contribute to U in PDECOMPOSITION - values(3)=0.0_pReal - elseif(C3 < TOL) then -! values(1) is equal to values(3) + elseif(C(3) < TOL) then ! EV_1 = EV_3, no contribution from EV_3 D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) - M1=M-math_I3*values(1) - M3=M-math_I3*values(3) EB2=math_mul33x33(M1,M3)*D2 EB1=math_I3-EB2 -! both EB3 and values(3) are set to zero so that they do not -! contribute to U in PDECOMPOSITION - values(3)=0.0_pReal - else -! all three eigenvectors are different + else ! all three eigenvectors are different D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) - M1=M-values(1)*math_I3 - M2=M-values(2)*math_I3 - M3=M-values(3)*math_I3 EB1=math_mul33x33(M2,M3)*D1 EB2=math_mul33x33(M1,M3)*D2 EB3=math_mul33x33(M1,M2)*D3 diff --git a/code/plastic_dislotwin.f90 b/code/plastic_dislotwin.f90 index e84321dee..953ab38ac 100644 --- a/code/plastic_dislotwin.f90 +++ b/code/plastic_dislotwin.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incoprorating dislocation and twinning physics From c7ab5a93967031bc85b8c7c2f0cfb126eb84a289 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 26 Feb 2016 20:21:47 +0100 Subject: [PATCH 010/134] simplified and got MPI Heidelberg solution for eigenvalues/vectors back --- code/math.f90 | 169 ++++++++++++++++++++++--------------- code/plastic_disloUCLA.f90 | 2 - 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/code/math.f90 b/code/math.f90 index a3ef37ce5..43ea66e6f 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -150,8 +150,8 @@ module math math_sampleFiberOri, & math_sampleGaussVar, & math_symmetricEulers, & - math_spectralDecompositionSym33, & - math_spectralDecompositionSym, & + math_eigenvectorBasisSym33, & + math_eigenvectorBasisSym, & math_eigenValuesVectorsSym33, & math_eigenValuesVectorsSym, & math_rotationalPart33, & @@ -1955,84 +1955,112 @@ end subroutine math_eigenValuesVectorsSym !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m +!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m using an analytical expression +!> and the general LAPACK powered version for arbritrary sized matrices as fallback +!> @author Joachim Kopp, Max–Planck–Institut für Kernphysik, Heidelberg (Copyright (C) 2006) +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @details See http://arxiv.org/abs/physics/0610206 (DSYEVH3) !-------------------------------------------------------------------------------------------------- subroutine math_eigenValuesVectorsSym33(m,values,vectors) - + implicit none - real(pReal), dimension(3,3), intent(in) :: m - real(pReal), dimension(3), intent(out) :: values - real(pReal), dimension(3,3), intent(out) :: vectors + real(pReal), dimension(3,3),intent(in) :: m + real(pReal), dimension(3), intent(out) :: values + real(pReal), dimension(3,3),intent(out) :: vectors + real(pReal) :: T, U, norm, threshold logical :: error - integer(pInt) :: info - real(pReal), dimension((64+2)*3) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f - vectors = m ! copy matrix to input (doubles as output) array -#if(FLOAT==8) - call dsyev('V','U',3,vectors,3,values,work,(64+2)*3,info) -#elif(FLOAT==4) - call ssyev('V','U',3,vectors,3,values,work,(64+2)*3,info) -#endif - error = (info == 0_pInt) + values = math_eigenvaluesSym33(m) + vectors(1:3,2) = [ m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2), & + m(1, 3) * m(1, 2) - m(2, 3) * m(1, 1), & + m(1, 2)**2_pInt] + + T = maxval(abs(values)) + U = max(T, T**2_pInt) + threshold = sqrt(5.68e-14_pReal * U**2_pInt) + +! Calculate first eigenvector by the formula v[0] = (m - lambda[0]).e1 x (m - lambda[0]).e2 + vectors(1:3,1) = [ vectors(1,2) + m(1, 3) * values(1), & + vectors(2,2) + m(2, 3) * values(1), & + (m(1,1) - values(1)) * (m(2,2) - values(1)) - vectors(3,2)] + norm = norm2(vectors(1:3, 1)) + + fallback1: if(norm < threshold) then + call math_eigenValuesVectorsSym(m,values,vectors,error) + return + endif fallback1 + + vectors(1:3,1) = vectors(1:3, 1) / norm + +! Calculate second eigenvector by the formula v[1] = (m - lambda[1]).e1 x (m - lambda[1]).e2 + vectors(1:3,2) = [ vectors(1,2) + m(1, 3) * values(2), & + vectors(2,2) + m(2, 3) * values(2), & + (m(1,1) - values(2)) * (m(2,2) - values(2)) - vectors(3,2)] + norm = norm2(vectors(1:3, 2)) + + fallback2: if(norm < threshold) then + call math_eigenValuesVectorsSym(m,values,vectors,error) + return + endif fallback2 + vectors(1:3,2) = vectors(1:3, 2) / norm + +! Calculate third eigenvector according to v[2] = v[0] x v[1] + vectors(1:3,3) = math_crossproduct(vectors(1:3,1),vectors(1:3,2)) end subroutine math_eigenValuesVectorsSym33 !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric matrix m +!> @brief eigenvector basis of symmetric matrix m !-------------------------------------------------------------------------------------------------- -function math_spectralDecompositionSym(m) +function math_eigenvectorBasisSym(m) implicit none real(pReal), dimension(:,:), intent(in) :: m real(pReal), dimension(size(m,1)) :: values real(pReal), dimension(size(m,1),size(m,1)) :: vectors - real(pReal), dimension(size(m,1),size(m,1)) :: math_spectralDecompositionSym + real(pReal), dimension(size(m,1),size(m,1)) :: math_eigenvectorBasisSym logical :: error integer(pInt) :: i - math_spectralDecompositionSym = 0.0_pReal + math_eigenvectorBasisSym = 0.0_pReal call math_eigenValuesVectorsSym(m,values,vectors,error) if(error) return do i=1_pInt, size(m,1) - math_spectralDecompositionSym = math_spectralDecompositionSym & - + sqrt(values(i)) * math_tensorproduct(vectors(:,i),vectors(:,i)) + math_eigenvectorBasisSym = math_eigenvectorBasisSym & + + sqrt(values(i)) * math_tensorproduct(vectors(:,i),vectors(:,i)) enddo -end function math_spectralDecompositionSym +end function math_eigenvectorBasisSym !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m +!> @brief eigenvector basis of symmetric 33 matrix m !-------------------------------------------------------------------------------------------------- -function math_spectralDecompositionSym33(m) +function math_eigenvectorBasisSym33(m) implicit none - real(pReal), dimension(3,3) :: math_spectralDecompositionSym33 - real(pReal), dimension(3) :: invariants, values,C + real(pReal), dimension(3,3) :: math_eigenvectorBasisSym33 + real(pReal), dimension(3) :: invariants, values real(pReal), dimension(3,3), intent(in) :: m real(pReal) :: P, Q, rho, phi real(pReal), parameter :: TOL=1.e-14_pReal - real(pReal), dimension(3,3) :: M1, M2, M3,EB1, EB2, EB3 - real(pReal) :: D1, D2, D3 + real(pReal), dimension(3,3,3) :: N, EB invariants = math_invariantsSym33(m) + EB = 0.0_pReal - P=invariants(2)-invariants(1)**2.0_pReal/3.0_pReal - Q=-2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+invariants(1)*invariants(2)/3.0_pReal-invariants(3) + P = invariants(2)-invariants(1)**2.0_pReal/3.0_pReal + Q = -2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+product(invariants(1:2))/3.0_pReal-invariants(3) - EB1=0.0_pReal - EB2=0.0_pReal - EB3=0.0_pReal - if((ABS(P) < TOL).AND.(ABS(Q) < TOL)) then ! EV_2 = EV_1 = EV_3 + threeSimilarEigenvalues: if(all(abs([P,Q]) < TOL)) then values = invariants(1)/3.0_pReal -! this is not really correct, but this way U is calculated -! correctly in PDECOMPOSITION (correct is EB?=I) - EB1(1,1)=1.0_pReal - EB2(2,2)=1.0_pReal - EB3(3,3)=1.0_pReal - else +! this is not really correct, but at least the basis is correct + EB(1,1,1)=1.0_pReal + EB(2,2,2)=1.0_pReal + EB(3,3,3)=1.0_pReal + else threeSimilarEigenvalues rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal phi=acos(math_limit(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) values = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & @@ -2040,35 +2068,36 @@ function math_spectralDecompositionSym33(m) cos((phi+2.0_pReal*PI)/3.0_pReal), & cos((phi+4.0_pReal*PI)/3.0_pReal) & ] + invariants(1)/3.0_pReal - C = abs([values(1)-values(2),values(2)-values(3),values(3)-values(1)]) - M1=M-values(1)*math_I3 - M2=M-values(2)*math_I3 - M3=M-values(3)*math_I3 - if (C(1) < TOL) then ! EV_2 = EV_1, no contribution from EV_2 - D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) - EB3=math_mul33x33(M1,M2)*D3 - EB1=math_I3-EB3 - elseif (C(2) < TOL) then ! EV_2 = EV_3, no contribution from EV_3 - D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) - EB1=math_mul33x33(M2,M3)*D1 - EB2=math_I3-EB1 - elseif(C(3) < TOL) then ! EV_1 = EV_3, no contribution from EV_3 - D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) - EB2=math_mul33x33(M1,M3)*D2 - EB1=math_I3-EB2 - else ! all three eigenvectors are different - D1=1.0_pReal/(values(1)-values(2))/(values(1)-values(3)) - D2=1.0_pReal/(values(2)-values(1))/(values(2)-values(3)) - D3=1.0_pReal/(values(3)-values(1))/(values(3)-values(2)) - EB1=math_mul33x33(M2,M3)*D1 - EB2=math_mul33x33(M1,M3)*D2 - EB3=math_mul33x33(M1,M2)*D3 - endif - endif + N(1:3,1:3,1) = m-values(1)*math_I3 + N(1:3,1:3,2) = m-values(2)*math_I3 + N(1:3,1:3,3) = m-values(3)*math_I3 + twoSimilarEigenvalues: if(abs(values(1)-values(2)) < TOL) then + EB(1:3,1:3,3)=math_mul33x33(N(1:3,1:3,1),N(1:3,1:3,2))/ & + ((values(3)-values(1))*(values(3)-values(2))) + EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,3) + elseif(abs(values(2)-values(3)) < TOL) then twoSimilarEigenvalues + EB(1:3,1:3,1)=math_mul33x33(N(1:3,1:3,2),N(1:3,1:3,3))/ & + ((values(1)-values(2))*(values(1)-values(3))) + EB(1:3,1:3,2)=math_I3-EB(1:3,1:3,1) + elseif(abs(values(3)-values(1)) < TOL) then twoSimilarEigenvalues + EB(1:3,1:3,2)=math_mul33x33(N(1:3,1:3,1),N(1:3,1:3,3))/ & + ((values(2)-values(1))*(values(2)-values(3))) + EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,2) + else twoSimilarEigenvalues + EB(1:3,1:3,1)=math_mul33x33(N(1:3,1:3,2),N(1:3,1:3,3))/ & + ((values(1)-values(2))*(values(1)-values(3))) + EB(1:3,1:3,2)=math_mul33x33(N(1:3,1:3,1),N(1:3,1:3,3))/ & + ((values(2)-values(1))*(values(2)-values(3))) + EB(1:3,1:3,3)=math_mul33x33(N(1:3,1:3,1),N(1:3,1:3,2))/ & + ((values(3)-values(1))*(values(3)-values(2))) + endif twoSimilarEigenvalues + endif threeSimilarEigenvalues - math_spectralDecompositionSym33 = sqrt(values(1)) * EB1 + sqrt(values(2)) * EB2 + sqrt(values(3)) * EB3 + math_eigenvectorBasisSym33 = sqrt(values(1)) * EB(1:3,1:3,1) & + + sqrt(values(2)) * EB(1:3,1:3,2) & + + sqrt(values(3)) * EB(1:3,1:3,3) -end function math_spectralDecompositionSym33 +end function math_eigenvectorBasisSym33 !-------------------------------------------------------------------------------------------------- @@ -2083,7 +2112,7 @@ function math_rotationalPart33(m) real(pReal), dimension(3,3) :: math_rotationalPart33 real(pReal), dimension(3,3) :: U , Uinv - U = math_spectralDecompositionSym33(math_mul33x33(transpose(m),m)) + U = math_eigenvectorBasisSym33(math_mul33x33(transpose(m),m)) Uinv = math_inv33(U) if (all(abs(Uinv) <= tiny(Uinv))) then ! math_inv33 returns zero when failed, avoid floating point equality comparison @@ -2143,7 +2172,7 @@ function math_eigenvaluesSym33(m) P = invariants(2)-invariants(1)**2.0_pReal/3.0_pReal Q = -2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+product(invariants(1:2))/3.0_pReal-invariants(3) - if(any(abs([p,q]) < TOL)) then + if(all(abs([P,Q]) < TOL)) then math_eigenvaluesSym33 = math_eigenvaluesSym(m) else rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal diff --git a/code/plastic_disloUCLA.f90 b/code/plastic_disloUCLA.f90 index d95a5e6a4..c9e3bc846 100644 --- a/code/plastic_disloUCLA.f90 +++ b/code/plastic_disloUCLA.f90 @@ -1207,13 +1207,11 @@ subroutine plastic_disloUCLA_LpAndItsTangent(Lp,dLp_dTstar99,Tstar_v,Temperature math_Plain3333to99, & math_Mandel6to33, & math_Mandel33to6, & - math_spectralDecompositionSym33, & math_symmetric33, & math_mul33x3 use material, only: & material_phase, & phase_plasticityInstance, & - !plasticState, & phaseAt, phasememberAt use lattice, only: & lattice_Sslip, & From 43270e0ad2cafce75a1d0ca867f8f844f42b6566 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 29 Feb 2016 04:22:34 +0100 Subject: [PATCH 011/134] updated version information after successful test of revision3813-1015-g3f93eb9 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b4b4acd04..2b0808084 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1002-gfc1a21e +revision3813-1015-g3f93eb9 From a7665bdab96caee72e52851c7dfb3c4101bef1cf Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 29 Feb 2016 14:26:06 +0100 Subject: [PATCH 012/134] removed empty line remaining from old ID string --- code/CPFEM.f90 | 2 -- code/CPFEM2.f90 | 2 -- code/DAMASK_abaqus_exp.f | 2 -- code/DAMASK_abaqus_std.f | 2 -- code/DAMASK_marc.f90 | 2 -- code/DAMASK_spectral.f90 | 2 -- code/FEsolving.f90 | 2 -- code/IO.f90 | 2 -- code/commercialFEM_fileList.f90 | 2 -- code/compilation_info.f90 | 2 -- code/constitutive.f90 | 2 -- code/core_quit.f90 | 3 --- code/crystallite.f90 | 8 +++----- code/damage_local.f90 | 2 -- code/damage_none.f90 | 2 -- code/damage_nonlocal.f90 | 2 -- code/debug.f90 | 2 -- code/homogenization.f90 | 2 -- code/homogenization_RGC.f90 | 2 -- code/homogenization_isostrain.f90 | 2 -- code/homogenization_none.f90 | 2 -- code/hydrogenflux_cahnhilliard.f90 | 2 -- code/hydrogenflux_isoconc.f90 | 2 -- code/kinematics_cleavage_opening.f90 | 6 ++---- code/kinematics_hydrogen_strain.f90 | 2 -- code/kinematics_slipplane_opening.f90 | 2 -- code/kinematics_thermal_expansion.f90 | 2 -- code/kinematics_vacancy_strain.f90 | 2 -- code/lattice.f90 | 2 -- code/libs.f90 | 2 -- code/material.f90 | 2 -- code/math.f90 | 2 -- code/mesh.f90 | 2 -- code/numerics.f90 | 2 -- code/plastic_disloUCLA.f90 | 2 -- code/plastic_dislotwin.f90 | 2 -- code/plastic_isotropic.f90 | 2 -- code/plastic_j2.f90 | 2 -- code/plastic_none.f90 | 2 -- code/plastic_nonlocal.f90 | 2 -- code/plastic_phenoplus.f90 | 8 +++----- code/plastic_phenopowerlaw.f90 | 2 -- code/plastic_titanmod.f90 | 2 -- code/porosity_none.f90 | 2 -- code/porosity_phasefield.f90 | 2 -- code/prec.f90 | 2 -- code/source_damage_anisoBrittle.f90 | 6 ++---- code/source_damage_anisoDuctile.f90 | 2 -- code/source_damage_isoBrittle.f90 | 2 -- code/source_damage_isoDuctile.f90 | 6 ++---- code/source_thermal_dissipation.f90 | 2 -- code/source_thermal_externalheat.f90 | 2 -- code/source_vacancy_irradiation.f90 | 2 -- code/source_vacancy_phenoplasticity.f90 | 2 -- code/source_vacancy_thermalfluc.f90 | 2 -- code/spectral_damage.f90 | 2 -- code/spectral_interface.f90 | 2 -- code/spectral_mech_AL.f90 | 2 -- code/spectral_mech_Basic.f90 | 2 -- code/spectral_mech_Polarisation.f90 | 2 -- code/spectral_thermal.f90 | 2 -- code/spectral_utilities.f90 | 2 -- code/thermal_adiabatic.f90 | 2 -- code/thermal_conduction.f90 | 2 -- code/thermal_isothermal.f90 | 2 -- code/vacancyflux_cahnhilliard.f90 | 2 -- code/vacancyflux_isochempot.f90 | 2 -- code/vacancyflux_isoconc.f90 | 2 -- 68 files changed, 12 insertions(+), 149 deletions(-) diff --git a/code/CPFEM.f90 b/code/CPFEM.f90 index 91c3eaa6f..0774fba86 100644 --- a/code/CPFEM.f90 +++ b/code/CPFEM.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief CPFEM engine diff --git a/code/CPFEM2.f90 b/code/CPFEM2.f90 index ea5691495..51a26dc55 100644 --- a/code/CPFEM2.f90 +++ b/code/CPFEM2.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id: CPFEM.f90 4761 2016-01-17 13:29:42Z MPIE\m.diehl $ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief needs a good name and description diff --git a/code/DAMASK_abaqus_exp.f b/code/DAMASK_abaqus_exp.f index eff898e3e..1fab2472d 100644 --- a/code/DAMASK_abaqus_exp.f +++ b/code/DAMASK_abaqus_exp.f @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Koen Janssens, Paul Scherrer Institut diff --git a/code/DAMASK_abaqus_std.f b/code/DAMASK_abaqus_std.f index faec60650..cdd12dac8 100644 --- a/code/DAMASK_abaqus_std.f +++ b/code/DAMASK_abaqus_std.f @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Koen Janssens, Paul Scherrer Institut diff --git a/code/DAMASK_marc.f90 b/code/DAMASK_marc.f90 index 14dcc5c06..fa96ea9f8 100644 --- a/code/DAMASK_marc.f90 +++ b/code/DAMASK_marc.f90 @@ -1,5 +1,3 @@ -#define QUOTE(x) #x -#define PASTE(x,y) x ## y #ifndef INT #define INT 4 diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index 0d83d1279..728b0fd6c 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/FEsolving.f90 b/code/FEsolving.f90 index ed11448d7..3b0aeb194 100644 --- a/code/FEsolving.f90 +++ b/code/FEsolving.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief triggering reading in of restart information when doing a restart diff --git a/code/IO.f90 b/code/IO.f90 index 95ac6fffd..1a36269c5 100644 --- a/code/IO.f90 +++ b/code/IO.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/commercialFEM_fileList.f90 b/code/commercialFEM_fileList.f90 index 8567da5b1..7d02eadfc 100644 --- a/code/commercialFEM_fileList.f90 +++ b/code/commercialFEM_fileList.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief all DAMASK files without solver !> @details List of files needed by MSC.Marc, Abaqus/Explicit, and Abaqus/Standard diff --git a/code/compilation_info.f90 b/code/compilation_info.f90 index 64e6b136c..3fc12f1ee 100644 --- a/code/compilation_info.f90 +++ b/code/compilation_info.f90 @@ -1,5 +1,3 @@ -!############################################################## -!$Id$ #ifdef __GFORTRAN__ write(6,*) 'Compiled with ', compiler_version() !not supported by and ifort <= 15 (and old gfortran) write(6,*) 'With options ', compiler_options() diff --git a/code/constitutive.f90 b/code/constitutive.f90 index 50c77b481..93fb9f577 100644 --- a/code/constitutive.f90 +++ b/code/constitutive.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief elasticity, plasticity, internal microstructure state diff --git a/code/core_quit.f90 b/code/core_quit.f90 index 8446e77c8..3a730c82d 100644 --- a/code/core_quit.f90 +++ b/code/core_quit.f90 @@ -1,6 +1,3 @@ -!################################################################################################## -! $Id$ -!################################################################################################## !******************************************************************** ! quit subroutine to satisfy IO_error for core module ! diff --git a/code/crystallite.f90 b/code/crystallite.f90 index 6ca40ffef..53378a70d 100644 --- a/code/crystallite.f90 +++ b/code/crystallite.f90 @@ -1,10 +1,8 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH +!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH -!> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH -!> @author Chen Zhang, Michigan State University +!> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH +!> @author Chen Zhang, Michigan State University !> @brief crystallite state integration functions and reporting of results !-------------------------------------------------------------------------------------------------- diff --git a/code/damage_local.f90 b/code/damage_local.f90 index 196382c13..1437213d7 100644 --- a/code/damage_local.f90 +++ b/code/damage_local.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for locally evolving damage field !-------------------------------------------------------------------------------------------------- diff --git a/code/damage_none.f90 b/code/damage_none.f90 index 956ba5cc8..a9ecfb5de 100644 --- a/code/damage_none.f90 +++ b/code/damage_none.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for constant damage field !-------------------------------------------------------------------------------------------------- diff --git a/code/damage_nonlocal.f90 b/code/damage_nonlocal.f90 index 311570781..86805c21b 100644 --- a/code/damage_nonlocal.f90 +++ b/code/damage_nonlocal.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for non-locally evolving damage field !> @details to be done diff --git a/code/debug.f90 b/code/debug.f90 index 2a9c6d800..01020dd39 100644 --- a/code/debug.f90 +++ b/code/debug.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/homogenization.f90 b/code/homogenization.f90 index 00186ff06..cbc2a5915 100644 --- a/code/homogenization.f90 +++ b/code/homogenization.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Denny Tjahjanto, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/homogenization_RGC.f90 b/code/homogenization_RGC.f90 index 323ca2934..0919b1e5e 100644 --- a/code/homogenization_RGC.f90 +++ b/code/homogenization_RGC.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Denny Tjahjanto, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/homogenization_isostrain.f90 b/code/homogenization_isostrain.f90 index 083107d9f..b12e30ab3 100644 --- a/code/homogenization_isostrain.f90 +++ b/code/homogenization_isostrain.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Isostrain (full constraint Taylor assuption) homogenization scheme diff --git a/code/homogenization_none.f90 b/code/homogenization_none.f90 index 59e483c27..7f9518e90 100644 --- a/code/homogenization_none.f90 +++ b/code/homogenization_none.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/hydrogenflux_cahnhilliard.f90 b/code/hydrogenflux_cahnhilliard.f90 index d8cb71edc..898e7ed8d 100644 --- a/code/hydrogenflux_cahnhilliard.f90 +++ b/code/hydrogenflux_cahnhilliard.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for conservative transport of solute hydrogen !> @details to be done diff --git a/code/hydrogenflux_isoconc.f90 b/code/hydrogenflux_isoconc.f90 index 74759d4c3..b4bcfb5e3 100644 --- a/code/hydrogenflux_isoconc.f90 +++ b/code/hydrogenflux_isoconc.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for constant hydrogen concentration !-------------------------------------------------------------------------------------------------- diff --git a/code/kinematics_cleavage_opening.f90 b/code/kinematics_cleavage_opening.f90 index 945e2d08a..8ac1a5646 100644 --- a/code/kinematics_cleavage_opening.f90 +++ b/code/kinematics_cleavage_opening.f90 @@ -1,8 +1,6 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating kinematics resulting from opening of cleavage planes !> @details to be done !-------------------------------------------------------------------------------------------------- diff --git a/code/kinematics_hydrogen_strain.f90 b/code/kinematics_hydrogen_strain.f90 index ceb3b1ef3..154b97e79 100644 --- a/code/kinematics_hydrogen_strain.f90 +++ b/code/kinematics_hydrogen_strain.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating kinematics resulting from interstitial hydrogen !> @details to be done diff --git a/code/kinematics_slipplane_opening.f90 b/code/kinematics_slipplane_opening.f90 index 8b49e1cf3..60487e5b4 100644 --- a/code/kinematics_slipplane_opening.f90 +++ b/code/kinematics_slipplane_opening.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating kinematics resulting from opening of slip planes diff --git a/code/kinematics_thermal_expansion.f90 b/code/kinematics_thermal_expansion.f90 index b99c499f3..c5a221a7b 100644 --- a/code/kinematics_thermal_expansion.f90 +++ b/code/kinematics_thermal_expansion.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating kinematics resulting from thermal expansion !> @details to be done diff --git a/code/kinematics_vacancy_strain.f90 b/code/kinematics_vacancy_strain.f90 index 899bccd9f..704de7d1f 100644 --- a/code/kinematics_vacancy_strain.f90 +++ b/code/kinematics_vacancy_strain.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating kinematics resulting from vacancy point defects !> @details to be done diff --git a/code/lattice.f90 b/code/lattice.f90 index 8e87ba2a9..f5717e8e1 100644 --- a/code/lattice.f90 +++ b/code/lattice.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/libs.f90 b/code/libs.f90 index 7c109cab6..71f300512 100644 --- a/code/libs.f90 +++ b/code/libs.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief dummy source for inclusion of Library files !-------------------------------------------------------------------------------------------------- diff --git a/code/material.f90 b/code/material.f90 index c1aacf751..1afbbed28 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Parses material config file, either solverJobName.materialConfig or material.config diff --git a/code/math.f90 b/code/math.f90 index 5b4a48905..2f76c1cb5 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/mesh.f90 b/code/mesh.f90 index 1cd80a625..29bb15aef 100644 --- a/code/mesh.f90 +++ b/code/mesh.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Koords, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/numerics.f90 b/code/numerics.f90 index 61f326c02..365b078ec 100644 --- a/code/numerics.f90 +++ b/code/numerics.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Managing of parameters related to numerics diff --git a/code/plastic_disloUCLA.f90 b/code/plastic_disloUCLA.f90 index c9e3bc846..77fd84900 100644 --- a/code/plastic_disloUCLA.f90 +++ b/code/plastic_disloUCLA.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author David Cereceda, Lawrence Livermore National Laboratory diff --git a/code/plastic_dislotwin.f90 b/code/plastic_dislotwin.f90 index 1b0ae31f2..b9ffde804 100644 --- a/code/plastic_dislotwin.f90 +++ b/code/plastic_dislotwin.f90 @@ -1,5 +1,3 @@ -!-------------------------------------------------------------------------------------------------- -!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incoprorating dislocation and twinning physics !> @details to be done diff --git a/code/plastic_isotropic.f90 b/code/plastic_isotropic.f90 index 13481b9a7..fe4c7a7f5 100644 --- a/code/plastic_isotropic.f90 +++ b/code/plastic_isotropic.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for isotropic (ISOTROPIC) plasticity diff --git a/code/plastic_j2.f90 b/code/plastic_j2.f90 index 89c022cc9..4d247677b 100644 --- a/code/plastic_j2.f90 +++ b/code/plastic_j2.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for isotropic (J2) plasticity diff --git a/code/plastic_none.f90 b/code/plastic_none.f90 index f624a80a2..a9007667f 100644 --- a/code/plastic_none.f90 +++ b/code/plastic_none.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for purely elastic material diff --git a/code/plastic_nonlocal.f90 b/code/plastic_nonlocal.f90 index 1922c08e2..b699c57ed 100644 --- a/code/plastic_nonlocal.f90 +++ b/code/plastic_nonlocal.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/plastic_phenoplus.f90 b/code/plastic_phenoplus.f90 index 0a40edd84..0887da239 100644 --- a/code/plastic_phenoplus.f90 +++ b/code/plastic_phenoplus.f90 @@ -1,9 +1,7 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH -!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH -!> @author Chen Zhang, Michigan State University +!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH +!> @author Chen Zhang, Michigan State University !> @brief material subroutine for phenomenological crystal plasticity formulation using a powerlaw !... fitting !-------------------------------------------------------------------------------------------------- diff --git a/code/plastic_phenopowerlaw.f90 b/code/plastic_phenopowerlaw.f90 index 1f8e16250..63e078329 100644 --- a/code/plastic_phenopowerlaw.f90 +++ b/code/plastic_phenopowerlaw.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for phenomenological crystal plasticity formulation using a powerlaw diff --git a/code/plastic_titanmod.f90 b/code/plastic_titanmod.f90 index abc6d661b..24bf543b7 100644 --- a/code/plastic_titanmod.f90 +++ b/code/plastic_titanmod.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Alankar Alankar, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/porosity_none.f90 b/code/porosity_none.f90 index 69f10a5c6..92d4d9fe5 100644 --- a/code/porosity_none.f90 +++ b/code/porosity_none.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for constant porosity !-------------------------------------------------------------------------------------------------- diff --git a/code/porosity_phasefield.f90 b/code/porosity_phasefield.f90 index dc8b82b76..ec7e4c341 100644 --- a/code/porosity_phasefield.f90 +++ b/code/porosity_phasefield.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for phase field modelling of pore nucleation and growth !> @details phase field model for pore nucleation and growth based on vacancy clustering diff --git a/code/prec.f90 b/code/prec.f90 index e39a32cfa..0f22cf649 100644 --- a/code/prec.f90 +++ b/code/prec.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/source_damage_anisoBrittle.f90 b/code/source_damage_anisoBrittle.f90 index a751eefdc..efd76091e 100644 --- a/code/source_damage_anisoBrittle.f90 +++ b/code/source_damage_anisoBrittle.f90 @@ -1,8 +1,6 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating anisotropic brittle damage source mechanism !> @details to be done !-------------------------------------------------------------------------------------------------- diff --git a/code/source_damage_anisoDuctile.f90 b/code/source_damage_anisoDuctile.f90 index 028fd479a..72480382a 100644 --- a/code/source_damage_anisoDuctile.f90 +++ b/code/source_damage_anisoDuctile.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incorporating anisotropic ductile damage source mechanism diff --git a/code/source_damage_isoBrittle.f90 b/code/source_damage_isoBrittle.f90 index c063ae86f..1603ecf48 100644 --- a/code/source_damage_isoBrittle.f90 +++ b/code/source_damage_isoBrittle.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incoprorating isotropic brittle damage source mechanism diff --git a/code/source_damage_isoDuctile.f90 b/code/source_damage_isoDuctile.f90 index b0290264c..3a85bab24 100644 --- a/code/source_damage_isoDuctile.f90 +++ b/code/source_damage_isoDuctile.f90 @@ -1,8 +1,6 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine incoprorating isotropic ductile damage source mechanism !> @details to be done !-------------------------------------------------------------------------------------------------- diff --git a/code/source_thermal_dissipation.f90 b/code/source_thermal_dissipation.f90 index 83ad85167..dd6453db0 100644 --- a/code/source_thermal_dissipation.f90 +++ b/code/source_thermal_dissipation.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for thermal source due to plastic dissipation !> @details to be done diff --git a/code/source_thermal_externalheat.f90 b/code/source_thermal_externalheat.f90 index 257012c06..203826205 100644 --- a/code/source_thermal_externalheat.f90 +++ b/code/source_thermal_externalheat.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for thermal source due to plastic dissipation !> @details to be done diff --git a/code/source_vacancy_irradiation.f90 b/code/source_vacancy_irradiation.f90 index c4bcfba04..fd7220020 100644 --- a/code/source_vacancy_irradiation.f90 +++ b/code/source_vacancy_irradiation.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for vacancy generation due to irradiation !> @details to be done diff --git a/code/source_vacancy_phenoplasticity.f90 b/code/source_vacancy_phenoplasticity.f90 index f9e766b2c..2690cf691 100644 --- a/code/source_vacancy_phenoplasticity.f90 +++ b/code/source_vacancy_phenoplasticity.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for vacancy generation due to plasticity !> @details to be done diff --git a/code/source_vacancy_thermalfluc.f90 b/code/source_vacancy_thermalfluc.f90 index c86406430..5891ff764 100644 --- a/code/source_vacancy_thermalfluc.f90 +++ b/code/source_vacancy_thermalfluc.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for vacancy generation due to thermal fluctuations !> @details to be done diff --git a/code/spectral_damage.f90 b/code/spectral_damage.f90 index 0b79d5e5d..e2bb80b31 100644 --- a/code/spectral_damage.f90 +++ b/code/spectral_damage.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id: spectral_damage.f90 4082 2015-04-11 20:28:07Z MPIE\m.diehl $ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Shaokang Zhang, Max-Planck-Institut für Eisenforschung GmbH !> @brief Spectral solver for nonlocal damage diff --git a/code/spectral_interface.f90 b/code/spectral_interface.f90 index b24c5f747..ad0ee4082 100644 --- a/code/spectral_interface.f90 +++ b/code/spectral_interface.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Interfacing between the spectral solver and the material subroutines provided diff --git a/code/spectral_mech_AL.f90 b/code/spectral_mech_AL.f90 index a937dcc86..b6a8c9353 100644 --- a/code/spectral_mech_AL.f90 +++ b/code/spectral_mech_AL.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/spectral_mech_Basic.f90 b/code/spectral_mech_Basic.f90 index a8344fabe..358a095d1 100644 --- a/code/spectral_mech_Basic.f90 +++ b/code/spectral_mech_Basic.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/spectral_mech_Polarisation.f90 b/code/spectral_mech_Polarisation.f90 index a28eb5adb..d7f1599e5 100644 --- a/code/spectral_mech_Polarisation.f90 +++ b/code/spectral_mech_Polarisation.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH diff --git a/code/spectral_thermal.f90 b/code/spectral_thermal.f90 index 843642394..83e290a4c 100644 --- a/code/spectral_thermal.f90 +++ b/code/spectral_thermal.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id: spectral_thermal.f90 4082 2015-04-11 20:28:07Z MPIE\m.diehl $ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Shaokang Zhang, Max-Planck-Institut für Eisenforschung GmbH !> @brief Spectral solver for thermal conduction diff --git a/code/spectral_utilities.f90 b/code/spectral_utilities.f90 index f547a98aa..8344ff7ce 100644 --- a/code/spectral_utilities.f90 +++ b/code/spectral_utilities.f90 @@ -1,5 +1,3 @@ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Utilities used by the different spectral solver variants diff --git a/code/thermal_adiabatic.f90 b/code/thermal_adiabatic.f90 index 7bb8620e7..e2d26fbb1 100644 --- a/code/thermal_adiabatic.f90 +++ b/code/thermal_adiabatic.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for adiabatic temperature evolution !> @details to be done diff --git a/code/thermal_conduction.f90 b/code/thermal_conduction.f90 index 2f9b766eb..c85923050 100644 --- a/code/thermal_conduction.f90 +++ b/code/thermal_conduction.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for temperature evolution from heat conduction !> @details to be done diff --git a/code/thermal_isothermal.f90 b/code/thermal_isothermal.f90 index 8c9d3a782..a3ac8f685 100644 --- a/code/thermal_isothermal.f90 +++ b/code/thermal_isothermal.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for isothermal temperature field !-------------------------------------------------------------------------------------------------- diff --git a/code/vacancyflux_cahnhilliard.f90 b/code/vacancyflux_cahnhilliard.f90 index 16a380ffc..be68e24a0 100644 --- a/code/vacancyflux_cahnhilliard.f90 +++ b/code/vacancyflux_cahnhilliard.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for conservative transport of vacancy concentration field !> @details to be done diff --git a/code/vacancyflux_isochempot.f90 b/code/vacancyflux_isochempot.f90 index 35db8d159..286eb37b7 100644 --- a/code/vacancyflux_isochempot.f90 +++ b/code/vacancyflux_isochempot.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for locally evolving vacancy concentration !> @details to be done diff --git a/code/vacancyflux_isoconc.f90 b/code/vacancyflux_isoconc.f90 index 63cfb1b62..c32cb648d 100644 --- a/code/vacancyflux_isoconc.f90 +++ b/code/vacancyflux_isoconc.f90 @@ -1,6 +1,4 @@ !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for constant vacancy concentration !-------------------------------------------------------------------------------------------------- From 54d0a0a70414bba1d1967721bf6a4a2e718d6c3f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 10:58:52 +0100 Subject: [PATCH 013/134] some important lines got lost during last commit --- code/DAMASK_marc.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/DAMASK_marc.f90 b/code/DAMASK_marc.f90 index fa96ea9f8..a4542f96a 100644 --- a/code/DAMASK_marc.f90 +++ b/code/DAMASK_marc.f90 @@ -1,3 +1,5 @@ +#define QUOTE(x) #x +#define PASTE(x,y) x ## y #ifndef INT #define INT 4 @@ -9,8 +11,6 @@ #include "prec.f90" !-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Luc Hantcherli, Max-Planck-Institut für Eisenforschung GmbH @@ -421,4 +421,4 @@ subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,layer,ndi,nshear,jpltcd) if (jpltcd > materialpoint_sizeResults) call IO_error(700_pInt,jpltcd) ! complain about out of bounds error v = materialpoint_results(jpltcd,nn,mesh_FEasCP('elem', m)) -end subroutine plotv +end subroutine plotv \ No newline at end of file From 3594f0ef477cc5dc43135bffae72fcfd60c5688b Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 1 Mar 2016 16:20:53 +0100 Subject: [PATCH 014/134] updated version information after successful test of revision3813-1018-g54d0a0a --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2b0808084..096cd6ab1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1015-g3f93eb9 +revision3813-1018-g54d0a0a From 2a50c6bf8607ed8250a5f56d9e944faafd50b0c2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 18:25:14 +0100 Subject: [PATCH 015/134] using prospector --tool=dodgy --tool=pyflakes -M to find python flaws --- processing/post/3Dvisualize.py | 2 +- processing/post/addAPS34IDEstrainCoords.py | 2 +- processing/post/addCalculation.py | 4 ++-- processing/post/addCauchy.py | 2 +- processing/post/addCauchyX.py | 3 +-- processing/post/addCompatibilityMismatch.py | 2 +- processing/post/addCumulative.py | 2 +- processing/post/addCurl.py | 2 +- processing/post/addDeformedConfiguration.py | 2 +- processing/post/addDeterminant.py | 2 +- processing/post/addDeviator.py | 2 +- processing/post/addDivergence.py | 2 +- processing/post/addEhkl.py | 2 +- processing/post/addEuclideanDistance.py | 2 +- processing/post/addGrainID.py | 2 +- processing/post/addIPFcolor.py | 2 +- processing/post/addMapped.py | 2 +- processing/post/addMises.py | 2 +- processing/post/addNorm.py | 2 +- processing/post/addOrientations.py | 2 +- processing/post/addPK2.py | 2 +- processing/post/addPole.py | 2 +- processing/post/addQuaternions.py | 2 +- processing/post/addSchmidfactors.py | 2 +- processing/post/addSpectralDecomposition.py | 2 +- processing/post/addStrainTensors.py | 2 +- processing/post/addTable.py | 2 +- processing/post/averageDown.py | 2 +- processing/post/averageTable.py | 2 +- processing/post/binXY.py | 2 +- processing/post/blowUp.py | 11 ++++++++--- processing/post/fillTable.py | 3 ++- processing/post/filterTable.py | 3 ++- processing/post/imageData.py | 2 +- processing/post/imageDataDeformed.py | 2 +- processing/post/imageDataRGB.py | 2 +- processing/post/mentat_colorMap.py | 2 +- processing/post/perceptualUniformColorMap.py | 2 +- processing/post/permuteData.py | 2 +- processing/post/reLabel.py | 2 +- processing/post/rotateData.py | 2 +- processing/post/sortTable.py | 2 +- processing/post/stddevDown.py | 4 ---- processing/post/vtk_addData.py | 2 +- processing/post/vtk_addPointcloudData.py | 2 +- processing/post/vtk_addRectilinearGridData.py | 2 +- processing/post/vtk_addVoxelcloudData.py | 2 +- processing/post/vtk_pointcloud.py | 2 +- processing/post/vtk_scalars2vectors.py | 2 +- 49 files changed, 58 insertions(+), 56 deletions(-) diff --git a/processing/post/3Dvisualize.py b/processing/post/3Dvisualize.py index 8abfe9676..6687156b8 100755 --- a/processing/post/3Dvisualize.py +++ b/processing/post/3Dvisualize.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,re,string,fnmatch,vtk +import os,sys,re,fnmatch,vtk import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addAPS34IDEstrainCoords.py b/processing/post/addAPS34IDEstrainCoords.py index 2dcfaa98f..f90587c43 100755 --- a/processing/post/addAPS34IDEstrainCoords.py +++ b/processing/post/addAPS34IDEstrainCoords.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addCalculation.py b/processing/post/addCalculation.py index dea3932e9..f4586964b 100755 --- a/processing/post/addCalculation.py +++ b/processing/post/addCalculation.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,re,sys,string -import math # flake8: noqa +import os,re,sys +import math # noqa import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addCauchy.py b/processing/post/addCauchy.py index 4dd1843bf..3fb889eec 100755 --- a/processing/post/addCauchy.py +++ b/processing/post/addCauchy.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addCauchyX.py b/processing/post/addCauchyX.py index 982bb6961..ddd748d29 100755 --- a/processing/post/addCauchyX.py +++ b/processing/post/addCauchyX.py @@ -1,9 +1,8 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,re,sys,math,string,h5py +import os,string,h5py import numpy as np -import damask from optparse import OptionParser, Option # ----------------------------- diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index 6c90fe0e4..6b5e704bd 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addCumulative.py b/processing/post/addCumulative.py index 2233a784e..a65677883 100755 --- a/processing/post/addCumulative.py +++ b/processing/post/addCumulative.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index 6e2affd9a..17144406e 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addDeformedConfiguration.py b/processing/post/addDeformedConfiguration.py index 0f5a5abc0..43de48e19 100755 --- a/processing/post/addDeformedConfiguration.py +++ b/processing/post/addDeformedConfiguration.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addDeterminant.py b/processing/post/addDeterminant.py index 263133bfa..c11eacc1f 100755 --- a/processing/post/addDeterminant.py +++ b/processing/post/addDeterminant.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys from optparse import OptionParser import damask diff --git a/processing/post/addDeviator.py b/processing/post/addDeviator.py index bc6319c7e..bcf1cc317 100755 --- a/processing/post/addDeviator.py +++ b/processing/post/addDeviator.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys from optparse import OptionParser import damask diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index b661b647b..35908e6a2 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addEhkl.py b/processing/post/addEhkl.py index 1e8688518..5ed585ba4 100755 --- a/processing/post/addEhkl.py +++ b/processing/post/addEhkl.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addEuclideanDistance.py b/processing/post/addEuclideanDistance.py index 8139e7536..3c15ef60b 100755 --- a/processing/post/addEuclideanDistance.py +++ b/processing/post/addEuclideanDistance.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,itertools +import os,sys,itertools import numpy as np from scipy import ndimage from optparse import OptionParser diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index 384d161ae..dd69ea1e4 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -import os,sys,string,time,copy +import os,sys,time,copy import numpy as np import damask from optparse import OptionParser diff --git a/processing/post/addIPFcolor.py b/processing/post/addIPFcolor.py index da45c1288..a66f55290 100755 --- a/processing/post/addIPFcolor.py +++ b/processing/post/addIPFcolor.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addMapped.py b/processing/post/addMapped.py index cf3419745..f2dc966ab 100755 --- a/processing/post/addMapped.py +++ b/processing/post/addMapped.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys from optparse import OptionParser import damask diff --git a/processing/post/addMises.py b/processing/post/addMises.py index 910f26c70..771cb7bc4 100755 --- a/processing/post/addMises.py +++ b/processing/post/addMises.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addNorm.py b/processing/post/addNorm.py index df2fa11f8..725321953 100755 --- a/processing/post/addNorm.py +++ b/processing/post/addNorm.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math from optparse import OptionParser import damask diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 91b4dbc8a..1f5ce14e7 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addPK2.py b/processing/post/addPK2.py index 82dc5a26c..831394935 100755 --- a/processing/post/addPK2.py +++ b/processing/post/addPK2.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addPole.py b/processing/post/addPole.py index 9228058a2..f7d64f4a5 100755 --- a/processing/post/addPole.py +++ b/processing/post/addPole.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addQuaternions.py b/processing/post/addQuaternions.py index 185d11a64..a35ab62a9 100755 --- a/processing/post/addQuaternions.py +++ b/processing/post/addQuaternions.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,numpy as np +import os,sys,numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 30d3d6f4a..c3656a9b8 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addSpectralDecomposition.py b/processing/post/addSpectralDecomposition.py index 3372e35f6..cc9bbe181 100755 --- a/processing/post/addSpectralDecomposition.py +++ b/processing/post/addSpectralDecomposition.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addStrainTensors.py b/processing/post/addStrainTensors.py index b8e1fc9cc..8cccdb2f2 100755 --- a/processing/post/addStrainTensors.py +++ b/processing/post/addStrainTensors.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/addTable.py b/processing/post/addTable.py index 1e94319b2..a0055e0b6 100755 --- a/processing/post/addTable.py +++ b/processing/post/addTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys from optparse import OptionParser import damask diff --git a/processing/post/averageDown.py b/processing/post/averageDown.py index 0632a7844..1b2b4f76b 100755 --- a/processing/post/averageDown.py +++ b/processing/post/averageDown.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np import scipy.ndimage from optparse import OptionParser diff --git a/processing/post/averageTable.py b/processing/post/averageTable.py index b3d99f49d..b74e2744f 100755 --- a/processing/post/averageTable.py +++ b/processing/post/averageTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/binXY.py b/processing/post/binXY.py index d9f0cb25a..b0118aedb 100755 --- a/processing/post/binXY.py +++ b/processing/post/binXY.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/blowUp.py b/processing/post/blowUp.py index f108da28e..04a4f91e7 100755 --- a/processing/post/blowUp.py +++ b/processing/post/blowUp.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask @@ -55,11 +55,16 @@ for name in filenames: # ------------------------------------------ read header ------------------------------------------ table.head_read() + errors = [] # ------------------------------------------ sanity checks ---------------------------------------- - if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) - else: coordCol = table.label_index(options.coords) + if table.label_dimension(options.coords) != 3: + damask.util.croak('coordinates {} are not a vector.'.format(options.coords)) + table.close(dismiss = True) + continue + else: + coordCol = table.label_index(options.coords) # ------------------------------------------ assemble header -------------------------------------- diff --git a/processing/post/fillTable.py b/processing/post/fillTable.py index 120f4eb8d..5f4a307af 100755 --- a/processing/post/fillTable.py +++ b/processing/post/fillTable.py @@ -1,7 +1,8 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,re,sys,string,fnmatch,math,random +import os,re,sys +import math # noqa import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/filterTable.py b/processing/post/filterTable.py index 87a95750c..6b936644b 100755 --- a/processing/post/filterTable.py +++ b/processing/post/filterTable.py @@ -1,7 +1,8 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,re,sys,fnmatch,math,random +import os,re,sys,fnmatch +import math # noqa import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/imageData.py b/processing/post/imageData.py index da1616e94..ca64e04fe 100755 --- a/processing/post/imageData.py +++ b/processing/post/imageData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser from PIL import Image diff --git a/processing/post/imageDataDeformed.py b/processing/post/imageDataDeformed.py index 692d377f4..c538627d7 100755 --- a/processing/post/imageDataDeformed.py +++ b/processing/post/imageDataDeformed.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser from PIL import Image, ImageDraw diff --git a/processing/post/imageDataRGB.py b/processing/post/imageDataRGB.py index 69310f529..f96ebf05d 100755 --- a/processing/post/imageDataRGB.py +++ b/processing/post/imageDataRGB.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser from PIL import Image diff --git a/processing/post/mentat_colorMap.py b/processing/post/mentat_colorMap.py index 8e630df9d..9b4c4c828 100755 --- a/processing/post/mentat_colorMap.py +++ b/processing/post/mentat_colorMap.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os, sys, string +import os,sys import damask from optparse import OptionParser diff --git a/processing/post/perceptualUniformColorMap.py b/processing/post/perceptualUniformColorMap.py index f84928f23..7a1ff3c50 100755 --- a/processing/post/perceptualUniformColorMap.py +++ b/processing/post/perceptualUniformColorMap.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import string,sys,os +import sys,os import damask from optparse import OptionParser diff --git a/processing/post/permuteData.py b/processing/post/permuteData.py index f873ca447..c85805d29 100755 --- a/processing/post/permuteData.py +++ b/processing/post/permuteData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/reLabel.py b/processing/post/reLabel.py index d74080efb..b1f8b898b 100755 --- a/processing/post/reLabel.py +++ b/processing/post/reLabel.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import damask from optparse import OptionParser diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 42e24579a..67dc9c662 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/sortTable.py b/processing/post/sortTable.py index 4735062dc..aa2d1ed48 100755 --- a/processing/post/sortTable.py +++ b/processing/post/sortTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask diff --git a/processing/post/stddevDown.py b/processing/post/stddevDown.py index 880961511..e14ee0058 100755 --- a/processing/post/stddevDown.py +++ b/processing/post/stddevDown.py @@ -144,16 +144,12 @@ for file in files: posOffset = (shift+[0.5,0.5,0.5])*dimension/resolution elementSize = dimension/resolution*packing - elem = 1 for c in xrange(downSized[2]): for b in xrange(downSized[1]): for a in xrange(downSized[0]): datavar[a,b,c,locationCol:locationCol+3] = posOffset + [a,b,c]*elementSize - datavar[a,b,c,elemCol] = elem table.data = datavar[a,b,c,:].tolist() table.data_write() # output processed line - elem += 1 - # ------------------------------------------ output result --------------------------------------- diff --git a/processing/post/vtk_addData.py b/processing/post/vtk_addData.py index b93f6e174..2e44714ca 100755 --- a/processing/post/vtk_addData.py +++ b/processing/post/vtk_addData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,string,glob,re +import os,glob,re import damask from optparse import OptionParser diff --git a/processing/post/vtk_addPointcloudData.py b/processing/post/vtk_addPointcloudData.py index 2dfbdd144..c0dafd63a 100755 --- a/processing/post/vtk_addPointcloudData.py +++ b/processing/post/vtk_addPointcloudData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys,vtk import damask from optparse import OptionParser diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index b1e35d2cd..1ab2c1db1 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,vtk import damask from collections import defaultdict from optparse import OptionParser diff --git a/processing/post/vtk_addVoxelcloudData.py b/processing/post/vtk_addVoxelcloudData.py index 61dfb0581..67e679cde 100755 --- a/processing/post/vtk_addVoxelcloudData.py +++ b/processing/post/vtk_addVoxelcloudData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys,vtk import damask from collections import defaultdict from optparse import OptionParser diff --git a/processing/post/vtk_pointcloud.py b/processing/post/vtk_pointcloud.py index b49c75c10..5f7c5c904 100755 --- a/processing/post/vtk_pointcloud.py +++ b/processing/post/vtk_pointcloud.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys,vtk import numpy as np import damask from optparse import OptionParser diff --git a/processing/post/vtk_scalars2vectors.py b/processing/post/vtk_scalars2vectors.py index 72b59588c..5b1ede858 100755 --- a/processing/post/vtk_scalars2vectors.py +++ b/processing/post/vtk_scalars2vectors.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,shutil +import os,sys,shutil import damask from optparse import OptionParser from vtk import * From 3b33d320b18be1a8742c858c034e72b0244aee50 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 19:06:00 +0100 Subject: [PATCH 016/134] getting pyflakes to ignore --- processing/post/addCalculation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/post/addCalculation.py b/processing/post/addCalculation.py index f4586964b..60732fd82 100755 --- a/processing/post/addCalculation.py +++ b/processing/post/addCalculation.py @@ -2,7 +2,7 @@ # -*- coding: UTF-8 no BOM -*- import os,re,sys -import math # noqa +import math # noqa import numpy as np from optparse import OptionParser import damask From 6eb170bc0754768c7661f3d5036cb0cb3be6c271 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 19:37:31 +0100 Subject: [PATCH 017/134] still struggling with prospector --- processing/post/addCalculation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/post/addCalculation.py b/processing/post/addCalculation.py index 60732fd82..f4586964b 100755 --- a/processing/post/addCalculation.py +++ b/processing/post/addCalculation.py @@ -2,7 +2,7 @@ # -*- coding: UTF-8 no BOM -*- import os,re,sys -import math # noqa +import math # noqa import numpy as np from optparse import OptionParser import damask From e55d0ae3ca57b3bbecc04fc46d18bd91a79d7198 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 20:44:43 +0100 Subject: [PATCH 018/134] further attemps to make it conform with best python practice --- processing/post/3Dvisualize.py | 14 +++++----- processing/post/addAPS34IDEstrainCoords.py | 12 ++++----- processing/post/addCalculation.py | 4 +-- processing/post/addCauchyX.py | 30 +++------------------ processing/post/addCompatibilityMismatch.py | 5 ++-- processing/post/addCurl.py | 8 +++--- processing/post/addDeformedConfiguration.py | 6 ++--- processing/post/addDeterminant.py | 4 +-- processing/post/addDeviator.py | 6 ++--- processing/post/addDivergence.py | 12 ++++----- processing/post/addEhkl.py | 4 +-- processing/post/addEuclideanDistance.py | 6 ++--- processing/post/addGrainID.py | 16 +++++------ 13 files changed, 51 insertions(+), 76 deletions(-) diff --git a/processing/post/3Dvisualize.py b/processing/post/3Dvisualize.py index 6687156b8..c18fbb694 100755 --- a/processing/post/3Dvisualize.py +++ b/processing/post/3Dvisualize.py @@ -56,8 +56,7 @@ def unravel(item): # ++++++++++++++++++++++++++++++++++++++++++++++++++++ def vtk_writeASCII_mesh(mesh,data,res,sep): -# ++++++++++++++++++++++++++++++++++++++++++++++++++++ - """ function writes data array defined on a hexahedral mesh (geometry) """ + """function writes data array defined on a hexahedral mesh (geometry)""" info = {\ 'tensor': {'name':'tensor','len':9},\ 'vector': {'name':'vector','len':3},\ @@ -110,11 +109,10 @@ def vtk_writeASCII_mesh(mesh,data,res,sep): ] return cmds - -# +++++++++++++++++++++++++++++++++++++++++++++++++++ + +#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def vtk_writeASCII_points(coordinates,data,res,sep): -# +++++++++++++++++++++++++++++++++++++++++++++++++++ - """ function writes data array defined on a point field """ + """function writes data array defined on a point field""" N = res[0]*res[1]*res[2] cmds = [\ @@ -216,7 +214,7 @@ for filename in args: content = file.readlines() file.close() m = re.search('(\d+)\s*head', content[0].lower()) - if m == None: + if m is None: continue print filename,'\n' sys.stdout.flush() @@ -432,4 +430,4 @@ for filename in args: vtk = open(os.path.join(head,what+'_'+os.path.splitext(tail)[0]+'.vtk'), 'w') output(out[what],{'filepointer':vtk},'File') vtk.close() - print + print \ No newline at end of file diff --git a/processing/post/addAPS34IDEstrainCoords.py b/processing/post/addAPS34IDEstrainCoords.py index f90587c43..0258606ca 100755 --- a/processing/post/addAPS34IDEstrainCoords.py +++ b/processing/post/addAPS34IDEstrainCoords.py @@ -19,13 +19,13 @@ Transform X,Y,Z,F APS BeamLine 34 coordinates to x,y,z APS strain coordinates. """, version = scriptID) -parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='', +parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='string string string string', help='APS X,Y,Z coords, and depth F') parser.set_defaults(frame = None) (options,filenames) = parser.parse_args() -if options.frame == None: +if options.frame is None: parser.error('no data column specified...') @@ -33,7 +33,7 @@ datainfo = {'len':3, 'label':[] } -if options.frame != None: datainfo['label'] += options.frame +datainfo['label'] += options.frame # --- loop over input files ------------------------------------------------------------------------- if filenames == []: @@ -75,8 +75,8 @@ for name in filenames: # ------------------------------------------ process data ------------------------------------------ theta=-0.75*np.pi RotMat2TSL=np.array([[1., 0., 0.], - [0., np.cos(theta), np.sin(theta)], - [0., -np.sin(theta), np.cos(theta)]]) # Orientation Matrix to account for -135 degree rotation for TSL Convention[Adapted from Chen Zhang's code] + [0., np.cos(theta), np.sin(theta)], # Orientation to account for -135 deg + [0., -np.sin(theta), np.cos(theta)]]) # rotation for TSL convention vec = np.zeros(4) outputAlive = True @@ -94,4 +94,4 @@ for name in filenames: table.input_close() # close input ASCII table (works for stdin) table.output_close() # close output ASCII table (works for stdout) if file['name'] != 'STDIN': - os.rename(file['name']+'_tmp',file['name']) # overwrite old one with tmp new + os.rename(file['name']+'_tmp',file['name']) # overwrite old one with tmp new \ No newline at end of file diff --git a/processing/post/addCalculation.py b/processing/post/addCalculation.py index f4586964b..7d7727a18 100755 --- a/processing/post/addCalculation.py +++ b/processing/post/addCalculation.py @@ -39,7 +39,7 @@ parser.add_option('-f','--formula', (options,filenames) = parser.parse_args() -if options.labels == None or options.formulas == None: +if options.labels is None or options.formulas is None: parser.error('no formulas and/or labels specified.') if len(options.labels) != len(options.formulas): parser.error('number of labels ({}) and formulas ({}) do not match.'.format(len(options.labels),len(options.formulas))) @@ -126,4 +126,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables + table.close() # close ASCII tables \ No newline at end of file diff --git a/processing/post/addCauchyX.py b/processing/post/addCauchyX.py index ddd748d29..dc94e2a2e 100755 --- a/processing/post/addCauchyX.py +++ b/processing/post/addCauchyX.py @@ -3,33 +3,14 @@ import os,string,h5py import numpy as np -from optparse import OptionParser, Option - -# ----------------------------- -class extendableOption(Option): -# ----------------------------- -# used for definition of new option parser action 'extend', which enables to take multiple option arguments -# taken from online tutorial http://docs.python.org/library/optparse.html - - ACTIONS = Option.ACTIONS + ("extend",) - STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) - TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) - ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) - - def take_action(self, action, dest, opt, value, values, parser): - if action == "extend": - lvalue = value.split(",") - values.ensure_value(dest, []).extend(lvalue) - else: - Option.take_action(self, action, dest, opt, value, values, parser) - - +from optparse import OptionParser +import damask # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ Add column(s) containing Cauchy stress based on given column(s) of deformation gradient and first Piola--Kirchhoff stress. @@ -49,7 +30,7 @@ parser.set_defaults(output = 'crystallite') (options,filenames) = parser.parse_args() -if options.defgrad == None or options.stress == None or options.output == None: +if options.defgrad is None or options.stress is None or options.output is None: parser.error('missing data column...') @@ -78,6 +59,3 @@ for myFile in files: cauchy[p,...] = 1.0/np.linalg.det(defgrad[p,...])*np.dot(stress[p,...],defgrad[p,...].T) # [Cauchy] = (1/det(F)) * [P].[F_transpose] cauchyFile = myFile['file']['increments/'+inc+'/'+options.output+'/'+instance].create_dataset('cauchy', data=cauchy) cauchyFile.attrs['units'] = 'Pa' - - - diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index 6b5e704bd..1753cb923 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -81,7 +81,6 @@ for name in filenames: table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) if options.shape: table.labels_append('shapeMismatch({})'.format(options.defgrad)) if options.volume: table.labels_append('volMismatch({})'.format(options.defgrad)) - #table.head_write() # --------------- figure out size and grid --------------------------------------------------------- @@ -92,7 +91,7 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings N = grid.prod() @@ -138,4 +137,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables + table.close() # close ASCII tables \ No newline at end of file diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index 17144406e..ac9715c36 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -92,7 +92,7 @@ parser.set_defaults(coords = 'ipinitialcoord', (options,filenames) = parser.parse_args() -if options.vector == None and options.tensor == None: +if options.vector is None and options.tensor is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- @@ -161,9 +161,9 @@ for name in filenames: stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(curlFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation - table.data[:,data['column'][i]:data['column'][i]+data['dim']].\ - reshape([grid[2],grid[1],grid[0]]+data['shape']))) + stack.append(curlFFT(size[::-1], # we need to reverse order here, because x + table.data[:,data['column'][i]:data['column'][i]+data['dim']]. # is fastest,ie rightmost, but leftmost in + reshape([grid[2],grid[1],grid[0]]+data['shape']))) # our x,y,z notation # ------------------------------------------ output result ----------------------------------------- diff --git a/processing/post/addDeformedConfiguration.py b/processing/post/addDeformedConfiguration.py index 43de48e19..3fb39ee0d 100755 --- a/processing/post/addDeformedConfiguration.py +++ b/processing/post/addDeformedConfiguration.py @@ -11,7 +11,7 @@ scriptID = ' '.join([scriptName,damask.version]) #-------------------------------------------------------------------------------------------------- def deformedCoordsFFT(F,undeformed=False): -#-------------------------------------------------------------------------------------------------- + wgt = 1.0/grid.prod() integrator = np.array([0.+1.j,0.+1.j,0.+1.j],'c16') * size/ 2.0 / math.pi step = size/grid @@ -127,7 +127,7 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings N = grid.prod() @@ -161,4 +161,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables + table.close() # close ASCII tables \ No newline at end of file diff --git a/processing/post/addDeterminant.py b/processing/post/addDeterminant.py index c11eacc1f..c537e5bd0 100755 --- a/processing/post/addDeterminant.py +++ b/processing/post/addDeterminant.py @@ -32,7 +32,7 @@ parser.add_option('-t','--tensor', (options,filenames) = parser.parse_args() -if options.tensor == None: +if options.tensor is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- @@ -89,4 +89,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) + table.close() # close input ASCII table (works for stdin) \ No newline at end of file diff --git a/processing/post/addDeviator.py b/processing/post/addDeviator.py index bcf1cc317..492f44c70 100755 --- a/processing/post/addDeviator.py +++ b/processing/post/addDeviator.py @@ -10,7 +10,7 @@ scriptID = ' '.join([scriptName,damask.version]) oneThird = 1.0/3.0 -def deviator(m,spherical = False): # Carefull, do not change the value of m (its intent(inout)!) +def deviator(m,spherical = False): # Careful, do not change the value of m, its intent(inout)! sph = oneThird*(m[0]+m[4]+m[8]) dev = [ m[0]-sph, m[1], m[2], @@ -39,7 +39,7 @@ parser.add_option('-s','--spherical', (options,filenames) = parser.parse_args() -if options.tensor == None: +if options.tensor is None: parser.error('no data column specified...') # --- loop over input files ------------------------------------------------------------------------- @@ -101,4 +101,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) + table.close() # close input ASCII table (works for stdin) \ No newline at end of file diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index 35908e6a2..75708a603 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -77,7 +77,7 @@ parser.set_defaults(coords = 'ipinitialcoord', (options,filenames) = parser.parse_args() -if options.vector == None and options.tensor == None: +if options.vector is None and options.tensor is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- @@ -140,16 +140,16 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings # ------------------------------------------ process value field ----------------------------------- stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(divFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation - table.data[:,data['column'][i]:data['column'][i]+data['dim']].\ - reshape([grid[2],grid[1],grid[0]]+data['shape']))) + stack.append(divFFT(size[::-1], # we need to reverse order here, because x + table.data[:,data['column'][i]:data['column'][i]+data['dim']]. # is fastest,ie rightmost, but leftmost in + reshape([grid[2],grid[1],grid[0]]+data['shape']))) # our x,y,z notation # ------------------------------------------ output result ----------------------------------------- @@ -158,4 +158,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) + table.close() # close input ASCII table (works for stdin) \ No newline at end of file diff --git a/processing/post/addEhkl.py b/processing/post/addEhkl.py index 5ed585ba4..96ec79a96 100755 --- a/processing/post/addEhkl.py +++ b/processing/post/addEhkl.py @@ -48,7 +48,7 @@ parser.set_defaults(hkl = (1,1,1), (options,filenames) = parser.parse_args() -if options.stiffness == None: +if options.stiffness is None: parser.error('no data column specified...') # --- loop over input files ------------------------------------------------------------------------- @@ -93,4 +93,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables + table.close() # close ASCII tables \ No newline at end of file diff --git a/processing/post/addEuclideanDistance.py b/processing/post/addEuclideanDistance.py index 3c15ef60b..7f32abb6b 100755 --- a/processing/post/addEuclideanDistance.py +++ b/processing/post/addEuclideanDistance.py @@ -105,7 +105,7 @@ parser.set_defaults(scale = 1.0) (options,filenames) = parser.parse_args() -if options.type == None: +if options.type is None: parser.error('no feature type selected.') if not set(options.type).issubset(set(list(itertools.chain(*map(lambda x: x['names'],features))))): parser.error('type must be chosen from (%s).'%(', '.join(map(lambda x:'|'.join(x['names']),features))) ) @@ -175,7 +175,7 @@ for name in filenames: max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\ ],'d') # size from bounding box, corrected for cell-centeredness - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings # ------------------------------------------ process value field ----------------------------------- @@ -219,4 +219,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) + table.close() # close input ASCII table (works for stdin) \ No newline at end of file diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index dd69ea1e4..b704fc6cd 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -68,15 +68,15 @@ parser.set_defaults(symmetry = 'cubic', (options, filenames) = parser.parse_args() -if options.radius == None: +if options.radius is None: parser.error('no radius specified.') -input = [options.eulers != None, - options.a != None and \ - options.b != None and \ - options.c != None, - options.matrix != None, - options.quaternion != None, +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, ] if np.sum(input) != 1: parser.error('needs exactly one input format.') @@ -262,4 +262,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables + table.close() # close ASCII tables \ No newline at end of file From 80dc23d93d432c7c14b811c391c11527a2739519 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 21:11:43 +0100 Subject: [PATCH 019/134] following "prospector -t pep8 -t pyflakes -t dodgy -t profile-validator -t pep257" --- processing/post/addIPFcolor.py | 12 ++++++------ processing/post/addMapped.py | 6 +++--- processing/post/addNorm.py | 2 +- processing/post/addOrientations.py | 12 ++++++------ processing/post/addPole.py | 14 +++++++------- processing/post/addQuaternions.py | 4 ++-- processing/post/addSchmidfactors.py | 6 +++--- processing/post/addSpectralDecomposition.py | 2 +- processing/post/addStrainTensors.py | 4 ++-- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/processing/post/addIPFcolor.py b/processing/post/addIPFcolor.py index a66f55290..24aeb3fa0 100755 --- a/processing/post/addIPFcolor.py +++ b/processing/post/addIPFcolor.py @@ -62,12 +62,12 @@ parser.set_defaults(pole = (0.0,0.0,1.0), (options, filenames) = parser.parse_args() -input = [options.eulers != None, - options.a != None and \ - options.b != None and \ - options.c != None, - options.matrix != None, - options.quaternion != None, +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, ] if np.sum(input) != 1: parser.error('needs exactly one input format.') diff --git a/processing/post/addMapped.py b/processing/post/addMapped.py index f2dc966ab..2ce84959c 100755 --- a/processing/post/addMapped.py +++ b/processing/post/addMapped.py @@ -39,14 +39,14 @@ parser.set_defaults(offset = 0, (options,filenames) = parser.parse_args() -if options.label == None: +if options.label is None: parser.error('no data columns specified.') -if options.map == None: +if options.map is None: parser.error('no mapping column given.') # ------------------------------------------ process mapping ASCIItable --------------------------- -if options.asciitable != None and os.path.isfile(options.asciitable): +if options.asciitable is not None and os.path.isfile(options.asciitable): mappedTable = damask.ASCIItable(name = options.asciitable, buffered = False, readonly = True) diff --git a/processing/post/addNorm.py b/processing/post/addNorm.py index 725321953..3aa9e8c04 100755 --- a/processing/post/addNorm.py +++ b/processing/post/addNorm.py @@ -43,7 +43,7 @@ parser.set_defaults(norm = 'frobenius', (options,filenames) = parser.parse_args() -if options.label == None: +if options.label is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 1f5ce14e7..912497d95 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -74,12 +74,12 @@ options.output = map(lambda x: x.lower(), options.output) if options.output == [] or (not set(options.output).issubset(set(outputChoices))): parser.error('output must be chosen from {}.'.format(', '.join(outputChoices))) -input = [options.eulers != None, - options.a != None and \ - options.b != None and \ - options.c != None, - options.matrix != None, - options.quaternion != None, +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, ] if np.sum(input) != 1: parser.error('needs exactly one input format.') diff --git a/processing/post/addPole.py b/processing/post/addPole.py index f7d64f4a5..c8e3991ee 100755 --- a/processing/post/addPole.py +++ b/processing/post/addPole.py @@ -62,12 +62,12 @@ parser.set_defaults(pole = (1.0,0.0,0.0), (options, filenames) = parser.parse_args() -input = [options.eulers != None, - options.a != None and \ - options.b != None and \ - options.c != None, - options.matrix != None, - options.quaternion != None, +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, ] if np.sum(input) != 1: parser.error('needs exactly one input format.') @@ -133,7 +133,7 @@ for name in filenames: rotatedPole = o.quaternion*pole # rotate pole according to crystal orientation (x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection - table.data_append([np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y]) # cartesian coordinates + table.data_append([np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y]) # cartesian coordinates outputAlive = table.data_write() # output processed line diff --git a/processing/post/addQuaternions.py b/processing/post/addQuaternions.py index a35ab62a9..db6276fc5 100755 --- a/processing/post/addQuaternions.py +++ b/processing/post/addQuaternions.py @@ -26,14 +26,14 @@ parser.set_defaults(frame = None) (options,filenames) = parser.parse_args() -if options.frame == None: +if options.frame is None: parser.error('no data column specified...') datainfo = {'len':4, 'label':[] } -if options.frame != None: datainfo['label'] += options.frame +if options.frame is not None: datainfo['label'] += options.frame # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index c3656a9b8..c61bb6cee 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -203,7 +203,7 @@ slipdirection = { \ } def applyEulers(phi1,Phi,phi2,x): - """ transform x given in crystal coordinates to xbar returned in lab coordinates for Euler angles phi1,Phi,phi2 """ + """transform x given in crystal coordinates to xbar returned in lab coordinates for Euler angles phi1,Phi,phi2""" eulerRot = [[ math.cos(phi1)*math.cos(phi2) - math.cos(Phi)*math.sin(phi1)*math.sin(phi2), -math.cos(phi1)*math.sin(phi2) - math.cos(Phi)*math.cos(phi2)*math.sin(phi1), @@ -285,8 +285,8 @@ datainfo = { datainfo['vector']['label'] += [options.eulers] toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians - -if options.lattice=='hex': # Convert 4 Miller indices notation of hex to orthogonal 3 Miller indices notation +# Convert 4 Miller indices notation of hex to orthogonal 3 Miller indices notation +if options.lattice=='hex': for i in range(Nslipsystems[options.lattice]): slipnormal[options.lattice][i][0]=slipnormal_temp[i][0] slipnormal[options.lattice][i][1]=(slipnormal_temp[i][0]+2.0*slipnormal_temp[i][1])/math.sqrt(3.0) diff --git a/processing/post/addSpectralDecomposition.py b/processing/post/addSpectralDecomposition.py index cc9bbe181..0555bb5bc 100755 --- a/processing/post/addSpectralDecomposition.py +++ b/processing/post/addSpectralDecomposition.py @@ -25,7 +25,7 @@ parser.add_option('-t','--tensor', (options,filenames) = parser.parse_args() -if options.tensor == None: +if options.tensor is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/post/addStrainTensors.py b/processing/post/addStrainTensors.py index 8cccdb2f2..bd5d7fccf 100755 --- a/processing/post/addStrainTensors.py +++ b/processing/post/addStrainTensors.py @@ -10,7 +10,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) def operator(stretch,strain,eigenvalues): - ''' Albrecht Bertram: Elasticity and Plasticity of Large Deformations An Introduction (3rd Edition, 2012), p. 102 ''' + """Albrecht Bertram: Elasticity and Plasticity of Large Deformations An Introduction (3rd Edition, 2012), p. 102""" return { 'V#ln': np.log(eigenvalues) , 'U#ln': np.log(eigenvalues) , @@ -75,7 +75,7 @@ if options.logarithmic: strains.append('ln') if options.biot: strains.append('Biot') if options.green: strains.append('Green') -if options.defgrad == None: +if options.defgrad is None: parser.error('no data column specified.') # --- loop over input files ------------------------------------------------------------------------- From 9cfc27d295884293f4008784193ca0496ff9eb05 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 21:14:06 +0100 Subject: [PATCH 020/134] line too long (132 lines max code, like Fortran, 159 including comments, Python standard) --- processing/post/addOrientations.py | 3 ++- processing/post/addQuaternions.py | 10 +++++--- processing/post/addSchmidfactors.py | 39 +++++++++++++++++------------ 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 912497d95..b806a56a0 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -15,7 +15,8 @@ scriptID = ' '.join([scriptName,damask.version]) parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ Add quaternion and/or Bunge Euler angle representation of crystal lattice orientation. -Orientation is given by quaternion, Euler angles, rotation matrix, or crystal frame coordinates (i.e. component vectors of rotation matrix). +Orientation is given by quaternion, Euler angles, rotation matrix, or crystal frame coordinates +(i.e. component vectors of rotation matrix). """, version = scriptID) diff --git a/processing/post/addQuaternions.py b/processing/post/addQuaternions.py index db6276fc5..fe0e3781f 100755 --- a/processing/post/addQuaternions.py +++ b/processing/post/addQuaternions.py @@ -18,10 +18,12 @@ Add Quaternions based on Crystal Frame Coordinates. """, version = scriptID) -parser.add_option('-f','--frame', dest='frame', nargs=4, type='string', metavar='', - help='heading of columns containing b* vector components and three frame vectors in that order') -parser.add_option('-s','--symmetry', dest='crysym', nargs=1,type='string',metavar='', - help='crystal symmetry definition') +parser.add_option('-f','--frame', + dest='frame', nargs=4, type='string', metavar='', + help='heading of columns containing b* vector components and three frame vectors in that order') +parser.add_option('-s','--symmetry', + dest='crysym', nargs=1,type='string',metavar='', + help='crystal symmetry definition') parser.set_defaults(frame = None) (options,filenames) = parser.parse_args() diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index c61bb6cee..e4837d54b 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -204,7 +204,6 @@ slipdirection = { \ def applyEulers(phi1,Phi,phi2,x): """transform x given in crystal coordinates to xbar returned in lab coordinates for Euler angles phi1,Phi,phi2""" - eulerRot = [[ math.cos(phi1)*math.cos(phi2) - math.cos(Phi)*math.sin(phi1)*math.sin(phi2), -math.cos(phi1)*math.sin(phi2) - math.cos(Phi)*math.cos(phi2)*math.sin(phi1), math.sin(Phi)*math.sin(phi1) @@ -239,22 +238,30 @@ Add columns listing Schmid factors (and optional trace vector of selected system """, version = scriptID) -parser.add_option('-l','--lattice', dest='lattice', type='choice', choices=('fcc','bcc','hex'), metavar='string', +parser.add_option('-l','--lattice', + dest='lattice', type='choice', choices=('fcc','bcc','hex'), metavar='string', help="type of lattice structure [%default] {fcc,bcc',hex}") -parser.add_option('--direction', dest='forcedirection', type='int', nargs=3, metavar='int int int', - help='force direction in lab coordinates %default') -parser.add_option('-n','--normal', dest='stressnormal', type='int', nargs=3, metavar='int int int', - help='stress plane normal in lab coordinates ') -parser.add_option('--trace', dest='traceplane', type='int', nargs=3, metavar='int int int', - help='normal (in lab coordinates) of plane on which the plane trace of the Schmid factor(s) is reported') -parser.add_option('--covera', dest='CoverA', type='float', metavar='float', - help='C over A ratio for hexagonal systems') -parser.add_option('-r','--rank', dest='rank', type='int', nargs=3, metavar='int int int', - help="report trace of r'th highest Schmid factor [%default]") -parser.add_option('-e', '--eulers', dest='eulers', metavar='string', - help='Euler angles label') -parser.add_option('-d', '--degrees', dest='degrees', action='store_true', - help='Euler angles are given in degrees [%default]') +parser.add_option('--direction', + dest='forcedirection', type='int', nargs=3, metavar='int int int', + help='force direction in lab coordinates %default') +parser.add_option('-n','--normal', + dest='stressnormal', type='int', nargs=3, metavar='int int int', + help='stress plane normal in lab coordinates ') +parser.add_option('--trace', + dest='traceplane', type='int', nargs=3, metavar='int int int', + help='normal (in lab coordinates) of plane on which the plane trace of the Schmid factor(s) is reported') +parser.add_option('--covera', + dest='CoverA', type='float', metavar='float', + help='C over A ratio for hexagonal systems') +parser.add_option('-r','--rank', + dest='rank', type='int', nargs=3, metavar='int int int', + help="report trace of r'th highest Schmid factor [%default]") +parser.add_option('-e', '--eulers', + dest='eulers', metavar='string', + help='Euler angles label') +parser.add_option('-d', '--degrees', + dest='degrees', action='store_true', + help='Euler angles are given in degrees [%default]') parser.set_defaults(lattice = 'fcc') parser.set_defaults(forcedirection = [0, 0, 1]) parser.set_defaults(stressnormal = None) From 98476ea29cd47e0e547b5debeb32f628678f3565 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 21:35:59 +0100 Subject: [PATCH 021/134] more improved scripts --- processing/post/averageDown.py | 6 +++--- processing/post/averageTable.py | 2 +- processing/post/binXY.py | 6 +++--- processing/post/blowUp.py | 2 +- processing/post/fillTable.py | 2 +- processing/post/filterTable.py | 8 ++++---- processing/post/imageDataDeformed.py | 6 +++--- processing/post/imageDataRGB.py | 5 ++--- processing/post/sortTable.py | 2 +- processing/post/vtk_addPointcloudData.py | 4 ++-- 10 files changed, 21 insertions(+), 22 deletions(-) diff --git a/processing/post/averageDown.py b/processing/post/averageDown.py index 1b2b4f76b..f77914374 100755 --- a/processing/post/averageDown.py +++ b/processing/post/averageDown.py @@ -101,10 +101,10 @@ for name in filenames: mincorner = np.array(map(min,coords)) maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') - size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings delta = size/np.maximum(np.ones(3,'d'), grid) - origin = mincorner - 0.5*delta # shift from cell center to corner + origin = mincorner - 0.5*delta # shift from cell center to corner else: grid = np.array(options.grid,'i') diff --git a/processing/post/averageTable.py b/processing/post/averageTable.py index b74e2744f..edb0a0661 100755 --- a/processing/post/averageTable.py +++ b/processing/post/averageTable.py @@ -28,7 +28,7 @@ parser.add_option('-l','--label', (options,filenames) = parser.parse_args() -if options.label == None: +if options.label is None: parser.error('no grouping column specified.') diff --git a/processing/post/binXY.py b/processing/post/binXY.py index b0118aedb..c44d60de2 100755 --- a/processing/post/binXY.py +++ b/processing/post/binXY.py @@ -77,11 +77,11 @@ minmax = np.array([np.array(options.xrange), grid = np.zeros(options.bins,'f') result = np.zeros((options.bins[0],options.bins[1],3),'f') -if options.data == None: parser.error('no data columns specified.') +if options.data is None: parser.error('no data columns specified.') labels = options.data -if options.weight != None: labels += [options.weight] # prevent character splitting of single string value +if options.weight is not None: labels += [options.weight] # prevent character splitting of single string value # --- loop over input files ------------------------------------------------------------------------- @@ -124,7 +124,7 @@ for name in filenames: x = int(options.bins[0]*(table.data[i,0]-minmax[0,0])/delta[0]) y = int(options.bins[1]*(table.data[i,1]-minmax[1,0])/delta[1]) if x >= 0 and x < options.bins[0] and y >= 0 and y < options.bins[1]: - grid[x,y] += 1. if options.weight == None else table.data[i,2] # count (weighted) occurrences + grid[x,y] += 1. if options.weight is None else table.data[i,2] # count (weighted) occurrences if options.normCol: for x in xrange(options.bins[0]): diff --git a/processing/post/blowUp.py b/processing/post/blowUp.py index 04a4f91e7..725e623b4 100755 --- a/processing/post/blowUp.py +++ b/processing/post/blowUp.py @@ -86,7 +86,7 @@ for name in filenames: max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\ ],'d') # size from bounding box, corrected for cell-centeredness - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings packing = np.array(options.packing,'i') diff --git a/processing/post/fillTable.py b/processing/post/fillTable.py index 5f4a307af..fc40eed8f 100755 --- a/processing/post/fillTable.py +++ b/processing/post/fillTable.py @@ -43,7 +43,7 @@ parser.set_defaults(condition = '', (options,filenames) = parser.parse_args() -if options.labels == None or options.formulae == None: +if options.labels is None or options.formulae is None: parser.error('no formulae specified.') if len(options.labels) != len(options.formulae): parser.error('number of labels ({}) and formulae ({}) do not match.'.format(len(options.labels),len(options.formulae))) diff --git a/processing/post/filterTable.py b/processing/post/filterTable.py index 6b936644b..d375785dc 100755 --- a/processing/post/filterTable.py +++ b/processing/post/filterTable.py @@ -80,14 +80,14 @@ for name in filenames: positions = [] for position,label in enumerate(table.labels): - if (options.whitelist == None or any([ position in table.label_indexrange(needle) \ + if (options.whitelist is None or any([ position in table.label_indexrange(needle) \ or fnmatch.fnmatch(label,needle) for needle in options.whitelist])) \ - and (options.blacklist == None or not any([ position in table.label_indexrange(needle) \ + and (options.blacklist is None or not any([ position in table.label_indexrange(needle) \ or fnmatch.fnmatch(label,needle) for needle in options.blacklist])): # a label to keep? labels.append(label) # remember name... positions.append(position) # ...and position - if len(labels) > 0 and options.whitelist != None and options.blacklist == None: # check whether reordering is possible + if len(labels) > 0 and options.whitelist is not None and options.blacklist is None: # check whether reordering is possible whitelistitem = np.zeros(len(labels),dtype=int) for i,label in enumerate(labels): # check each selected label match = [ positions[i] in table.label_indexrange(needle) \ @@ -119,7 +119,7 @@ for name in filenames: # ------------------------------------------ assemble header --------------------------------------- - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) # read ASCII header info + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.labels_clear() table.labels_append(np.array(labels)[order]) # update with new label set table.head_write() diff --git a/processing/post/imageDataDeformed.py b/processing/post/imageDataDeformed.py index c538627d7..c45f0eeeb 100755 --- a/processing/post/imageDataDeformed.py +++ b/processing/post/imageDataDeformed.py @@ -112,7 +112,7 @@ for name in filenames: try: table = damask.ASCIItable(name = name, buffered = False, - labeled = options.label != None, + labeled = options.label is not None, readonly = True) except: continue table.report_name(scriptName,name) @@ -162,8 +162,8 @@ for name in filenames: nodes -= boundingBox[0].repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1)) nodes *= (options.pixelsize*options.dimension/options.size).repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1)) - imagesize = (options.pixelsize*(boundingBox[1]-boundingBox[0])*options.dimension\ - /options.size)[:2].astype('i') # determine image size from number of cells in overall bounding box + imagesize = (options.pixelsize*(boundingBox[1]-boundingBox[0])* # determine image size from number of + options.dimension/options.size)[:2].astype('i') # cells in overall bounding box im = Image.new('RGBA',imagesize) draw = ImageDraw.Draw(im) diff --git a/processing/post/imageDataRGB.py b/processing/post/imageDataRGB.py index f96ebf05d..ac51746ca 100755 --- a/processing/post/imageDataRGB.py +++ b/processing/post/imageDataRGB.py @@ -80,7 +80,7 @@ for name in filenames: try: table = damask.ASCIItable(name = name, buffered = False, - labeled = options.label != None, + labeled = options.label is not None, readonly = True) except: continue damask.util.report(scriptName,name) @@ -104,8 +104,7 @@ for name in filenames: damask.util.croak(errors) table.close(dismiss = True) # close ASCII table file handles and delete output file continue - - # convert data to shape and arrange according to given options +# convert data to shape and arrange according to given options if options.dimension != []: table.data = table.data.reshape(options.dimension[1],options.dimension[0],3) if options.flipLR: table.data = np.fliplr(table.data) if options.flipUD: table.data = np.flipud(table.data) diff --git a/processing/post/sortTable.py b/processing/post/sortTable.py index aa2d1ed48..92fe221ee 100755 --- a/processing/post/sortTable.py +++ b/processing/post/sortTable.py @@ -36,7 +36,7 @@ parser.set_defaults(key = [], (options,filenames) = parser.parse_args() -if options.keys == None: +if options.keys is None: parser.error('No sorting column(s) specified.') options.keys.reverse() # numpy sorts with most significant column as last diff --git a/processing/post/vtk_addPointcloudData.py b/processing/post/vtk_addPointcloudData.py index c0dafd63a..95b91d8ee 100755 --- a/processing/post/vtk_addPointcloudData.py +++ b/processing/post/vtk_addPointcloudData.py @@ -49,8 +49,8 @@ Polydata = reader.GetOutput() if Npoints != Ncells or Npoints != Nvertices: parser.error('Number of points, cells, and vertices in VTK differ from each other'); sys.exit() -if options.scalar != None: datainfo['scalar']['label'] += options.scalar -if options.color != None: datainfo['color']['label'] += options.color +if options.scalar is not None: datainfo['scalar']['label'] += options.scalar +if options.color is not None: datainfo['color']['label'] += options.color # ------------------------------------------ setup file handles --------------------------------------- From 043f2faeb35df26aa31a25b7fce66e5e484e9e5a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 21:59:12 +0100 Subject: [PATCH 022/134] line too long --- processing/post/imageDataDeformed.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/processing/post/imageDataDeformed.py b/processing/post/imageDataDeformed.py index c45f0eeeb..71086cf72 100755 --- a/processing/post/imageDataDeformed.py +++ b/processing/post/imageDataDeformed.py @@ -161,7 +161,8 @@ for name in filenames: ]) # find x-y bounding box for given z layer nodes -= boundingBox[0].repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1)) - nodes *= (options.pixelsize*options.dimension/options.size).repeat(np.prod(options.dimension+1)).reshape([3]+list(options.dimension+1)) + nodes *= (options.pixelsize*options.dimension/options.size).repeat(np.prod(options.dimension+1)).\ + reshape([3]+list(options.dimension+1)) imagesize = (options.pixelsize*(boundingBox[1]-boundingBox[0])* # determine image size from number of options.dimension/options.size)[:2].astype('i') # cells in overall bounding box im = Image.new('RGBA',imagesize) From 974b8cde41d75a65a555bd98c28ea2826a888d36 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 22:12:04 +0100 Subject: [PATCH 023/134] some more syntax improvements --- processing/pre/abq_addUserOutput.py | 27 +++++--------------- processing/pre/geom_addPrimitive.py | 9 +++---- processing/pre/geom_canvas.py | 7 ++--- processing/pre/geom_check.py | 7 +++-- processing/pre/geom_clean.py | 2 +- processing/pre/geom_fromEuclideanDistance.py | 2 +- processing/pre/geom_fromImage.py | 6 ++--- processing/pre/geom_fromMinimalSurface.py | 2 +- processing/pre/geom_fromOsteonGeometry.py | 2 +- processing/pre/geom_pack.py | 2 +- 10 files changed, 25 insertions(+), 41 deletions(-) diff --git a/processing/pre/abq_addUserOutput.py b/processing/pre/abq_addUserOutput.py index b14399509..1e0614c21 100755 --- a/processing/pre/abq_addUserOutput.py +++ b/processing/pre/abq_addUserOutput.py @@ -1,16 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -''' -Writes meaningful labels to the Abaqus input file (*.inp) -based on the files -.output -that are written during the first run of the model. -See Abaqus Keyword Reference Manual (AKRM) *DEPVAR for details. -Original script: marc_addUserOutput.py modified by Benjamin Bode -''' - -import sys,os,re,string +import sys,os,re from optparse import OptionParser import damask @@ -19,7 +10,6 @@ scriptID = ' '.join([scriptName,damask.version]) # ----------------------------- def ParseOutputFormat(filename,what,me): -# ----------------------------- format = {'outputs':{},'specials':{'brothers':[]}} outputmetafile = filename+'.output'+what @@ -120,7 +110,7 @@ for file in files: for what in me: outputFormat[what] = ParseOutputFormat(formatFile,what,me[what]) - if not '_id' in outputFormat[what]['specials']: + if '_id' not in outputFormat[what]['specials']: print "'%s' not found in <%s>"%(me[what],what) print '\n'.join(map(lambda x:' '+x,outputFormat[what]['specials']['brothers'])) sys.exit(1) @@ -164,19 +154,14 @@ for file in files: if m: lastSection = thisSection thisSection = m.group(1) - #Abaqus keyword can be upper or lower case - if (lastSection.upper() == '*DEPVAR' and thisSection.upper() == '*USER'): - #Abaqus SDVs are named SDV1...SDVn if no specific name is given - #Abaqus needs total number of SDVs in the line after *Depvar keyword + if (lastSection.upper() == '*DEPVAR' and thisSection.upper() == '*USER'): #Abaqus keyword can be upper or lower case if options.number > 0: - #number of SDVs - output.write('%i\n'%options.number) + output.write('%i\n'%options.number) #Abaqus needs total number of SDVs in the line after *Depvar keyword else: - #number of SDVs output.write('%i\n'%len(UserVars)) - #index,output variable key,output variable description + for i in range(len(UserVars)): - output.write('%i,"%i%s","%i%s"\n'%(i+1,0,UserVars[i],0,UserVars[i])) + output.write('%i,"%i%s","%i%s"\n'%(i+1,0,UserVars[i],0,UserVars[i])) #index,output variable key,output variable description if (thisSection.upper() != '*DEPVAR' or not re.match('\s*\d',line)): output.write(line) output.close() diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 9200f2df7..3dd60bc24 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask @@ -114,7 +114,7 @@ for name in filenames: microstructure = microstructure.reshape(info['grid'],order='F') - if options.dimension != None: + if options.dimension is not None: mask = (np.array(options.dimension) < 0).astype(float) # zero where positive dimension, otherwise one dim = abs(np.array(options.dimension)) # dimensions of primitive body pos = np.zeros(3,dtype='float') @@ -134,10 +134,9 @@ for name in filenames: # --- report --------------------------------------------------------------------------------------- + if ( newInfo['microstructures'] != info['microstructures']): + damask.util.croak('--> microstructures: %i'%newInfo['microstructures']) - remarks = [] - if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) - if remarks != []: damask.util.croak(remarks) #--- write header --------------------------------------------------------------------------------- diff --git a/processing/pre/geom_canvas.py b/processing/pre/geom_canvas.py index 93df742da..882f32c88 100755 --- a/processing/pre/geom_canvas.py +++ b/processing/pre/geom_canvas.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask @@ -81,7 +81,8 @@ for name in filenames: 'microstructures': 0, } - newInfo['grid'] = np.array([int(o*float(n.translate(None,'xX'))) if n[-1].lower() == 'x' else int(n) for o,n in zip(info['grid'],options.grid)],'i') + newInfo['grid'] = np.array([int(o*float(n.translate(None,'xX'))) if n[-1].lower() == 'x'\ + else int(n) for o,n in zip(info['grid'],options.grid)],'i') newInfo['grid'] = np.where(newInfo['grid'] > 0, newInfo['grid'],info['grid']) microstructure_cropped = np.zeros(newInfo['grid'],'i') @@ -143,7 +144,7 @@ for name in filenames: "origin\tx {origin[0]}\ty {origin[1]}\tz {origin[2]}".format(origin=newInfo['origin']), "homogenization\t{homog}".format(homog=info['homogenization']), "microstructures\t{microstructures}".format(microstructures=newInfo['microstructures']), - extra_header + extra_header ]) table.labels_clear() table.head_write() diff --git a/processing/pre/geom_check.py b/processing/pre/geom_check.py index 3f9e50864..d607a1f73 100755 --- a/processing/pre/geom_check.py +++ b/processing/pre/geom_check.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys,vtk import numpy as np from optparse import OptionParser import damask @@ -91,8 +91,7 @@ for name in filenames: (directory,filename) = os.path.split(name) writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] - +'.'+writer.GetDefaultFileExtension())) + writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]+'.'+writer.GetDefaultFileExtension())) else: writer = vtk.vtkDataSetWriter() writer.WriteToOutputStringOn() @@ -101,6 +100,6 @@ for name in filenames: if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(grid) else: writer.SetInputData(grid) writer.Write() - if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) + if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) table.close() diff --git a/processing/pre/geom_clean.py b/processing/pre/geom_clean.py index b55149a61..18caf68b9 100755 --- a/processing/pre/geom_clean.py +++ b/processing/pre/geom_clean.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np import damask from scipy import ndimage diff --git a/processing/pre/geom_fromEuclideanDistance.py b/processing/pre/geom_fromEuclideanDistance.py index 405fca630..a932583c2 100755 --- a/processing/pre/geom_fromEuclideanDistance.py +++ b/processing/pre/geom_fromEuclideanDistance.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math,itertools +import os,sys,math,itertools import numpy as np from scipy import ndimage from optparse import OptionParser diff --git a/processing/pre/geom_fromImage.py b/processing/pre/geom_fromImage.py index 5ef524dcb..0977c5e7e 100755 --- a/processing/pre/geom_fromImage.py +++ b/processing/pre/geom_fromImage.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser -from PIL import Image,ImageOps +from PIL import Image import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -51,7 +51,7 @@ for name in filenames: try: img.seek(slice) # advance to slice layer = np.expand_dims(1+np.array(img,dtype = 'uint16'),axis = 0) # read image layer - microstructure = layer if slice == 0 else np.vstack((microstructure,layer)) # add to microstructure data + microstructure = layer if slice == 0 else np.vstack((microstructure,layer)) # noqa slice += 1 # advance to next slice except EOFError: break diff --git a/processing/pre/geom_fromMinimalSurface.py b/processing/pre/geom_fromMinimalSurface.py index 915f1f9f3..a3729dc30 100755 --- a/processing/pre/geom_fromMinimalSurface.py +++ b/processing/pre/geom_fromMinimalSurface.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/pre/geom_fromOsteonGeometry.py b/processing/pre/geom_fromOsteonGeometry.py index 9e8280a72..bc49b9dca 100755 --- a/processing/pre/geom_fromOsteonGeometry.py +++ b/processing/pre/geom_fromOsteonGeometry.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/pre/geom_pack.py b/processing/pre/geom_pack.py index 9edb8c3dc..17d1cb63c 100755 --- a/processing/pre/geom_pack.py +++ b/processing/pre/geom_pack.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask From c1dd5febd52e20810d9f6a812907045d90173bd7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 22:23:30 +0100 Subject: [PATCH 024/134] some more scripts passed --- processing/pre/OIMlinear2linearODF.py | 4 ++-- processing/pre/geom_fromBarycentric.py | 19 +++++++++---------- processing/pre/geom_rotate.py | 4 ++-- processing/pre/geom_translate.py | 8 +++++--- processing/pre/geom_unpack.py | 2 +- processing/pre/geom_vicinityOffset.py | 7 +++---- processing/pre/seeds_check.py | 11 +++++------ processing/pre/seeds_fromGeom.py | 8 +++++--- 8 files changed, 32 insertions(+), 31 deletions(-) diff --git a/processing/pre/OIMlinear2linearODF.py b/processing/pre/OIMlinear2linearODF.py index 980f861af..280457be4 100755 --- a/processing/pre/OIMlinear2linearODF.py +++ b/processing/pre/OIMlinear2linearODF.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: UTF-8 no BOM -*- -import os,string,sys,re +import os,sys from optparse import OptionParser import numpy as np import damask @@ -73,7 +73,7 @@ for file in files: for iPhi1 in range(nPhi1): for iPHI in range(nPHI): for iPhi2 in range(nPhi2): - ODF[iPhi1,iPHI,iPhi2] = float(line.split()[3])*0.125 # extract intensity (in column 4) and weight by 1/8 (since we convert from the 8 corners to the center later on) + ODF[iPhi1,iPHI,iPhi2] = float(line.split()[3])*0.125 # extract intensity (in column 4) and weight by 1/8 line = file['input'].readline() for iPhi1 in range(nPhi1-1): diff --git a/processing/pre/geom_fromBarycentric.py b/processing/pre/geom_fromBarycentric.py index 383681ef9..fe687fd2a 100755 --- a/processing/pre/geom_fromBarycentric.py +++ b/processing/pre/geom_fromBarycentric.py @@ -10,10 +10,11 @@ # maintain meaningful microstructure(reduce artifacts). -import sys, os, string +import os import numpy as np import argparse from scipy.spatial import Delaunay +import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -23,16 +24,14 @@ OFFSET = 0.1 #resize the seeded volume to give space for rim/pan PHANTOM_ID = -1 #grain ID for phantom seeds def d_print(info, data, separator=False): - '''quickly print debug information''' - if(separator): print "*"*80 - print info - print data + """quickly print debug information""" + if(separator): print "*"*80 + print info + print data def meshgrid2(*arrs): - ''' - code inspired by http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d - ''' + """code inspired by http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d""" arrs = tuple(reversed(arrs)) arrs = tuple(arrs) lens = np.array(map(len, arrs)) @@ -121,9 +120,9 @@ args = parser.parse_args() # get all the arguments right after #quick help to user print "*"*80 parser.print_help() -print '''Sample usage: +print """Sample usage: ./geoFromBarycentic.py 20grains.seeds -g 128 128 128 -S -r; geom_check seeds.geom; seeds_check new_seed.seeds. -''' +""" print "*"*80 if (args.debug): d_print("args are:", parser.parse_args(),separator=True) diff --git a/processing/pre/geom_rotate.py b/processing/pre/geom_rotate.py index ecd0da09c..7ae47f894 100755 --- a/processing/pre/geom_rotate.py +++ b/processing/pre/geom_rotate.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np import damask from scipy import ndimage @@ -49,7 +49,7 @@ parser.set_defaults(degrees = False, (options, filenames) = parser.parse_args() -if sum(x != None for x in [options.rotation,options.eulers,options.matrix,options.quaternion]) !=1: +if sum(x is not None for x in [options.rotation,options.eulers,options.matrix,options.quaternion]) !=1: parser.error('not exactly one rotation specified...') toRadian = math.pi/180. if options.degrees else 1.0 diff --git a/processing/pre/geom_translate.py b/processing/pre/geom_translate.py index c6c93f0d3..13f4ef592 100755 --- a/processing/pre/geom_translate.py +++ b/processing/pre/geom_translate.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np import damask from optparse import OptionParser @@ -95,8 +95,10 @@ for name in filenames: # --- report --------------------------------------------------------------------------------------- remarks = [] - if (any(newInfo['origin'] != info['origin'])): remarks.append('--> origin x y z: %s'%(' : '.join(map(str,newInfo['origin'])))) - if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) + if (any(newInfo['origin'] != info['origin'])): + remarks.append('--> origin x y z: %s'%(' : '.join(map(str,newInfo['origin'])))) + if ( newInfo['microstructures'] != info['microstructures']): + remarks.append('--> microstructures: %i'%newInfo['microstructures']) if remarks != []: damask.util.croak(remarks) # --- write header --------------------------------------------------------------------------------- diff --git a/processing/pre/geom_unpack.py b/processing/pre/geom_unpack.py index 43e2764b4..a07166cdd 100755 --- a/processing/pre/geom_unpack.py +++ b/processing/pre/geom_unpack.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask diff --git a/processing/pre/geom_vicinityOffset.py b/processing/pre/geom_vicinityOffset.py index c11188997..8a2a0c912 100755 --- a/processing/pre/geom_vicinityOffset.py +++ b/processing/pre/geom_vicinityOffset.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from scipy import ndimage from optparse import OptionParser @@ -87,9 +87,8 @@ for name in filenames: # --- report --------------------------------------------------------------------------------------- - remarks = [] - if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) - if remarks != []: damask.util.croak(remarks) + if (newInfo['microstructures'] != info['microstructures']): + damask.util.croak('--> microstructures: %i'%newInfo['microstructures']) # --- write header --------------------------------------------------------------------------------- diff --git a/processing/pre/seeds_check.py b/processing/pre/seeds_check.py index 7460fa9a3..27341e0fe 100755 --- a/processing/pre/seeds_check.py +++ b/processing/pre/seeds_check.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys,vtk import numpy as np import damask from optparse import OptionParser @@ -66,8 +66,8 @@ for name in filenames: if info['size'][i] <= 0.0: # any invalid size? info['size'][i] = float(info['grid'][i])/max(info['grid']) # normalize to grid remarks.append('rescaling size {} to {}...'.format({0:'x',1:'y',2:'z'}[i],info['size'][i])) - if table.label_dimension(options.position) != 3: errors.append('columns "{}" have dimension {}'.format(options.position, - table.label_dimension(options.position))) + if table.label_dimension(options.position) != 3: + errors.append('columns "{}" have dimension {}'.format(options.position,table.label_dimension(options.position))) if remarks != []: damask.util.croak(remarks) if errors != []: damask.util.croak(errors) @@ -110,8 +110,7 @@ for name in filenames: (directory,filename) = os.path.split(name) writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] - +'.'+writer.GetDefaultFileExtension())) + writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]+'.'+writer.GetDefaultFileExtension())) else: writer = vtk.vtkDataSetWriter() writer.WriteToOutputStringOn() @@ -120,7 +119,7 @@ for name in filenames: if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(grid) else: writer.SetInputData(grid) writer.Write() - if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) + if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) table.close() diff --git a/processing/pre/seeds_fromGeom.py b/processing/pre/seeds_fromGeom.py index b3fb1677c..b2b12b95f 100755 --- a/processing/pre/seeds_fromGeom.py +++ b/processing/pre/seeds_fromGeom.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string +import os,sys import numpy as np from optparse import OptionParser import damask @@ -88,8 +88,10 @@ for name in filenames: yy = np.tile(np.repeat(y,info['grid'][0] ),info['grid'][2]) zz = np.repeat(z,info['grid'][0]*info['grid'][1]) - mask = np.logical_and(np.in1d(microstructure,options.whitelist,invert=False) if options.whitelist != [] else np.full_like(microstructure,True,dtype=bool), - np.in1d(microstructure,options.blacklist,invert=True ) if options.blacklist != [] else np.full_like(microstructure,True,dtype=bool)) + mask = np.logical_and(np.in1d(microstructure,options.whitelist,invert=False) if options.whitelist != [] + else np.full_like(microstructure,True,dtype=bool), + np.in1d(microstructure,options.blacklist,invert=True ) if options.blacklist != [] + else np.full_like(microstructure,True,dtype=bool)) # ------------------------------------------ assemble header --------------------------------------- From 4d8aad36f127649ef3fe1964ce0cc7135b4af004 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Mar 2016 23:02:47 +0100 Subject: [PATCH 025/134] first round of libraries --- lib/damask/solver/__init__.py | 11 +++++------ lib/damask/solver/abaqus.py | 3 ++- lib/damask/solver/marc.py | 11 ++--------- lib/damask/solver/solver.py | 9 +++++---- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/lib/damask/solver/__init__.py b/lib/damask/solver/__init__.py index aebeae33e..cd8f0b193 100644 --- a/lib/damask/solver/__init__.py +++ b/lib/damask/solver/__init__.py @@ -1,8 +1,7 @@ # -*- coding: UTF-8 no BOM -*- +"""Tools to control the various BVP solvers""" -# $Id$ - -from .solver import Solver # only one class -from .spectral import Spectral # only one class -from .marc import Marc # only one class -from .abaqus import Abaqus # only one class +from .solver import Solver # noqa +from .spectral import Spectral # noqa +from .marc import Marc # noqa +from .abaqus import Abaqus # noqa diff --git a/lib/damask/solver/abaqus.py b/lib/damask/solver/abaqus.py index f016e2794..7a8321a9c 100644 --- a/lib/damask/solver/abaqus.py +++ b/lib/damask/solver/abaqus.py @@ -7,7 +7,8 @@ from .solver import Solver class Abaqus(Solver): - def __init__(self,version='',solver=''): # example of version string: 6.12-2, solver: either std or exp + + def __init__(self,version='',solver=''): # example version string: 6.12-2, solver: std or exp self.solver='Abaqus' if version =='': import subprocess diff --git a/lib/damask/solver/marc.py b/lib/damask/solver/marc.py index 3b47ee773..660f2f6ef 100644 --- a/lib/damask/solver/marc.py +++ b/lib/damask/solver/marc.py @@ -7,9 +7,7 @@ from .solver import Solver class Marc(Solver): -#-------------------------- def __init__(self): -#-------------------------- self.solver = 'Marc' self.releases = { \ '2015': ['linux64',''], @@ -24,7 +22,6 @@ class Marc(Solver): #-------------------------- def version(self,rootRelation = ''): -#-------------------------- import os,damask.environment MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT'] @@ -40,7 +37,6 @@ class Marc(Solver): #-------------------------- def libraryPath(self,rootRelation = '',releases = []): -#-------------------------- import os,damask.environment MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT'] @@ -59,7 +55,6 @@ class Marc(Solver): #-------------------------- def toolsPath(self,rootRelation = '',release = ''): -#-------------------------- import os,damask.environment MSCpath = damask.environment.Environment(rootRelation).options['MSC_ROOT'] @@ -72,7 +67,6 @@ class Marc(Solver): #-------------------------- def submit_job(self, -#-------------------------- rootRelation = '', release = '', model = 'model', @@ -84,7 +78,7 @@ class Marc(Solver): ): import os,damask.environment - import subprocess,shlex,shutil + import subprocess,shlex if len(release) == 0: release = self.version(rootRelation) @@ -94,7 +88,7 @@ class Marc(Solver): damaskEnv = damask.environment.Environment(rootRelation) - user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc') # might be updated if special version is found (usually symlink) + user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc') # might be updated if special version (symlink) is found if compile: if os.path.isfile(os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc%s.f90'%release)): user = os.path.join(damaskEnv.relPath('code/'),'DAMASK_marc%s'%release) @@ -123,7 +117,6 @@ class Marc(Solver): #-------------------------- def exit_number_from_outFile(self,outFile=None): -#-------------------------- import string exitnumber = -1 fid_out = open(outFile,'r') diff --git a/lib/damask/solver/solver.py b/lib/damask/solver/solver.py index bef87ed4a..53c055f05 100644 --- a/lib/damask/solver/solver.py +++ b/lib/damask/solver/solver.py @@ -5,10 +5,11 @@ import damask.solver class Solver(): - ''' - General class for solver specific functionality. - Sub-classed by the individual solvers. - ''' + """ + General class for solver specific functionality. + + Sub-classed by the individual solvers. + """ def __init__(self,solver=''): solverClass = { From c188b13a5a0e70a48f5a8d3f1883c9fd516825ca Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 2 Mar 2016 04:21:44 +0100 Subject: [PATCH 026/134] updated version information after successful test of revision3813-1031-g4d8aad3 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 096cd6ab1..509bf817b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1018-g54d0a0a +revision3813-1031-g4d8aad3 From f77de7ac6e34d2246c2e2d8bac40748127d8e661 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 10:52:24 +0100 Subject: [PATCH 027/134] adjusting style (mainly long lines an "== None") --- processing/post/addGrainID.py | 30 +++++----- processing/post/marc_deformedGeometry.py | 11 ++-- processing/post/marc_extractData.py | 60 ++++++++----------- processing/post/mentat_colorMap.py | 13 ++-- processing/post/permuteData.py | 2 +- processing/post/rotateData.py | 5 +- processing/post/vtk_addRectilinearGridData.py | 11 ++-- 7 files changed, 60 insertions(+), 72 deletions(-) diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index b704fc6cd..5443d1c70 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -123,7 +123,7 @@ for name in filenames: table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.labels_append('grainID_{}@{}'.format(label, - options.disorientation if options.degrees else np.degrees(options.disorientation))) # report orientation source and disorientation in degrees + options.disorientation if options.degrees else np.degrees(options.disorientation))) # report orientation source and disorientation in degrees table.head_write() # ------------------------------------------ process data ------------------------------------------ @@ -161,7 +161,8 @@ for name in filenames: if p > 0 and p % 1000 == 0: time_delta = (time.clock()-tick) * (len(grainID) - p) / p - bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'%(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) + bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'\ + %(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) if inputtype == 'eulers': o = damask.Orientation(Eulers = np.array(map(float,table.data[column:column+3]))*toRadians, @@ -191,11 +192,11 @@ for name in filenames: bestDisorientation = damask.Quaternion([0,0,0,1]) # initialize to 180 deg rotation as worst case for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points gID = grainID[i] - if gID != -1 and gID not in alreadyChecked: # an already indexed point belonging to a grain not yet tested? + if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested? alreadyChecked[gID] = True # remember not to check again - disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against that grain's orientation (and skip requirement of axis within SST) + disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation if disorientation.quaternion.w > cos_disorientation and \ - disorientation.quaternion.w >= bestDisorientation.w: # within disorientation threshold and better than current best? + disorientation.quaternion.w >= bestDisorientation.w: # within threshold and betterthan current best? matched = True matchedID = gID # remember that grain bestDisorientation = disorientation.quaternion @@ -217,11 +218,11 @@ for name in filenames: memberCounts = np.array(memberCounts) similarOrientations = [[] for i in xrange(len(orientations))] - for i,orientation in enumerate(orientations[:-1]): # compare each identified orientation... - for j in xrange(i+1,len(orientations)): # ...against all others that were defined afterwards - if orientation.disorientation(orientations[j],SST = False)[0].quaternion.w > cos_disorientation: # similar orientations in both grainIDs? - similarOrientations[i].append(j) # remember in upper triangle... - similarOrientations[j].append(i) # ...and lower triangle of matrix + for i,orientation in enumerate(orientations[:-1]): # compare each identified orientation... + for j in xrange(i+1,len(orientations)): # ...against all others that were defined afterwards + if orientation.disorientation(orientations[j],SST = False)[0].quaternion.w > cos_disorientation: # similar orientations in both grainIDs? + similarOrientations[i].append(j) # remember in upper triangle... + similarOrientations[j].append(i) # ...and lower triangle of matrix if similarOrientations[i] != []: bg.set_message('grainID {} is as: {}'.format(i,' '.join(map(str,similarOrientations[i])))) @@ -235,10 +236,11 @@ for name in filenames: if p > 0 and p % 1000 == 0: time_delta = (time.clock()-tick) * (len(grainID) - p) / p - bg.set_message('(%02i:%02i:%02i) shifting ID of point %i out of %i (grain count %i)...'%(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) + bg.set_message('(%02i:%02i:%02i) shifting ID of point %i out of %i (grain count %i)...' + %(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) if similarOrientations[gID] != []: # orientation of my grainID is similar to someone else? - similarNeighbors = defaultdict(int) # dict holding frequency of neighboring grainIDs that share my orientation (freq info not used...) - for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points + similarNeighbors = defaultdict(int) # frequency of neighboring grainIDs sharing my orientation + for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring point if grainID[i] in similarOrientations[gID]: # neighboring point shares my orientation? similarNeighbors[grainID[i]] += 1 # remember its grainID if similarNeighbors != {}: # found similar orientation(s) in neighborhood @@ -262,4 +264,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables \ No newline at end of file + table.close() # close ASCII tables diff --git a/processing/post/marc_deformedGeometry.py b/processing/post/marc_deformedGeometry.py index e59c982a6..f0fbee8b1 100755 --- a/processing/post/marc_deformedGeometry.py +++ b/processing/post/marc_deformedGeometry.py @@ -55,7 +55,7 @@ else: sys.path.append(damask.solver.Marc().libraryPath('../../')) try: - from py_post import * + import py_post except: print('error: no valid Mentat release found') sys.exit(-1) @@ -63,7 +63,7 @@ except: # --------------------------- open results file and initialize mesh ---------- -p = post_open(filename+'.t16') +p = py_post.post_open(filename+'.t16') p.moveto(0) Nnodes = p.nodes() Nincrements = p.increments() - 1 # t16 contains one "virtual" increment (at 0) @@ -114,7 +114,7 @@ for incCount,position in enumerate(locations): # walk through locations p.moveto(position+1) # wind to correct position - # --- get displacements +# --- get displacements node_displacement = [[0,0,0] for i in range(Nnodes)] for n in range(Nnodes): @@ -124,10 +124,11 @@ for incCount,position in enumerate(locations): # walk through locations cellnode_displacement = [[c[i][n] for i in range(3)] for n in range(Ncellnodes)] - # --- append displacements to corresponding files +# --- append displacements to corresponding files for geomtype in options.type: - outFilename = eval('"'+eval("'%%s_%%s_inc%%0%ii.vtk'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])') + outFilename = eval('"'+eval("'%%s_%%s_inc%%0%ii.vtk'%(math.log10(max(increments+[1]))+1)")\ + +'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])') print outFilename shutil.copyfile('%s_%s.vtk'%(filename,geomtype),outFilename) diff --git a/processing/post/marc_extractData.py b/processing/post/marc_extractData.py index 1e5b76f60..1b0074135 100755 --- a/processing/post/marc_extractData.py +++ b/processing/post/marc_extractData.py @@ -10,12 +10,8 @@ scriptID = ' '.join([scriptName,damask.version]) # ----------------------------- def ParseOutputFormat(filename,homogID,crystID,phaseID): -# -# parse .output* files in order to get a list of outputs -# ----------------------------- - - myID = { - 'Homogenization': homogID, + """parse .output* files in order to get a list of outputs""" + myID = {'Homogenization': homogID, 'Crystallite': crystID, 'Constitutive': phaseID, } @@ -61,24 +57,24 @@ def ParseOutputFormat(filename,homogID,crystID,phaseID): elif length > 0: format[what]['outputs'].append([output,length]) - if not '_id' in format[what]['specials']: + if '_id' not in format[what]['specials']: print "\nsection '%s' not found in <%s>"%(myID[what], what) print '\n'.join(map(lambda x:' [%s]'%x, format[what]['specials']['brothers'])) - + return format # ----------------------------- def ParsePostfile(p,filename, outputFormat, legacyFormat): -# -# parse postfile in order to get position and labels of outputs -# needs "outputFormat" for mapping of output names to postfile output indices -# ----------------------------- + """ + parse postfile in order to get position and labels of outputs + needs "outputFormat" for mapping of output names to postfile output indices + """ startVar = {True: 'GrainCount', False:'HomogenizationCount'} - # --- build statistics +# --- build statistics stat = { \ 'IndexOfLabel': {}, \ @@ -95,7 +91,7 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat): 'LabelOfElementalTensor': [None]*p.element_tensors(), \ } - # --- find labels +# --- find labels for labelIndex in range(stat['NumberOfNodalScalars']): label = p.node_scalar_label(labelIndex) @@ -119,9 +115,9 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat): startIndex = stat['IndexOfLabel'][startVar[legacyFormat]] stat['LabelOfElementalScalar'][startIndex] = startVar[legacyFormat] - # We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file - # Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels - # given in the .output* file +# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file +# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels +# given in the .output* file offset = 1 if legacyFormat: @@ -177,10 +173,7 @@ def ParsePostfile(p,filename, outputFormat, legacyFormat): # ----------------------------- def GetIncrementLocations(p,Nincrements,options): -# -# get mapping between positions in postfile and increment number -# ----------------------------- - + """get mapping between positions in postfile and increment number""" incAtPosition = {} positionOfInc = {} @@ -209,7 +202,6 @@ def GetIncrementLocations(p,Nincrements,options): # ----------------------------- def SummarizePostfile(stat,where=sys.stdout): -# ----------------------------- where.write('\n\n') where.write('title:\t%s'%stat['Title'] + '\n\n') @@ -220,13 +212,12 @@ def SummarizePostfile(stat,where=sys.stdout): where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfNodalScalar']) + '\n\n') where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n') where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n ' + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n') - + return True # ----------------------------- def SummarizeOutputfile(format,where=sys.stdout): -# ----------------------------- where.write('\nUser Defined Outputs') for what in format.keys(): @@ -239,7 +230,6 @@ def SummarizeOutputfile(format,where=sys.stdout): # ----------------------------- def writeHeader(myfile,stat,geomtype): -# ----------------------------- myfile.write('2\theader\n') myfile.write(string.replace('$Id$','\n','\\n')+ @@ -316,7 +306,7 @@ if not os.path.exists(filename+'.t16'): sys.path.append(damask.solver.Marc().libraryPath('../../')) try: - from py_post import * + import py_post except: print('error: no valid Mentat release found') sys.exit(-1) @@ -336,14 +326,14 @@ if damask.core.mesh.mesh_init_postprocessing(filename+'.mesh'): # --- check if ip data available for all elements; if not, then .t19 file is required -p = post_open(filename+'.t16') +p = py_post.post_open(filename+'.t16') asciiFile = False p.moveto(1) for e in range(p.elements()): if not damask.core.mesh.mesh_get_nodeAtIP(str(p.element(e).type),1): if os.path.exists(filename+'.t19'): p.close() - p = post_open(filename+'.t19') + p = py_post.post_open(filename+'.t19') asciiFile = True break @@ -383,18 +373,20 @@ time_start = time.time() for incCount,position in enumerate(locations): # walk through locations p.moveto(position+1) # wind to correct position time_delta = (float(len(locations)) / float(incCount+1) - 1.0) * (time.time() - time_start) - sys.stdout.write("\r(%02i:%02i:%02i) processing increment %i of %i..."%(time_delta//3600,time_delta%3600//60,time_delta%60,incCount+1,len(locations))) + sys.stdout.write("\r(%02i:%02i:%02i) processing increment %i of %i..."\ + %(time_delta//3600,time_delta%3600//60,time_delta%60,incCount+1,len(locations))) sys.stdout.flush() - # --- write header +# --- write header outFilename = {} for geomtype in options.type: - outFilename[geomtype] = eval('"'+eval("'%%s_%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])') + outFilename[geomtype] = eval('"'+eval("'%%s_%%s_inc%%0%ii.txt'%(math.log10(max(increments+[1]))+1)")\ + +'"%(dirname + os.sep + os.path.split(filename)[1],geomtype,increments[incCount])') with open(outFilename[geomtype],'w') as myfile: writeHeader(myfile,stat,geomtype) - # --- write node based data + # --- write node based data if geomtype == 'nodebased': for n in range(stat['NumberOfNodes']): @@ -403,7 +395,7 @@ for incCount,position in enumerate(locations): # walk through locations myfile.write('\t'+str(p.node_scalar(n,l))) myfile.write('\n') - # --- write ip based data + # --- write ip based data elif geomtype == 'ipbased': for e in range(stat['NumberOfElements']): @@ -424,5 +416,3 @@ for incCount,position in enumerate(locations): # walk through locations p.close() sys.stdout.write("\n") - -# --------------------------- DONE -------------------------------- diff --git a/processing/post/mentat_colorMap.py b/processing/post/mentat_colorMap.py index 9b4c4c828..b4ecd6bd3 100755 --- a/processing/post/mentat_colorMap.py +++ b/processing/post/mentat_colorMap.py @@ -14,9 +14,9 @@ def outMentat(cmd,locals): exec(cmd[3:]) elif cmd[0:3] == '(?)': cmd = eval(cmd[3:]) - py_send(cmd) + py_mentat.py_send(cmd) else: - py_send(cmd) + py_mentat.py_send(cmd) return @@ -121,13 +121,12 @@ if options.palettef: elif options.palette: for theColor in theMap.export(format='list',steps=options.colorcount): print '\t'.join(map(lambda x: str(int(255*x)),theColor)) -else: -### connect to Mentat and change colorMap +else: # connect to Mentat and change colorMap sys.path.append(damask.solver.Marc().libraryPath('../../')) try: - from py_mentat import * + import py_mentat print 'waiting to connect...' - py_connect('',options.port) + py_mentat.py_connect('',options.port) print 'connected...' mentat = True except: @@ -138,7 +137,7 @@ else: cmds = colorMap(theMap.export(format='list',steps=options.colorcount),options.baseIdx) if mentat: output(['*show_table']+cmds+['*show_model *redraw'],outputLocals,'Mentat') - py_disconnect() + py_mentat.py_disconnect() if options.verbose: output(cmds,outputLocals,'Stdout') diff --git a/processing/post/permuteData.py b/processing/post/permuteData.py index c85805d29..9669f1b20 100755 --- a/processing/post/permuteData.py +++ b/processing/post/permuteData.py @@ -79,7 +79,7 @@ for name in filenames: # ------------------------------------------ assemble header --------------------------------------- - randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed == None else options.randomSeed # random seed per file + randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None else options.randomSeed # random seed per file np.random.seed(randomSeed) table.info_append([scriptID + '\t' + ' '.join(sys.argv[1:]), diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 67dc9c662..36bda7761 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -41,7 +41,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.), (options,filenames) = parser.parse_args() -if options.vector == None and options.tensor == None: +if options.vector is None and options.tensor is None: parser.error('no data column specified.') toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians @@ -107,8 +107,7 @@ for name in filenames: for column in items[datatype]['column']: # loop over all requested labels table.data[column:column+items[datatype]['dim']] = \ np.dot(R,np.dot(np.array(map(float,table.data[column:column+items[datatype]['dim']])).\ - reshape(items[datatype]['shape']),R.transpose())).\ - reshape(items[datatype]['dim']) + reshape(items[datatype]['shape']),R.transpose())).reshape(items[datatype]['dim']) outputAlive = table.data_write() # output processed line diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index 1ab2c1db1..922b4b696 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -164,10 +164,10 @@ if options.render: actor = vtk.vtkActor() actor.SetMapper(mapper) - # Create the graphics structure. The renderer renders into the - # render window. The render window interactor captures mouse events - # and will perform appropriate camera or actor manipulation - # depending on the nature of the events. +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. ren = vtk.vtkRenderer() @@ -181,9 +181,6 @@ if options.render: iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) - #ren.ResetCamera() - #ren.GetActiveCamera().Zoom(1.5) - iren.Initialize() renWin.Render() iren.Start() From 5d7e138a9b74ad21487b93ad1f67e7d6b200314b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 10:54:14 +0100 Subject: [PATCH 028/134] long line --- processing/post/marc_extractData.py | 9 ++++++--- processing/post/mentat_colorMap.py | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/processing/post/marc_extractData.py b/processing/post/marc_extractData.py index 1b0074135..b920a9cdd 100755 --- a/processing/post/marc_extractData.py +++ b/processing/post/marc_extractData.py @@ -209,9 +209,12 @@ def SummarizePostfile(stat,where=sys.stdout): where.write('increments:\t%i'%(stat['NumberOfIncrements']) + '\n\n') where.write('nodes:\t%i'%stat['NumberOfNodes'] + '\n\n') where.write('elements:\t%i'%stat['NumberOfElements'] + '\n\n') - where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfNodalScalar']) + '\n\n') - where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n') - where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n ' + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n') + where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n '\ + +'\n '.join(stat['LabelOfNodalScalar']) + '\n\n') + where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n '\ + + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n') + where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n '\ + + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n') return True diff --git a/processing/post/mentat_colorMap.py b/processing/post/mentat_colorMap.py index b4ecd6bd3..c2ce63238 100755 --- a/processing/post/mentat_colorMap.py +++ b/processing/post/mentat_colorMap.py @@ -59,7 +59,8 @@ def colorMap(colors,baseIdx=32): # MAIN FUNCTION STARTS HERE # ----------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage="%prog [options] predefinedScheme | (lower_h,s,l upper_h,s,l)", description = """ +parser = OptionParser(option_class=damask.extendableOption, +usage="%prog [options] predefinedScheme | (lower_h,s,l upper_h,s,l)", description = """ Changes the color map in MSC.Mentat. Interpolates colors between "lower_hsl" and "upper_hsl". From e89923d6d366e375d86e7dccf999824f769eaea2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 11:11:20 +0100 Subject: [PATCH 029/134] next round --- processing/post/imageData.py | 10 +++++----- processing/post/perceptualUniformColorMap.py | 6 +++--- processing/post/vtk_addVoxelcloudData.py | 2 +- processing/post/vtk_pointcloud.py | 6 +++--- processing/post/vtk_rectilinearGrid.py | 2 +- processing/post/vtk_voxelcloud.py | 8 ++++---- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/processing/post/imageData.py b/processing/post/imageData.py index ca64e04fe..e2c6658dd 100755 --- a/processing/post/imageData.py +++ b/processing/post/imageData.py @@ -115,7 +115,7 @@ for name in filenames: try: table = damask.ASCIItable(name = name, buffered = False, - labeled = options.label != None, + labeled = options.label is not None, readonly = True) except: continue damask.util.report(scriptName,name) @@ -131,15 +131,15 @@ for name in filenames: damask.util.croak('column {} not found.'.format(options.label)) table.close(dismiss = True) # close ASCIItable and remove empty file continue - - # convert data to values between 0 and 1 and arrange according to given options +# convert data to values between 0 and 1 and arrange according to given options if options.dimension != []: table.data = table.data.reshape(options.dimension[1],options.dimension[0]) if options.abs: table.data = np.abs(table.data) if options.log: table.data = np.log10(table.data);options.range = np.log10(options.range) if options.flipLR: table.data = np.fliplr(table.data) if options.flipUD: table.data = np.flipud(table.data) - mask = np.logical_or(table.data == options.gap, np.isnan(table.data)) if options.gap else np.logical_not(np.isnan(table.data)) # mask gap and NaN (if gap present) + mask = np.logical_or(table.data == options.gap, np.isnan(table.data))\ + if options.gap else np.logical_not(np.isnan(table.data)) # mask gap and NaN (if gap present) if np.all(np.array(options.range) == 0.0): options.range = [table.data[mask].min(), table.data[mask].max()] @@ -176,7 +176,7 @@ for name in filenames: im.save(sys.stdout if not name else os.path.splitext(name)[0]+ \ - ('' if options.label == None else '_'+options.label)+ \ + ('' if options.label is None else '_'+options.label)+ \ '.png', format = "PNG") diff --git a/processing/post/perceptualUniformColorMap.py b/processing/post/perceptualUniformColorMap.py index 7a1ff3c50..dcb6e3aab 100755 --- a/processing/post/perceptualUniformColorMap.py +++ b/processing/post/perceptualUniformColorMap.py @@ -9,7 +9,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- - # MAIN +# MAIN # -------------------------------------------------------------------- #Borland, D., & Taylor, R. M. (2007). Rainbow Color Map (Still) Considered Harmful. Computer Graphics and Applications, IEEE, 27(2), 14--17. #Moreland, K. (2009). Diverging Color Maps for Scientific Visualization. In Proc. 5th Int. Symp. Visual Computing (pp. 92--103). @@ -62,8 +62,8 @@ if options.trim[0] < -1.0 or \ parser.error('invalid trim range (-1 +1).') -name = options.format if options.basename == None else options.basename -output = sys.stdout if options.basename == None else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w') +name = options.format if options.basename is None else options.basename +output = sys.stdout if options.basename is None else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w') colorLeft = damask.Color(options.colormodel.upper(), list(options.left)) colorRight = damask.Color(options.colormodel.upper(), list(options.right)) diff --git a/processing/post/vtk_addVoxelcloudData.py b/processing/post/vtk_addVoxelcloudData.py index 67e679cde..549b80be8 100755 --- a/processing/post/vtk_addVoxelcloudData.py +++ b/processing/post/vtk_addVoxelcloudData.py @@ -32,7 +32,7 @@ parser.set_defaults(scalar = [], (options, filenames) = parser.parse_args() -if options.vtk == None or not os.path.exists(options.vtk): +if options.vtk is None or not os.path.exists(options.vtk): parser.error('VTK file does not exist') if os.path.splitext(options.vtk)[1] == '.vtu': diff --git a/processing/post/vtk_pointcloud.py b/processing/post/vtk_pointcloud.py index 5f7c5c904..7701421fc 100755 --- a/processing/post/vtk_pointcloud.py +++ b/processing/post/vtk_pointcloud.py @@ -86,8 +86,8 @@ for name in filenames: (directory,filename) = os.path.split(name) writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] - +'.'+writer.GetDefaultFileExtension())) + writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]\ + +'.'+writer.GetDefaultFileExtension())) else: writer = vtk.vtkDataSetWriter() writer.WriteToOutputStringOn() @@ -96,6 +96,6 @@ for name in filenames: if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(Polydata) else: writer.SetInputData(Polydata) writer.Write() - if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) + if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) table.close() diff --git a/processing/post/vtk_rectilinearGrid.py b/processing/post/vtk_rectilinearGrid.py index 758e4df22..a00d60185 100755 --- a/processing/post/vtk_rectilinearGrid.py +++ b/processing/post/vtk_rectilinearGrid.py @@ -111,6 +111,6 @@ for name in filenames: if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(rGrid) else: writer.SetInputData(rGrid) writer.Write() - if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) + if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) table.close() diff --git a/processing/post/vtk_voxelcloud.py b/processing/post/vtk_voxelcloud.py index 47eb4df1a..096212b40 100755 --- a/processing/post/vtk_voxelcloud.py +++ b/processing/post/vtk_voxelcloud.py @@ -66,7 +66,7 @@ for name in filenames: max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\ ],'d') # size from bounding box, corrected for cell-centeredness - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings # ------------------------------------------ process data --------------------------------------- hexPoints = np.array([[-1,-1,-1], @@ -101,8 +101,8 @@ for name in filenames: (directory,filename) = os.path.split(name) writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] - +'.'+writer.GetDefaultFileExtension())) + writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0]\ + +'.'+writer.GetDefaultFileExtension())) else: writer = vtk.vtkDataSetWriter() writer.WriteToOutputStringOn() @@ -111,7 +111,7 @@ for name in filenames: if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(uGrid) else: writer.SetInputData(uGrid) writer.Write() - if name == None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) + if name is None: sys.stdout.write(writer.GetOutputString()[0:writer.GetOutputStringLength()]) table.close() # close input ASCII table From 3ed3073eff9aa89757e6ce3f8a8e77519442db73 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 11:29:07 +0100 Subject: [PATCH 030/134] more... --- processing/pre/geom_fromAng.py | 18 ++++++++----- processing/pre/geom_fromVPSC.py | 18 ++++++++----- .../pre/geom_fromVoronoiTessellation.py | 21 +++++++-------- processing/pre/geom_rescale.py | 26 +++++++++++-------- processing/pre/geom_toTable.py | 2 +- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/processing/pre/geom_fromAng.py b/processing/pre/geom_fromAng.py index 3cf031db8..987ff8ac1 100755 --- a/processing/pre/geom_fromAng.py +++ b/processing/pre/geom_fromAng.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask @@ -124,16 +124,22 @@ for name in filenames: continue eulerangles=np.around(eulerangles,int(options.precision)) # round to desired precision +# ensure, that rounded euler angles are not out of bounds (modulo by limits) for i,angle in enumerate(['phi1','PHI','phi2']): - eulerangles[:,i]%=limits[i] # ensure, that rounded euler angles are not out of bounds (modulo by limits) + eulerangles[:,i]%=limits[i] +# scale angles by desired precision and convert to int. create unique integer key from three euler angles by +# concatenating the string representation with leading zeros and store as integer and search unique euler angle keys. +# Texture IDs are the indices of the first occurrence, the inverse is used to construct the microstructure +# create a microstructure (texture/phase pair) for each point using unique texture IDs. +# Use longInt (64bit, i8) because the keys might be long if options.compress: formatString='{0:0>'+str(int(options.precision)+3)+'}' - euleranglesRadInt = (eulerangles*10**int(options.precision)).astype('int') # scale by desired precision and convert to int + euleranglesRadInt = (eulerangles*10**int(options.precision)).astype('int') eulerKeys = np.array([int(''.join(map(formatString.format,euleranglesRadInt[i,:]))) \ - for i in xrange(info['grid'].prod())]) # create unique integer key from three euler angles by concatenating the string representation with leading zeros and store as integer - devNull, texture, eulerKeys_idx = np.unique(eulerKeys, return_index = True, return_inverse=True)# search unique euler angle keys. Texture IDs are the indices of the first occurrence, the inverse is used to construct the microstructure - msFull = np.array([[eulerKeys_idx[i],phase[i]] for i in xrange(info['grid'].prod())],'i8') # create a microstructure (texture/phase pair) for each point using unique texture IDs. Use longInt (64bit, i8) because the keys might be long + for i in xrange(info['grid'].prod())]) + devNull, texture, eulerKeys_idx = np.unique(eulerKeys, return_index = True, return_inverse=True) + msFull = np.array([[eulerKeys_idx[i],phase[i]] for i in xrange(info['grid'].prod())],'i8') devNull,msUnique,matPoints = np.unique(msFull.view('c16'),True,True) matPoints+=1 microstructure = np.array([msFull[i] for i in msUnique]) # pick only unique microstructures diff --git a/processing/pre/geom_fromVPSC.py b/processing/pre/geom_fromVPSC.py index 99762fd5e..a555f6d07 100755 --- a/processing/pre/geom_fromVPSC.py +++ b/processing/pre/geom_fromVPSC.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np from optparse import OptionParser import damask @@ -101,16 +101,22 @@ for name in filenames: %(angle,n,eulerangles[n,0],eulerangles[n,1],eulerangles[n,2])) continue eulerangles=np.around(eulerangles,int(options.precision)) # round to desired precision +# ensure, that rounded euler angles are not out of bounds (modulo by limits) for i,angle in enumerate(['phi1','PHI','phi2']): - eulerangles[:,i]%=limits[i] # ensure, that rounded euler angles are not out of bounds (modulo by limits) + eulerangles[:,i]%=limits[i] +# scale angles by desired precision and convert to int. create unique integer key from three euler angles by +# concatenating the string representation with leading zeros and store as integer and search unique euler angle keys. +# Texture IDs are the indices of the first occurrence, the inverse is used to construct the microstructure +# create a microstructure (texture/phase pair) for each point using unique texture IDs. +# Use longInt (64bit, i8) because the keys might be long if options.compress: formatString='{0:0>'+str(int(options.precision)+3)+'}' - euleranglesRadInt = (eulerangles*10**int(options.precision)).astype('int') # scale by desired precision and convert to int + euleranglesRadInt = (eulerangles*10**int(options.precision)).astype('int') eulerKeys = np.array([int(''.join(map(formatString.format,euleranglesRadInt[i,:]))) \ - for i in xrange(info['grid'].prod())]) # create unique integer key from three euler angles by concatenating the string representation with leading zeros and store as integer - devNull, texture, eulerKeys_idx = np.unique(eulerKeys, return_index = True, return_inverse=True)# search unique euler angle keys. Texture IDs are the indices of the first occurence, the inverse is used to construct the microstructure - msFull = np.array([[eulerKeys_idx[i],phase[i]] for i in xrange(info['grid'].prod())],'i8') # create a microstructure (texture/phase pair) for each point using unique texture IDs. Use longInt (64bit, i8) because the keys might be long + for i in xrange(info['grid'].prod())]) + devNull, texture, eulerKeys_idx = np.unique(eulerKeys, return_index = True, return_inverse=True) + msFull = np.array([[eulerKeys_idx[i],phase[i]] for i in xrange(info['grid'].prod())],'i8') devNull,msUnique,matPoints = np.unique(msFull.view('c16'),True,True) matPoints+=1 microstructure = np.array([msFull[i] for i in msUnique]) # pick only unique microstructures diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index 0a6e186fe..ee29f4536 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,string +import os,sys,math import numpy as np import multiprocessing from optparse import OptionParser @@ -13,9 +13,7 @@ scriptID = ' '.join([scriptName,damask.version]) def meshgrid2(*arrs): - ''' - code inspired by http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d - ''' + """code inspired by http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d""" arrs = tuple(reversed(arrs)) arrs = tuple(arrs) lens = np.array(map(len, arrs)) @@ -45,7 +43,7 @@ def laguerreTessellation(undeformed, coords, weights, grains, nonperiodic = Fals np.array([ [ 0, 0, 0 ], ]).astype(float) if nonperiodic else \ - np.array([ + np.array([ [ -1,-1,-1 ], [ 0,-1,-1 ], [ 1,-1,-1 ], @@ -99,7 +97,8 @@ def laguerreTessellation(undeformed, coords, weights, grains, nonperiodic = Fals for i,arg in enumerate(arguments): closestSeeds[i] = findClosestSeed(arg) - return grains[closestSeeds%coords.shape[0]] # closestSeed is modulo number of original seed points (i.e. excluding periodic copies) +# closestSeed is modulo number of original seed points (i.e. excluding periodic copies) + return grains[closestSeeds%coords.shape[0]] # -------------------------------------------------------------------- # MAIN @@ -210,9 +209,9 @@ for name in filenames: table.head_read() info,extra_header = table.head_getGeom() - if options.grid != None: info['grid'] = options.grid - if options.size != None: info['size'] = options.size - if options.origin != None: info['origin'] = options.origin + if options.grid is not None: info['grid'] = options.grid + if options.size is not None: info['size'] = options.size + if options.origin is not None: info['origin'] = options.origin # ------------------------------------------ sanity checks --------------------------------------- @@ -298,7 +297,7 @@ for name in filenames: phase = options.phase * np.ones(info['microstructures'],'i') if int(options.secondphase*info['microstructures']) > 0: phase[0:int(options.secondphase*info['microstructures'])] += 1 - randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed == None \ + randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None \ else options.randomSeed # random seed for second phase np.random.seed(randomSeed) np.random.shuffle(phase) @@ -317,7 +316,7 @@ for name in filenames: config_header += ['[Grain%s]'%(str(ID).zfill(formatwidth)), '(gauss)\tphi1 %g\tPhi %g\tphi2 %g\tscatter 0.0\tfraction 1.0'%tuple(eulers[eulerID]) ] - if options.axes != None: config_header.append('axes\t%s %s %s'%tuple(options.axes)) + if options.axes is not None: config_header.append('axes\t%s %s %s'%tuple(options.axes)) table.labels_clear() table.info_clear() diff --git a/processing/pre/geom_rescale.py b/processing/pre/geom_rescale.py index b0d27f474..e005e41a9 100755 --- a/processing/pre/geom_rescale.py +++ b/processing/pre/geom_rescale.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser import damask @@ -82,8 +82,12 @@ for name in filenames: 'microstructures': 0, } - newInfo['grid'] = np.array([{True:round(o*float(n.translate(None,'xX'))), False: round(float(n.translate(None,'xX')))}[n[-1].lower() == 'x'] for o,n in zip(info['grid'],options.grid)],'i') - newInfo['size'] = np.array([{True: o*float(n.translate(None,'xX')) , False: float(n.translate(None,'xX')) }[n[-1].lower() == 'x'] for o,n in zip(info['size'],options.size)],'d') + newInfo['grid'] = np.array([{True:round(o*float(n.translate(None,'xX'))), + False: round(float(n.translate(None,'xX')))}[n[-1].lower() == 'x'] + for o,n in zip(info['grid'],options.grid)],'i') + newInfo['size'] = np.array([{True: o*float(n.translate(None,'xX')) , + False: float(n.translate(None,'xX')) }[n[-1].lower() == 'x'] + for o,n in zip(info['size'],options.size)],'d') newInfo['grid'] = np.where(newInfo['grid'] <= 0 , info['grid'],newInfo['grid']) newInfo['size'] = np.where(newInfo['size'] <= 0.0, info['size'],newInfo['size']) @@ -97,11 +101,8 @@ for name in filenames: last = this microstructure = microstructure.reshape(info['grid'],order='F') - microstructure = np.repeat( - np.repeat( - np.repeat(microstructure,multiplicity[0], axis=0), - multiplicity[1], axis=1), - multiplicity[2], axis=2) + microstructure = np.repeat(np.repeat(np.repeat(microstructure, + multiplicity[0], axis=0),multiplicity[1], axis=1),multiplicity[2], axis=2) # --- renumber to sequence 1...Ngrains if requested ------------------------------------------------ # http://stackoverflow.com/questions/10741346/np-frequency-counts-for-unique-values-in-an-array @@ -119,9 +120,12 @@ for name in filenames: remarks = [] errors = [] - if (any(newInfo['grid'] != info['grid'])): remarks.append('--> grid a b c: %s'%(' x '.join(map(str,newInfo['grid'])))) - if (any(newInfo['size'] != info['size'])): remarks.append('--> size x y z: %s'%(' x '.join(map(str,newInfo['size'])))) - if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) + if (any(newInfo['grid'] != info['grid'])): + remarks.append('--> grid a b c: %s'%(' x '.join(map(str,newInfo['grid'])))) + if (any(newInfo['size'] != info['size'])): + remarks.append('--> size x y z: %s'%(' x '.join(map(str,newInfo['size'])))) + if ( newInfo['microstructures'] != info['microstructures']): + remarks.append('--> microstructures: %i'%newInfo['microstructures']) if np.any(newInfo['grid'] < 1): errors.append('invalid new grid a b c.') if np.any(newInfo['size'] <= 0.0): errors.append('invalid new size x y z.') diff --git a/processing/pre/geom_toTable.py b/processing/pre/geom_toTable.py index 79ace7d24..dff0c8150 100755 --- a/processing/pre/geom_toTable.py +++ b/processing/pre/geom_toTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk +import os,sys import numpy as np from optparse import OptionParser import damask From f7fedc4744df10e67e8f20e4c260c91d8f0cdc7b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 12:43:09 +0100 Subject: [PATCH 031/134] next bunch of accepted scripts --- processing/pre/geom_fromTable.py | 45 ++--- processing/pre/geom_grainGrowth.py | 57 +++--- processing/pre/gmsh_identifySurfaces.py | 4 +- processing/pre/hybridIA_linODFsampling.py | 39 ++-- processing/pre/marc_addUserOutput.py | 12 +- processing/pre/mentat_pbcOnBoxMesh.py | 28 ++- processing/pre/mentat_spectralBox.py | 53 +++--- .../pre/patchFromReconstructedBoundaries.py | 180 +++++++++--------- processing/pre/seeds_fromRandom.py | 18 +- processing/pre/seeds_fromTable.py | 18 +- 10 files changed, 221 insertions(+), 233 deletions(-) diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index 68b8aa12d..53281c5df 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math,types,time +import os,sys,math,types,time import scipy.spatial, numpy as np from optparse import OptionParser import damask @@ -94,18 +94,18 @@ parser.set_defaults(symmetry = [damask.Symmetry.lattices[-1]], (options,filenames) = parser.parse_args() -input = [options.eulers != None, - options.a != None and \ - options.b != None and \ - options.c != None, - options.matrix != None, - options.quaternion != None, - options.microstructure != None, +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, + options.microstructure is not None, ] if np.sum(input) != 1: parser.error('need either microstructure label or exactly one orientation input format.') -if options.axes != None and not set(options.axes).issubset(set(['x','+x','-x','y','+y','-y','z','+z','-z'])): +if options.axes is not None and not set(options.axes).issubset(set(['x','+x','-x','y','+y','-y','z','+z','-z'])): parser.error('invalid axes {} {} {}.'.format(*options.axes)) (label,dim,inputtype) = [(options.eulers,3,'eulers'), @@ -157,7 +157,7 @@ for name in filenames: if coordDim == 2: table.data = np.insert(table.data,2,np.zeros(len(table.data)),axis=1) # add zero z coordinate for two-dimensional input if options.verbose: damask.util.croak('extending to 3D...') - if options.phase == None: + if options.phase is None: table.data = np.column_stack((table.data,np.ones(len(table.data)))) # add single phase if no phase column given if options.verbose: damask.util.croak('adding dummy phase info...') @@ -168,7 +168,7 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings delta = size/np.maximum(np.ones(3,'d'), grid) origin = mincorner - 0.5*delta # shift from cell center to corner @@ -188,7 +188,7 @@ for name in filenames: # ------------------------------------------ process data ------------------------------------------ - colOri = table.label_index(label)+(3-coordDim) # column(s) of orientation data (following 3 or 2 coordinates that were expanded to 3!) + colOri = table.label_index(label)+(3-coordDim) # column(s) of orientation data followed by 3 coordinates if inputtype == 'microstructure': @@ -207,9 +207,9 @@ for name in filenames: statistics = {'global': 0, 'local': 0} grain = -np.ones(N,dtype = 'int32') # initialize empty microstructure - orientations = [] # empty list of orientations - multiplicity = [] # empty list of orientation multiplicity (number of group members) - phases = [] # empty list of phase info + orientations = [] # orientations + multiplicity = [] # orientation multiplicity (number of group members) + phases = [] # phase info nGrains = 0 # counter for detected grains existingGrains = np.arange(nGrains) myPos = 0 # position (in list) of current grid point @@ -227,7 +227,7 @@ for name in filenames: myData = table.data[index[myPos]] # read data for current grid point myPhase = int(myData[colPhase]) - mySym = options.symmetry[min(myPhase,len(options.symmetry))-1] # select symmetry from option (take last specified option for all with higher index) + mySym = options.symmetry[min(myPhase,len(options.symmetry))-1] # take last specified option for all with higher index if inputtype == 'eulers': o = damask.Orientation(Eulers = myData[colOri:colOri+3]*toRadians, @@ -250,26 +250,27 @@ for name in filenames: if options.tolerance > 0.0: # only try to compress orientations if asked to neighbors = np.array(KDTree.query_ball_point([x,y,z], 3)) # point indices within radius +# filter neighbors: skip myself, anyone further ahead (cannot yet have a grain ID), and other phases neighbors = neighbors[(neighbors < myPos) & \ - (table.data[index[neighbors],colPhase] == myPhase)] # filter neighbors: skip myself, anyone further ahead (cannot yet have a grain ID), and other phases + (table.data[index[neighbors],colPhase] == myPhase)] grains = np.unique(grain[neighbors]) # unique grain IDs among valid neighbors if len(grains) > 0: # check immediate neighborhood first cos_disorientations = np.array([o.disorientation(orientations[grainID], SST = False)[0].quaternion.w \ for grainID in grains]) # store disorientation per grainID - closest_grain = np.argmax(cos_disorientations) # find grain among grains that has closest orientation to myself + closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself match = 'local' if cos_disorientations[closest_grain] < threshold: # orientation not close enough? - grains = existingGrains[np.atleast_1d( ( np.array(phases) == myPhase ) & \ - ( np.in1d(existingGrains,grains,invert=True) ) )] # check every other already identified grain (of my phase) + grains = existingGrains[np.atleast_1d( (np.array(phases) == myPhase ) & \ + (np.in1d(existingGrains,grains,invert=True)))] # other already identified grains (of my phase) if len(grains) > 0: cos_disorientations = np.array([o.disorientation(orientations[grainID], SST = False)[0].quaternion.w \ for grainID in grains]) # store disorientation per grainID - closest_grain = np.argmax(cos_disorientations) # find grain among grains that has closest orientation to myself + closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself match = 'global' if cos_disorientations[closest_grain] >= threshold: # orientation now close enough? @@ -331,7 +332,7 @@ for name in filenames: config_header += [''] for i,orientation in enumerate(orientations): config_header += ['[Grain%s]'%(str(i+1).zfill(formatwidth)), - 'axes\t%s %s %s'%tuple(options.axes) if options.axes != None else '', + 'axes\t%s %s %s'%tuple(options.axes) if options.axes is not None else '', '(gauss)\tphi1 %g\tPhi %g\tphi2 %g\tscatter 0.0\tfraction 1.0'%tuple(orientation.asEulers(degrees = True)), ] diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index 70fdc095f..4d5aa1b6e 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math +import os,sys,math import numpy as np from optparse import OptionParser from scipy import ndimage @@ -73,15 +73,16 @@ for name in filenames: # --- read data ------------------------------------------------------------------------------------ microstructure = np.tile(np.array(table.microstructure_read(info['grid']),'i').reshape(info['grid'],order='F'), - np.where(info['grid'] == 1, 2,1)) # make one copy along dimensions with grid == 1 + np.where(info['grid'] == 1, 2,1)) # make one copy along dimensions with grid == 1 grid = np.array(microstructure.shape) #--- initialize support data ----------------------------------------------------------------------- periodic_microstructure = np.tile(microstructure,(3,3,3))[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # periodically extend the microstructure - microstructure_original = np.copy(microstructure) # store a copy the initial microstructure to find locations of immutable indices + grid[2]/2:-grid[2]/2] # periodically extend the microstructure +# store a copy the initial microstructure to find locations of immutable indices + microstructure_original = np.copy(microstructure) X,Y,Z = np.mgrid[0:grid[0],0:grid[1],0:grid[2]] gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d))/math.pow(2.0*np.pi*options.d*options.d,1.5) @@ -99,44 +100,50 @@ for name in filenames: for i in (-1,0,1): for j in (-1,0,1): for k in (-1,0,1): + # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood) interfaceEnergy = np.maximum(boundary, interfacialEnergy(microstructure,np.roll(np.roll(np.roll( - microstructure,i,axis=0), j,axis=1), k,axis=2))) # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood) + microstructure,i,axis=0), j,axis=1), k,axis=2))) + # periodically extend interfacial energy array by half a grid size in positive and negative directions periodic_interfaceEnergy = np.tile(interfaceEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # periodically extend interfacial energy array by half a grid size in positive and negative directions - index = ndimage.morphology.distance_transform_edt(periodic_interfaceEnergy == 0., # transform bulk volume (i.e. where interfacial energy is zero) + grid[2]/2:-grid[2]/2] + # transform bulk volume (i.e. where interfacial energy is zero) + index = ndimage.morphology.distance_transform_edt(periodic_interfaceEnergy == 0., return_distances = False, - return_indices = True) # want array index of nearest voxel on periodically extended boundary -# boundaryExt = boundaryExt[index[0].flatten(),index[1].flatten(),index[2].flatten()].reshape(boundaryExt.shape) # fill bulk with energy of nearest interface | question PE: what "flatten" for? + return_indices = True) + # want array index of nearest voxel on periodically extended boundary periodic_bulkEnergy = periodic_interfaceEnergy[index[0], index[1], - index[2]].reshape(2*grid) # fill bulk with energy of nearest interface - diffusedEnergy = np.fft.irfftn(np.fft.rfftn(np.where(ndimage.morphology.binary_dilation(interfaceEnergy > 0., - structure = struc, - iterations = options.d/2 + 1), # fat boundary | question PE: why 2d - 1? I would argue for d/2 + 1 !! - periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... - grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2], # ...and zero everywhere else - 0.)\ - )*gauss) + index[2]].reshape(2*grid) # fill bulk with energy of nearest interface + diffusedEnergy = np.fft.irfftn(np.fft.rfftn( + np.where( + ndimage.morphology.binary_dilation(interfaceEnergy > 0., + structure = struc, + terations = options.d/2 + 1), # fat boundary | PE: why 2d-1? I would argue for d/2 + 1 + periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... + grid[1]/2:-grid[1]/2, + grid[2]/2:-grid[2]/2], # ...and zero everywhere else + 0.))*gauss) periodic_diffusedEnergy = np.tile(diffusedEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # periodically extend the smoothed bulk energy - index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5, # transform voxels close to interface region | question PE: what motivates 1/2 (could be any small number, or)? + grid[2]/2:-grid[2]/2] # periodically extend the smoothed bulk energy + # transform voxels close to interface region | question PE: what motivates 1/2 (could be any small number, or)? + index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5, return_distances = False, - return_indices = True) # want index of closest bulk grain + return_indices = True) # want index of closest bulk grain microstructure = periodic_microstructure[index[0], index[1], index[2]].reshape(2*grid)[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # extent grains into interface region + grid[2]/2:-grid[2]/2] # extent grains into interface region immutable = np.zeros(microstructure.shape, dtype=bool) + # find locations where immutable microstructures have been or are now for micro in options.immutable: - immutable += np.logical_or(microstructure == micro, microstructure_original == micro) # find locations where immutable microstructures have been or are now - - microstructure = np.where(immutable, microstructure_original,microstructure) # undo any changes involving immutable microstructures + immutable += np.logical_or(microstructure == micro, microstructure_original == micro) + # undo any changes involving immutable microstructures + microstructure = np.where(immutable, microstructure_original,microstructure) # --- renumber to sequence 1...Ngrains if requested ------------------------------------------------ # http://stackoverflow.com/questions/10741346/np-frequency-counts-for-unique-values-in-an-array diff --git a/processing/pre/gmsh_identifySurfaces.py b/processing/pre/gmsh_identifySurfaces.py index f35579566..71c80a1dc 100755 --- a/processing/pre/gmsh_identifySurfaces.py +++ b/processing/pre/gmsh_identifySurfaces.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,string,re +import os,re from optparse import OptionParser import damask @@ -142,7 +142,7 @@ if (options.dimension == 3): elif (options.dimension == 2): for i,l in enumerate(line): - # for pts in line[int(abs(lines)-1)]: + # for pts in line[int(abs(lines)-1)]: for pts in l: x_coord.append(point[int(pts)-1][0]) y_coord.append(point[int(pts)-1][1]) diff --git a/processing/pre/hybridIA_linODFsampling.py b/processing/pre/hybridIA_linODFsampling.py index fee991aa2..a16c0db09 100755 --- a/processing/pre/hybridIA_linODFsampling.py +++ b/processing/pre/hybridIA_linODFsampling.py @@ -3,7 +3,7 @@ from optparse import OptionParser import damask -import os,sys,math,re,random,string +import os,sys,math,random import numpy as np scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -19,7 +19,7 @@ def integerFactorization(i): return j def binAsBins(bin,intervals): - """ explode compound bin into 3D bins list """ + """explode compound bin into 3D bins list""" bins = [0]*3 bins[0] = (bin//(intervals[1] * intervals[2])) % intervals[0] bins[1] = (bin//intervals[2]) % intervals[1] @@ -27,17 +27,17 @@ def binAsBins(bin,intervals): return bins def binsAsBin(bins,intervals): - """ implode 3D bins into compound bin """ + """implode 3D bins into compound bin""" return (bins[0]*intervals[1] + bins[1])*intervals[2] + bins[2] def EulersAsBins(Eulers,intervals,deltas,center): - """ return list of Eulers translated into 3D bins list """ + """return list of Eulers translated into 3D bins list""" return [int((euler+(0.5-center)*delta)//delta)%interval \ for euler,delta,interval in zip(Eulers,deltas,intervals) \ ] def binAsEulers(bin,intervals,deltas,center): - """ compound bin number translated into list of Eulers """ + """compound bin number translated into list of Eulers""" Eulers = [0.0]*3 Eulers[2] = (bin%intervals[2] + center)*deltas[2] Eulers[1] = (bin//intervals[2]%intervals[1] + center)*deltas[1] @@ -45,7 +45,7 @@ def binAsEulers(bin,intervals,deltas,center): return Eulers def directInvRepetitions(probability,scale): - """ calculate number of samples drawn by direct inversion """ + """calculate number of samples drawn by direct inversion""" nDirectInv = 0 for bin in range(len(probability)): # loop over bins nDirectInv += int(round(probability[bin]*scale)) # calc repetition @@ -55,15 +55,12 @@ def directInvRepetitions(probability,scale): # ---------------------- sampling methods ----------------------------------------------------------------------- # ----- efficient algorithm --------- - def directInversion (ODF,nSamples): - """ ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians) """ - + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" nOptSamples = max(ODF['nNonZero'],nSamples) # random subsampling if too little samples requested nInvSamples = 0 repetition = [None]*ODF['nBins'] - probabilityScale = nOptSamples # guess scaleLower = 0.0 nInvSamplesLower = 0 @@ -96,7 +93,7 @@ def directInversion (ODF,nSamples): for bin in range(ODF['nBins']): # loop over bins repetition[bin] = int(round(ODF['dV_V'][bin]*scale)) # calc repetition - # build set +# build set set = [None]*nInvSamples i = 0 for bin in range(ODF['nBins']): @@ -110,7 +107,6 @@ def directInversion (ODF,nSamples): if (j == nInvSamples-1): ex = j else: ex = int(round(random.uniform(j+0.5,nInvSamples-0.5))) bin = set[ex] - bins = binAsBins(bin,ODF['interval']) # PE: why are we doing this?? Eulers = binAsEulers(bin,ODF['interval'],ODF['delta'],ODF['center']) orientations[j] = np.degrees(Eulers) reconstructedODF[bin] += unitInc @@ -122,8 +118,7 @@ def directInversion (ODF,nSamples): # ----- trial and error algorithms --------- def MonteCarloEulers (ODF,nSamples): - """ ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians) """ - + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" countMC = 0 maxdV_V = max(ODF['dV_V']) orientations = np.zeros((nSamples,3),'f') @@ -146,8 +141,7 @@ def MonteCarloEulers (ODF,nSamples): def MonteCarloBins (ODF,nSamples): - """ ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians) """ - + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" countMC = 0 maxdV_V = max(ODF['dV_V']) orientations = np.zeros((nSamples,3),'f') @@ -169,8 +163,7 @@ def MonteCarloBins (ODF,nSamples): def TothVanHoutteSTAT (ODF,nSamples): - """ ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians) """ - + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" orientations = np.zeros((nSamples,3),'f') reconstructedODF = np.zeros(ODF['nBins'],'f') unitInc = 1.0/nSamples @@ -199,7 +192,7 @@ def TothVanHoutteSTAT (ODF,nSamples): # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description =""" Transform linear binned ODF data into given number of orientations. IA: integral approximation, STAT: Van Houtte, MC: Monte Carlo @@ -251,7 +244,7 @@ for name in filenames: continue damask.util.report(scriptName,name) - randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed == None else options.randomSeed # random seed per file for second phase + randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase random.seed(randomSeed) # ------------------------------------------ read header and data --------------------------------- @@ -308,13 +301,13 @@ for name in filenames: 'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))), ]) - # call methods +# call methods Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'} method = Functions[options.algorithm] Orientations, ReconstructedODF = (globals()[method])(ODF,nSamples) - # calculate accuracy of sample +# calculate accuracy of sample squaredDiff = {'orig':0.0,method:0.0} squaredRelDiff = {'orig':0.0,method:0.0} mutualProd = {'orig':0.0,method:0.0} @@ -375,7 +368,7 @@ for name in filenames: '(gauss) phi1 {} Phi {} phi2 {} scatter 0.0 fraction 1.0'.format(*eulers), ] - #--- output finalization -------------------------------------------------------------------------- +#--- output finalization -------------------------------------------------------------------------- with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(nSamples)+'_material.config','w')) as outfile: outfile.write('\n'.join(materialConfig)+'\n') diff --git a/processing/pre/marc_addUserOutput.py b/processing/pre/marc_addUserOutput.py index b81c0d826..c453be63f 100755 --- a/processing/pre/marc_addUserOutput.py +++ b/processing/pre/marc_addUserOutput.py @@ -1,13 +1,14 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -''' +""" Writes meaningful labels to the marc input file (*.dat) -based on the files + +output is based on the files .output that are written during the first run of the model. -''' -import sys,os,re,string +""" +import sys,os,re from optparse import OptionParser import damask @@ -16,7 +17,6 @@ scriptID = ' '.join([scriptName,damask.version]) # ----------------------------- def ParseOutputFormat(filename,what,me): -# ----------------------------- format = {'outputs':{},'specials':{'brothers':[]}} outputmetafile = filename+'.output'+what @@ -121,7 +121,7 @@ for file in files: for what in me: outputFormat[what] = ParseOutputFormat(formatFile,what,me[what]) - if not '_id' in outputFormat[what]['specials']: + if '_id' not in outputFormat[what]['specials']: print "'%s' not found in <%s>"%(me[what],what) print '\n'.join(map(lambda x:' '+x,outputFormat[what]['specials']['brothers'])) sys.exit(1) diff --git a/processing/pre/mentat_pbcOnBoxMesh.py b/processing/pre/mentat_pbcOnBoxMesh.py index ca18af0b5..12351f410 100755 --- a/processing/pre/mentat_pbcOnBoxMesh.py +++ b/processing/pre/mentat_pbcOnBoxMesh.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import sys,os,string +import sys,os import numpy as np from optparse import OptionParser import damask @@ -17,14 +17,13 @@ def outMentat(cmd,locals): exec(cmd[3:]) elif cmd[0:3] == '(?)': cmd = eval(cmd[3:]) - py_send(cmd) + py_mentat.py_send(cmd) else: - py_send(cmd) + py_mentat.py_send(cmd) return #------------------------------------------------------------------------------------------------- def outFile(cmd,locals,dest): -#------------------------------------------------------------------------------------------------- if cmd[0:3] == '(!)': exec(cmd[3:]) elif cmd[0:3] == '(?)': @@ -37,7 +36,6 @@ def outFile(cmd,locals,dest): #------------------------------------------------------------------------------------------------- def output(cmds,locals,dest): -#------------------------------------------------------------------------------------------------- for cmd in cmds: if isinstance(cmd,list): output(cmd,locals,dest) @@ -58,12 +56,12 @@ def servoLink(): 'max': np.zeros(3,dtype='d'), 'delta': np.zeros(3,dtype='d'), } - Nnodes = py_get_int("nnodes()") + Nnodes = py_mentat.py_get_int("nnodes()") NodeCoords = np.zeros((Nnodes,3),dtype='d') for node in xrange(Nnodes): - NodeCoords[node,0] = py_get_float("node_x(%i)"%(node+1)) - NodeCoords[node,1] = py_get_float("node_y(%i)"%(node+1)) - NodeCoords[node,2] = py_get_float("node_z(%i)"%(node+1)) + NodeCoords[node,0] = py_mentat.py_get_float("node_x(%i)"%(node+1)) + NodeCoords[node,1] = py_mentat.py_get_float("node_y(%i)"%(node+1)) + NodeCoords[node,2] = py_mentat.py_get_float("node_z(%i)"%(node+1)) box['min'] = NodeCoords.min(axis=0) # find the bounding box box['max'] = NodeCoords.max(axis=0) box['delta'] = box['max']-box['min'] @@ -79,7 +77,6 @@ def servoLink(): #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # loop over all nodes for node in xrange(Nnodes): - pos = {} key = {} maxFlag = [False, False, False] Nmax = 0 @@ -97,7 +94,7 @@ def servoLink(): maxFlag[coord] = True # remember face membership (for linked nodes) if Nmin > 0: # node is on a back face - # prepare for any non-existing entries in the data structure + # prepare for any non-existing entries in the data structure if key['x'] not in baseNode.keys(): baseNode[key['x']] = {} if key['y'] not in baseNode[key['x']].keys(): @@ -166,7 +163,7 @@ else: file={'croak':sys.stdout} try: - from py_mentat import * + import py_mentat except: file['croak'].write('error: no valid Mentat release found') sys.exit(-1) @@ -176,8 +173,9 @@ outputLocals = {} file['croak'].write('\033[1m'+scriptName+'\033[0m\n\n') file['croak'].write( 'waiting to connect...\n') try: - py_connect('',options.port) - output(['*draw_manual'],outputLocals,'Mentat') # prevent redrawing in Mentat, should be much faster. Since py_connect has no return value, try this to determine if failed or not + py_mentat.py_connect('',options.port) +# prevent redrawing in Mentat, should be much faster. Since py_connect has no return value, try this to determine if failed or not + output(['*draw_manual'],outputLocals,'Mentat') except: file['croak'].write('Could not connect. Set Tools/Python/"Run as Separate Process" & "Initiate"...\n') sys.exit() @@ -191,7 +189,7 @@ output(['*remove_all_servos', cmds = servoLink() output(cmds,outputLocals,'Mentat') -py_disconnect() +py_mentat.py_disconnect() if options.verbose: output(cmds,outputLocals,sys.stdout) diff --git a/processing/pre/mentat_spectralBox.py b/processing/pre/mentat_spectralBox.py index 780698564..07154ea42 100755 --- a/processing/pre/mentat_spectralBox.py +++ b/processing/pre/mentat_spectralBox.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os, sys, string +import os,sys import numpy as np from optparse import OptionParser import damask @@ -12,19 +12,17 @@ sys.path.append(damask.solver.Marc().libraryPath('../../')) #------------------------------------------------------------------------------------------------- def outMentat(cmd,locals): -#------------------------------------------------------------------------------------------------- if cmd[0:3] == '(!)': exec(cmd[3:]) elif cmd[0:3] == '(?)': cmd = eval(cmd[3:]) - py_send(cmd) + py_mentat.py_send(cmd) else: - py_send(cmd) + py_mentat.py_send(cmd) return #------------------------------------------------------------------------------------------------- def outFile(cmd,locals,dest): -#------------------------------------------------------------------------------------------------- if cmd[0:3] == '(!)': exec(cmd[3:]) elif cmd[0:3] == '(?)': @@ -36,7 +34,6 @@ def outFile(cmd,locals,dest): #------------------------------------------------------------------------------------------------- def output(cmds,locals,dest): -#------------------------------------------------------------------------------------------------- for cmd in cmds: if isinstance(cmd,list): output(cmd,locals,dest) @@ -51,26 +48,24 @@ def output(cmds,locals,dest): #------------------------------------------------------------------------------------------------- def init(): -#------------------------------------------------------------------------------------------------- - return [ - "#"+' '.join([scriptID] + sys.argv[1:]), - "*draw_manual", # prevent redrawing in Mentat, should be much faster - "*new_model yes", - "*reset", - "*select_clear", - "*set_element_class hex8", - "*set_nodes off", - "*elements_solid", - "*show_view 4", - "*reset_view", - "*view_perspective", - "*redraw", - ] + return [ + "#"+' '.join([scriptID] + sys.argv[1:]), + "*draw_manual", # prevent redrawing in Mentat, should be much faster + "*new_model yes", + "*reset", + "*select_clear", + "*set_element_class hex8", + "*set_nodes off", + "*elements_solid", + "*show_view 4", + "*reset_view", + "*view_perspective", + "*redraw", + ] #------------------------------------------------------------------------------------------------- def mesh(r,d): -#------------------------------------------------------------------------------------------------- return [ "*add_nodes", "%f %f %f"%(0.0,0.0,0.0), @@ -102,7 +97,6 @@ def mesh(r,d): #------------------------------------------------------------------------------------------------- def material(): -#------------------------------------------------------------------------------------------------- cmds = [\ "*new_mater standard", "*mater_option general:state:solid", @@ -112,7 +106,7 @@ def material(): "*add_mater_elements", "all_existing", "*geometry_type mech_three_solid", -# "*geometry_option red_integ_capacity:on", # see below: reduced integration with one IP gave trouble being always OUTDATED... +# "*geometry_option red_integ_capacity:on", reduced integration with one IP gave trouble being always OUTDATED... "*add_geometry_elements", "all_existing", ] @@ -122,13 +116,13 @@ def material(): #------------------------------------------------------------------------------------------------- def geometry(): -#------------------------------------------------------------------------------------------------- cmds = [\ "*geometry_type mech_three_solid", # "*geometry_option red_integ_capacity:on", "*add_geometry_elements", "all_existing", - "*element_type 7", # we are NOT using reduced integration (type 117) but opt for /elementhomogeneous/ in the respective phase description (material.config) +# we are NOT using reduced integration (type 117) but opt for /elementhomogeneous/ in the respective phase description (material.config) + "*element_type 7", "all_existing", ] @@ -137,7 +131,6 @@ def geometry(): #------------------------------------------------------------------------------------------------- def initial_conditions(homogenization,microstructures): -#------------------------------------------------------------------------------------------------- elements = [] element = 0 for id in microstructures: @@ -204,7 +197,7 @@ parser.set_defaults(port = None, if options.port: try: - from py_mentat import * + import py_mentat except: parser.error('no valid Mentat release found.') @@ -258,9 +251,9 @@ for name in filenames: outputLocals = {} if options.port: - py_connect('',options.port) + py_mentat.py_connect('',options.port) output(cmds,outputLocals,'Mentat') - py_disconnect() + py_mentat.py_disconnect() else: output(cmds,outputLocals,table.__IO__['out']) # bad hack into internals of table class... diff --git a/processing/pre/patchFromReconstructedBoundaries.py b/processing/pre/patchFromReconstructedBoundaries.py index 9dd04f773..35266e245 100755 --- a/processing/pre/patchFromReconstructedBoundaries.py +++ b/processing/pre/patchFromReconstructedBoundaries.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import sys,os,math,re,string +import sys,os,math,re from optparse import OptionParser import damask @@ -18,7 +18,7 @@ except: sys.path.append(damask.solver.Marc().libraryPath('../../')) try: # check for MSC.Mentat Python interface - from py_mentat import * + import py_mentat MentatCapability = True except: MentatCapability = False @@ -29,10 +29,10 @@ def outMentat(cmd,locals): exec(cmd[3:]) elif cmd[0:3] == '(?)': cmd = eval(cmd[3:]) - py_send(cmd) + py_mentat.py_send(cmd) if 'log' in locals: locals['log'].append(cmd) else: - py_send(cmd) + py_mentat.py_send(cmd) if 'log' in locals: locals['log'].append(cmd) return @@ -83,10 +83,9 @@ def rcbOrientationParser(content,idcolumn): return grains -def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): # parser for TSL-OIM reconstructed boundary files - +def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): + """parser for TSL-OIM reconstructed boundary files""" # find bounding box - boxX = [1.*sys.maxint,-1.*sys.maxint] boxY = [1.*sys.maxint,-1.*sys.maxint] x = [0.,0.] @@ -145,8 +144,8 @@ def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): # parser for T match = True break break +# force to boundary if inside tolerance to it if (not match): - # force to boundary if inside tolerance to it if (abs(x[i])= y) # am I above testpoint? - for i in range(npoints): # loop through all points - (x2,y2) = points[i] # next point - endover = (y2 >= y) # am I above testpoint? - if (startover != endover): # one above one below testpoint? - if((y2 - y)*(x2 - x1) <= (y2 - y1)*(x2 - x)): # check for intersection - if (endover): - inside = not inside # found intersection - else: - if (not endover): - inside = not inside # found intersection - startover = endover # make second point first point - (x1,y1) = (x2,y2) - - return inside +def inside(x,y,points): + """tests whether point(x,y) is within polygon described by points""" + inside = False + npoints=len(points) + (x1,y1) = points[npoints-1] # start with last point of points + startover = (y1 >= y) # am I above testpoint? + for i in range(npoints): # loop through all points + (x2,y2) = points[i] # next point + endover = (y2 >= y) # am I above testpoint? + if (startover != endover): # one above one below testpoint? + if((y2 - y)*(x2 - x1) <= (y2 - y1)*(x2 - x)): # check for intersection + if (endover): + inside = not inside # found intersection + else: + if (not endover): + inside = not inside # found intersection + startover = endover # make second point first point + (x1,y1) = (x2,y2) + + return inside # ------------------------- -def fftbuild(rcData,height,xframe,yframe,resolution,extrusion): # build array of grain numbers -# ------------------------- - maxX = -1.*sys.maxint - maxY = -1.*sys.maxint - for line in rcData['point']: # find data range - (x,y) = line - maxX = max(maxX, x) - maxY = max(maxY, y) - xsize = maxX+2*xframe # add framsize - ysize = maxY+2*yframe - xres = int(round(resolution/2.0)*2) # use only even resolution - yres = int(round(xres/xsize*ysize/2.0)*2) # calculate other resolutions - zres = extrusion - zsize = extrusion*min([xsize/xres,ysize/yres]) +def fftbuild(rcData,height,xframe,yframe,resolution,extrusion): + """build array of grain numbers""" + maxX = -1.*sys.maxint + maxY = -1.*sys.maxint + for line in rcData['point']: # find data range + (x,y) = line + maxX = max(maxX, x) + maxY = max(maxY, y) + xsize = maxX+2*xframe # add framsize + ysize = maxY+2*yframe + xres = int(round(resolution/2.0)*2) # use only even resolution + yres = int(round(xres/xsize*ysize/2.0)*2) # calculate other resolutions + zres = extrusion + zsize = extrusion*min([xsize/xres,ysize/yres]) + + fftdata = {'fftpoints':[], \ + 'resolution':(xres,yres,zres), \ + 'dimension':(xsize,ysize,zsize)} + + frameindex=len(rcData['grain'])+1 # calculate frame index as largest grain index plus one + dx = xsize/(xres+1) # calculate step sizes + dy = ysize/(yres+1) - fftdata = {'fftpoints':[], \ - 'resolution':(xres,yres,zres), \ - 'dimension':(xsize,ysize,zsize)} + grainpoints = [] + for segments in rcData['grain']: # get segments of each grain + points = {} + for i,segment in enumerate(segments[:-1]): # loop thru segments except last (s=[start,end]) + points[rcData['segment'][segment][0]] = i # assign segment index to start point + points[rcData['segment'][segment][1]] = i # assigne segment index to endpoint + for i in range(2): # check points of last segment + if points[rcData['segment'][segments[-1]][i]] != 0: # not on first segment + points[rcData['segment'][segments[-1]][i]] = len(segments)-1 # assign segment index to last point + + grainpoints.append([]) # start out blank for current grain + for p in sorted(points, key=points.get): # loop thru set of sorted points + grainpoints[-1].append([rcData['point'][p][0],rcData['point'][p][1]]) # append x,y of point - frameindex=len(rcData['grain'])+1 # calculate frame index as largest grain index plus one - dx = xsize/(xres+1) # calculate step sizes - dy = ysize/(yres+1) - - grainpoints = [] - for segments in rcData['grain']: # get segments of each grain - points = {} - for i,segment in enumerate(segments[:-1]): # loop thru segments except last (s=[start,end]) - points[rcData['segment'][segment][0]] = i # assign segment index to start point - points[rcData['segment'][segment][1]] = i # assigne segment index to endpoint - for i in range(2): # check points of last segment - if points[rcData['segment'][segments[-1]][i]] != 0: # not on first segment - points[rcData['segment'][segments[-1]][i]] = len(segments)-1 # assign segment index to last point - - grainpoints.append([]) # start out blank for current grain - for p in sorted(points, key=points.get): # loop thru set of sorted points - grainpoints[-1].append([rcData['point'][p][0],rcData['point'][p][1]]) # append x,y of point - - bestGuess = 0 # assume grain 0 as best guess - for i in range(int(xres*yres)): # walk through all points in xy plane - xtest = -xframe+((i%xres)+0.5)*dx # calculate coordinates - ytest = -yframe+(int(i/xres)+0.5)*dy - if(xtest < 0 or xtest > maxX): # check wether part of frame - if( ytest < 0 or ytest > maxY): # part of edges - fftdata['fftpoints'].append(frameindex+2) # append frameindex to result array - else: # part of xframe - fftdata['fftpoints'].append(frameindex) # append frameindex to result array - elif( ytest < 0 or ytest > maxY): # part of yframe - fftdata['fftpoints'].append(frameindex+1) # append frameindex to result array - else: - if inside(xtest,ytest,grainpoints[bestGuess]): # check best guess first - fftdata['fftpoints'].append(bestGuess+1) - else: # no success - for g in range(len(grainpoints)): # test all - if inside(xtest,ytest,grainpoints[g]): - fftdata['fftpoints'].append(g+1) - bestGuess = g - break - - return fftdata + bestGuess = 0 # assume grain 0 as best guess + for i in range(int(xres*yres)): # walk through all points in xy plane + xtest = -xframe+((i%xres)+0.5)*dx # calculate coordinates + ytest = -yframe+(int(i/xres)+0.5)*dy + if(xtest < 0 or xtest > maxX): # check wether part of frame + if( ytest < 0 or ytest > maxY): # part of edges + fftdata['fftpoints'].append(frameindex+2) # append frameindex to result array + else: # part of xframe + fftdata['fftpoints'].append(frameindex) # append frameindex to result array + elif( ytest < 0 or ytest > maxY): # part of yframe + fftdata['fftpoints'].append(frameindex+1) # append frameindex to result array + else: + if inside(xtest,ytest,grainpoints[bestGuess]): # check best guess first + fftdata['fftpoints'].append(bestGuess+1) + else: # no success + for g in range(len(grainpoints)): # test all + if inside(xtest,ytest,grainpoints[g]): + fftdata['fftpoints'].append(g+1) + bestGuess = g + break + + return fftdata # ----------------------- MAIN ------------------------------- @@ -926,12 +924,12 @@ if 'mentat' in options.output: ] outputLocals = {'log':[]} - if (options.port != None): - py_connect('',options.port) + if (options.port is not None): + py_mentat.py_connect('',options.port) try: output(cmds,outputLocals,'Mentat') finally: - py_disconnect() + py_mentat.py_disconnect() if 'procedure' in options.output: output(outputLocals['log'],outputLocals,'Stdout') else: diff --git a/processing/pre/seeds_fromRandom.py b/processing/pre/seeds_fromRandom.py index a6ce90cec..29bf85712 100755 --- a/processing/pre/seeds_fromRandom.py +++ b/processing/pre/seeds_fromRandom.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,math,random +import os,sys,math,random import numpy as np import damask from optparse import OptionParser,OptionGroup @@ -14,9 +14,7 @@ scriptID = ' '.join([scriptName,damask.version]) # ------------------------------------------ aux functions --------------------------------- def kdtree_search(cloud, queryPoints): - ''' - find distances to nearest neighbor among cloud (N,d) for each of the queryPoints (n,d) - ''' + """find distances to nearest neighbor among cloud (N,d) for each of the queryPoints (n,d)""" n = queryPoints.shape[0] distances = np.zeros(n,dtype=float) tree = spatial.cKDTree(cloud) @@ -112,7 +110,7 @@ parser.set_defaults(randomSeed = None, options.grid = np.array(options.grid) gridSize = options.grid.prod() -if options.randomSeed == None: options.randomSeed = int(os.urandom(4).encode('hex'), 16) +if options.randomSeed is None: options.randomSeed = int(os.urandom(4).encode('hex'), 16) np.random.seed(options.randomSeed) # init random generators random.seed(options.randomSeed) @@ -133,10 +131,12 @@ for name in filenames: remarks = [] errors = [] - if gridSize == 0: errors.append('zero grid dimension for %s.'%(', '.join([['a','b','c'][x] for x in np.where(options.grid == 0)[0]]))) + if gridSize == 0: + errors.append('zero grid dimension for %s.'%(', '.join([['a','b','c'][x] for x in np.where(options.grid == 0)[0]]))) if options.N > gridSize/10.: errors.append('seed count exceeds 0.1 of grid points.') if options.selective and 4./3.*math.pi*(options.distance/2.)**3*options.N > 0.5: - (remarks if options.force else errors).append('maximum recommended seed point count for given distance is {}.{}'.format(int(3./8./math.pi/(options.distance/2.)**3),'..'*options.force)) + (remarks if options.force else errors).append('maximum recommended seed point count for given distance is {}.{}'. + format(int(3./8./math.pi/(options.distance/2.)**3),'..'*options.force)) if remarks != []: damask.util.croak(remarks) if errors != []: @@ -153,7 +153,7 @@ for name in filenames: if not options.selective: seeds = np.zeros((3,options.N),dtype='d') # seed positions array - gridpoints = random.sample(range(gridSize),options.N) # create random permutation of all grid positions and choose first N + gridpoints = random.sample(range(gridSize),options.N) # choose first N from random permutation of grid positions seeds[0,:] = (np.mod(gridpoints ,options.grid[0])\ +np.random.random(options.N)) /options.grid[0] @@ -174,7 +174,7 @@ for name in filenames: distances = kdtree_search(seeds[:i],candidates) best = distances.argmax() if distances[best] > options.distance: # require minimum separation - seeds[i] = candidates[best] # take candidate with maximum separation to existing point cloud + seeds[i] = candidates[best] # maximum separation to existing point cloud i += 1 if i%(options.N/100.) < 1: damask.util.croak('.',False) diff --git a/processing/pre/seeds_fromTable.py b/processing/pre/seeds_fromTable.py index 293c1a66f..45a2b386b 100755 --- a/processing/pre/seeds_fromTable.py +++ b/processing/pre/seeds_fromTable.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,string,itertools +import os,itertools import numpy as np from optparse import OptionParser import damask @@ -50,8 +50,8 @@ parser.set_defaults(pos = 'pos', (options,filenames) = parser.parse_args() -if options.whitelist != None: options.whitelist = map(int,options.whitelist) -if options.blacklist != None: options.blacklist = map(int,options.blacklist) +if options.whitelist is not None: options.whitelist = map(int,options.whitelist) +if options.blacklist is not None: options.blacklist = map(int,options.blacklist) # --- loop over input files ------------------------------------------------------------------------- @@ -101,13 +101,11 @@ for name in filenames: # --- filtering of grain voxels -------------------------------------------------------------------- - mask = np.logical_and(\ - np.ones_like(table.data[:,3],bool) \ - if options.whitelist == None \ - else np.in1d(table.data[:,3].ravel(), options.whitelist).reshape(table.data[:,3].shape), - np.ones_like(table.data[:,3],bool) \ - if options.blacklist == None \ - else np.invert(np.in1d(table.data[:,3].ravel(), options.blacklist).reshape(table.data[:,3].shape)) + mask = np.logical_and( + np.ones_like(table.data[:,3],bool) if options.whitelist is None \ + else np.in1d(table.data[:,3].ravel(), options.whitelist).reshape(table.data[:,3].shape), + np.ones_like(table.data[:,3],bool) if options.blacklist is None \ + else np.invert(np.in1d(table.data[:,3].ravel(), options.blacklist).reshape(table.data[:,3].shape)) ) table.data = table.data[mask] From 9fa49b858481c73b6e3946d463abdb131769eb4c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 2 Mar 2016 13:52:33 +0100 Subject: [PATCH 032/134] vtk files, mainly removed from vtk import * --- processing/post/vtk2ang.py | 118 ++++++++++++------------- processing/post/vtk_addData.py | 1 - processing/post/vtk_scalars2vectors.py | 20 ++--- 3 files changed, 65 insertions(+), 74 deletions(-) diff --git a/processing/post/vtk2ang.py b/processing/post/vtk2ang.py index 639158293..a744d2e3b 100755 --- a/processing/post/vtk2ang.py +++ b/processing/post/vtk2ang.py @@ -4,17 +4,15 @@ import os,string,math,sys import numpy as np from optparse import OptionParser -from vtk import * +import vtk +import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) # ----------------------------- def getHeader(filename,sizeFastIndex,sizeSlowIndex,stepsize): -# ----------------------------- -# returns header for ang file -# step size in micrometer - + """returns header for ang file step size in micrometer""" return '\n'.join([ \ '# TEM_PIXperUM 1.000000', \ '# x-star 1.000000', \ @@ -50,10 +48,7 @@ def getHeader(filename,sizeFastIndex,sizeSlowIndex,stepsize): # ----------------------------- def positiveRadians(angle): -# ----------------------------- -# returns positive angle in radians -# gets angle in degrees - + """returns positive angle in radians from angle in degrees""" angle = math.radians(float(angle)) while angle < 0.0: angle += 2.0 * math.pi @@ -63,11 +58,12 @@ def positiveRadians(angle): # ----------------------------- def getDataLine(angles,x,y,validData=True): -# ----------------------------- -# returns string of one line in ang file -# convention in ang file: y coordinate comes first and is fastest index -# positions in micrometer - + """ + returns string of one line in ang file + + convention in ang file: y coordinate comes first and is fastest index + positions in micrometer + """ info = {True: (9999.9, 1.0, 0,99999,0.0), False: ( -1.0,-1.0,-1, -1,1.0)} return '%9.5f %9.5f %9.5f %12.5f %12.5f %6.1f %6.3f %2i %6i %6.3f \n'%(tuple(map(positiveRadians,angles))+(y*1e6,x*1e6)+info[validData]) @@ -155,10 +151,9 @@ if options.hexagonal: for filename in filenames: - # Read the source file - if options.verbose: sys.stdout.write("\nREADING VTK FILE\n") - reader = vtkUnstructuredGridReader() +# Read the source file + reader = vtk.vtkUnstructuredGridReader() reader.SetFileName(filename) reader.ReadAllScalarsOn() reader.ReadAllVectorsOn() @@ -166,7 +161,7 @@ for filename in filenames: undeformedMesh = reader.GetOutput() - # Get euler angles from cell data +# Get euler angles from cell data if options.verbose: sys.stdout.write("\nGETTING EULER ANGLES\n") angles = {} @@ -177,14 +172,14 @@ for filename in filenames: if options.verbose: sys.stdout.write(" found scalar with name %s\n"%scalarName) if len(angles) < 3: # found data for all three euler angles? for label in options.eulerLabel: - if not label in angles.keys(): + if label not in angles.keys(): parser.error('Could not find scalar data with name %s'%label) - # Get deformed mesh +# Get deformed mesh if options.verbose: sys.stdout.write("\nDEFORM MESH\n") - warpVector = vtkWarpVector() + warpVector = vtk.vtkWarpVector() undeformedMesh.GetPointData().SetActiveVectors(options.dispLabel) warpVector.SetInput(undeformedMesh) warpVector.Update() @@ -197,29 +192,29 @@ for filename in filenames: sys.stdout.write(" z (% .8f % .8f)\n"%(box[4],box[5])) - # Get cell centers of deformed mesh (position of ips) +# Get cell centers of deformed mesh (position of ips) if options.verbose: sys.stdout.write("\nGETTING CELL CENTERS OF DEFORMED MESH\n") - cellCenter = vtkCellCenters() + cellCenter = vtk.vtkCellCenters() cellCenter.SetVertexCells(0) # do not generate vertex cells, just points cellCenter.SetInput(deformedMesh) cellCenter.Update() meshIPs = cellCenter.GetOutput() - # Get outer surface of deformed mesh +# Get outer surface of deformed mesh if options.verbose: sys.stdout.write("\nGETTING OUTER SURFACE OF DEFORMED MESH\n") - surfaceFilter = vtkDataSetSurfaceFilter() + surfaceFilter = vtk.vtkDataSetSurfaceFilter() surfaceFilter.SetInput(deformedMesh) surfaceFilter.Update() surface = surfaceFilter.GetOutput() - # Get coordinate system for ang files - # z-vector is normal to slices - # x-vector corresponds to the up-direction - # "R" rotates coordinates from the mesh system into the TSL system +# Get coordinate system for ang files +# z-vector is normal to slices +# x-vector corresponds to the up-direction +# "R" rotates coordinates from the mesh system into the TSL system if options.verbose: sys.stdout.write("\nGETTING COORDINATE SYSTEM FOR ANG FILES\n") z = np.array(options.normal,dtype='float') @@ -235,7 +230,7 @@ for filename in filenames: sys.stdout.write(" z (% .8f % .8f % .8f)\n"%tuple(z)) - # Get bounding box in rotated system (x,y,z) +# Get bounding box in rotated system (x,y,z) if options.verbose: sys.stdout.write("\nGETTING BOUNDING BOX IN ROTATED SYSTEM\n") rotatedbox = [[np.inf,-np.inf] for i in range(3)] # bounding box in rotated TSL system @@ -254,8 +249,8 @@ for filename in filenames: sys.stdout.write(" z (% .8f % .8f)\n"%tuple(rotatedbox[2])) - # Correct bounding box so that a multiplicity of the resolution fits into it - # and get number of points and extent in each (rotated) axis direction +# Correct bounding box so that a multiplicity of the resolution fits into it +# and get number of points and extent in each (rotated) axis direction if options.verbose: sys.stdout.write("\nCORRECTING EXTENT OF BOUNDING BOX IN ROTATED SYSTEM\n") correction = [] @@ -284,12 +279,12 @@ for filename in filenames: sys.stdout.write(" z (% .8f % .8f)\n"%tuple(rotatedbox[2])) - # Generate new regular point grid for ang files - # Use "polydata" object with points as single vertices - # beware of TSL convention: y direction is fastest index +# Generate new regular point grid for ang files +# Use "polydata" object with points as single vertices +# beware of TSL convention: y direction is fastest index if options.verbose: sys.stdout.write("\nGENERATING POINTS FOR POINT GRID") - points = vtkPoints() + points = vtk.vtkPoints() for k in xrange(Npoints[2]): for j in xrange(Npoints[0]): for i in xrange(Npoints[1]): # y is fastest index @@ -309,9 +304,9 @@ for filename in filenames: sys.stdout.write(" grid resolution: %.8f\n"%options.resolution) if options.verbose: sys.stdout.write("\nGENERATING VERTICES FOR POINT GRID") - vertices = vtkCellArray() + vertices = vtk.vtkCellArray() for i in xrange(totalNpoints): - vertex = vtkVertex() + vertex = vtk.vtkVertex() vertex.GetPointIds().SetId(0,i) # each vertex consists of exactly one (index 0) point with ID "i" vertices.InsertNextCell(vertex) if options.verbose: @@ -319,34 +314,35 @@ for filename in filenames: sys.stdout.flush() if options.verbose: sys.stdout.write("\n\nGENERATING POINT GRID\n") - pointgrid = vtkPolyData() + pointgrid = vtk.vtkPolyData() pointgrid.SetPoints(points) pointgrid.SetVerts(vertices) pointgrid.Update() - # Find out which points reside inside mesh geometry +# Find out which points reside inside mesh geometry if options.verbose: sys.stdout.write("\nIDENTIFYING POINTS INSIDE MESH GEOMETRY\n") - enclosedPoints = vtkSelectEnclosedPoints() + enclosedPoints = vtk.vtkSelectEnclosedPoints() enclosedPoints.SetSurface(surface) enclosedPoints.SetInput(pointgrid) enclosedPoints.Update() - # Build kdtree from mesh IPs and match mesh IPs to point grid +# Build kdtree from mesh IPs and match mesh IPs to point grid if options.verbose: sys.stdout.write("\nBUILDING MAPPING OF GRID POINTS") - kdTree = vtkKdTree() + kdTree = vtk.vtkKdTree() kdTree.BuildLocatorFromPoints(meshIPs.GetPoints()) gridToMesh = [] - ids = vtkIdList() + ids = vtk.vtkIdList() NenclosedPoints = 0 for i in range(pointgrid.GetNumberOfPoints()): gridToMesh.append([]) if enclosedPoints.IsInside(i): NenclosedPoints += 1 - kdTree.FindClosestNPoints(options.interpolation,pointgrid.GetPoint(i),ids) # here one could use faster(?) "FindClosestPoint" if only first nearest neighbor required +# here one could use faster(?) "FindClosestPoint" if only first nearest neighbor required + kdTree.FindClosestNPoints(options.interpolation,pointgrid.GetPoint(i),ids) for j in range(ids.GetNumberOfIds()): gridToMesh[-1].extend([ids.GetId(j)]) if options.verbose: @@ -358,7 +354,7 @@ for filename in filenames: - # ITERATE OVER SLICES AND CREATE ANG FILE +# ITERATE OVER SLICES AND CREATE ANG FILE if options.verbose: sys.stdout.write("\nWRITING OUT ANG FILES\n") @@ -404,13 +400,13 @@ for filename in filenames: angfile.write(getDataLine(interpolatedPhi,x,y,enclosedPoints.IsInside(i))) - # Visualize slices +# Visualize slices if options.visualize: - meshMapper = vtkDataSetMapper() + meshMapper = vtk.vtkDataSetMapper() meshMapper.SetInput(surface) meshMapper.ScalarVisibilityOff() # do not use scalar data for coloring - meshActor = vtkActor() + meshActor = vtk.vtkActor() meshActor.SetMapper(meshMapper) meshActor.GetProperty().SetOpacity(0.2) meshActor.GetProperty().SetColor(1.0,1.0,0) @@ -418,43 +414,43 @@ for filename in filenames: # meshActor.GetProperty().SetEdgeColor(1,1,0.5) # meshActor.GetProperty().EdgeVisibilityOn() - boxpoints = vtkPoints() + boxpoints = vtk.vtkPoints() for n in range(8): P = [rotatedbox[0][(n/1)%2], rotatedbox[1][(n/2)%2], rotatedbox[2][(n/4)%2]] boxpoints.InsertNextPoint(list(np.dot(R.T,np.array(P)))) - box = vtkHexahedron() + box = vtk.vtkHexahedron() for n,i in enumerate([0,1,3,2,4,5,7,6]): box.GetPointIds().SetId(n,i) - boxgrid = vtkUnstructuredGrid() + boxgrid = vtk.vtkUnstructuredGrid() boxgrid.SetPoints(boxpoints) boxgrid.InsertNextCell(box.GetCellType(), box.GetPointIds()) - boxsurfaceFilter = vtkDataSetSurfaceFilter() + boxsurfaceFilter = vtk.vtkDataSetSurfaceFilter() boxsurfaceFilter.SetInput(boxgrid) boxsurfaceFilter.Update() boxsurface = boxsurfaceFilter.GetOutput() - boxMapper = vtkDataSetMapper() + boxMapper = vtk.vtkDataSetMapper() boxMapper.SetInput(boxsurface) - boxActor = vtkActor() + boxActor = vtk.vtkActor() boxActor.SetMapper(boxMapper) boxActor.GetProperty().SetLineWidth(2.0) boxActor.GetProperty().SetRepresentationToWireframe() - gridMapper = vtkDataSetMapper() + gridMapper = vtk.vtkDataSetMapper() gridMapper.SetInput(pointgrid) - gridActor = vtkActor() + gridActor = vtk.vtkActor() gridActor.SetMapper(gridMapper) gridActor.GetProperty().SetColor(0,0,0) gridActor.GetProperty().SetPointSize(3) - renderer = vtkRenderer() - renderWindow = vtkRenderWindow() + renderer = vtk.vtkRenderer() + renderWindow = vtk.vtkRenderWindow() renderWindow.FullScreenOn() renderWindow.AddRenderer(renderer) - renderWindowInteractor = vtkRenderWindowInteractor() + renderWindowInteractor = vtk.vtkRenderWindowInteractor() renderWindowInteractor.SetRenderWindow(renderWindow) renderer.AddActor(meshActor) renderer.AddActor(boxActor) @@ -462,6 +458,6 @@ for filename in filenames: renderer.SetBackground(1,1,1) renderWindow.Render() - renderWindowInteractor.SetInteractorStyle(vtkInteractorStyleTrackballCamera()) + renderWindowInteractor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera()) renderWindowInteractor.Start() diff --git a/processing/post/vtk_addData.py b/processing/post/vtk_addData.py index 2e44714ca..97937dd86 100755 --- a/processing/post/vtk_addData.py +++ b/processing/post/vtk_addData.py @@ -10,7 +10,6 @@ scriptID = ' '.join([scriptName,damask.version]) # ----------------------------- def findTag(filename,tag): -# ----------------------------- with open(filename,'r') as myfile: mypattern = re.compile(str(tag)) diff --git a/processing/post/vtk_scalars2vectors.py b/processing/post/vtk_scalars2vectors.py index 5b1ede858..4aca33236 100755 --- a/processing/post/vtk_scalars2vectors.py +++ b/processing/post/vtk_scalars2vectors.py @@ -4,7 +4,7 @@ import os,sys,shutil import damask from optparse import OptionParser -from vtk import * +import vtk scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -44,18 +44,16 @@ for filename in filenames: for filename in filenames: - # Read the source file - sys.stdout.write('read file "%s" ...'%filename) sys.stdout.flush() suffix = os.path.splitext(filename)[1] if suffix == '.vtk': - reader = vtkUnstructuredGridReader() + reader = vtk.vtkUnstructuredGridReader() reader.ReadAllScalarsOn() reader.ReadAllVectorsOn() reader.ReadAllTensorsOn() elif suffix == '.vtu': - reader = vtkXMLUnstructuredGridReader() + reader = vtk.vtkXMLUnstructuredGridReader() else: parser.error('filetype "%s" not supported'%suffix) reader.SetFileName(filename) @@ -65,7 +63,7 @@ for filename in filenames: sys.stdout.flush() - # Read the scalar data +# Read the scalar data scalarData = {} scalarsToBeRemoved = [] @@ -83,19 +81,18 @@ for filename in filenames: scalarsToBeRemoved.append(scalarName) for scalarName in scalarsToBeRemoved: uGrid.GetCellData().RemoveArray(scalarName) - # uGrid.UpdateData() sys.stdout.write('\rread scalar data done\n') sys.stdout.flush() - # Convert the scalar data to vector data +# Convert the scalar data to vector data NscalarData = len(scalarData) for n,label in enumerate(scalarData): sys.stdout.write("\rconvert to vector data %d%%" %(100*n/NscalarData)) sys.stdout.flush() Nvalues = scalarData[label][0].GetNumberOfTuples() - vectorData = vtkDoubleArray() + vectorData = vtk.vtkDoubleArray() vectorData.SetName(label) vectorData.SetNumberOfComponents(3) # set this before NumberOfTuples !!! vectorData.SetNumberOfTuples(Nvalues) @@ -103,16 +100,15 @@ for filename in filenames: for j in range(3): vectorData.SetComponent(i,j,scalarData[label][j].GetValue(i)) uGrid.GetCellData().AddArray(vectorData) - # uGrid.GetCellData().SetActiveVectors(label) sys.stdout.write('\rconvert to vector data done\n') - # Write to new vtk file +# Write to new vtk file outfilename = os.path.splitext(filename)[0]+'.vtu' sys.stdout.write('write to file "%s" ...'%outfilename) sys.stdout.flush() - writer = vtkXMLUnstructuredGridWriter() + writer = vtk.vtkXMLUnstructuredGridWriter() writer.SetFileName(outfilename+'_tmp') writer.SetDataModeToAscii() writer.SetInput(uGrid) From 5233236abab2102e282300a43987143436de8084 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 2 Mar 2016 16:22:42 +0100 Subject: [PATCH 033/134] updated version information after successful test of revision3813-1035-g5d7e138 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 509bf817b..2e183f9ba 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1031-g4d8aad3 +revision3813-1035-g5d7e138 From bce256ad22f5cc9ba84ec2427f29238967147888 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 3 Mar 2016 04:15:49 +0100 Subject: [PATCH 034/134] updated version information after successful test of revision3813-1036-g5233236 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2e183f9ba..e8f9f40c8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1035-g5d7e138 +revision3813-1036-g5233236 From 93d7643875f2949019e23204139c7a59806af7fa Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Mar 2016 10:43:43 +0100 Subject: [PATCH 035/134] no long lines anymore and prospector is also happy --- processing/post/addCompatibilityMismatch.py | 6 +- processing/post/addPK2.py | 3 +- processing/post/perceptualUniformColorMap.py | 6 +- processing/post/postResults.py | 219 +++++++------------ processing/post/vtk2ang.py | 3 +- processing/post/vtk_voxelcloud.py | 7 +- 6 files changed, 99 insertions(+), 145 deletions(-) diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index 1753cb923..f237f7d19 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -115,8 +115,8 @@ for name in filenames: while table.data_read(): (x,y,z) = damask.util.gridLocation(idx,grid) # figure out (x,y,z) position from line count idx += 1 - F[0:3,0:3,x,y,z] = np.array(map(float,table.data[column:column+9]),'d').reshape(3,3) - print 'hm' + F[0:3,0:3,x,y,z] = np.array(map(float,table.data[column:column+9]),'d').reshape(3,3) + Favg = damask.core.math.tensorAvg(F) centres = damask.core.mesh.deformedCoordsFFT(size,F,Favg,[1.0,1.0,1.0]) @@ -137,4 +137,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close ASCII tables \ No newline at end of file + table.close() # close ASCII tables diff --git a/processing/post/addPK2.py b/processing/post/addPK2.py index 831394935..349b9e106 100755 --- a/processing/post/addPK2.py +++ b/processing/post/addPK2.py @@ -14,7 +14,8 @@ scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add column(s) containing Second Piola--Kirchhoff stress based on given column(s) of deformation gradient and first Piola--Kirchhoff stress. +Add column(s) containing Second Piola--Kirchhoff stress based on given column(s) of deformation +gradient and first Piola--Kirchhoff stress. """, version = scriptID) diff --git a/processing/post/perceptualUniformColorMap.py b/processing/post/perceptualUniformColorMap.py index dcb6e3aab..c2201f76b 100755 --- a/processing/post/perceptualUniformColorMap.py +++ b/processing/post/perceptualUniformColorMap.py @@ -62,8 +62,10 @@ if options.trim[0] < -1.0 or \ parser.error('invalid trim range (-1 +1).') -name = options.format if options.basename is None else options.basename -output = sys.stdout if options.basename is None else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w') +name = options.format if options.basename is None\ + else options.basename +output = sys.stdout if options.basename is None\ + else open(os.path.basename(options.basename)+extensions[outtypes.index(options.format)],'w') colorLeft = damask.Color(options.colormodel.upper(), list(options.left)) colorRight = damask.Color(options.colormodel.upper(), list(options.right)) diff --git a/processing/post/postResults.py b/processing/post/postResults.py index 0dfca8279..baa306003 100755 --- a/processing/post/postResults.py +++ b/processing/post/postResults.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,math,re,threading,time,struct,string +import os,sys,math,re,time,struct,string import damask from optparse import OptionParser, OptionGroup @@ -17,7 +17,6 @@ fileExtensions = { \ # ----------------------------- class vector: # mimic py_post node object -# ----------------------------- x,y,z = [None,None,None] def __init__(self,coords): @@ -27,7 +26,6 @@ class vector: # mimic py_post node object # ----------------------------- class element: # mimic py_post element object -# ----------------------------- items = [] type = None @@ -37,7 +35,6 @@ class element: # mimic py_post element object # ----------------------------- class elemental_scalar: # mimic py_post element_scalar object -# ----------------------------- id = None value = None @@ -48,7 +45,6 @@ class elemental_scalar: # mimic py_post element_scalar object # ----------------------------- class MPIEspectral_result: # mimic py_post result object -# ----------------------------- file = None dataOffset = 0 @@ -68,7 +64,8 @@ class MPIEspectral_result: # mimic py_post result object increment = 0 startingIncrement = 0 position = 0 - time = 0.0 # this is a dummy at the moment, we need to parse the load file and figure out what time a particular increment corresponds to +# this is a dummy at the moment, we need to parse the load file and figure out what time a particular increment corresponds to + time = 0.0 N_nodes = 0 N_node_scalars = 0 N_elements = 0 @@ -87,40 +84,40 @@ class MPIEspectral_result: # mimic py_post result object self.dataOffset += 7 #search first for the new keywords with ':', if not found try to find the old ones self.theTitle = self._keyedString('load:') - if self.theTitle == None: + if self.theTitle is None: self.theTitle = self._keyedString('load') self.wd = self._keyedString('workingdir:') - if self.wd == None: + if self.wd is None: self.wd = self._keyedString('workingdir') self.geometry = self._keyedString('geometry:') - if self.geometry == None: + if self.geometry is None: self.geometry = self._keyedString('geometry') self.N_loadcases = self._keyedPackedArray('loadcases:',count=1,type='i')[0] - if self.N_loadcases == None: + if self.N_loadcases is None: self.N_loadcases = self._keyedPackedArray('loadcases',count=1,type='i')[0] self._frequencies = self._keyedPackedArray('frequencies:',count=self.N_loadcases,type='i') - if all ( i == None for i in self._frequencies): + if all ( i is None for i in self._frequencies): self._frequencies = self._keyedPackedArray('frequencies',count=self.N_loadcases,type='i') self._increments = self._keyedPackedArray('increments:',count=self.N_loadcases,type='i') - if all (i == None for i in self._increments): + if all (i is None for i in self._increments): self._increments = self._keyedPackedArray('increments',count=self.N_loadcases,type='i') self.startingIncrement = self._keyedPackedArray('startingIncrement:',count=1,type='i')[0] - if self.startingIncrement == None: + if self.startingIncrement is None: self.startingIncrement = self._keyedPackedArray('startingIncrement',count=1,type='i')[0] self._times = self._keyedPackedArray('times:',count=self.N_loadcases,type='d') - if all (i == None for i in self._times): + if all (i is None for i in self._times): self._times = self._keyedPackedArray('times',count=self.N_loadcases,type='d') self._logscales = self._keyedPackedArray('logscales:',count=self.N_loadcases,type='i') - if all (i == None for i in self._logscales): + if all (i is None for i in self._logscales): self._logscales = self._keyedPackedArray('logscales',count=self.N_loadcases,type='i') self.size = self._keyedPackedArray('size:',count=3,type='d') @@ -135,7 +132,7 @@ class MPIEspectral_result: # mimic py_post result object self.N_elements = self.grid[0] * self.grid[1] * self.grid[2] self.N_element_scalars = self._keyedPackedArray('materialpoint_sizeResults:',count=1,type='i')[0] - if self.N_element_scalars == None: + if self.N_element_scalars is None: self.N_element_scalars = self._keyedPackedArray('materialpoint_sizeResults',count=1,type='i')[0] self.N_positions = (self.filesize-self.dataOffset)/(self.N_elements*self.N_element_scalars*8) @@ -156,8 +153,7 @@ class MPIEspectral_result: # mimic py_post result object print '\n**\n* Unexpected file size. Incomplete simulation or file corrupted!\n**' def __str__(self): - - + """Summary of results file""" return '\n'.join([ 'workdir: %s'%self.wd, 'geometry: %s'%self.geometry, @@ -181,13 +177,14 @@ class MPIEspectral_result: # mimic py_post result object filepos=0 # start at the beginning while name != identifier and filepos < self.dataOffset: # stop searching when found or when reached end of header self.file.seek(filepos) - dataLen=struct.unpack('i',self.file.read(4))[0] # read the starting tag in front of the keyword (Fortran indicates start and end of writing by a 4 byte tag indicating the length of the following data) - name = self.file.read(len(identifier)) # anticipate identifier - start=filepos+(4+len(identifier)) # this is the position where the values for the found key are stored - filepos=filepos+(4+dataLen+4) # forward to next keyword +# read the starting tag in front of the keyword (Fortran indicates start and end of writing by a 4 byte tag indicating the length of the following data) + dataLen=struct.unpack('i',self.file.read(4))[0] + name = self.file.read(len(identifier)) # anticipate identifier + start=filepos+(4+len(identifier)) # position of the values for the found key + filepos=filepos+(4+dataLen+4) # forward to next keyword - if name==identifier: # found the correct name - key['pos'] = start # save position + if name==identifier: # found the correct name + key['pos'] = start # save position key['name'] = name return key @@ -195,7 +192,7 @@ class MPIEspectral_result: # mimic py_post result object bytecount = {'d': 8,'i': 4} values = [default]*count key = self.locateKeyValue(identifier) - if key['name'] == identifier and key['pos'] != None: + if key['name'] == identifier and key['pos'] is not None: self.file.seek(key['pos']) for i in range(count): values[i] = struct.unpack(type,self.file.read(bytecount[type]))[0] @@ -286,8 +283,6 @@ class MPIEspectral_result: # mimic py_post result object if not options.legacy: incStart = self.dataOffset \ + self.position*8*self.N_elements*self.N_element_scalars - # header & footer + extra header and footer for 4 byte int range (Fortran) - # values where = (e*self.N_element_scalars + idx)*8 try: self.file.seek(incStart+where) @@ -299,15 +294,15 @@ class MPIEspectral_result: # mimic py_post result object else: self.fourByteLimit = 2**31 -1 -8 +# header & footer + extra header and footer for 4 byte int range (Fortran) +# values incStart = self.dataOffset \ + self.position*8*( 1 + self.N_elements*self.N_element_scalars*8//self.fourByteLimit \ + self.N_elements*self.N_element_scalars) - # header & footer + extra header and footer for 4 byte int range (Fortran) - # values where = (e*self.N_element_scalars + idx)*8 try: - if where%self.fourByteLimit + 8 >= self.fourByteLimit: # danger of reading into fortran record footer at 4 byte limit + if where%self.fourByteLimit + 8 >= self.fourByteLimit: # danger of reading into fortran record footer at 4 byte limit data='' for i in xrange(8): self.file.seek(incStart+where+(where//self.fourByteLimit)*8+4) @@ -329,51 +324,10 @@ class MPIEspectral_result: # mimic py_post result object def element_tensors(self): return self.N_element_tensors - -# ----------------------------- -class backgroundMessage(threading.Thread): -# ----------------------------- - - def __init__(self): - threading.Thread.__init__(self) - self.message = '' - self.new_message = '' - self.counter = 0 - self.symbols = ['- ', '\ ', '| ', '/ ',] - self.waittime = 0.5 - - def __quit__(self): - length = len(self.message) + len(self.symbols[self.counter]) - sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length) - sys.stderr.write('') - - def run(self): - while not threading.enumerate()[0]._Thread__stopped: - time.sleep(self.waittime) - self.update_message() - self.__quit__() - - def set_message(self, new_message): - self.new_message = new_message - self.print_message() - - def print_message(self): - length = len(self.message) + len(self.symbols[self.counter]) - sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length) # delete former message - sys.stderr.write(self.symbols[self.counter] + self.new_message) # print new message - self.message = self.new_message - - def update_message(self): - self.counter = (self.counter + 1)%len(self.symbols) - self.print_message() - # ----------------------------- def ipCoords(elemType, nodalCoordinates): -# -# returns IP coordinates for a given element -# ----------------------------- - + """returns IP coordinates for a given element""" nodeWeightsPerNode = { 7: [ [27.0, 9.0, 3.0, 9.0, 9.0, 3.0, 1.0, 3.0], [ 9.0, 27.0, 9.0, 3.0, 3.0, 9.0, 3.0, 1.0], @@ -422,10 +376,7 @@ def ipCoords(elemType, nodalCoordinates): # ----------------------------- def ipIDs(elemType): -# -# returns IP numbers for given element type -# ----------------------------- - + """returns IP numbers for given element type""" ipPerNode = { 7: [ 1, 2, 4, 3, 5, 6, 8, 7 ], 57: [ 1, 2, 4, 3, 5, 6, 8, 7 ], @@ -441,9 +392,7 @@ def ipIDs(elemType): # ----------------------------- def substituteLocation(string, mesh, coords): -# -# do variable interpolation in group and filter strings -# ----------------------------- + """do variable interpolation in group and filter strings""" substitute = string substitute = substitute.replace('elem', str(mesh[0])) substitute = substitute.replace('node', str(mesh[1])) @@ -458,10 +407,7 @@ def substituteLocation(string, mesh, coords): # ----------------------------- def heading(glue,parts): -# -# joins pieces from parts by glue. second to last entry in pieces tells multiplicity -# ----------------------------- - + """joins pieces from parts by glue. second to last entry in pieces tells multiplicity""" header = [] for pieces in parts: if pieces[-2] == 0: @@ -473,12 +419,12 @@ def heading(glue,parts): # ----------------------------- def mapIncremental(label, mapping, N, base, new): -# -# applies the function defined by "mapping" -# (can be either 'min','max','avg', 'sum', or user specified) -# to a list of data -# ----------------------------- + """ + applies the function defined by "mapping" + (can be either 'min','max','avg', 'sum', or user specified) + to a list of data + """ theMap = { 'min': lambda n,b,a: a if n==0 else min(b,a), 'max': lambda n,b,a: a if n==0 else max(b,a), 'avg': lambda n,b,a: (n*b+a)/(n+1), @@ -504,10 +450,7 @@ def mapIncremental(label, mapping, N, base, new): # ----------------------------- def OpenPostfile(name,type,nodal = False): -# -# open postfile with extrapolation mode "translate" -# ----------------------------- - + """open postfile with extrapolation mode 'translate'""" p = {\ 'spectral': MPIEspectral_result,\ 'marc': post_open,\ @@ -520,10 +463,7 @@ def OpenPostfile(name,type,nodal = False): # ----------------------------- def ParseOutputFormat(filename,what,me): -# -# parse .output* files in order to get a list of outputs -# ----------------------------- - + """parse .output* files in order to get a list of outputs""" content = [] format = {'outputs':{},'specials':{'brothers':[]}} for prefix in ['']+map(str,range(1,17)): @@ -567,13 +507,11 @@ def ParseOutputFormat(filename,what,me): # ----------------------------- def ParsePostfile(p,filename, outputFormat): -# -# parse postfile in order to get position and labels of outputs -# needs "outputFormat" for mapping of output names to postfile output indices -# ----------------------------- - - # --- build statistics + """ + parse postfile in order to get position and labels of outputs + needs "outputFormat" for mapping of output names to postfile output indices + """ stat = { \ 'IndexOfLabel': {}, \ 'Title': p.title(), \ @@ -589,7 +527,7 @@ def ParsePostfile(p,filename, outputFormat): 'LabelOfElementalTensor': [None]*p.element_tensors(), \ } - # --- find labels +# --- find labels for labelIndex in range(stat['NumberOfNodalScalars']): label = p.node_scalar_label(labelIndex) @@ -613,9 +551,9 @@ def ParsePostfile(p,filename, outputFormat): startIndex = stat['IndexOfLabel']['HomogenizationCount'] stat['LabelOfElementalScalar'][startIndex] = 'HomogenizationCount' - # We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file - # Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels - # given in the .output* file +# We now have to find a mapping for each output label as defined in the .output* files to the output position in the post file +# Since we know where the user defined outputs start ("startIndex"), we can simply assign increasing indices to the labels +# given in the .output* file offset = 1 for (name,N) in outputFormat['Homogenization']['outputs']: @@ -663,7 +601,6 @@ def ParsePostfile(p,filename, outputFormat): # ----------------------------- def SummarizePostfile(stat,where=sys.stdout,format='marc'): -# ----------------------------- where.write('\n\n') where.write('title:\t%s'%stat['Title'] + '\n\n') @@ -671,9 +608,12 @@ def SummarizePostfile(stat,where=sys.stdout,format='marc'): where.write('increments:\t%i'%(stat['NumberOfIncrements']) + '\n\n') where.write('nodes:\t%i'%stat['NumberOfNodes'] + '\n\n') where.write('elements:\t%i'%stat['NumberOfElements'] + '\n\n') - where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfNodalScalar']) + '\n\n') - where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n ' + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n') - where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n ' + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n') + where.write('nodal scalars:\t%i'%stat['NumberOfNodalScalars'] + '\n\n '\ + +'\n '.join(stat['LabelOfNodalScalar']) + '\n\n') + where.write('elemental scalars:\t%i'%stat['NumberOfElementalScalars'] + '\n\n '\ + + '\n '.join(stat['LabelOfElementalScalar']) + '\n\n') + where.write('elemental tensors:\t%i'%stat['NumberOfElementalTensors'] + '\n\n '\ + + '\n '.join(stat['LabelOfElementalTensor']) + '\n\n') return True @@ -799,14 +739,14 @@ if not os.path.exists(files[0]): # --- figure out filetype -if options.filetype == None: +if options.filetype is None: ext = os.path.splitext(files[0])[1] for theType in fileExtensions.keys(): if ext in fileExtensions[theType]: options.filetype = theType break -if options.filetype != None: options.filetype = options.filetype.lower() +if options.filetype is not None: options.filetype = options.filetype.lower() if options.filetype == 'marc': offset_pos = 1 else: offset_pos = 0 @@ -822,7 +762,7 @@ if options.filetype == 'marc': sys.path.append(damask.solver.Marc().libraryPath('../../')) try: - from py_post import * + from py_post import post_open except: print('error: no valid Mentat release found') sys.exit(-1) @@ -834,7 +774,7 @@ if options.constitutiveResult and not options.phase: parser.print_help() parser.error('constitutive results require phase...') -if options.nodalScalar and ( options.elemScalar or options.elemTensor +if options.nodalScalar and ( options.elemScalar or options.elemTensor\ or options.homogenizationResult or options.crystalliteResult or options.constitutiveResult ): parser.print_help() parser.error('not allowed to mix nodal with elemental results...') @@ -851,7 +791,7 @@ options.sep.reverse() # --- start background messaging -bg = backgroundMessage() +bg = damask.util.backgroundMessage() bg.start() # --- parse .output and .t16 files @@ -874,7 +814,7 @@ bg.set_message('parsing .output files...') for what in me: outputFormat[what] = ParseOutputFormat(filename, what, me[what]) - if not '_id' in outputFormat[what]['specials']: + if '_id' not in outputFormat[what]['specials']: print "\nsection '%s' not found in <%s>"%(me[what], what) print '\n'.join(map(lambda x:' [%s]'%x, outputFormat[what]['specials']['brothers'])) @@ -886,15 +826,18 @@ if options.filetype == 'marc': stat['NumberOfIncrements'] -= 1 # t16 contains one "virtual" increment (at 0) # --- sanity check for output variables -# for mentat variables (nodalScalar,elemScalar,elemTensor) we simply have to check whether the label is found in the stat[indexOfLabel] dictionary -# for user defined variables (homogenizationResult,crystalliteResult,constitutiveResult) we have to check the corresponding outputFormat, since the namescheme in stat['IndexOfLabel'] is different +# for mentat variables (nodalScalar,elemScalar,elemTensor) we simply have to check whether the label +# is found in the stat[indexOfLabel] dictionary for user defined variables (homogenizationResult, +# crystalliteResult,constitutiveResult) we have to check the corresponding outputFormat, since the +# namescheme in stat['IndexOfLabel'] is different for opt in ['nodalScalar','elemScalar','elemTensor','homogenizationResult','crystalliteResult','constitutiveResult']: if eval('options.%s'%opt): for label in eval('options.%s'%opt): if (opt in ['nodalScalar','elemScalar','elemTensor'] and label not in stat['IndexOfLabel'] and label not in ['elements',]) \ or (opt in ['homogenizationResult','crystalliteResult','constitutiveResult'] \ - and (not outputFormat[opt[:-6].capitalize()]['outputs'] or not label in zip(*outputFormat[opt[:-6].capitalize()]['outputs'])[0])): + and (not outputFormat[opt[:-6].capitalize()]['outputs'] \ + or label not in zip(*outputFormat[opt[:-6].capitalize()]['outputs'])[0])): parser.error('%s "%s" unknown...'%(opt,label)) @@ -952,15 +895,14 @@ if options.nodalScalar: myIpID = 0 myGrainID = 0 - # --- filter valid locations - - filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) # generates an expression that is only true for the locations specified by options.filter + # generate an expression that is only true for the locations specified by options.filter + filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) if filter != '' and not eval(filter): # for all filter expressions that are not true:... continue # ... ignore this data point and continue with next # --- group data locations - - grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) # generates a unique key for a group of separated data based on the separation criterium for the location + # generate a unique key for a group of separated data based on the separation criterium for the location + grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myNodeCoordinates) if grp not in index: # create a new group if not yet present index[grp] = groupCount @@ -983,26 +925,28 @@ else: if e%1000 == 0: bg.set_message('scan elem %i...'%e) myElemID = p.element_id(e) - myIpCoordinates = ipCoords(p.element(e).type, map(lambda node: [node.x, node.y, node.z], map(p.node, map(p.node_sequence, p.element(e).items)))) + myIpCoordinates = ipCoords(p.element(e).type, map(lambda node: [node.x, node.y, node.z], + map(p.node, map(p.node_sequence, p.element(e).items)))) myIpIDs = ipIDs(p.element(e).type) Nips = len(myIpIDs) myNodeIDs = p.element(e).items[:Nips] for n in range(Nips): myIpID = myIpIDs[n] myNodeID = myNodeIDs[n] - for g in range(('GrainCount' in stat['IndexOfLabel'] and int(p.element_scalar(e, stat['IndexOfLabel']['GrainCount'])[0].value)) - or 1): + for g in range(('GrainCount' in stat['IndexOfLabel']\ + and int(p.element_scalar(e, stat['IndexOfLabel']['GrainCount'])[0].value))\ + or 1): myGrainID = g + 1 # --- filter valid locations - - filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) # generates an expression that is only true for the locations specified by options.filter + # generates an expression that is only true for the locations specified by options.filter + filter = substituteLocation(options.filter, [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) if filter != '' and not eval(filter): # for all filter expressions that are not true:... continue # ... ignore this data point and continue with next # --- group data locations - - grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) # generates a unique key for a group of separated data based on the separation criterium for the location + # generates a unique key for a group of separated data based on the separation criterium for the location + grp = substituteLocation('#'.join(options.sep), [myElemID,myNodeID,myIpID,myGrainID], myIpCoordinates[n]) if grp not in index: # create a new group if not yet present index[grp] = groupCount @@ -1104,7 +1048,8 @@ for incCount,position in enumerate(locations): # walk through locations if fileOpen: file.close() fileOpen = False - outFilename = eval('"'+eval("'%%s_inc%%0%ii%%s.txt'%(math.log10(max(increments+[1]))+1)")+'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increments[incCount],options.suffix)') + outFilename = eval('"'+eval("'%%s_inc%%0%ii%%s.txt'%(math.log10(max(increments+[1]))+1)")\ + +'"%(dirname + os.sep + options.prefix + os.path.split(filename)[1],increments[incCount],options.suffix)') else: outFilename = '%s.txt'%(dirname + os.sep + options.prefix + os.path.split(filename)[1] + options.suffix) @@ -1128,7 +1073,8 @@ for incCount,position in enumerate(locations): # walk through locations member += 1 if member%1000 == 0: time_delta = ((len(locations)*memberCount)/float(member+incCount*memberCount)-1.0)*(time.time()-time_start) - bg.set_message('(%02i:%02i:%02i) processing point %i of %i from increment %i (position %i)...'%(time_delta//3600,time_delta%3600//60,time_delta%60,member,memberCount,increments[incCount],position)) + bg.set_message('(%02i:%02i:%02i) processing point %i of %i from increment %i (position %i)...' + %(time_delta//3600,time_delta%3600//60,time_delta%60,member,memberCount,increments[incCount],position)) newby = [] # current member's data @@ -1140,7 +1086,9 @@ for incCount,position in enumerate(locations): # walk through locations else: length = 1 content = [ p.node_scalar(p.node_sequence(n),stat['IndexOfLabel'][label]) ] - if assembleHeader: header += heading('_',[[component,''.join( label.split() )] for component in range(int(length>1),length+int(length>1))]) + if assembleHeader: + header += heading('_',[[component,''.join( label.split() )] + for component in range(int(length>1),length+int(length>1))]) newby.append({'label':label, 'len':length, 'content':content }) @@ -1156,7 +1104,8 @@ for incCount,position in enumerate(locations): # walk through locations if options.elemTensor: for label in options.elemTensor: if assembleHeader: - header += heading('.',[[''.join( label.split() ),component] for component in ['intensity','t11','t22','t33','t12','t23','t13']]) + header += heading('.',[[''.join( label.split() ),component] + for component in ['intensity','t11','t22','t33','t12','t23','t13']]) myTensor = p.element_tensor(p.element_sequence(e),stat['IndexOfLabel'][label])[n_local] newby.append({'label':label, 'len':7, diff --git a/processing/post/vtk2ang.py b/processing/post/vtk2ang.py index a744d2e3b..40b06e41d 100755 --- a/processing/post/vtk2ang.py +++ b/processing/post/vtk2ang.py @@ -66,7 +66,8 @@ def getDataLine(angles,x,y,validData=True): """ info = {True: (9999.9, 1.0, 0,99999,0.0), False: ( -1.0,-1.0,-1, -1,1.0)} - return '%9.5f %9.5f %9.5f %12.5f %12.5f %6.1f %6.3f %2i %6i %6.3f \n'%(tuple(map(positiveRadians,angles))+(y*1e6,x*1e6)+info[validData]) + return '%9.5f %9.5f %9.5f %12.5f %12.5f %6.1f %6.3f %2i %6i %6.3f \n'\ + %(tuple(map(positiveRadians,angles))+(y*1e6,x*1e6)+info[validData]) diff --git a/processing/post/vtk_voxelcloud.py b/processing/post/vtk_voxelcloud.py index 096212b40..239771c74 100755 --- a/processing/post/vtk_voxelcloud.py +++ b/processing/post/vtk_voxelcloud.py @@ -48,9 +48,10 @@ for name in filenames: # --------------- interprete header ----------------------------------------------------------------- table.head_read() errors=[] - if table.label_dimension(options.deformed) != 3: errors.append('columns "{}" have dimension {}'.format(options.deformed, - table.label_dimension(options.deformed))) - if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) + if table.label_dimension(options.deformed) != 3: + errors.append('columns "{}" have dimension {}'.format(options.deformed,table.label_dimension(options.deformed))) + if table.label_dimension(options.coords) != 3: + errors.append('coordinates {} are not a vector.'.format(options.coords)) table.data_readArray([options.coords,options.deformed]) From 3ff3bb1a5b62db989e9d73020ee8b8f0de67d125 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Mar 2016 14:44:51 +0100 Subject: [PATCH 036/134] pre processing finished --- processing/pre/mentat_pbcOnBoxMesh.py | 3 +- .../pre/patchFromReconstructedBoundaries.py | 12 ++++--- processing/pre/seeds_fromDistribution.py | 33 +++++++++---------- processing/pre/seeds_fromPokes.py | 5 ++- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/processing/pre/mentat_pbcOnBoxMesh.py b/processing/pre/mentat_pbcOnBoxMesh.py index 12351f410..7213bbd42 100755 --- a/processing/pre/mentat_pbcOnBoxMesh.py +++ b/processing/pre/mentat_pbcOnBoxMesh.py @@ -129,7 +129,8 @@ def servoLink(): ]) for i in range(nLinks): cmds.append([ - "*link_class servo *servo_ret_node %i %i"%(i+1,baseNode["%.8e"%linkCoord[i][0]]["%.8e"%linkCoord[i][1]]["%.8e"%linkCoord[i][2]]), + "*link_class servo *servo_ret_node %i %i"\ + %(i+1,baseNode["%.8e"%linkCoord[i][0]]["%.8e"%linkCoord[i][1]]["%.8e"%linkCoord[i][2]]), "*link_class servo *servo_ret_dof %i %i"%(i+1,dof), "*link_class servo *servo_ret_coef %i 1"%(i+1), ]) diff --git a/processing/pre/patchFromReconstructedBoundaries.py b/processing/pre/patchFromReconstructedBoundaries.py index 35266e245..31d8a7461 100755 --- a/processing/pre/patchFromReconstructedBoundaries.py +++ b/processing/pre/patchFromReconstructedBoundaries.py @@ -234,7 +234,8 @@ def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): crappyData = False for pointId,point in enumerate(points): if len(point['segments']) < 2: # point marks a dead end! - print "Dead end at segment %i (%f,%f)"%(1+point['segments'][0],boxX[0]+point['coords'][0]/scalePatch,boxY[0]+point['coords'][1]/scalePatch,) + print "Dead end at segment %i (%f,%f)"\ + %(1+point['segments'][0],boxX[0]+point['coords'][0]/scalePatch,boxY[0]+point['coords'][1]/scalePatch,) crappyData = True grains = {'draw': [], 'legs': []} @@ -367,7 +368,8 @@ def sample(size,aspect,n,xmargin,ymargin): def patch(a,n,mesh,rcData): cmds = [] for l in range(len(rcData['point'])): # generate all points - cmds.append("*add_points %f %f %f"%(rcData['point'][l][0]-a/2.0,rcData['point'][l][1]-a/rcData['dimension'][0]*rcData['dimension'][1]/2.0,0)) + cmds.append("*add_points %f %f %f"\ + %(rcData['point'][l][0]-a/2.0,rcData['point'][l][1]-a/rcData['dimension'][0]*rcData['dimension'][1]/2.0,0)) cmds.append(["*set_curve_type line", "*set_curve_div_type_fix_ndiv", @@ -891,7 +893,8 @@ if 'spectral' in options.output: (y+1)*fftdata['resolution'][0]]))+'\n') # grain indexes, x-row per line geomFile.close() # close geom file - print('assigned %i out of %i (2D) Fourier points.'%(len(fftdata['fftpoints']), int(fftdata['resolution'][0])*int(fftdata['resolution'][1]))) + print('assigned %i out of %i (2D) Fourier points.'\ + %(len(fftdata['fftpoints']), int(fftdata['resolution'][0])*int(fftdata['resolution'][1]))) # ----- write Mentat procedure ----- @@ -974,7 +977,8 @@ if 'mentat' in options.output or 'spectral' in options.output: for grain in rcData['grainMapping']: output += '\n[grain %i]\n'%grain + \ '(gauss)\tphi1\t%f\tphi\t%f\tphi2\t%f\tscatter\t%f\tfraction\t1.0\n'\ - %(math.degrees(orientationData[grain-1][0]),math.degrees(orientationData[grain-1][1]),math.degrees(orientationData[grain-1][2]),options.scatter) + %(math.degrees(orientationData[grain-1][0]),math.degrees(orientationData[grain-1][1]),\ + math.degrees(orientationData[grain-1][2]),options.scatter) if (options.xmargin > 0.0 or options.ymargin > 0.0): output += '\n[margin]\n' + \ '(random)\t\tscatter\t0.0\tfraction\t1.0\n' diff --git a/processing/pre/seeds_fromDistribution.py b/processing/pre/seeds_fromDistribution.py index a68c8c802..dd813e334 100755 --- a/processing/pre/seeds_fromDistribution.py +++ b/processing/pre/seeds_fromDistribution.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: UTF-8 no BOM -*- -import threading,time,os,subprocess,shlex,string,sys,random +import threading,time,os,sys,random import numpy as np from optparse import OptionParser from operator import mul @@ -16,10 +16,8 @@ currentSeedsName = None #--------------------------------------------------------------------------------------------------- class myThread (threading.Thread): -#--------------------------------------------------------------------------------------------------- - ''' - perturbes seed in seed file, performes Voronoi tessellation, evaluates, and updates best match - ''' + """perturbes seed in seed file, performes Voronoi tessellation, evaluates, and updates best match""" + def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID @@ -40,17 +38,17 @@ class myThread (threading.Thread): s.release() random.seed(options.randomSeed+self.threadID) # initializes to given seeds - knownSeedsUpdate = bestSeedsUpdate -1.0 # trigger update of local best seeds (time when the best seed file was found known to thread) + knownSeedsUpdate = bestSeedsUpdate -1.0 # trigger update of local best seeds randReset = True # aquire new direction - myBestSeedsVFile = StringIO() # in-memory file to store local copy of best seeds file - perturbedSeedsVFile = StringIO() # in-memory file for perturbed best seeds file - perturbedGeomVFile = StringIO() # in-memory file for tessellated geom file + myBestSeedsVFile = StringIO() # store local copy of best seeds file + perturbedSeedsVFile = StringIO() # perturbed best seeds file + perturbedGeomVFile = StringIO() # tessellated geom file #--- still not matching desired bin class ---------------------------------------------------------- while bestMatch < options.threshold: - s.acquire() # accessing global data, ensure only one thread does it per time - if bestSeedsUpdate > knownSeedsUpdate: # if a newer best seed file exist, read it into a virtual file + s.acquire() # ensure only one thread acces global data + if bestSeedsUpdate > knownSeedsUpdate: # write best fit to virtual file knownSeedsUpdate = bestSeedsUpdate bestSeedsVFile.reset() myBestSeedsVFile.close() @@ -78,7 +76,7 @@ class myThread (threading.Thread): perturbedSeedsVFile = StringIO() myBestSeedsVFile.reset() - perturbedSeedsTable = damask.ASCIItable(myBestSeedsVFile,perturbedSeedsVFile,labeled=True) # read current best fitting seed file and to perturbed seed file + perturbedSeedsTable = damask.ASCIItable(myBestSeedsVFile,perturbedSeedsVFile,labeled=True) # write best fit to perturbed seed file perturbedSeedsTable.head_read() perturbedSeedsTable.head_write() outputAlive=True @@ -87,7 +85,7 @@ class myThread (threading.Thread): while outputAlive and perturbedSeedsTable.data_read(): # perturbe selected microstructure if ms in selectedMs: newCoords=np.array(tuple(map(float,perturbedSeedsTable.data[0:3]))+direction[i]) - newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box (move one side out, other side in) + newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box newCoords=np.where(newCoords <0.0,newCoords+1.0,newCoords) perturbedSeedsTable.data[0:3]=[format(f, '8.6f') for f in newCoords] direction[i]*=2. @@ -115,8 +113,9 @@ class myThread (threading.Thread): for i in xrange(nMicrostructures): # calculate the deviation in all bins per histogram currentHist.append(np.histogram(currentData,bins=target[i]['bins'])[0]) currentError.append(np.sqrt(np.square(np.array(target[i]['histogram']-currentHist[i])).sum())) - - if currentError[0]>0.0: # as long as not all grains are within the range of the target, use the deviation to left and right as error + +# as long as not all grains are within the range of the target, use the deviation to left and right as error + if currentError[0]>0.0: currentError[0] *=((target[0]['bins'][0]-np.min(currentData))**2.0+ (target[0]['bins'][1]-np.max(currentData))**2.0)**0.5 # norm of deviations by number of usual bin deviation s.acquire() # do the evaluation serially @@ -154,7 +153,7 @@ class myThread (threading.Thread): match=myMatch sys.stdout.flush() break - if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before (for the considered bins): take it to keep on moving + if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before: take it to keep on moving bestSeedsUpdate = time.time() perturbedSeedsVFile.reset() bestSeedsVFile.close() @@ -215,7 +214,7 @@ options = parser.parse_args()[0] damask.util.report(scriptName,options.seedFile) -if options.randomSeed == None: +if options.randomSeed is None: options.randomSeed = int(os.urandom(4).encode('hex'), 16) damask.util.croak(options.randomSeed) delta = (options.scale/options.grid[0],options.scale/options.grid[1],options.scale/options.grid[2]) diff --git a/processing/pre/seeds_fromPokes.py b/processing/pre/seeds_fromPokes.py index 80f13c85c..76f1fb003 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -122,10 +122,9 @@ for name in filenames: newInfo['microstructures'] = len(np.unique(seeds[:,3])) # --- report --------------------------------------------------------------------------------------- + if (newInfo['microstructures'] != info['microstructures']): + damask.util.croak(remarks.append('--> microstructures: %i'%newInfo['microstructures'])) - remarks = [] - if ( newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) - if remarks != []: damask.util.croak(remarks) # ------------------------------------------ assemble header --------------------------------------- table.info_clear() From 76a0a93c428b4c97c2b02abf32c64a3c2c6bc291 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Mar 2016 14:52:47 +0100 Subject: [PATCH 037/134] removed unneeded variables, fixed docstrings. missing variable jc in Barlat1989 from 46c33b0 --- processing/misc/yieldSurface.py | 299 +++++++++++++++----------------- 1 file changed, 141 insertions(+), 158 deletions(-) diff --git a/processing/misc/yieldSurface.py b/processing/misc/yieldSurface.py index b6ca40265..44777bf52 100755 --- a/processing/misc/yieldSurface.py +++ b/processing/misc/yieldSurface.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: UTF-8 no BOM -*- -import threading,time,os,subprocess,string,sys +import threading,time,os import numpy as np from optparse import OptionParser import damask @@ -56,10 +56,11 @@ def runFit(exponent, eqStress, dimension, criterion): damask.util.croak(fitResidual) def principalStresses(sigmas): - ''' - computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses. - sorted in descending order. - ''' + """ + computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses. + + sorted in descending order. + """ lambdas=np.zeros(0,'d') for i in xrange(np.shape(sigmas)[1]): eigenvalues = np.linalg.eigvalsh(sym6toT33(sigmas[:,i])) @@ -82,27 +83,25 @@ def principalStress(p): t1 + t2*np.cos(phi+np.pi*4.0/3.0)]) def principalStrs_Der(p, (s1, s2, s3, s4, s5, s6), dim, Karafillis=False): - ''' - Derivative of principal stress with respect to stress - ''' + """Derivative of principal stress with respect to stress""" third = 1.0/3.0 third2 = 2.0*third I = invariant(p) I1s3I2= np.sqrt(I[0]**2 - 3.0*I[1]) - numer = 2.0*I1**3 - 9.0*I[0]*I[1] + 27.0*I[2] + numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2] denom = 2.0*I1s3I2**3 cs = numer/denom phi = np.arccos(cs)/3.0 dphidcs = -third/np.sqrt(1.0 - cs**2) dcsddenom = 0.5*numer*(-1.5)*I1s3I2**(-5.0) - dcsdI1 = (6.0*I1**2 - 9.0*I2)*denom + dcsddenom*(2.0*I1) - dcsdI2 = ( - 9.0*I1)*denom + dcsddenom*(-3.0) + dcsdI1 = (6.0*I[0]**2 - 9.0*I[1])*denom + dcsddenom*(2.0*I[0]) + dcsdI2 = ( - 9.0*I[0])*denom + dcsddenom*(-3.0) dcsdI3 = 27.0*denom dphidI1, dphidI2, dphidI3 = dphidcs*dcsdI1, dphidcs*dcsdI2, dphidcs*dcsdI3 - dI1s3I2dI1 = I1/I1s3I2 + dI1s3I2dI1 = I[0]/I1s3I2 dI1s3I2dI2 = -1.5/I1s3I2 tcoeff = third2*I1s3I2 @@ -150,13 +149,13 @@ def math_ln(x): return np.log(x + 1.0e-32) def sym6toT33(sym6): - ''' Shape the symmetric stress tensor(6) into (3,3) ''' + """Shape the symmetric stress tensor(6) into (3,3)""" return np.array([[sym6[0],sym6[3],sym6[5]], [sym6[3],sym6[1],sym6[4]], [sym6[5],sym6[4],sym6[2]]]) def t33toSym6(t33): - ''' Shape the stress tensor(3,3) into symmetric (6) ''' + """Shape the stress tensor(3,3) into symmetric (6)""" return np.array([ t33[0,0], t33[1,1], t33[2,2], @@ -165,9 +164,6 @@ def t33toSym6(t33): (t33[2,0] + t33[0,2])/2.0,]) # * * 2 class Criteria(object): - ''' - needs doc string - ''' def __init__(self, criterion, uniaxialStress,exponent, dimension): self.stress0 = uniaxialStress if exponent < 0.0: # Fitting exponent m @@ -183,9 +179,8 @@ class Criteria(object): return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim,Jac=True) class Vegter(object): - ''' - Vegter yield criterion - ''' + """Vegter yield criterion""" + def __init__(self, refPts, refNormals,nspace=11): self.refPts, self.refNormals = self._getRefPointsNormals(refPts, refNormals) self.hingePts = self._getHingePoints() @@ -211,11 +206,12 @@ class Vegter(object): return refPts,refNormals def _getHingePoints(self): - ''' - calculate the hinge point B according to the reference points A,C and the normals n,m - refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]); - refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]]) - ''' + """ + calculate the hinge point B according to the reference points A,C and the normals n,m + + refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]); + refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]]) + """ def hingPoint(points, normals): A1 = points[0][0]; A2 = points[0][1] C1 = points[1][0]; C2 = points[1][1] @@ -235,9 +231,7 @@ class Vegter(object): return np.array([bezier(self.refPts[i:i+2],self.hingePts[i]) for i in xrange(len(self.refPts)-1)]) def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0): - ''' - 0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial - ''' + """0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial""" def getFourierParas(r): # get the value after Fourier transformation nset = len(r) @@ -262,12 +256,6 @@ def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0): for j in xrange(3): refPts[j,i] = np.dot(getFourierParas(strsSet[:,j,i]), fouriercoeffs) - rhoUn = np.dot(getFourierParas(-lankford/(lankford+1)), fouriercoeffs) - rhoBi = (rhoBi0+1 + (rhoBi0-1)*np.cos(2.0*theta))/(rhoBi0+1 - (rhoBi0-1)*np.cos(2.0*theta)) - nVec = lambda rho : np.array([1.0,rho]/np.sqrt(1.0+rho**2)) - refNormals = np.array([nVec(-1.0),nVec(rhoUn),nVec(0.0),nVec(rhoBi)]) - - vegter = Vegter(refPts, refNormals) def Tresca(eqStress=None, #not needed/supported paras=None, @@ -276,10 +264,11 @@ def Tresca(eqStress=None, #not needed/supported criteria=None, #not needed/supported dim=3, Jac=False): - ''' - Tresca yield criterion - the fitted parameters is: paras(sigma0) - ''' + """ + Tresca yield criterion + + the fitted parameter is paras(sigma0) + """ if not Jac: lambdas = principalStresses(sigmas) r = np.amax(np.array([abs(lambdas[2,:]-lambdas[1,:]),\ @@ -296,13 +285,14 @@ def Cazacu_Barlat(eqStress=None, criteria=None, dim=3, #2D also possible Jac=False): - ''' - Cazacu-Barlat (CB) yield criterion - the fitted parameters are: - a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress - a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case - mFix are invalid input - ''' + """ + Cazacu-Barlat (CB) yield criterion + + the fitted parameters are: + a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress + a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case + mFix is ignored + """ s11,s22,s33,s12,s23,s31 = sigmas if dim == 2: (a1,a2,a3,a4), (b1,b2,b3,b4,b5,b10), c = paras[0:4],paras[4:10],paras[10] @@ -356,13 +346,14 @@ def Drucker(eqStress=None,#not needed/supported criteria=None, dim=3, Jac=False): - ''' - Drucker yield criterion - the fitted parameters are - sigma0, C_D for Drucker(p=1); - sigma0, C_D, p for general Drucker - eqStress, mFix are invalid inputs - ''' + """ + Drucker yield criterion + + the fitted parameters are + sigma0, C_D for Drucker(p=1); + sigma0, C_D, p for general Drucker + eqStress, mFix are invalid inputs + """ if criteria == 'drucker': sigma0, C_D= paras p = 1.0 @@ -386,7 +377,7 @@ def Drucker(eqStress=None,#not needed/supported if criteria == 'drucker': return np.vstack((-r/sigma0, -drdl*J3_2p)).T else: - dldp = 3.0*J2_3p*math_ln(J2) - 2.0*C_D*J3_2p*math_ln(J3) + dldp = 3.0*J2_3p*math_ln(J[1]) - 2.0*C_D*J3_2p*math_ln(J[2]) jp = drdl*dldp + r*math_ln(left)/(-6.0*p*p) if mFix[0]: return np.vstack((-r/sigma0, -drdl*J3_2p)).T @@ -399,12 +390,13 @@ def Hill1948(eqStress=None,#not needed/supported criteria=None,#not needed/supported dim=3, Jac=False): - ''' - Hill 1948 yield criterion - the fitted parameters are: - F, G, H, L, M, N for 3D - F, G, H, N for 2D - ''' + """ + Hill 1948 yield criterion + + the fitted parameters are: + F, G, H, L, M, N for 3D + F, G, H, N for 2D + """ s11,s22,s33,s12,s23,s31 = sigmas if dim == 2: # plane stress jac = np.array([ s22**2, s11**2, (s11-s22)**2, 2.0*s12**2]) @@ -423,11 +415,11 @@ def Hill1979(eqStress=None,#not needed/supported criteria=None,#not needed/supported dim=3, Jac=False): - ''' - Hill 1979 yield criterion - the fitted parameters are: f,g,h,a,b,c,m - ''' - + """ + Hill 1979 yield criterion + + the fitted parameters are: f,g,h,a,b,c,m + """ if mFix[0]: m = mFix[1] else: @@ -458,14 +450,14 @@ def Hosford(eqStress=None, criteria=None, dim=3, Jac=False): - ''' - Hosford family criteria - the fitted parameters are: - von Mises: sigma0 - Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed - general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed - ''' + """ + Hosford family criteria + the fitted parameters are: + von Mises: sigma0 + Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed + general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed + """ if criteria == 'vonmises': sigma0 = paras coeff = np.ones(3) @@ -509,11 +501,12 @@ def Barlat1989(eqStress=None, criteria=None, dim=3, Jac=False): - ''' - Barlat-Lian 1989 yield criteria - the fitted parameters are: - Anisotropic: a, h, p, m; m is optional - ''' + """ + Barlat-Lian 1989 yield criteria + + the fitted parameters are: + Anisotropic: a, h, p, m; m is optional + """ a, h, p = paras[0:3] if mFix[0]: m = mFix[1] else: m = paras[-1] @@ -536,7 +529,7 @@ def Barlat1989(eqStress=None, drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) dldm = np.dot(np.array([a,a,c]),fm*math_ln(fs))*0.5 - ja = drdl*dlda + ja,jc = drdl*dlda, drdl*dldc jh,jp = drdl*(dldk1*dk1dh + dldk2*dk2dh), drdl*dldk2*dk2dp jm = drdl*dldm + drdm @@ -544,13 +537,14 @@ def Barlat1989(eqStress=None, else: return np.vstack((ja,jc,jh,jp,jm)).T def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - Barlat 1991 criteria - the fitted parameters are: - Anisotropic: a, b, c, f, g, h, m for 3D - a, b, c, h, m for plane stress - m is optional - ''' + """ + Barlat 1991 criteria + + the fitted parameters are: + Anisotropic: a, b, c, f, g, h, m for 3D + a, b, c, h, m for plane stress + m is optional + """ if dim == 2: coeff = paras[0:4] # plane stress else: coeff = paras[0:6] # general case if mFix[0]: m = mFix[1] @@ -605,12 +599,13 @@ def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): else: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx, jm)).T def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - BBC2000 yield criterion - the fitted parameters are - d,e,f,g, b,c,a, k; k is optional - criteria are invalid input - ''' + """ + BBC2000 yield criterion + + the fitted parameters are + d,e,f,g, b,c,a, k; k is optional + criteria are invalid input + """ d,e,f,g, b,c,a= paras[0:7] if mFix[0]: k = mFix[1] else: k = paras[-1] @@ -647,12 +642,13 @@ def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - BBC2003 yield criterion - the fitted parameters are - M,N,P,Q,R,S,T,a, k; k is optional - criteria are invalid input - ''' + """ + BBC2003 yield criterion + + the fitted parameters are + M,N,P,Q,R,S,T,a, k; k is optional + criteria are invalid input + """ M,N,P,Q,R,S,T,a = paras[0:8] if mFix[0]: k = mFix[1] else: k = paras[-1] @@ -689,12 +685,13 @@ def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): else : return np.vstack((J, drdl*dldk+drdk)).T def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - BBC2005 yield criterion - the fitted parameters are - a, b, L ,M, N, P, Q, R, k; k is optional - criteria are invalid input - ''' + """ + BBC2005 yield criterion + + the fitted parameters are + a, b, L ,M, N, P, Q, R, k k are optional + criteria is invalid input + """ a,b,L, M, N, P, Q, R = paras[0:8] if mFix[0]: k = mFix[1] else: k = paras[-1] @@ -739,10 +736,12 @@ def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): else : return np.vstack(J, dldk+dsBarde*dedk).T def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS - D: d11,d12,d21,d22,d66 - ''' + """ + Yld2000 yield criterion + + C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS + D: d11,d12,d21,d22,d66 + """ C,D = paras[0:3], paras[3:8] if mFix[0]: m = mFix[1] else: m = paras[-1] @@ -769,8 +768,7 @@ def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) #/(-m*m) dldm = ( phi1*math_ln(phi1s) + phi21*math_ln(phi21s) + phi22*math_ln(phi22s) )*0.5 zero = np.zeros_like(s11); num = len(s11) - def dPrincipalds((X1,X2,X12)): - # the derivative of principla with regards to stress + def dPrincipalds((X1,X2,X12)): # derivative of principla with respect to stress temp = 1.0/np.sqrt( (X1-X2)**2 + 4.0*X12**2 ) dP1dsi = 0.5*np.array([ 1.0+temp*(X1-X2), 1.0-temp*(X1-X2), temp*4.0*X12]) dP2dsi = 0.5*np.array([ 1.0-temp*(X1-X2), 1.0+temp*(X1-X2), -temp*4.0*X12]) @@ -798,14 +796,15 @@ def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): else: return np.vstack((jC,jD,jm)).T def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - Yld2004-18p yield criterion - the fitted parameters are - C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D - C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D - and m, m is optional - criteria are invalid input - ''' + """ + Yld2004-18p yield criterion + + the fitted parameters are + C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D + C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D + and m, m are optional + criteria is ignored + """ if dim == 2: C,D = np.append(paras[0:7],[0.0,0.0]), np.append(paras[7:14],[0.0,0.0]) else: C,D = paras[0:9], paras[9:18] if mFix[0]: m = mFix[1] @@ -843,14 +842,15 @@ def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): else: return np.vstack((jc,jd,jm)).T def KarafillisBoyce(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - ''' - Karafillis-Boyce - the fitted parameters are - c11,c12,c13,c14,c15,c16,c,m for 3D - c11,c12,c13,c14,c,m for plane stress - 0 0.0: nExponent = nExpo + if options.exponent > 0.0: nExponent = options.exponent else: nExponent = 0 nameCriterion = self.name.lower() criteria = Criteria(nameCriterion,self.uniaxial,self.expo, self.dimen) @@ -1225,13 +1213,10 @@ class Criterion(object): pass return popt - #--------------------------------------------------------------------------------------------------- class myThread (threading.Thread): -#--------------------------------------------------------------------------------------------------- - ''' - Runner class - ''' + """Runner""" + def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID @@ -1246,8 +1231,6 @@ class myThread (threading.Thread): s.release() def doSim(thread): - -# if load case do not exist, create new one s.acquire() global myLoad loadNo=loadcaseNo() @@ -1337,7 +1320,7 @@ def doSim(thread): strainAll[i]=np.append(strainAll[i], deformationRate[i]) f.write( str(threshold)+' '+ ' '.join(map(str,myFit.fit(stressAll[i].reshape(len(stressAll[i])//6,6).transpose())))+'\n') - except Exception as detail: + except Exception: damask.util.croak('Could not fit results of simulation (%s)'%thread) s.release() return @@ -1440,7 +1423,7 @@ else : stressUnit = 1.0e6 if options.dimension not in fitCriteria[options.criterion]['dimen']: parser.error('invalid dimension for selected criterion') -if options.criterion not in ['vonmises','tresca','drucker','hill1984'] and options.eqStress == None: +if options.criterion not in ['vonmises','tresca','drucker','hill1984'] and options.eqStress is None: parser.error('please specifie an equivalent stress (e.g. fitting to von Mises)') run = runFit(options.exponent, options.eqStress, options.dimension, options.criterion) From a51f2a29f6b1099e81d0e419308ef78ea21e8b61 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Mar 2016 14:53:55 +0100 Subject: [PATCH 038/134] cleaning --- processing/misc/ang_toTable.py | 5 +- processing/misc/calculateAnisotropy.py | 64 ++++++++++---------------- processing/misc/gwyddion_filter.py | 30 +++--------- processing/misc/vtk_fromGwyddion.py | 36 ++++----------- 4 files changed, 42 insertions(+), 93 deletions(-) diff --git a/processing/misc/ang_toTable.py b/processing/misc/ang_toTable.py index 8820c514a..48b38f0b0 100755 --- a/processing/misc/ang_toTable.py +++ b/processing/misc/ang_toTable.py @@ -1,8 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,vtk -import numpy as np +import os from optparse import OptionParser import damask @@ -48,7 +47,7 @@ for name in filenames: table.labels_append(['1_Euler','2_Euler','3_Euler', '1_pos','2_pos', 'IQ','CI','PhaseID','Intensity','Fit', - ], # labels according to OIM Analysis 7.2 Manual, p 403 (of 517) + ], # OIM Analysis 7.2 Manual, p 403 (of 517) reset = True) # ------------------------------------------ assemble header --------------------------------------- diff --git a/processing/misc/calculateAnisotropy.py b/processing/misc/calculateAnisotropy.py index d93431f50..c390926bb 100644 --- a/processing/misc/calculateAnisotropy.py +++ b/processing/misc/calculateAnisotropy.py @@ -1,9 +1,9 @@ #!/usr/bin/python # -*- coding: UTF-8 no BOM -*- -import threading,time,os,subprocess,shlex,string +import threading,os,string import numpy as np -from optparse import OptionParser, OptionGroup +from optparse import OptionParser from shutil import copy2 from re import split import damask @@ -14,26 +14,10 @@ scriptID = ' '.join([scriptName,damask.version]) def list_split(option, opt, value, parser): setattr(parser.values, option.dest, value.split(',')) -def execute(cmd,streamIn=None,wd='./'): - ''' - executes a command in given directory and returns stdout and stderr for optional stdin - ''' - initialPath=os.getcwd() - os.chdir(wd) - process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE) - if streamIn != None: - out,error = process.communicate(streamIn.read()) - else: - out,error = process.communicate() - os.chdir(initialPath) - return out,error - #--------------------------------------------------------------------------------------------------- class myThread (threading.Thread): -#--------------------------------------------------------------------------------------------------- - ''' - Runner class - ''' + """Runner""" + def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID @@ -48,8 +32,6 @@ class myThread (threading.Thread): s.release() def doSim(delay,thread): -# s.acquire() and s.release() are couple -# global dirCurrent s.acquire() delta_angle = offsetPhi() @@ -63,22 +45,22 @@ def doSim(delay,thread): os.mkdir(dire,0755) for file in [options.geometry+'.geom',options.load+'.load','numerics.config']: copy2(dirCurrent+'/'+file, dire) - newMatConfig = newMaterialConfig(dirCurrent,delta_angle) + newMaterialConfig(dirCurrent,delta_angle) os.chdir(dire) if not os.path.isfile('%s_%s.spectralOut'%(options.geometry,options.load)): print('starting uniaxial tension in direction of angle %s from %s'%(file_angle,thread)) s.release() - execute('DAMASK_spectral -g %s -l %s'%(options.geometry,options.load)) + damask.util.execute('DAMASK_spectral -g %s -l %s'%(options.geometry,options.load)) else: s.release() s.acquire() if not os.path.isfile('./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)): print('starting post processing for angle %s from %s'%(file_angle,thread)) s.release() - execute('postResults --cr f,p -d %s %s_%s.spectralOut'%('Rvalues',options.geometry,options.load)) - execute('addCauchy ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)) - execute('addStrainTensors -l -v ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)) + damask.util.execute('postResults --cr f,p -d %s %s_%s.spectralOut'%('Rvalues',options.geometry,options.load)) + damask.util.execute('addCauchy ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)) + damask.util.execute('addStrainTensors -l -v ./%s/%s_%s.txt'%('Rvalues',options.geometry,options.load)) print('post processing for angle %s from %s is finished'%(file_angle,thread)) else: @@ -122,7 +104,6 @@ def newMaterialConfig(dire,angle): line2 = line f.write(line2) f.close() - return True # -------------------------------------------------------------------- # MAIN @@ -135,16 +116,21 @@ strength anisotropic coefficients (normalized yield stress) """, version=string.replace(scriptID,'\n','\\n') ) -parser.add_option('-l','--load' , dest='load', type='string', - help='name of the load file [%default]', metavar='string') -parser.add_option('-g','--geometry', dest='geometry', type='string', - help='name of the geometry file [%default]', metavar='string') -parser.add_option('-s', '--strain', dest='strain', type='string', action='callback', callback=list_split, - help='the threshold strains, using comma to seperate multiple strains [%default]', metavar='string') -parser.add_option('-t','--threads', dest='threads', type='int', - help='number of parallel executions [%default]', metavar='int') -parser.add_option('-n','--number', dest='number', type='int', - help='Number of uni-axial tensile tests [%default]', metavar='int') +parser.add_option('-l','--load' , + dest='load', type='string', + help='name of the load file [%default]', metavar='string') +parser.add_option('-g','--geometry', + dest='geometry', type='string', + help='name of the geometry file [%default]', metavar='string') +parser.add_option('-s', '--strain', + dest='strain', type='string', action='callback', callback=list_split, + help='threshold strains, using comma to seperate multiple strains [%default]', metavar='string') +parser.add_option('-t','--threads', + dest='threads', type='int', + help='number of parallel executions [%default]', metavar='int') +parser.add_option('-n','--number', + dest='number', type='int', + help='Number of uni-axial tensile tests [%default]', metavar='int') parser.set_defaults(geometry = '20grains16x16x16') parser.set_defaults(load = 'tensionX') @@ -248,4 +234,4 @@ for i in xrange(2): aniso_list_ang_strain.append('none') writeformat = writeformat+'%-12s' f.write('%-10s'%file_angle + writeformat%(tuple(aniso_list_ang_strain))+'\n') -f.close() \ No newline at end of file +f.close() diff --git a/processing/misc/gwyddion_filter.py b/processing/misc/gwyddion_filter.py index 100c61976..7748b101f 100755 --- a/processing/misc/gwyddion_filter.py +++ b/processing/misc/gwyddion_filter.py @@ -1,33 +1,15 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,re,numpy,scipy.ndimage,scipy.signal,vtk +import os,string,scipy +import numpy as np import damask -from optparse import OptionParser, OptionGroup, Option, SUPPRESS_HELP +from optparse import OptionParser scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -#-------------------------------------------------------------------------------------------------- -class extendedOption(Option): -#-------------------------------------------------------------------------------------------------- -# used for definition of new option parser action 'extend', which enables to take multiple option arguments -# taken from online tutorial http://docs.python.org/library/optparse.html - - ACTIONS = Option.ACTIONS + ("extend",) - STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) - TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) - ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) - - def take_action(self, action, dest, opt, value, values, parser): - if action == "extend": - lvalue = value.split(",") - values.ensure_value(dest, []).extend(lvalue) - else: - Option.take_action(self, action, dest, opt, value, values, parser) - - -parser = OptionParser(option_class=extendedOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ Apply filter(s) to Gwyddion data. """ + string.replace(scriptID,'\n','\\n') ) @@ -59,7 +41,7 @@ for file in filenames: if pieces[1] == 'Height:': height = float(pieces[2]) header.append(line.lstrip('#').strip()) - elevation = numpy.loadtxt(file)#*1e6 + elevation = np.loadtxt(file)#*1e6 if options.opening > 0: elevation = scipy.ndimage.morphology.grey_opening(elevation,options.opening) @@ -80,5 +62,5 @@ for file in filenames: elevation = scipy.ndimage.filters.median_filter(elevation,options.median) filters += '_median%i'%options.median - numpy.savetxt(os.path.splitext(file)[0]+filters+os.path.splitext(file)[1],elevation,header='\n'.join(header)) + np.savetxt(os.path.splitext(file)[0]+filters+os.path.splitext(file)[1],elevation,header='\n'.join(header)) diff --git a/processing/misc/vtk_fromGwyddion.py b/processing/misc/vtk_fromGwyddion.py index 398999c75..6f13a2e0f 100755 --- a/processing/misc/vtk_fromGwyddion.py +++ b/processing/misc/vtk_fromGwyddion.py @@ -1,9 +1,10 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,string,re,numpy,scipy.ndimage,scipy.signal,vtk +import os,string,vtk +import numpy as np import damask -from optparse import OptionParser, OptionGroup, Option, SUPPRESS_HELP +from optparse import OptionParser scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -26,26 +27,7 @@ scalingFactor = { \ }, } -#-------------------------------------------------------------------------------------------------- -class extendedOption(Option): -#-------------------------------------------------------------------------------------------------- -# used for definition of new option parser action 'extend', which enables to take multiple option arguments -# taken from online tutorial http://docs.python.org/library/optparse.html - - ACTIONS = Option.ACTIONS + ("extend",) - STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) - TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) - ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) - - def take_action(self, action, dest, opt, value, values, parser): - if action == "extend": - lvalue = value.split(",") - values.ensure_value(dest, []).extend(lvalue) - else: - Option.take_action(self, action, dest, opt, value, values, parser) - - -parser = OptionParser(option_class=extendedOption, usage='%prog options [file[s]]', description = """ +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ Produce VTK rectilinear grid from Gwyddion dataset exported as text. """ + string.replace(scriptID,'\n','\\n') ) @@ -78,16 +60,16 @@ for file in filenames: if options.scaling == 0.0: options.scaling = scalingFactor[lateralunit][elevationunit] - elevation = numpy.loadtxt(file)*options.scaling + elevation = np.loadtxt(file)*options.scaling grid = vtk.vtkRectilinearGrid() grid.SetDimensions(elevation.shape[1],elevation.shape[0],1) xCoords = vtk.vtkDoubleArray() - for x in numpy.arange(0.0,width,width/elevation.shape[1],'d'): + for x in np.arange(0.0,width,width/elevation.shape[1],'d'): xCoords.InsertNextValue(x) yCoords = vtk.vtkDoubleArray() - for y in numpy.arange(0.0,height,height/elevation.shape[0],'d'): + for y in np.arange(0.0,height,height/elevation.shape[0],'d'): yCoords.InsertNextValue(y) zCoords = vtk.vtkDoubleArray() zCoords.InsertNextValue(0.0) @@ -99,8 +81,8 @@ for file in filenames: vector = vtk.vtkFloatArray() vector.SetName("elevation"); vector.SetNumberOfComponents(3); - vector.SetNumberOfTuples(numpy.prod(elevation.shape)); - for i,z in enumerate(numpy.ravel(elevation)): + vector.SetNumberOfTuples(np.prod(elevation.shape)); + for i,z in enumerate(np.ravel(elevation)): vector.SetTuple3(i,0,0,z) grid.GetPointData().AddArray(vector) From 48233d27678dff94bc9acd1ee08c0eb72f2efcbc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 3 Mar 2016 14:58:04 +0100 Subject: [PATCH 039/134] missing variable --- processing/pre/seeds_fromPokes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/pre/seeds_fromPokes.py b/processing/pre/seeds_fromPokes.py index 76f1fb003..7915e8951 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -123,7 +123,7 @@ for name in filenames: # --- report --------------------------------------------------------------------------------------- if (newInfo['microstructures'] != info['microstructures']): - damask.util.croak(remarks.append('--> microstructures: %i'%newInfo['microstructures'])) + damask.util.croak('--> microstructures: %i'%newInfo['microstructures']) # ------------------------------------------ assemble header --------------------------------------- From 75480bc677002606dc072483dcdebeab22a08016 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 15:22:01 +0100 Subject: [PATCH 040/134] modified background threading because using it in postResults led to an dead lock. rest modifications are just style --- lib/damask/util.py | 414 ++++++++++++++++++++++----------------------- 1 file changed, 200 insertions(+), 214 deletions(-) diff --git a/lib/damask/util.py b/lib/damask/util.py index b3e35812a..1b239b7b0 100644 --- a/lib/damask/util.py +++ b/lib/damask/util.py @@ -6,11 +6,13 @@ import numpy as np from optparse import Option class bcolors: - ''' - ASCII Colors (Blender code) - https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py - http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python - ''' + """ + ASCII Colors (Blender code) + + https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py + http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python + """ + HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' @@ -32,30 +34,28 @@ class bcolors: # ----------------------------- -def srepr(arg, - glue = '\n'): -# ----------------------------- - if (not hasattr(arg, "strip") and - hasattr(arg, "__getitem__") or - hasattr(arg, "__iter__")): - return glue.join(srepr(x) for x in arg) - return arg if isinstance(arg,basestring) else repr(arg) +def srepr(arg,glue = '\n'): + """joins arguments as individual lines""" + if (not hasattr(arg, "strip") and + hasattr(arg, "__getitem__") or + hasattr(arg, "__iter__")): + return glue.join(srepr(x) for x in arg) + return arg if isinstance(arg,basestring) else repr(arg) # ----------------------------- -def croak(what, - newline = True): -# ----------------------------- +def croak(what, newline = True): + """writes formated to stderr""" sys.stderr.write(srepr(what,glue = '\n') + ('\n' if newline else '')) sys.stderr.flush() # ----------------------------- def report(who,what): -# ----------------------------- + """reports script and file name""" croak( (emph(who) if who else '') + (': '+what if what else '') ) # ----------------------------- def emph(what): -# ----------------------------- + """emphasizes string on screen""" return bcolors.BOLD+srepr(what)+bcolors.ENDC # ----------------------------- @@ -68,7 +68,6 @@ for f in ['cos', 'sin', 'tan']: # ----------------------------- def gridLocation(idx,res): -# ----------------------------- return ( idx % res[0], \ ( idx // res[0]) % res[1], \ ( idx // res[0] // res[1]) % res[2] ) @@ -76,7 +75,6 @@ def gridLocation(idx,res): # ----------------------------- def gridIndex(location,res): -# ----------------------------- return ( location[0] % res[0] + \ ( location[1] % res[1]) * res[0] + \ ( location[2] % res[2]) * res[1] * res[0] ) @@ -84,10 +82,12 @@ def gridIndex(location,res): # ----------------------------- class extendableOption(Option): -# ----------------------------- -# used for definition of new option parser action 'extend', which enables to take multiple option arguments -# taken from online tutorial http://docs.python.org/library/optparse.html - + """ + used for definition of new option parser action 'extend', which enables to take multiple option arguments + + taken from online tutorial http://docs.python.org/library/optparse.html + """ + ACTIONS = Option.ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) @@ -102,28 +102,34 @@ class extendableOption(Option): # ----------------------------- class backgroundMessage(threading.Thread): -# ----------------------------- + """reporting with animation to indicate progress""" + choices = {'bounce': ['_','o','O','°','¯','¯','°','O','o',], 'circle': [u'\u25f4',u'\u25f5',u'\u25f6',u'\u25f7'], 'hexagon': [u'\u2b22',u'\u2b23'], 'square': [u'\u2596',u'\u2598',u'\u259d',u'\u2597'], 'triangle': [u'\u140a',u'\u140a',u'\u1403',u'\u1405',u'\u1405',u'\u1403'], - 'amoeba': [u'\u2596',u'\u258f',u'\u2598',u'\u2594',u'\u259d',u'\u2595',u'\u2597',u'\u2582'], - 'beat': [u'\u2581',u'\u2582',u'\u2583',u'\u2585',u'\u2586',u'\u2587',u'\u2587',u'\u2586',u'\u2585',u'\u2583',u'\u2582',], - 'prison': [u'\u168b',u'\u168c',u'\u168d',u'\u168f',u'\u168e',u'\u168d',u'\u168c',u'\u168b',], - 'breath': [u'\u1690',u'\u1691',u'\u1692',u'\u1693',u'\u1694',u'\u1693',u'\u1692',u'\u1691',u'\u1690',], + 'amoeba': [u'\u2596',u'\u258f',u'\u2598',u'\u2594',u'\u259d',u'\u2595', + u'\u2597',u'\u2582'], + 'beat': [u'\u2581',u'\u2582',u'\u2583',u'\u2585',u'\u2586',u'\u2587', + u'\u2587',u'\u2586',u'\u2585',u'\u2583',u'\u2582',], + 'prison': [u'\u168b',u'\u168c',u'\u168d',u'\u168f',u'\u168e',u'\u168d', + u'\u168c',u'\u168b',], + 'breath': [u'\u1690',u'\u1691',u'\u1692',u'\u1693',u'\u1694',u'\u1693', + u'\u1692',u'\u1691',u'\u1690',], 'pulse': [u'·',u'•',u'\u25cf',u'\u25cf',u'•',], - 'ant': [u'\u2801',u'\u2802',u'\u2810',u'\u2820',u'\u2804',u'\u2840',u'\u2880',u'\u2820',u'\u2804',u'\u2802',u'\u2810',u'\u2808'], - 'juggle': [u'\ua708',u'\ua709',u'\ua70a',u'\ua70b',u'\ua70c',u'\ua711',u'\ua710',u'\ua70f',u'\ua70d',], + 'ant': [u'\u2801',u'\u2802',u'\u2810',u'\u2820',u'\u2804',u'\u2840', + u'\u2880',u'\u2820',u'\u2804',u'\u2802',u'\u2810',u'\u2808'], + 'juggle': [u'\ua708',u'\ua709',u'\ua70a',u'\ua70b',u'\ua70c',u'\ua711', + u'\ua710',u'\ua70f',u'\ua70d',], # 'wobbler': [u'\u2581',u'\u25e3',u'\u258f',u'\u25e4',u'\u2594',u'\u25e5',u'\u2595',u'\u25e2',], 'grout': [u'\u2581',u'\u258f',u'\u2594',u'\u2595',], 'partner': [u'\u26ac',u'\u26ad',u'\u26ae',u'\u26af',u'\u26ae',u'\u26ad',], 'classic': ['-', '\\', '|', '/',], } - def __init__(self, - symbol = None, - wait = 0.1): + def __init__(self,symbol = None,wait = 0.1): + """sets animation symbol""" super(backgroundMessage, self).__init__() self._stop = threading.Event() self.message = '' @@ -134,6 +140,7 @@ class backgroundMessage(threading.Thread): self.waittime = wait def __quit__(self): + """cleans output""" length = len(self.symbols[self.counter] + self.gap + self.message) sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length) sys.stderr.write('') @@ -146,8 +153,7 @@ class backgroundMessage(threading.Thread): return self._stop.is_set() def run(self): -# while not threading.enumerate()[0]._Thread__stopped: - while not self.stopped(): + while not threading.enumerate()[0]._Thread__stopped: time.sleep(self.waittime) self.update_message() self.__quit__() @@ -170,24 +176,38 @@ class backgroundMessage(threading.Thread): def animation(self,which = None): return ''.join(self.choices[which]) if which in self.choices else '' -''' -Non-linear least square fitting (Levenberg-Marquardt method) with -bounded parameters. -the codes of transformation between int <-> ext refers to the work of -Jonathan J. Helmus: https://github.com/jjhelmus/leastsqbound-scipy -other codes refers to the source code of minpack.py: -..\Lib\site-packages\scipy\optimize\minpack.py -''' -from numpy import (array, arcsin, asarray, cos, dot, eye, empty_like, - isscalar,finfo, take, triu, transpose, sqrt, sin) -def _check_func(checker, argname, thefunc, x0, args, numinputs, +def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0, + col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8, + gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None): + from scipy.optimize import _minpack + """ + Non-linear least square fitting (Levenberg-Marquardt method) with + bounded parameters. + the codes of transformation between int <-> ext refers to the work of + Jonathan J. Helmus: https://github.com/jjhelmus/leastsqbound-scipy + other codes refers to the source code of minpack.py: + ..\Lib\site-packages\scipy\optimize\minpack.py + + An internal parameter list is used to enforce contraints on the fitting + parameters. The transfomation is based on that of MINUIT package. + please see: F. James and M. Winkler. MINUIT User's Guide, 2004. + + bounds : list + (min, max) pairs for each parameter, use None for 'min' or 'max' + when there is no bound in that direction. + For example: if there are two parameters needed to be fitting, then + bounds is [(min1,max1), (min2,max2)] + + This function is based on 'leastsq' of minpack.py, the annotation of + other parameters can be found in 'leastsq'. + ..\Lib\site-packages\scipy\optimize\minpack.py + """ + + def _check_func(checker, argname, thefunc, x0, args, numinputs, output_shape=None): - from numpy import atleast_1d, shape, issubdtype, dtype, inexact - ''' - The same as that of minpack.py, - ''' - res = atleast_1d(thefunc(*((x0[:numinputs],) + args))) + """The same as that of minpack.py""" + res = np.atleast_1d(thefunc(*((x0[:numinputs],) + args))) if (output_shape is not None) and (shape(res) != output_shape): if (output_shape[0] != 1): if len(output_shape) > 1: @@ -201,203 +221,171 @@ def _check_func(checker, argname, thefunc, x0, args, numinputs, else: msg += "." raise TypeError(msg) - if issubdtype(res.dtype, inexact): + if np.issubdtype(res.dtype, np.inexact): dt = res.dtype else: dt = dtype(float) return shape(res), dt - -def _int2extGrad(p_int, bounds): - """ - Calculate the gradients of transforming the internal (unconstrained) - to external (constained) parameter. - """ - grad = empty_like(p_int) + + def _int2extGrad(p_int, bounds): + """Calculate the gradients of transforming the internal (unconstrained) to external (constained) parameter.""" + grad = np.empty_like(p_int) for i, (x, bound) in enumerate(zip(p_int, bounds)): lower, upper = bound if lower is None and upper is None: # No constraints grad[i] = 1.0 elif upper is None: # only lower bound - grad[i] = x/sqrt(x*x + 1.0) + grad[i] = x/np.sqrt(x*x + 1.0) elif lower is None: # only upper bound - grad[i] = -x/sqrt(x*x + 1.0) + grad[i] = -x/np.sqrt(x*x + 1.0) else: # lower and upper bounds - grad[i] = (upper - lower)*cos(x)/2.0 + grad[i] = (upper - lower)*np.cos(x)/2.0 return grad - -def _int2extFunc(bounds): - ''' - transform internal parameters into external parameters. - ''' + + def _int2extFunc(bounds): + """transform internal parameters into external parameters.""" local = [_int2extLocal(b) for b in bounds] def _transform_i2e(p_int): - p_ext = empty_like(p_int) + p_ext = np.empty_like(p_int) p_ext[:] = [i(j) for i, j in zip(local, p_int)] return p_ext return _transform_i2e - -def _ext2intFunc(bounds): - ''' - transform external parameters into internal parameters. - ''' + + def _ext2intFunc(bounds): + """transform external parameters into internal parameters.""" local = [_ext2intLocal(b) for b in bounds] def _transform_e2i(p_ext): - p_int = empty_like(p_ext) + p_int = np.empty_like(p_ext) p_int[:] = [i(j) for i, j in zip(local, p_ext)] return p_int return _transform_e2i - -def _int2extLocal(bound): - ''' - transform a single internal parameter to an external parameter. - ''' + + def _int2extLocal(bound): + """transform a single internal parameter to an external parameter.""" lower, upper = bound if lower is None and upper is None: # no constraints return lambda x: x elif upper is None: # only lower bound - return lambda x: lower - 1.0 + sqrt(x*x + 1.0) + return lambda x: lower - 1.0 + np.sqrt(x*x + 1.0) elif lower is None: # only upper bound - return lambda x: upper + 1.0 - sqrt(x*x + 1.0) + return lambda x: upper + 1.0 - np.sqrt(x*x + 1.0) else: - return lambda x: lower + ((upper - lower)/2.0)*(sin(x) + 1.0) - -def _ext2intLocal(bound): - ''' - transform a single external parameter to an internal parameter. - ''' + return lambda x: lower + ((upper - lower)/2.0)*(np.sin(x) + 1.0) + + def _ext2intLocal(bound): + """transform a single external parameter to an internal parameter.""" lower, upper = bound if lower is None and upper is None: # no constraints return lambda x: x elif upper is None: # only lower bound - return lambda x: sqrt((x - lower + 1.0)**2 - 1.0) + return lambda x: np.sqrt((x - lower + 1.0)**2 - 1.0) elif lower is None: # only upper bound - return lambda x: sqrt((x - upper - 1.0)**2 - 1.0) + return lambda x: np.sqrt((x - upper - 1.0)**2 - 1.0) else: - return lambda x: arcsin((2.0*(x - lower)/(upper - lower)) - 1.0) + return lambda x: np.arcsin((2.0*(x - lower)/(upper - lower)) - 1.0) + + i2e = _int2extFunc(bounds) + e2i = _ext2intFunc(bounds) + + x0 = np.asarray(x0).flatten() + n = len(x0) -def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0, - col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8, - gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None): - from scipy.optimize import _minpack - ''' - An internal parameter list is used to enforce contraints on the fitting - parameters. The transfomation is based on that of MINUIT package. - please see: F. James and M. Winkler. MINUIT User's Guide, 2004. + if len(bounds) != n: + raise ValueError('the length of bounds is inconsistent with the number of parameters ') + + if not isinstance(args, tuple): + args = (args,) + + shape, dtype = _check_func('leastsq', 'func', func, x0, args, n) + m = shape[0] - bounds : list - (min, max) pairs for each parameter, use None for 'min' or 'max' - when there is no bound in that direction. - For example: if there are two parameters needed to be fitting, then - bounds is [(min1,max1), (min2,max2)] - - This function is based on 'leastsq' of minpack.py, the annotation of - other parameters can be found in 'leastsq'. - ..\Lib\site-packages\scipy\optimize\minpack.py - ''' - i2e = _int2extFunc(bounds) - e2i = _ext2intFunc(bounds) - - x0 = asarray(x0).flatten() - n = len(x0) + if n > m: + raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) + if epsfcn is None: + epsfcn = np.finfo(dtype).eps - if len(bounds) != n: - raise ValueError('the length of bounds is inconsistent with the number of parameters ') - - if not isinstance(args, tuple): - args = (args,) - - shape, dtype = _check_func('leastsq', 'func', func, x0, args, n) - m = shape[0] + def funcWarp(x, *args): + return func(i2e(x), *args) - if n > m: - raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) - if epsfcn is None: - epsfcn = finfo(dtype).eps + xi0 = e2i(x0) + + if Dfun is None: + if maxfev == 0: + maxfev = 200*(n + 1) + retval = _minpack._lmdif(funcWarp, xi0, args, full_output, ftol, xtol, + gtol, maxfev, epsfcn, factor, diag) + else: + if col_deriv: + _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n, m)) + else: + _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m, n)) + if maxfev == 0: + maxfev = 100*(n + 1) - # wrapped func - def funcWarp(x, *args): - return func(i2e(x), *args) + def DfunWarp(x, *args): + return Dfun(i2e(x), *args) - xi0 = e2i(x0) - - if Dfun is None: - if maxfev == 0: - maxfev = 200*(n + 1) - retval = _minpack._lmdif(funcWarp, xi0, args, full_output, ftol, xtol, - gtol, maxfev, epsfcn, factor, diag) - else: - if col_deriv: - _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n, m)) - else: - _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m, n)) - if maxfev == 0: - maxfev = 100*(n + 1) + retval = _minpack._lmder(funcWarp, DfunWarp, xi0, args, full_output, col_deriv, + ftol, xtol, gtol, maxfev, factor, diag) - # wrapped Dfun - def DfunWarp(x, *args): - return Dfun(i2e(x), *args) + errors = {0: ["Improper input parameters.", TypeError], + 1: ["Both actual and predicted relative reductions " + "in the sum of squares\n are at most %f" % ftol, None], + 2: ["The relative error between two consecutive " + "iterates is at most %f" % xtol, None], + 3: ["Both actual and predicted relative reductions in " + "the sum of squares\n are at most %f and the " + "relative error between two consecutive " + "iterates is at \n most %f" % (ftol, xtol), None], + 4: ["The cosine of the angle between func(x) and any " + "column of the\n Jacobian is at most %f in " + "absolute value" % gtol, None], + 5: ["Number of calls to function has reached " + "maxfev = %d." % maxfev, ValueError], + 6: ["ftol=%f is too small, no further reduction " + "in the sum of squares\n is possible.""" % ftol, + ValueError], + 7: ["xtol=%f is too small, no further improvement in " + "the approximate\n solution is possible." % xtol, + ValueError], + 8: ["gtol=%f is too small, func(x) is orthogonal to the " + "columns of\n the Jacobian to machine " + "precision." % gtol, ValueError], + 'unknown': ["Unknown error.", TypeError]} - retval = _minpack._lmder(funcWarp, DfunWarp, xi0, args, full_output, col_deriv, - ftol, xtol, gtol, maxfev, factor, diag) + info = retval[-1] # The FORTRAN return value + + if info not in [1, 2, 3, 4] and not full_output: + if info in [5, 6, 7, 8]: + np.warnings.warn(errors[info][0], RuntimeWarning) + else: + try: + raise errors[info][1](errors[info][0]) + except KeyError: + raise errors['unknown'][1](errors['unknown'][0]) - errors = {0: ["Improper input parameters.", TypeError], - 1: ["Both actual and predicted relative reductions " - "in the sum of squares\n are at most %f" % ftol, None], - 2: ["The relative error between two consecutive " - "iterates is at most %f" % xtol, None], - 3: ["Both actual and predicted relative reductions in " - "the sum of squares\n are at most %f and the " - "relative error between two consecutive " - "iterates is at \n most %f" % (ftol, xtol), None], - 4: ["The cosine of the angle between func(x) and any " - "column of the\n Jacobian is at most %f in " - "absolute value" % gtol, None], - 5: ["Number of calls to function has reached " - "maxfev = %d." % maxfev, ValueError], - 6: ["ftol=%f is too small, no further reduction " - "in the sum of squares\n is possible.""" % ftol, - ValueError], - 7: ["xtol=%f is too small, no further improvement in " - "the approximate\n solution is possible." % xtol, - ValueError], - 8: ["gtol=%f is too small, func(x) is orthogonal to the " - "columns of\n the Jacobian to machine " - "precision." % gtol, ValueError], - 'unknown': ["Unknown error.", TypeError]} + mesg = errors[info][0] + x = i2e(retval[0]) - info = retval[-1] # The FORTRAN return value - - if info not in [1, 2, 3, 4] and not full_output: - if info in [5, 6, 7, 8]: - warnings.warn(errors[info][0], RuntimeWarning) - else: - try: - raise errors[info][1](errors[info][0]) - except KeyError: - raise errors['unknown'][1](errors['unknown'][0]) - - mesg = errors[info][0] - x = i2e(retval[0]) - - if full_output: - grad = _int2extGrad(retval[0], bounds) - retval[1]['fjac'] = (retval[1]['fjac'].T / take(grad, - retval[1]['ipvt'] - 1)).T - cov_x = None - if info in [1, 2, 3, 4]: - from numpy.dual import inv - from numpy.linalg import LinAlgError - perm = take(eye(n), retval[1]['ipvt'] - 1, 0) - r = triu(transpose(retval[1]['fjac'])[:n, :]) - R = dot(r, perm) - try: - cov_x = inv(dot(transpose(R), R)) - except LinAlgError as inverror: - print inverror - pass - return (x, cov_x) + retval[1:-1] + (mesg, info) - else: - return (x, info) + if full_output: + grad = _int2extGrad(retval[0], bounds) + retval[1]['fjac'] = (retval[1]['fjac'].T / np.take(grad, + retval[1]['ipvt'] - 1)).T + cov_x = None + if info in [1, 2, 3, 4]: + from numpy.dual import inv + from numpy.linalg import LinAlgError + perm = np.take(np.eye(n), retval[1]['ipvt'] - 1, 0) + r = np.triu(np.transpose(retval[1]['fjac'])[:n, :]) + R = np.dot(r, perm) + try: + cov_x = inv(np.dot(np.transpose(R), R)) + except LinAlgError as inverror: + print inverror + pass + return (x, cov_x) + retval[1:-1] + (mesg, info) + else: + return (x, info) def _general_function(params, ydata, xdata, function): return function(xdata, *params) - ydata @@ -405,7 +393,7 @@ def _weighted_general_function(params, ydata, xdata, function, weights): return (function(xdata, *params) - ydata)*weights def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): - ''' Similar as 'curve_fit' in minpack.py''' + """Similar as 'curve_fit' in minpack.py""" if p0 is None: # determine number of parameters by inspecting the function import inspect @@ -418,15 +406,15 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): else: p0 = [1.0] * (len(args)-1) - if isscalar(p0): - p0 = array([p0]) + if np.isscalar(p0): + p0 = np.array([p0]) args = (ydata, xdata, f) if sigma is None: func = _general_function else: func = _weighted_general_function - args += (1.0/asarray(sigma),) + args += (1.0/np.asarray(sigma),) return_full = kw.pop('full_output', False) res = leastsqBound(func, p0, args=args, bounds = bounds, full_output=True, **kw) @@ -440,7 +428,7 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0)) pcov = pcov * s_sq else: - pcov = inf + pcov = np.inf if return_full: return popt, pcov, infodict, errmsg, ier @@ -449,13 +437,11 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): def execute(cmd,streamIn=None,wd='./'): - ''' - executes a command in given directory and returns stdout and stderr for optional stdin - ''' + """executes a command in given directory and returns stdout and stderr for optional stdin""" initialPath=os.getcwd() os.chdir(wd) process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE) - if streamIn != None: + if streamIn is not None: out,error = process.communicate(streamIn.read()) else: out,error = process.communicate() From 9a405ef41b9a220fe08f0e3ce83c96e01f33e7a8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 17:23:38 +0100 Subject: [PATCH 041/134] using more stable way of handling unicode printing, cleaning unicode delete from output of execute --- lib/damask/util.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/damask/util.py b/lib/damask/util.py index 1b239b7b0..77bc30403 100644 --- a/lib/damask/util.py +++ b/lib/damask/util.py @@ -147,10 +147,10 @@ class backgroundMessage(threading.Thread): sys.stderr.flush() def stop(self): - self._stop.set() + self._stop.set() def stopped(self): - return self._stop.is_set() + return self._stop.is_set() def run(self): while not threading.enumerate()[0]._Thread__stopped: @@ -165,7 +165,7 @@ class backgroundMessage(threading.Thread): def print_message(self): length = len(self.symbols[self.counter] + self.gap + self.message) sys.stderr.write(chr(8)*length + ' '*length + chr(8)*length + \ - self.symbols[self.counter] + self.gap + self.new_message) # delete former and print new message + self.symbols[self.counter].encode('utf-8') + self.gap + self.new_message) # delete former and print new message sys.stderr.flush() self.message = self.new_message @@ -442,9 +442,9 @@ def execute(cmd,streamIn=None,wd='./'): os.chdir(wd) process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE) if streamIn is not None: - out,error = process.communicate(streamIn.read()) + out,error = [i.replace("\x08","") for i in process.communicate(streamIn.read())] else: - out,error = process.communicate() + out,error =[i.replace("\x08","") for i in process.communicate()] os.chdir(initialPath) if process.returncode !=0: raise RuntimeError(cmd+' failed with returncode '+str(process.returncode)) return out,error From f13ba71f6eedba467b7553dc4b71fc09770efd35 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 17:24:13 +0100 Subject: [PATCH 042/134] fixed typo --- processing/pre/geom_grainGrowth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index 4d5aa1b6e..0f72a3589 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -120,7 +120,7 @@ for name in filenames: np.where( ndimage.morphology.binary_dilation(interfaceEnergy > 0., structure = struc, - terations = options.d/2 + 1), # fat boundary | PE: why 2d-1? I would argue for d/2 + 1 + iterations = options.d/2 + 1), # fat boundary | PE: why 2d-1? I would argue for d/2 + 1 periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... grid[1]/2:-grid[1]/2, grid[2]/2:-grid[2]/2], # ...and zero everywhere else From 24391b5398b41c9f5c0f3181d66187b0a840ca11 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 17:53:55 +0100 Subject: [PATCH 043/134] checked with prospector, adopted mainly docstrings --- lib/damask/colormaps.py | 221 ++++++++++++++++++++---------------- lib/damask/environment.py | 2 +- lib/damask/test/__init__.py | 4 +- lib/damask/test/test.py | 117 +++++++------------ 4 files changed, 169 insertions(+), 175 deletions(-) diff --git a/lib/damask/colormaps.py b/lib/damask/colormaps.py index f0045f4a7..314581471 100644 --- a/lib/damask/colormaps.py +++ b/lib/damask/colormaps.py @@ -5,11 +5,12 @@ import math,numpy as np ### --- COLOR CLASS -------------------------------------------------- class Color(): - ''' - Conversion of colors between different color-spaces. Colors should be given in the form - Color('model',[vector]).To convert and copy color from one space to other, use the methods - convertTo('model') and expressAs('model')spectively - ''' + """Conversion of colors between different color-spaces. + + Colors should be given in the form + Color('model',[vector]).To convert and copy color from one space to other, use the methods + convertTo('model') and expressAs('model')spectively + """ __slots__ = [ 'model', @@ -17,7 +18,7 @@ class Color(): ] - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def __init__(self, model = 'RGB', color = np.zeros(3,'d')): @@ -32,30 +33,32 @@ class Color(): model = model.upper() if model not in self.__transforms__.keys(): model = 'RGB' - if model == 'RGB' and max(color) > 1.0: # are we RGB255 ? + if model == 'RGB' and max(color) > 1.0: # are we RGB255 ? for i in range(3): - color[i] /= 255.0 # rescale to RGB + color[i] /= 255.0 # rescale to RGB - if model == 'HSL': # are we HSL ? - if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue? - while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range - while color[0] < 0.0: color[0] += 1.0 # rewind to proper range + if model == 'HSL': # are we HSL ? + if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue? + while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range + while color[0] < 0.0: color[0] += 1.0 # rewind to proper range self.model = model self.color = np.array(color,'d') - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def __repr__(self): + """Color model and values""" return 'Model: %s Color: %s'%(self.model,str(self.color)) - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def __str__(self): + """Color model and values""" return self.__repr__() - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def convertTo(self,toModel = 'RGB'): toModel = toModel.upper() if toModel not in self.__transforms__.keys(): return @@ -73,17 +76,19 @@ class Color(): return self - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def expressAs(self,asModel = 'RGB'): return self.__class__(self.model,self.color).convertTo(asModel) - # ------------------------------------------------------------------ - # convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue) - # with S,L,H,R,G,B running from 0 to 1 - # from http://en.wikipedia.org/wiki/HSL_and_HSV - def _HSL2RGB(self): + def _HSL2RGB(self): + """ + convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue) + + with S,L,H,R,G,B running from 0 to 1 + from http://en.wikipedia.org/wiki/HSL_and_HSV + """ if self.model != 'HSL': return sextant = self.color[0]*6.0 @@ -102,13 +107,14 @@ class Color(): self.model = converted.model self.color = converted.color - - # ------------------------------------------------------------------ - # convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance) - # with S,L,H,R,G,B running from 0 to 1 - # from http://130.113.54.154/~monger/hsl-rgb.html + def _RGB2HSL(self): - + """ + convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance) + + with S,L,H,R,G,B running from 0 to 1 + from http://130.113.54.154/~monger/hsl-rgb.html + """ if self.model != 'RGB': return HSL = np.zeros(3,'d') @@ -129,7 +135,7 @@ class Color(): HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor) elif (maxcolor == self.color[2]): HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor) - HSL[0] = HSL[0]*60.0 # is it necessary to scale to 360 hue values? might be dangerous for small values <1..! + HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values if (HSL[0] < 0.0): HSL[0] = HSL[0] + 360.0 for i in xrange(2): @@ -141,12 +147,14 @@ class Color(): self.color = converted.color - # ------------------------------------------------------------------ - # convert R(ed) G(reen) B(lue) to CIE XYZ - # with all values in the range of 0 to 1 - # from http://www.cs.rit.edu/~ncs/color/t_convert.html - def _RGB2XYZ(self): + def _RGB2XYZ(self): + """ + convert R(ed) G(reen) B(lue) to CIE XYZ + + with all values in the range of 0 to 1 + from http://www.cs.rit.edu/~ncs/color/t_convert.html + """ if self.model != 'RGB': return XYZ = np.zeros(3,'d') @@ -168,12 +176,14 @@ class Color(): self.color = converted.color - # ------------------------------------------------------------------ - # convert CIE XYZ to R(ed) G(reen) B(lue) - # with all values in the range of 0 to 1 - # from http://www.cs.rit.edu/~ncs/color/t_convert.html - def _XYZ2RGB(self): + def _XYZ2RGB(self): + """ + convert CIE XYZ to R(ed) G(reen) B(lue) + + with all values in the range of 0 to 1 + from http://www.cs.rit.edu/~ncs/color/t_convert.html + """ if self.model != 'XYZ': return convert = np.array([[ 3.240479,-1.537150,-0.498535], @@ -189,7 +199,7 @@ class Color(): RGB[i] = min(RGB[i],1.0) RGB[i] = max(RGB[i],0.0) - maxVal = max(RGB) # clipping colors according to the display gamut + maxVal = max(RGB) # clipping colors according to the display gamut if (maxVal > 1.0): RGB /= maxVal converted = Color('RGB', RGB) @@ -197,15 +207,17 @@ class Color(): self.color = converted.color - # ------------------------------------------------------------------ - # convert CIE Lab to CIE XYZ - # with XYZ in the range of 0 to 1 - # from http://www.easyrgb.com/index.php?X=MATH&H=07#text7 - def _CIELAB2XYZ(self): + def _CIELAB2XYZ(self): + """ + convert CIE Lab to CIE XYZ + + with XYZ in the range of 0 to 1 + from http://www.easyrgb.com/index.php?X=MATH&H=07#text7 + """ if self.model != 'CIELAB': return - ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 + ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 XYZ = np.zeros(3,'d') XYZ[1] = (self.color[0] + 16.0 ) / 116.0 @@ -220,16 +232,16 @@ class Color(): self.model = converted.model self.color = converted.color - - # ------------------------------------------------------------------ - # convert CIE XYZ to CIE Lab - # with XYZ in the range of 0 to 1 - # from http://en.wikipedia.org/wiki/Lab_color_space, http://www.cs.rit.edu/~ncs/color/t_convert.html def _XYZ2CIELAB(self): + """ + convert CIE XYZ to CIE Lab + with XYZ in the range of 0 to 1 + from http://en.wikipedia.org/wiki/Lab_color_space, http://www.cs.rit.edu/~ncs/color/t_convert.html + """ if self.model != 'XYZ': return - ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 + ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 XYZ = self.color/ref_white for i in xrange(len(XYZ)): @@ -242,12 +254,13 @@ class Color(): self.model = converted.model self.color = converted.color - - # ------------------------------------------------------------------ - # convert CIE Lab to Msh colorspace - # from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls + def _CIELAB2MSH(self): - + """ + convert CIE Lab to Msh colorspace + + from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls + """ if self.model != 'CIELAB': return Msh = np.zeros(3,'d') @@ -261,13 +274,14 @@ class Color(): self.model = converted.model self.color = converted.color - - # ------------------------------------------------------------------ - # convert Msh colorspace to CIE Lab - # s,h in radians - # from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls - def _MSH2CIELAB(self): + def _MSH2CIELAB(self): + """ + convert Msh colorspace to CIE Lab + + s,h in radians + from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls + """ if self.model != 'MSH': return Lab = np.zeros(3,'d') @@ -280,13 +294,8 @@ class Color(): self.color = converted.color - -### --- COLORMAP CLASS ----------------------------------------------- - class Colormap(): - ''' - perceptually uniform diverging or sequential colormaps. - ''' + """perceptually uniform diverging or sequential colormaps.""" __slots__ = [ 'left', @@ -294,20 +303,40 @@ class Colormap(): 'interpolate', ] __predefined__ = { - 'gray': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'}, - 'grey': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'}, - 'red': {'left': Color('HSL',[0,1,0.14]), 'right': Color('HSL',[0,0.35,0.91]), 'interpolate': 'perceptualuniform'}, - 'green': {'left': Color('HSL',[0.33333,1,0.14]), 'right': Color('HSL',[0.33333,0.35,0.91]), 'interpolate': 'perceptualuniform'}, - 'blue': {'left': Color('HSL',[0.66,1,0.14]), 'right': Color('HSL',[0.66,0.35,0.91]), 'interpolate': 'perceptualuniform'}, - 'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), 'right': Color('HSL',[0.40000,0.1,0.9]), 'interpolate': 'perceptualuniform'}, - 'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.11,0.75,0.38]), 'interpolate': 'perceptualuniform'}, - 'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), 'right': Color('HSL',[0.33333,1.0,0.14]), 'interpolate': 'perceptualuniform'}, - 'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.97,0.96,0.36]), 'interpolate': 'perceptualuniform'}, - 'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), 'right': Color('HSL',[0,1,0.5]), 'interpolate': 'linear' }, + 'gray': {'left': Color('HSL',[0,1,1]), + 'right': Color('HSL',[0,0,0.15]), + 'interpolate': 'perceptualuniform'}, + 'grey': {'left': Color('HSL',[0,1,1]), + 'right': Color('HSL',[0,0,0.15]), + 'interpolate': 'perceptualuniform'}, + 'red': {'left': Color('HSL',[0,1,0.14]), + 'right': Color('HSL',[0,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'green': {'left': Color('HSL',[0.33333,1,0.14]), + 'right': Color('HSL',[0.33333,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'blue': {'left': Color('HSL',[0.66,1,0.14]), + 'right': Color('HSL',[0.66,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), + 'right': Color('HSL',[0.40000,0.1,0.9]), + 'interpolate': 'perceptualuniform'}, + 'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), + 'right': Color('HSL',[0.11,0.75,0.38]), + 'interpolate': 'perceptualuniform'}, + 'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), + 'right': Color('HSL',[0.33333,1.0,0.14]), + 'interpolate': 'perceptualuniform'}, + 'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), + 'right': Color('HSL',[0.97,0.96,0.36]), + 'interpolate': 'perceptualuniform'}, + 'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), + 'right': Color('HSL',[0,1,0.5]), + 'interpolate': 'linear' }, } - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def __init__(self, left = Color('RGB',[1,1,1]), right = Color('RGB',[0,0,0]), @@ -330,26 +359,27 @@ class Colormap(): self.interpolate = interpolate - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def __repr__(self): + """left and right value of colormap""" return 'Left: %s Right: %s'%(self.left,self.right) - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def invert(self): (self.left, self.right) = (self.right, self.left) return self - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def color(self,fraction = 0.5): def interpolate_Msh(lo, hi, frac): def rad_diff(a,b): return abs(a[2]-b[2]) - - def adjust_hue(Msh_sat, Msh_unsat): # if saturation of one of the two colors is too less than the other, hue of the less +# if saturation of one of the two colors is too less than the other, hue of the less + def adjust_hue(Msh_sat, Msh_unsat): if Msh_sat[0] >= Msh_unsat[0]: return Msh_sat[2] else: @@ -375,10 +405,11 @@ class Colormap(): return Color('MSH',Msh) def interpolate_linear(lo, hi, frac): - ''' - linearly interpolate color at given fraction between lower and higher color in model of lower color - ''' - + """ + linearly interpolate color at given fraction between lower and + + higher color in model of lower color + """ interpolation = (1.0 - frac) * np.array(lo.color[:]) \ + frac * np.array(hi.expressAs(lo.model).color[:]) @@ -393,23 +424,23 @@ class Colormap(): else: raise NameError('unknown color interpolation method') - # ------------------------------------------------------------------ +# ------------------------------------------------------------------ def export(self,name = 'uniformPerceptualColorMap',\ format = 'paraview',\ steps = 2,\ crop = [-1.0,1.0], model = 'RGB'): - ''' + """ [RGB] colormap for use in paraview or gmsh, or as raw string, or array. + arguments: name, format, steps, crop. format is one of (paraview, gmsh, raw, list). crop selects a (sub)range in [-1.0,1.0]. generates sequential map if one limiting color is either white or black, diverging map otherwise. - ''' - - format = format.lower() # consistent comparison basis - frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions + """ + format = format.lower() # consistent comparison basis + frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).expressAs(model).color for i in xrange(steps)] if format == 'paraview': @@ -439,4 +470,4 @@ class Colormap(): raise NameError('unknown color export format') return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap - \ No newline at end of file + diff --git a/lib/damask/environment.py b/lib/damask/environment.py index 30fa7b31d..cd9b247e8 100644 --- a/lib/damask/environment.py +++ b/lib/damask/environment.py @@ -2,7 +2,7 @@ # $Id$ -import os,sys,string,re,subprocess,shlex +import os,subprocess,shlex class Environment(): __slots__ = [ \ diff --git a/lib/damask/test/__init__.py b/lib/damask/test/__init__.py index 9ecfb0c57..264ec7eb7 100644 --- a/lib/damask/test/__init__.py +++ b/lib/damask/test/__init__.py @@ -1,5 +1,5 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ +"""Test functionality""" -from .test import Test +from .test import Test "noqa diff --git a/lib/damask/test/test.py b/lib/damask/test/test.py index 235d74bcd..523f25d60 100644 --- a/lib/damask/test/test.py +++ b/lib/damask/test/test.py @@ -2,17 +2,19 @@ # $Id$ -import os, sys, shlex, inspect -import subprocess,shutil,string -import logging, logging.config +import os,sys,shutil +import logging,logging.config import damask +import numpy as np +from collections import Iterable from optparse import OptionParser class Test(): - ''' - General class for testing. - Is sub-classed by the individual tests. - ''' + """ + General class for testing. + + Is sub-classed by the individual tests. + """ variants = [] @@ -24,7 +26,7 @@ class Test(): fh.setLevel(logging.DEBUG) full = logging.Formatter('%(asctime)s - %(levelname)s: \n%(message)s') fh.setFormatter(full) - ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level + ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level ch.setLevel(logging.INFO) # create formatter and add it to the handlers plain = logging.Formatter('%(message)s') @@ -52,9 +54,7 @@ class Test(): accept=False) def execute(self): - ''' - Run all variants and report first failure. - ''' + """Run all variants and report first failure.""" if self.options.debug: for variant in xrange(len(self.variants)): try: @@ -84,15 +84,11 @@ class Test(): return 0 def testPossible(self): - ''' - Check if test is possible or not (e.g. no license available). - ''' + """Check if test is possible or not (e.g. no license available).""" return True def clean(self): - ''' - Delete directory tree containing current results. - ''' + """Delete directory tree containing current results.""" status = True try: @@ -110,103 +106,77 @@ class Test(): return status def prepareAll(self): - ''' - Do all necessary preparations for the whole test - ''' + """Do all necessary preparations for the whole test""" return True def prepare(self,variant): - ''' - Do all necessary preparations for the run of each test variant - ''' + """Do all necessary preparations for the run of each test variant""" return True def run(self,variant): - ''' - Execute the requested test variant. - ''' + """Execute the requested test variant.""" return True def postprocess(self,variant): - ''' - Perform post-processing of generated results for this test variant. - ''' + """Perform post-processing of generated results for this test variant.""" return True def compare(self,variant): - ''' - Compare reference to current results. - ''' + """Compare reference to current results.""" return True def update(self,variant): - ''' - Update reference with current results. - ''' + """Update reference with current results.""" logging.debug('Update not necessary') return True def dirReference(self): - ''' - Directory containing reference results of the test. - ''' + """Directory containing reference results of the test.""" return os.path.normpath(os.path.join(self.dirBase,'reference/')) def dirCurrent(self): - ''' - Directory containing current results of the test. - ''' + """Directory containing current results of the test.""" return os.path.normpath(os.path.join(self.dirBase,'current/')) def dirProof(self): - ''' - Directory containing human readable proof of correctness for the test. - ''' + """Directory containing human readable proof of correctness for the test.""" return os.path.normpath(os.path.join(self.dirBase,'proof/')) def fileInRoot(self,dir,file): - ''' - Path to a file in the root directory of DAMASK. - ''' + """Path to a file in the root directory of DAMASK.""" return os.path.join(damask.Environment().rootDir(),dir,file) def fileInReference(self,file): - ''' - Path to a file in the refrence directory for the test. - ''' + """Path to a file in the refrence directory for the test.""" return os.path.join(self.dirReference(),file) def fileInCurrent(self,file): - ''' - Path to a file in the current results directory for the test. - ''' + """Path to a file in the current results directory for the test.""" return os.path.join(self.dirCurrent(),file) def fileInProof(self,file): - ''' - Path to a file in the proof directory for the test. - ''' + """Path to a file in the proof directory for the test.""" return os.path.join(self.dirProof(),file) - + def copy(self, mapA, mapB, A = [], B = []): - ''' + """ copy list of files from (mapped) source to target. + mapA/B is one of self.fileInX. - ''' - + """ if not B or len(B) == 0: B = A for source,target in zip(map(mapA,A),map(mapB,B)): @@ -328,7 +298,8 @@ class Test(): logging.info('comparing ASCII Tables\n %s \n %s'%(file0,file1)) if normHeadings == '': normHeadings = headings0 - if len(headings0) == len(headings1) == len(normHeadings): #check if comparison is possible and determine lenght of columns +# check if comparison is possible and determine lenght of columns + if len(headings0) == len(headings1) == len(normHeadings): dataLength = len(headings0) length = [1 for i in xrange(dataLength)] shape = [[] for i in xrange(dataLength)] @@ -431,15 +402,11 @@ class Test(): meanTol = 1.0e-4, stdTol = 1.0e-6, preFilter = 1.0e-9): - - ''' - calculate statistics of tables - threshold can be used to ignore small values (a negative number disables this feature) - ''' - - import numpy as np - from collections import Iterable + """ + calculate statistics of tables + threshold can be used to ignore small values (a negative number disables this feature) + """ if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested files = [str(files)] @@ -491,15 +458,11 @@ class Test(): preFilter = -1.0, postFilter = -1.0, debug = False): - - ''' - compare tables with np.allclose - threshold can be used to ignore small values (a negative number disables this feature) - ''' - - import numpy as np - from collections import Iterable + """ + compare tables with np.allclose + threshold can be used to ignore small values (a negative number disables this feature) + """ if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested files = [str(files)] From d1e8f698578f6fe5cac11d15a4af784b063ff732 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 17:55:11 +0100 Subject: [PATCH 044/134] added docstrings etc --- lib/damask/config/__init__.py | 4 ++-- lib/damask/config/material.py | 38 ++++++++++----------------------- lib/damask/geometry/__init__.py | 8 +++---- lib/damask/geometry/geometry.py | 9 ++++---- 4 files changed, 22 insertions(+), 37 deletions(-) diff --git a/lib/damask/config/__init__.py b/lib/damask/config/__init__.py index 3c75ebd19..ba31241d0 100644 --- a/lib/damask/config/__init__.py +++ b/lib/damask/config/__init__.py @@ -1,5 +1,5 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ +"""Aggregator for configuration file handling""" -from .material import Material +from .material import Material #noqa diff --git a/lib/damask/config/material.py b/lib/damask/config/material.py index 09b716e04..4c228e312 100644 --- a/lib/damask/config/material.py +++ b/lib/damask/config/material.py @@ -100,20 +100,19 @@ class Texture(Section): class Material(): - - ''' - Reads, manipulates and writes material.config files - ''' + """Reads, manipulates and writes material.config files""" + __slots__ = ['data'] def __init__(self,verbose=True): + """generates ordered list of parts""" self.parts = [ 'homogenization', 'microstructure', 'crystallite', 'phase', 'texture', - ] # ordered (!) list of parts + ] self.data = {\ 'homogenization': {'__order__': []}, 'microstructure': {'__order__': []}, @@ -124,6 +123,7 @@ class Material(): self.verbose = verbose def __repr__(self): + """returns current configuration to be used as material.config""" me = [] for part in self.parts: if self.verbose: print('doing '+part) @@ -144,7 +144,6 @@ class Material(): re_sec = re.compile(r'^\[(.+)\]$') # pattern for section name_section = '' - idx_section = 0 active = False for line in content: @@ -197,8 +196,7 @@ class Material(): return saveFile def add_section(self, part=None, section=None, initialData=None, merge = False): - '''adding/updating''' - + """adding/updating""" part = part.lower() section = section.lower() if part not in self.parts: raise Exception('invalid part %s'%part) @@ -227,10 +225,10 @@ class Material(): def add_microstructure(self, section='', components={}, # dict of phase,texture, and fraction lists ): - ''' Experimental! Needs expansion to multi-constituent microstructures...''' - + """Experimental! Needs expansion to multi-constituent microstructures...""" microstructure = Microstructure() - components=dict((k.lower(), v) for k,v in components.iteritems()) # make keys lower case (http://stackoverflow.com/questions/764235/dictionary-to-lowercase-in-python) + # make keys lower case (http://stackoverflow.com/questions/764235/dictionary-to-lowercase-in-python) + components=dict((k.lower(), v) for k,v in components.iteritems()) for key in ['phase','texture','fraction','crystallite']: if type(components[key]) is not list: @@ -259,8 +257,8 @@ class Material(): section=None, key=None, value=None): - if type(value) is not type([]): - if type(value) is not type('s'): + if not isinstance(value,list): + if not isinstance(value,str): value = '%s'%value value = [value] newlen = len(value) @@ -271,17 +269,3 @@ class Material(): if newlen is not oldlen: print('Length of value was changed from %i to %i!'%(oldlen,newlen)) - - -def ex1(): - mat=Material() - p=Phase({'constitution':'lump'}) - t=Texture() - t.add_component('gauss',{'eulers':[1,2,3]}) - mat.add_section('phase','phase1',p) - mat.add_section('texture','tex1',t) - mat.add_microstructure('mustruct1',{'phase':['phase1']*2,'texture':['tex1']*2,'fraction':[0.2]*2}) - print(mat) - mat.write(file='poop') - mat.write(file='poop',overwrite=True) - diff --git a/lib/damask/geometry/__init__.py b/lib/damask/geometry/__init__.py index 3d35ad4fe..51199965b 100644 --- a/lib/damask/geometry/__init__.py +++ b/lib/damask/geometry/__init__.py @@ -1,7 +1,7 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ +"""Aggregator for geometry handling""" -from .geometry import Geometry # only one class -from .spectral import Spectral # only one class -from .marc import Marc # only one class +from .geometry import Geometry # noqa +from .spectral import Spectral # noqa +from .marc import Marc # noqa diff --git a/lib/damask/geometry/geometry.py b/lib/damask/geometry/geometry.py index 83a7c58a6..25a676b83 100644 --- a/lib/damask/geometry/geometry.py +++ b/lib/damask/geometry/geometry.py @@ -5,10 +5,11 @@ import damask.geometry class Geometry(): - ''' - General class for geometry parsing. - Sub-classed by the individual solvers. - ''' + """ + General class for geometry parsing. + + Sub-classed by the individual solvers. + """ def __init__(self,solver=''): solverClass = { From a4bbdd5ecb3a118b36c1d8ae88442b948d8bdafc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 18:50:13 +0100 Subject: [PATCH 045/134] further commenting, removing not used variables and code (marc2vtk) --- lib/damask/__init__.py | 22 ++--- lib/damask/asciitable.py | 128 +++++++++++----------------- lib/damask/config/__init__.py | 2 +- lib/damask/config/material.py | 3 +- lib/damask/orientation.py | 148 ++++++++++++++++++-------------- lib/damask/result.py | 9 +- lib/damask/result/marc2vtk.py | 153 ++++++++++------------------------ lib/damask/test/__init__.py | 2 +- 8 files changed, 194 insertions(+), 273 deletions(-) diff --git a/lib/damask/__init__.py b/lib/damask/__init__.py index 6b980b750..1b6ec409d 100644 --- a/lib/damask/__init__.py +++ b/lib/damask/__init__.py @@ -1,27 +1,27 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ +"""Main aggregator""" import sys, os with open(os.path.join(os.path.dirname(__file__),'../../VERSION')) as f: version = f.readline()[:-1] -from .environment import Environment # only one class -from .asciitable import ASCIItable # only one class -from .config import Material # will be extended to debug and numerics -from .colormaps import Colormap, Color -from .orientation import Quaternion, Rodrigues, Symmetry, Orientation +from .environment import Environment # noqa +from .asciitable import ASCIItable # noqa +from .config import Material # noqa +from .colormaps import Colormap, Color # noqa +from .orientation import Quaternion, Rodrigues, Symmetry, Orientation # noqa # try: # from .corientation import Quaternion, Rodrigues, Symmetry, Orientation # print "Import Cython version of Orientation module" # except: # from .orientation import Quaternion, Rodrigues, Symmetry, Orientation #from .block import Block # only one class -from .result import Result # only one class -from .geometry import Geometry # one class with subclasses -from .solver import Solver # one class with subclasses -from .test import Test -from .util import extendableOption +from .result import Result # noqa +from .geometry import Geometry # noqa +from .solver import Solver # noqa +from .test import Test # noqa +from .util import extendableOption # noqa try: from . import core diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 448c790ef..4abe4297d 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -4,12 +4,9 @@ import os,sys import numpy as np -import util class ASCIItable(): - ''' - There should be a doc string here :) - ''' + """Read and write to ASCII tables""" __slots__ = ['__IO__', 'info', @@ -58,8 +55,8 @@ class ASCIItable(): self.data = [] self.line = '' - if self.__IO__['in'] == None \ - or self.__IO__['out'] == None: raise IOError # complain if any required file access not possible + if self.__IO__['in'] is None \ + or self.__IO__['out'] is None: raise IOError # complain if any required file access not possible # ------------------------------------------------------------------ def _transliterateToFloat(self, @@ -86,9 +83,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def output_write(self, what): - ''' - aggregate a single row (string) or list of (possibly containing further lists of) rows into output - ''' + """aggregate a single row (string) or list of (possibly containing further lists of) rows into output""" if not isinstance(what, (str, unicode)): try: for item in what: self.output_write(item) @@ -104,7 +99,7 @@ class ASCIItable(): clear = True): try: self.__IO__['output'] == [] or self.__IO__['out'].write('\n'.join(self.__IO__['output']) + '\n') - except IOError as e: + except IOError: return False if clear: self.output_clear() return True @@ -127,11 +122,12 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_read(self): - ''' - get column labels by either reading - the first row or, if keyword "head[*]" is present, - the last line of the header - ''' + """ + get column labels by either reading + + the first row or, if keyword "head[*]" is present, + the last line of the header + """ import re try: @@ -180,10 +176,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_write(self, header = True): - ''' - write current header information (info + labels) - ''' - + """write current header information (info + labels)""" head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else [] head.append(self.info) if self.__IO__['labeled']: head.append('\t'.join(self.labels)) @@ -192,9 +185,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_getGeom(self): - ''' - interpret geom header - ''' + """interpret geom header""" identifiers = { 'grid': ['a','b','c'], 'size': ['x','y','z'], @@ -234,9 +225,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_putGeom(self,info): - ''' - translate geometry description to header - ''' + """translate geometry description to header""" self.info_append([ "grid\ta {}\tb {}\tc {}".format(*info['grid']), "size\tx {}\ty {}\tz {}".format(*info['size']), @@ -249,9 +238,7 @@ class ASCIItable(): def labels_append(self, what, reset = False): - ''' - add item or list to existing set of labels (and switch on labeling) - ''' + """add item or list to existing set of labels (and switch on labeling)""" if not isinstance(what, (str, unicode)): try: for item in what: self.labels_append(item) @@ -265,26 +252,25 @@ class ASCIItable(): # ------------------------------------------------------------------ def labels_clear(self): - ''' - delete existing labels and switch to no labeling - ''' + """delete existing labels and switch to no labeling""" self.labels = [] self.__IO__['labeled'] = False # ------------------------------------------------------------------ def label_index(self, labels): - ''' - tell index of column label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell index of column label(s). + + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested idx = [] for label in labels: - if label != None: + if label is not None: try: idx.append(int(label)) # column given as integer number? except ValueError: @@ -305,25 +291,25 @@ class ASCIItable(): try: idx = self.labels.index('1_'+labels) # locate '1_'+string in label list except ValueError: - idx = None if labels == None else -1 + idx = None if labels is None else -1 return np.array(idx) if isinstance(idx,list) else idx # ------------------------------------------------------------------ def label_dimension(self, labels): - ''' - tell dimension (length) of column label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell dimension (length) of column label(s). + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested dim = [] for label in labels: - if label != None: + if label is not None: myDim = -1 try: # column given as number? idx = int(label) @@ -364,12 +350,12 @@ class ASCIItable(): # ------------------------------------------------------------------ def label_indexrange(self, labels): - ''' - tell index range for given label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell index range for given label(s). + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable start = self.label_index(labels) @@ -381,9 +367,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_append(self, what): - ''' - add item or list to existing set of infos - ''' + """add item or list to existing set of infos""" if not isinstance(what, (str, unicode)): try: for item in what: self.info_append(item) @@ -394,9 +378,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_clear(self): - ''' - delete any info block - ''' + """delete any info block""" self.info = [] # ------------------------------------------------------------------ @@ -409,9 +391,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_skipLines(self, count): - ''' - wind forward by count number of lines - ''' + """wind forward by count number of lines""" for i in xrange(count): alive = self.data_read() @@ -421,9 +401,7 @@ class ASCIItable(): def data_read(self, advance = True, respectLabels = True): - ''' - read next line (possibly buffered) and parse it into data array - ''' + """read next line (possibly buffered) and parse it into data array""" self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \ else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file @@ -434,7 +412,7 @@ class ASCIItable(): if self.__IO__['labeled'] and respectLabels: # if table has labels items = self.line.split()[:len(self.__IO__['labels'])] # use up to label count (from original file info) - self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if correct number, i.e. not too few compared to label count + self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if label count matches else: self.data = self.line.split() # otherwise take all @@ -443,9 +421,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_readArray(self, labels = []): - ''' - read whole data of all (given) labels as numpy array - ''' + """read whole data of all (given) labels as numpy array""" from collections import Iterable try: @@ -453,7 +429,7 @@ class ASCIItable(): except: pass # assume/hope we are at data start already... - if labels == None or labels == []: + if labels is None or labels == []: use = None # use all columns (and keep labels intact) labels_missing = [] else: @@ -467,9 +443,10 @@ class ASCIItable(): columns = [] for i,(c,d) in enumerate(zip(indices[present],dimensions[present])): # for all valid labels ... + # ... transparently add all components unless column referenced by number or with explicit dimension columns += range(c,c + \ (d if str(c) != str(labels[present[i]]) else \ - 1)) # ... transparently add all components unless column referenced by number or with explicit dimension + 1)) use = np.array(columns) self.labels = list(np.array(self.labels)[use]) # update labels with valid subset @@ -481,9 +458,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_write(self, delimiter = '\t'): - ''' - write current data array and report alive output back - ''' + """write current data array and report alive output back""" if len(self.data) == 0: return True if isinstance(self.data[0],list): @@ -495,9 +470,7 @@ class ASCIItable(): def data_writeArray(self, fmt = None, delimiter = '\t'): - ''' - write whole numpy array data - ''' + """write whole numpy array data""" for row in self.data: try: output = [fmt % value for value in row] if fmt else map(repr,row) @@ -520,9 +493,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_set(self, what, where): - ''' - update data entry in column "where". grows data array if needed. - ''' + """update data entry in column "where". grows data array if needed.""" idx = -1 try: idx = self.label_index(where) @@ -547,10 +518,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def microstructure_read(self, grid): - ''' - read microstructure data (from .geom format) - ''' - + """read microstructure data (from .geom format)""" N = grid.prod() # expected number of microstructure indices in data microstructure = np.zeros(N,'i') # initialize as flat array diff --git a/lib/damask/config/__init__.py b/lib/damask/config/__init__.py index ba31241d0..f3635d2a9 100644 --- a/lib/damask/config/__init__.py +++ b/lib/damask/config/__init__.py @@ -2,4 +2,4 @@ """Aggregator for configuration file handling""" -from .material import Material #noqa +from .material import Material # noqa diff --git a/lib/damask/config/material.py b/lib/damask/config/material.py index 4c228e312..bca005e0e 100644 --- a/lib/damask/config/material.py +++ b/lib/damask/config/material.py @@ -243,7 +243,8 @@ class Material(): except AttributeError: pass - for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'],components['fraction'],components['crystallite']): + for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'], + components['fraction'],components['crystallite']): microstructure.add_multiKey('constituent','phase %i\ttexture %i\tfraction %g\ncrystallite %i'%( self.data['phase']['__order__'].index(phase)+1, self.data['texture']['__order__'].index(texture)+1, diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index c3f54dffa..886cd5a36 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -9,7 +9,6 @@ import numpy as np # ****************************************************************************************** class Rodrigues: -# ****************************************************************************************** def __init__(self, vector = np.zeros(3)): self.vector = vector @@ -28,20 +27,22 @@ class Rodrigues: # ****************************************************************************************** class Quaternion: -# ****************************************************************************************** - # All methods and naming conventions based off - # http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions + """ + Orientation represented as unit quaternion + + All methods and naming conventions based on http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions - # w is the real part, (x, y, z) are the imaginary parts - - # Representation of rotation is in ACTIVE form! - # (derived directly or through angleAxis, Euler angles, or active matrix) - # vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b" - # b = Q * a - # b = np.dot(Q.asMatrix(),a) + w is the real part, (x, y, z) are the imaginary parts + Representation of rotation is in ACTIVE form! + (derived directly or through angleAxis, Euler angles, or active matrix) + vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b" + b = Q * a + b = np.dot(Q.asMatrix(),a) + """ def __init__(self, quatArray = [1.0,0.0,0.0,0.0]): + """initializes to identity if not given""" self.w, \ self.x, \ self.y, \ @@ -49,19 +50,23 @@ class Quaternion: self.homomorph() def __iter__(self): + """components""" return iter([self.w,self.x,self.y,self.z]) def __copy__(self): + """create copy""" Q = Quaternion([self.w,self.x,self.y,self.z]) return Q copy = __copy__ def __repr__(self): + """readbable string""" return 'Quaternion(real=%+.6f, imag=<%+.6f, %+.6f, %+.6f>)' % \ (self.w, self.x, self.y, self.z) def __pow__(self, exponent): + """power""" omega = math.acos(self.w) vRescale = math.sin(exponent*omega)/math.sin(omega) Q = Quaternion() @@ -72,6 +77,7 @@ class Quaternion: return Q def __ipow__(self, exponent): + """in place power""" omega = math.acos(self.w) vRescale = math.sin(exponent*omega)/math.sin(omega) self.w = np.cos(exponent*omega) @@ -81,6 +87,7 @@ class Quaternion: return self def __mul__(self, other): + """multiplication""" try: # quaternion Aw = self.w Ax = self.x @@ -128,6 +135,7 @@ class Quaternion: return self.copy() def __imul__(self, other): + """in place multiplication""" try: # Quaternion Ax = self.x Ay = self.y @@ -145,6 +153,7 @@ class Quaternion: return self def __div__(self, other): + """division""" if isinstance(other, (int,float,long)): w = self.w / other x = self.x / other @@ -155,6 +164,7 @@ class Quaternion: return NotImplemented def __idiv__(self, other): + """in place division""" if isinstance(other, (int,float,long)): self.w /= other self.x /= other @@ -163,6 +173,7 @@ class Quaternion: return self def __add__(self, other): + """addition""" if isinstance(other, Quaternion): w = self.w + other.w x = self.x + other.x @@ -173,6 +184,7 @@ class Quaternion: return NotImplemented def __iadd__(self, other): + """in place division""" if isinstance(other, Quaternion): self.w += other.w self.x += other.x @@ -181,6 +193,7 @@ class Quaternion: return self def __sub__(self, other): + """subtraction""" if isinstance(other, Quaternion): Q = self.copy() Q.w -= other.w @@ -192,6 +205,7 @@ class Quaternion: return self.copy() def __isub__(self, other): + """in place subtraction""" if isinstance(other, Quaternion): self.w -= other.w self.x -= other.x @@ -200,6 +214,7 @@ class Quaternion: return self def __neg__(self): + """additive inverse""" self.w = -self.w self.x = -self.x self.y = -self.y @@ -207,6 +222,7 @@ class Quaternion: return self def __abs__(self): + """norm""" return math.sqrt(self.w ** 2 + \ self.x ** 2 + \ self.y ** 2 + \ @@ -215,6 +231,7 @@ class Quaternion: magnitude = __abs__ def __eq__(self,other): + """equal at e-8 precision""" return (abs(self.w-other.w) < 1e-8 and \ abs(self.x-other.x) < 1e-8 and \ abs(self.y-other.y) < 1e-8 and \ @@ -226,9 +243,11 @@ class Quaternion: abs(-self.z-other.z) < 1e-8) def __ne__(self,other): + """not equal at e-8 precision""" return not self.__eq__(self,other) def __cmp__(self,other): + """linear ordering""" return cmp(self.Rodrigues(),other.Rodrigues()) def magnitude_squared(self): @@ -290,9 +309,10 @@ class Quaternion: return np.outer([i for i in self],[i for i in self]) def asMatrix(self): - return np.array([[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)], - [ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)], - [ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]]) + return np.array( + [[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)], + [ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)], + [ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]]) def asAngleAxis(self, degrees = False): @@ -315,15 +335,17 @@ class Quaternion: return np.inf*np.ones(3) if self.w == 0.0 else np.array([self.x, self.y, self.z])/self.w def asEulers(self, - type = 'bunge', + type = "bunge", degrees = False, standardRange = False): - ''' + u""" + Orientation as Bunge-Euler angles + conversion of ACTIVE rotation to Euler angles taken from: Melcher, A.; Unser, A.; Reichhardt, M.; Nestler, B.; Pötschke, M.; Selzer, M. Conversion of EBSD data by a quaternion based algorithm to be used for grain structure simulations Technische Mechanik 30 (2010) pp 401--413 - ''' + """ angles = [0.0,0.0,0.0] if type.lower() == 'bunge' or type.lower() == 'zxz': @@ -369,7 +391,7 @@ class Quaternion: @classmethod def fromRandom(cls,randomSeed = None): - if randomSeed == None: + if randomSeed is None: randomSeed = int(os.urandom(4).encode('hex'), 16) np.random.seed(randomSeed) r = np.random.random(3) @@ -420,7 +442,6 @@ class Quaternion: y = - c1 * s2 * s3 + s1 * s2 * c3 z = c1 * c2 * s3 + s1 * c2 * c3 else: -# print 'unknown Euler convention' w = c1 * c2 * c3 - s1 * s2 * s3 x = s1 * s2 * c3 + c1 * c2 * s3 y = s1 * c2 * c3 + c1 * s2 * s3 @@ -428,7 +449,8 @@ class Quaternion: return cls([w,x,y,z]) -## Modified Method to calculate Quaternion from Orientation Matrix, Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ +# Modified Method to calculate Quaternion from Orientation Matrix, +# Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ @classmethod def fromMatrix(cls, m): @@ -482,8 +504,12 @@ class Quaternion: @classmethod def new_interpolate(cls, q1, q2, t): -# see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf for (another?) way to interpolate quaternions - + """ + interpolation + + see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf + for (another?) way to interpolate quaternions + """ assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion) Q = cls() @@ -522,11 +548,11 @@ class Quaternion: # ****************************************************************************************** class Symmetry: -# ****************************************************************************************** lattices = [None,'orthorhombic','tetragonal','hexagonal','cubic',] def __init__(self, symmetry = None): + """lattice with given symmetry, defaults to None""" if isinstance(symmetry, basestring) and symmetry.lower() in Symmetry.lattices: self.lattice = symmetry.lower() else: @@ -534,29 +560,31 @@ class Symmetry: def __copy__(self): + """copy""" return self.__class__(self.lattice) copy = __copy__ def __repr__(self): + """readbable string""" return '%s' % (self.lattice) def __eq__(self, other): + """equal""" return self.lattice == other.lattice - def __neq__(self, other): + """not equal""" return not self.__eq__(other) def __cmp__(self,other): + """linear ordering""" return cmp(Symmetry.lattices.index(self.lattice),Symmetry.lattices.index(other.lattice)) def symmetryQuats(self,who = []): - ''' - List of symmetry operations as quaternions. - ''' + """List of symmetry operations as quaternions.""" if self.lattice == 'cubic': symQuats = [ [ 1.0, 0.0, 0.0, 0.0 ], @@ -629,18 +657,15 @@ class Symmetry: def equivalentQuaternions(self, quaternion, who = []): - ''' - List of symmetrically equivalent quaternions based on own symmetry. - ''' + """List of symmetrically equivalent quaternions based on own symmetry.""" return [quaternion*q for q in self.symmetryQuats(who)] def inFZ(self,R): - ''' - Check whether given Rodrigues vector falls into fundamental zone of own symmetry. - ''' + """Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion - R = abs(R) # fundamental zone in Rodrigues space is point symmetric around origin +# fundamental zone in Rodrigues space is point symmetric around origin + R = abs(R) if self.lattice == 'cubic': return math.sqrt(2.0)-1.0 >= R[0] \ and math.sqrt(2.0)-1.0 >= R[1] \ @@ -662,12 +687,13 @@ class Symmetry: def inDisorientationSST(self,R): - ''' + """ Check whether given Rodrigues vector (of misorientation) falls into standard stereographic triangle of own symmetry. + Determination of disorientations follow the work of A. Heinz and P. Neumann: Representation of Orientation and Disorientation Data for Cubic, Hexagonal, Tetragonal and Orthorhombic Crystals Acta Cryst. (1991). A47, 780-789 - ''' + """ if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion epsilon = 0.0 @@ -691,11 +717,12 @@ class Symmetry: vector, proper = False, color = False): - ''' + """ Check whether given vector falls into standard stereographic triangle of own symmetry. + proper considers only vectors with z >= 0, hence uses two neighboring SSTs. Return inverse pole figure color if requested. - ''' + """ # basis = {'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red # [1.,0.,1.]/np.sqrt(2.), # direction of green # [1.,1.,1.]/np.sqrt(3.)]).transpose()), # direction of blue @@ -752,15 +779,15 @@ class Symmetry: inSST = np.all(theComponents >= 0.0) else: v = np.array(vector,dtype = float) - if proper: # check both improper ... + if proper: # check both improper ... theComponents = np.dot(basis['improper'],v) inSST = np.all(theComponents >= 0.0) if not inSST: # ... and proper SST theComponents = np.dot(basis['proper'],v) inSST = np.all(theComponents >= 0.0) else: - v[2] = abs(v[2]) # z component projects identical for positive and negative values - theComponents = np.dot(basis['improper'],v) + v[2] = abs(v[2]) # z component projects identical + theComponents = np.dot(basis['improper'],v) # for positive and negative values inSST = np.all(theComponents >= 0.0) if color: # have to return color array @@ -781,7 +808,6 @@ class Symmetry: # ****************************************************************************************** class Orientation: -# ****************************************************************************************** __slots__ = ['quaternion','symmetry'] @@ -791,7 +817,7 @@ class Orientation: angleAxis = None, matrix = None, Eulers = None, - random = False, # put any integer to have a fixed seed or True for real random + random = False, # integer to have a fixed seed or True for real random symmetry = None, ): if random: # produce random orientation @@ -815,12 +841,14 @@ class Orientation: self.symmetry = Symmetry(symmetry) def __copy__(self): + """copy""" return self.__class__(quaternion=self.quaternion,symmetry=self.symmetry.lattice) copy = __copy__ def __repr__(self): + """value as all implemented representations""" return 'Symmetry: %s\n' % (self.symmetry) + \ 'Quaternion: %s\n' % (self.quaternion) + \ 'Matrix:\n%s\n' % ( '\n'.join(['\t'.join(map(str,self.asMatrix()[i,:])) for i in range(3)]) ) + \ @@ -863,10 +891,7 @@ class Orientation: self.equivalentQuaternions(who)) def reduced(self): - ''' - Transform orientation to fall into fundamental zone according to symmetry - ''' - + """Transform orientation to fall into fundamental zone according to symmetry""" for me in self.symmetry.equivalentQuaternions(self.quaternion): if self.symmetry.inFZ(me.asRodrigues()): break @@ -876,13 +901,13 @@ class Orientation: def disorientation(self, other, SST = True): - ''' + """ Disorientation between myself and given other orientation. + Rotation axis falls into SST if SST == True. (Currently requires same symmetry for both orientations. Look into A. Heinz and P. Neumann 1991 for cases with differing sym.) - ''' - + """ if self.symmetry != other.symmetry: raise TypeError('disorientation between different symmetry classes not supported yet.') misQ = self.quaternion.conjugated()*other.quaternion @@ -900,32 +925,27 @@ class Orientation: if breaker: break if breaker: break +# disorientation, own sym, other sym, self-->other: True, self<--other: False return (Orientation(quaternion = theQ,symmetry = self.symmetry.lattice), - i,j,k == 1) # disorientation, own sym, other sym, self-->other: True, self<--other: False + i,j,k == 1) def inversePole(self, axis, proper = False, SST = True): - ''' - axis rotated according to orientation (using crystal symmetry to ensure location falls into SST) - ''' - + """axis rotated according to orientation (using crystal symmetry to ensure location falls into SST)""" if SST: # pole requested to be within SST for i,q in enumerate(self.symmetry.equivalentQuaternions(self.quaternion)): # test all symmetric equivalent quaternions pole = q.conjugated()*axis # align crystal direction to axis - if self.symmetry.inSST(pole,proper): break # found SST version + if self.symmetry.inSST(pole,proper): break # found SST version else: pole = self.quaternion.conjugated()*axis # align crystal direction to axis return (pole,i if SST else 0) def IPFcolor(self,axis): - ''' - TSL color of inverse pole figure for given axis - ''' - + """TSL color of inverse pole figure for given axis""" color = np.zeros(3,'d') for q in self.symmetry.equivalentQuaternions(self.quaternion): @@ -939,7 +959,9 @@ class Orientation: def average(cls, orientations, multiplicity = []): - """RETURN THE AVERAGE ORIENTATION + """ + average orientation + ref: F. Landis Markley, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman. Averaging Quaternions, Journal of Guidance, Control, and Dynamics, Vol. 30, No. 4 (2007), pp. 1193-1197. @@ -949,7 +971,6 @@ class Orientation: b = Orientation(Eulers=np.radians([20, 0, 0]), symmetry='hexagonal') avg = Orientation.average([a,b]) """ - if not all(isinstance(item, Orientation) for item in orientations): raise TypeError("Only instances of Orientation can be averaged.") @@ -960,8 +981,7 @@ class Orientation: reference = orientations[0] # take first as reference for i,(o,n) in enumerate(zip(orientations,multiplicity)): closest = o.equivalentOrientations(reference.disorientation(o,SST = False)[2])[0] # select sym orientation with lowest misorientation - M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # add (multiples) of this orientation to average - + M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # noqa add (multiples) of this orientation to average noqa eig, vec = np.linalg.eig(M/N) return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])), diff --git a/lib/damask/result.py b/lib/damask/result.py index e65fa2afe..36e4ba81b 100644 --- a/lib/damask/result.py +++ b/lib/damask/result.py @@ -11,10 +11,11 @@ except (ImportError) as e: sys.stderr.write('\nREMARK: h5py module not available \n\n') class Result(): - ''' - General class for result parsing. - Needs h5py to be installed - ''' + """ + General class for result parsing. + + Needs h5py to be installed + """ def __init__(self,resultsFile): self.data=h5py.File(resultsFile,"r") diff --git a/lib/damask/result/marc2vtk.py b/lib/damask/result/marc2vtk.py index 84c2a6313..a04c710d7 100644 --- a/lib/damask/result/marc2vtk.py +++ b/lib/damask/result/marc2vtk.py @@ -1,6 +1,5 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ # This tool converts a msc.marc result file into the vtk format that # can be viewed by Paraview software (Kitware), or MayaVi (needs xml-vtk, or ... # @@ -8,13 +7,8 @@ # Some example vtk files: http://people.sc.fsu.edu/~jburkardt/data/vtk/vtk.html # www.paraview.org -import os,sys,math,time,re -# python external -try: - import numpy as N - import numpy -except: - print('Could not import numpy.') +import os,sys,re +import numpy as np import py_post # MSC closed source module to access marc result files @@ -27,7 +21,7 @@ class MARC_POST(): self.fpath=os.path.join(self.projdir,self.postname) print('Trying to open ',self.fpath,' ...') self.p=py_post.post_open(self.fpath) - if self.p==None: + if self.p is None: print('Could not open %s.'%self.postname); #return 'err'#; sys.exit(1) raise Exception('Could not open t16') print('Postfile %s%s is open ...'%(self.projdir,self.postname)) @@ -105,7 +99,6 @@ class MARC_POST(): def writeNodes2VTK(self, fobj): self.points=[] self.VTKcnt=200 # number of values per line in vtk file - ndCnt=1 fobj.write('POINTS %i'%self.p.nodes()+' float\n') self.nodes_dict={} # store the node IDs in case of holes in the numbering for iNd in self.nodes: @@ -126,8 +119,6 @@ class MARC_POST(): el=self.p.element(iEl) cell_nodes=[] # for pyvtk ndlist=el.items - #for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL - #for k in [0, 4, 3, 1, 5, 7, 6, 2]: for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON node=ndlist[k]-1 cell_nodes.append(self.nodes_dict[node]) @@ -147,7 +138,6 @@ class MARC_POST(): fobj.write('\n');cnt=0 fobj.write('\n') print('Elements written to VTK: %i'%self.p.elements()) - #print('Nr of nodes: ',self.nodes) def writeElScalars2NodesVTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) @@ -157,7 +147,6 @@ class MARC_POST(): fobj.write('LOOKUP_TABLE default\n') idxScal=self.nscal_list.index('Displacement Z') for iNd in self.nodes: - #fobj.write('%f %f '%(self.p.node_scalar(iNd,idxScal), N.random.rand())) fobj.write('%f '%(self.p.node_scalar(iNd,idxScal))) for iEl in range(0,self.nel): el=self.p.element(iEl) @@ -173,8 +162,6 @@ class MARC_POST(): def writeNodeScalars2VTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) - nNdDat=self.nscals - nComponents=1+nNdDat self.pointDataScalars=[] for idxNdScal in range(-3,self.nscals): #now include node x,y,z if idxNdScal>=0: @@ -209,8 +196,6 @@ class MARC_POST(): idx_sig_vMises=self.getLabelNr('Equivalent Von Mises Stress') idx_sig33=self.getLabelNr('Comp 33 of Cauchy Stress') fobj.write('\nCELL_DATA %i\n'%self.p.elements()) - nElDat=self.elscals - nComponents=1+nElDat for idxElScal in range(0,self.elscals): datalabel=self.elscal_list[idxElScal] datalabel=re.sub("\s",'_',datalabel) @@ -250,19 +235,16 @@ class MARC_POST(): result.append(avgScal) return result - def writeUniaxiality2VTK(self,fobj): - #fobj.write('\nCELL_DATA %i\n'%self.p.elements()) + def writeUniaxiality2VTK(self,fobj): datalabel='uniaxiality_sig_vMises_durch_sig33' fobj.write('SCALARS %s float %i\n'%(datalabel,1)) fobj.write('LOOKUP_TABLE default\n') cnt=0 for iEl in range(0,self.nel): cnt=cnt+1 - #if abs(self.sig33[iEl])<1e-5: if abs(self.sig_vMises[iEl])<1e-5: datum=0. else: - #datum=self.sig_vMises[iEl]/self.sig33[iEl] datum=self.sig33[iEl]/self.sig_vMises[iEl] fobj.write('%E '%(datum)) if cnt>self.VTKcnt: @@ -283,8 +265,8 @@ class MARC_POST(): self.mean_stress.append(self.meanStress(sig)) def triaxiality_per_element(self): - # classical triaxiality - # 1/3 : uniax tension + # classical triaxiality + # 1/3 : uniax tension self.triaxiality=[] for iEl in range(0,self.nel): t=self.mean_stress[iEl]/self.sig_vMises[iEl] @@ -303,10 +285,6 @@ class MARC_POST(): fobj.write('\n') def calc_lode_parameter(self): - # [-1 ... +1] see e.g. Wippler & Boehlke triaxiality measures doi:10.1002/pamm.201010061 - # +1 : uniax tensile? - # 0 : shear - # -1 : uniax compr ? self.lode=[] try: self.stress @@ -328,10 +306,11 @@ class MARC_POST(): def princStress(self, stress): """ Function to compute 3D principal stresses and sort them. + from: http://geodynamics.org/svn/cig/short/3D/PyLith/trunk/playpen/postproc/vtkcff.py """ - stressMat=N.array(stress) - (princStress, princAxes) = numpy.linalg.eigh(stressMat) + stressMat=np.array(stress) + (princStress, princAxes) = np.linalg.eigh(stressMat) idx = princStress.argsort() princStressOrdered = princStress[idx] princAxesOrdered = princAxes[:,idx] @@ -339,36 +318,28 @@ class MARC_POST(): def avg_elten(self, idxElTen, mat=0, elID=None): - tensum=N.zeros((3,3)); - T=N.zeros((3,3)); + tensum=np.zeros((3,3)); + T=np.zeros((3,3)); pts=0; - avg=N.zeros((3,3)); - #print 'Element Scalars' - #print self.p.element_scalar_label(elscal2) - if elID==None: + avg=np.zeros((3,3)); + + if elID is None: averaged_elements=range(0,self.nel) else: averaged_elements=[elID] - #for i in range (0,self.nel): for i in averaged_elements: if mat==0 or int(self.p.element_scalar(i,4)[0].value)==mat: - eldata=self.p.element(i) T=self.p.element_tensor(i,idxElTen) for k in range (0,8): tensum[0][0] = tensum[0][0] + T[k].t11 tensum[0][1] = tensum[0][1] + T[k].t12 tensum[0][2] = tensum[0][2] + T[k].t13 - #tensum1[1][0] = tensum1[1][0] + T1[k].t21 tensum[1][1] = tensum[1][1] + T[k].t22 tensum[1][2] = tensum[1][2] + T[k].t23 - #tensum1[2][0] = tensum1[2][0] + T1[k].t31 - #tensum1[2][1] = tensum1[2][1] + T1[k].t32 tensum[2][2] = tensum[2][2] + T[k].t33 pts=pts+1 avg=tensum/pts - #print avg avg=self.fillComponents(avg) - #print avg del [T] return (avg,tensum,pts) @@ -384,7 +355,7 @@ class MARC_POST(): t=tensor33 s=(t[0,0]-t[1,1])**2+(t[1,1]-t[2,2])**2+(t[0,0]-t[2,2])**2+\ 6*(t[0,1]**2+t[1,2]**2+t[2,0]**2) - vM=N.sqrt(s/2.) + vM=np.sqrt(s/2.) return vM def meanStress(self,tensor33): @@ -397,8 +368,7 @@ class MARC_POST(): t=tensor33 I1=t[0,0]+t[1,1]+t[2,2] I2=t[0,0]*t[1,1]+t[1,1]*t[2,2]+t[0,0]*t[2,2]-\ - t[0,1]**2-t[1,2]**2-t[0,2]**2 - # I3 = det(t) + t[0,1]**2-t[1,2]**2-t[0,2]**2 I3=t[0,0]*t[1,1]*t[2,2]+\ 2*t[0,1]*t[1,2]*t[2,0]-\ t[2,2]*t[0,1]**2-t[0,0]*t[1,2]**2-t[1,1]*t[0,2]**2 @@ -406,17 +376,18 @@ class MARC_POST(): class VTK_WRITER(): - ''' - The resulting vtk-file can be imported in Paraview 3.12 - Then use Filters: Cell Data to Point Data + Contour - to plot semi-transparent iso-surfaces. - ''' + """ + The resulting vtk-file can be imported in Paraview 3.12 + + Then use Filters: Cell Data to Point Data + Contour + to plot semi-transparent iso-surfaces. + """ + import re def __init__(self): self.p=MARC_POST() # self.p def openFile(self, filename='test.vtp'): - #if not self.f:#==None: self.f=open(filename,'w+') self.fname=filename @@ -427,7 +398,7 @@ class VTK_WRITER(): dformat='ASCII', # BINARY | [ASCII] dtype='UNSTRUCTURED_GRID' # UNSTRUCTURED GRID ): - if vtkFile==None: + if vtkFile is None: vtkFile=self.f # First Line contains Data format version self.versionVTK=version @@ -440,7 +411,6 @@ class VTK_WRITER(): def marc2vtkBatch(self): for iori in range(1,63): - #self.p=msc_post.MSC_POST() self.p.postname='indent_fric0.3_R2.70_cA146.0_h0.320_ori%03i_OST_h19d.t16'%(iori) if os.path.exists(self.p.postname): self.marc2vtk(mode='fast', batchMode=1) @@ -496,14 +466,14 @@ class VTK_WRITER(): def scaleBar(self, length=1.0, posXYZ=[0., 0., 0.]): self.fsb=open('micronbar_l%.1f.vtp'%length,'w+') self.writeFirstLines(self.fsb, comment='micronbar') - pts=N.array([]) + pts=np.array([]) width=length*1. height=length*1. - wVec=N.array([0., width, 0.]) - lVec=N.array([length,0.,0.]) - hVec=N.array([0.,0.,height]) + wVec=np.array([0., width, 0.]) + lVec=np.array([length,0.,0.]) + hVec=np.array([0.,0.,height]) posXYZ=posXYZ-0.5*wVec-0.5*lVec#-0.5*hVec # CENTERING Y/N - posXYZ=N.array(posXYZ) + posXYZ=np.array(posXYZ) pts=[posXYZ, posXYZ+lVec, posXYZ+wVec, posXYZ+wVec+lVec] @@ -514,34 +484,22 @@ class VTK_WRITER(): self.fsb.write('%f %f %f\n'%(pts[npts][0], pts[npts][1], pts[npts][2])) if 1: #Triad nCells=3 - #nCells=1 #One Line ptsPerCell=2 # Lines (Type=3) - #ptsPerCell=4 # Quads (Type=9) - #ptsPerCell=8 # Hexahedron (Type=12) cellSize=(ptsPerCell+1)*nCells self.fsb.write('CELLS %i %i\n'%(nCells,cellSize)) self.fsb.write('2 0 1\n') #X-Line self.fsb.write('2 0 2\n') #Y-Line self.fsb.write('2 0 4\n') #Z-Line - #self.fsb.write('4 0 1 3 2\n') #Quad - #self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron self.fsb.write('CELL_TYPES %i\n'%(nCells)) self.fsb.write('3\n3\n3\n')#Line - #self.fsb.write('12\n')#Hexahedron else: # Cube, change posXYZ nCells=1 ptsPerCell=2 # Lines (Type=3) - #ptsPerCell=4 # Quads (Type=9) - #ptsPerCell=8 # Hexahedron (Type=12) cellSize=(ptsPerCell+1)*nCells self.fsb.write('CELLS %i %i\n'%(nCells,cellSize)) self.fsb.write('2 0 1\n') #Line - #self.fsb.write('4 0 1 3 2\n') #Quad - #self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron self.fsb.write('CELL_TYPES %i\n'%(nCells)) self.fsb.write('3\n')#Line - #self.fsb.write('12\n')#Hexahedron - self.fsb.write('\n') self.fsb.close() @@ -549,8 +507,7 @@ class VTK_WRITER(): def example_unstructured(self): self.openFile(filename='example_unstructured_grid.vtk') - #self.writeFirstLines() - self.f.write(''' + self.f.write(""" # vtk DataFile Version 2.0 example_unstruct_grid ASCII @@ -590,61 +547,40 @@ LOOKUP_TABLE default 1.02 1.50 0.00 -3 5 6 23423423423423423423.23423423''') +3 5 6 23423423423423423423.23423423""") self.f.close() def writeNodes2VTK(self, fobj): self.VTKcnt=200 # how many numbers per line in vtk file - #self.VTKcnt=6 - ndCnt=1 - #self.nodes=range(0,10) fobj.write('POINTS %i'%self.p.nodes()+' float\n') for iNd in self.nodes: nd=self.p.node(iNd) disp=self.p.node_displacement(iNd) - #contact=self.p.node_scalar(iNd,contactNr) - #ndCnt=ndCnt+1 fobj.write('%f %f %f \n'% - #(nd.x, nd.y, nd.z)) (nd.x+disp[0], nd.y+disp[1], nd.z+disp[2])) - - #if ndCnt>6: - # fobj.write('\n') - # ndCnt=1 fobj.write('\n') print('Nodes written to VTK: %i'%self.p.nodes()) - #print('Nr of nodes: ',self.nodes) def writeElements2VTK(self, fobj): fobj.write('\nCELLS %i %i'%(self.p.elements(),self.p.elements()*9)+'\n') for iEl in range(0,self.nel): el=self.p.element(iEl) - #disp=self.p.node_displacement(iNd) - #contact=self.p.node_scalar(iNd,contactNr) - #ndCnt=ndCnt+1 fobj.write('8 ') ndlist=el.items - #for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL - #for k in [0, 4, 3, 1, 5, 7, 6, 2]: for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON fobj.write('%6i '%(ndlist[k]-1)) fobj.write('\n') - #if ndCnt>6: - # fobj.write('\n') - # ndCnt=1 fobj.write('\nCELL_TYPES %i'%self.p.elements()+'\n') cnt=0 for iEl in range(0,self.nel): cnt=cnt+1 - #fobj.write('11\n') #VTK_VOXEL fobj.write('12 ') #VTK_HEXAHEDRON if cnt>self.VTKcnt: fobj.write('\n');cnt=0 fobj.write('\n') print('Elements written to VTK: %i'%self.p.elements()) - #print('Nr of nodes: ',self.nodes) def writeElScalars2NodesVTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) @@ -668,10 +604,7 @@ LOOKUP_TABLE default fobj.write('\n') def writeNodeScalars2VTK(self,fobj): - #print('writeElementData2VTK') fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) - nNdDat=self.nscals - nComponents=1+nNdDat for idxNdScal in range(-3,self.nscals): # include node x,y,z if idxNdScal>=0: datalabel=self.nscal_list[idxNdScal] @@ -700,10 +633,7 @@ LOOKUP_TABLE default fobj.write('\n') def writeElementData2VTK(self,fobj): - #print('writeElementData2VTK') fobj.write('\nCELL_DATA %i\n'%self.p.elements()) - nElDat=self.elscals - nComponents=1+nElDat for idxElScal in range(0,self.elscals): datalabel=self.elscal_list[idxElScal] datalabel=re.sub("\s",'_',datalabel) @@ -730,7 +660,7 @@ LOOKUP_TABLE default def example1(self): self.openFile() self.writeFirstLines() - self.f.write('''DATASET POLYDATA + self.f.write("""DATASET POLYDATA POINTS 8 float 0.0 0.0 0.0 1.0 0.0 0.0 @@ -789,18 +719,20 @@ LOOKUP_TABLE my_table 8 0.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 -1.0 1.0 1.0 1.0''') +1.0 1.0 1.0 1.0""") self.f.close() import pyvtk class marc_to_vtk(): - ''' - Anybody wants to implement it with pyvtk? - The advantage would be that pyvtk can also wirte the - -VTK format and binary. - These can be plotted with mayavi. - ''' + """ + Anybody wants to implement it with pyvtk? + + The advantage would be that pyvtk can also wirte the + -VTK format and binary. + These can be plotted with mayavi. + """ + def __init__(self): self.p=[]#MARC_POST() # self.p @@ -810,5 +742,4 @@ class marc_to_vtk(): hexahedron=self.p.cells), 'm2v output') vtk.tofile('m2v_file') - #vtk.tofile('example3b','binary') - #VtkData('example3') \ No newline at end of file + diff --git a/lib/damask/test/__init__.py b/lib/damask/test/__init__.py index 264ec7eb7..c81d9eecb 100644 --- a/lib/damask/test/__init__.py +++ b/lib/damask/test/__init__.py @@ -2,4 +2,4 @@ """Test functionality""" -from .test import Test "noqa +from .test import Test #noqa From 83ccd7c982d63b9c0ec45f43d4161dc825033d31 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 5 Mar 2016 21:37:22 +0100 Subject: [PATCH 046/134] introduced (in)equality comparison for double precision --- code/prec.f90 | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/code/prec.f90 b/code/prec.f90 index 0f22cf649..129681fd5 100644 --- a/code/prec.f90 +++ b/code/prec.f90 @@ -172,9 +172,9 @@ end subroutine prec_init !-------------------------------------------------------------------------------------------------- !> @brief figures out if a floating point number is NaN -! basically just a small wrapper, because gfortran < 4.9 does not have the IEEE module +! basically just a small wrapper, because gfortran < 5.0 does not have the IEEE module !-------------------------------------------------------------------------------------------------- -logical elemental function prec_isNaN(a) +logical elemental pure function prec_isNaN(a) implicit none real(pReal), intent(in) :: a @@ -187,4 +187,30 @@ logical elemental function prec_isNaN(a) #endif end function prec_isNaN + + +!-------------------------------------------------------------------------------------------------- +!> @brief equality comparison for double precision +! replaces "==" but for certain (absolute) tolerance. Counterpart to dNeq +!-------------------------------------------------------------------------------------------------- +logical elemental pure function dEq(a,b,tol) + real(pReal), intent(in) :: a,b + real(pReal), intent(in), optional :: tol + real(pReal), parameter :: eps = 1.0e-15_pReal + dEq = merge(.True., .False.,abs(a-b) < merge(tol,eps,present(tol))) +end function dEq + + + +!-------------------------------------------------------------------------------------------------- +!> @brief inequality comparison for double precision +! replaces "!=" but for certain (absolute) tolerance. Counterpart to dEq +!-------------------------------------------------------------------------------------------------- +logical elemental pure function dNeq(a,b,tol) + real(pReal), intent(in) :: a,b + real(pReal), intent(in), optional :: tol + real(pReal), parameter :: eps = 1.0e-15_pReal + dNeq = merge(.True., .False.,abs(a-b) < merge(tol,eps,present(tol))) +end function dNeq + end module prec From efde4d363d04ef8f23be14c90cbea27198986ec1 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 19:38:55 +0100 Subject: [PATCH 047/134] changed encoding --- DAMASK_env.bat | 6 +++--- LICENSE | 2 +- README | 4 ++-- lib/damask/test/__init__.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DAMASK_env.bat b/DAMASK_env.bat index 0c1afb0d6..202ddb00e 100644 --- a/DAMASK_env.bat +++ b/DAMASK_env.bat @@ -5,10 +5,10 @@ set LOCATION=%~dp0 set DAMASK_ROOT=%LOCATION%\DAMASK set DAMASK_NUM_THREADS=2 chcp 1252 -Title Düsseldorf Advanced Materials Simulation Kit - DAMASK, MPIE Düsseldorf +Title Düsseldorf Advanced Materials Simulation Kit - DAMASK, MPIE Düsseldorf echo. -echo Düsseldorf Advanced Materials Simulation Kit - DAMASK -echo Max-Planck-Institut für Eisenforschung, Düsseldorf +echo Düsseldorf Advanced Materials Simulation Kit - DAMASK +echo Max-Planck-Institut für Eisenforschung, Düsseldorf echo http://damask.mpie.de echo. echo Preparing environment ... diff --git a/LICENSE b/LICENSE index 2402b1685..5a76343a0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2011-15 Max-Planck-Institut für Eisenforschung GmbH +Copyright 2011-16 Max-Planck-Institut für Eisenforschung GmbH This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/README b/README index 7fd364644..6705c13fa 100644 --- a/README +++ b/README @@ -2,9 +2,9 @@ visit damask.mpie.de for installation and usage instructions CONTACT INFORMATION -Max-Planck-Institut für Eisenforschung GmbH +Max-Planck-Institut für Eisenforschung GmbH Max-Planck-Str. 1 -40237 Düsseldorf +40237 Düsseldorf Germany Email: DAMASK@mpie.de diff --git a/lib/damask/test/__init__.py b/lib/damask/test/__init__.py index c81d9eecb..ba8d14a00 100644 --- a/lib/damask/test/__init__.py +++ b/lib/damask/test/__init__.py @@ -2,4 +2,4 @@ """Test functionality""" -from .test import Test #noqa +from .test import Test # noqa From 858e322e06ce718a9c4408d5e6c53ff2fd6eb7cf Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 7 Mar 2016 16:12:42 +0100 Subject: [PATCH 048/134] updated version information after successful test of revision3813-1054-gefde4d3 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e8f9f40c8..d2a79f7f5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1036-g5233236 +revision3813-1054-gefde4d3 From 0c1fe236b4988a1b22c90513140781fd84f9e343 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 7 Mar 2016 17:12:37 -0500 Subject: [PATCH 049/134] fixed issue with multiple allocation of param%outputID (was done every line) --- code/plastic_isotropic.f90 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/plastic_isotropic.f90 b/code/plastic_isotropic.f90 index fe4c7a7f5..da4198007 100644 --- a/code/plastic_isotropic.f90 +++ b/code/plastic_isotropic.f90 @@ -167,7 +167,7 @@ subroutine plastic_isotropic_init(fileUnit) allocate(plastic_isotropic_Noutput(maxNinstance), source=0_pInt) allocate(param(maxNinstance)) ! one container of parameters per instance - + rewind(fileUnit) phase = 0_pInt do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to @@ -184,14 +184,13 @@ subroutine plastic_isotropic_init(fileUnit) if (IO_getTag(line,'[',']') /= '') then ! next section phase = phase + 1_pInt ! advance section counter if (phase_plasticity(phase) == PLASTICITY_ISOTROPIC_ID) then - instance = phase_plasticityInstance(phase) - + instance = phase_plasticityInstance(phase) ! count instances of my constitutive law + allocate(param(instance)%outputID(phase_Noutput(phase))) ! allocate space for IDs of every requested output endif cycle ! skip to next line endif if (phase > 0_pInt) then; if (phase_plasticity(phase) == PLASTICITY_ISOTROPIC_ID) then ! one of my phases. Do not short-circuit here (.and. between if-statements), it's not safe in Fortran instance = phase_plasticityInstance(phase) ! which instance of my plasticity is present phase - allocate(param(instance)%outputID(phase_Noutput(phase))) ! allocate space for IDs of every requested output chunkPos = IO_stringPos(line) tag = IO_lc(IO_stringValue(line,chunkPos,1_pInt)) ! extract key extmsg = trim(tag)//' ('//PLASTICITY_ISOTROPIC_label//')' ! prepare error message identifier From 761e698dfd19f974bdb4bc2f5dbdacfb5943e444 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 8 Mar 2016 04:13:33 +0100 Subject: [PATCH 050/134] updated version information after successful test of revision3813-1056-g0c1fe23 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d2a79f7f5..325c6feb2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1054-gefde4d3 +revision3813-1056-g0c1fe23 From 4dfd59a9e26b5228bb1bfb6d656394da03d33c3b Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 7 Mar 2016 22:12:02 -0500 Subject: [PATCH 051/134] output complete microstructure and texture info instead of limiting to grainIDs used in geometry --- .../pre/geom_fromVoronoiTessellation.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index ee29f4536..c7a860e79 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -276,29 +276,29 @@ for name in filenames: grid = np.vstack(meshgrid2(x, y, z)).reshape(3,-1).T indices = laguerreTessellation(grid, coords, weights, grains, options.nonperiodic, options.cpus) -# --- write header --------------------------------------------------------------------------------- +# --- write header ------------------------------------------------------------------------ - grainIDs = np.intersect1d(grainIDs,indices) - info['microstructures'] = len(grainIDs) + usedGrainIDs = np.intersect1d(grainIDs,indices) + info['microstructures'] = len(usedGrainIDs) if info['homogenization'] == 0: info['homogenization'] = options.homogenization damask.util.croak(['grid a b c: %s'%(' x '.join(map(str,info['grid']))), - 'size x y z: %s'%(' x '.join(map(str,info['size']))), - 'origin x y z: %s'%(' : '.join(map(str,info['origin']))), - 'homogenization: %i'%info['homogenization'], - 'microstructures: %i%s'%(info['microstructures'], + 'size x y z: %s'%(' x '.join(map(str,info['size']))), + 'origin x y z: %s'%(' : '.join(map(str,info['origin']))), + 'homogenization: %i'%info['homogenization'], + 'microstructures: %i%s'%(info['microstructures'], (' out of %i'%NgrainIDs if NgrainIDs != info['microstructures'] else '')), - ]) + ]) config_header = [] - formatwidth = 1+int(math.log10(info['microstructures'])) + formatwidth = 1+int(math.log10(NgrainIDs)) - phase = options.phase * np.ones(info['microstructures'],'i') + phase = options.phase * np.ones(NgrainIDs,'i') if int(options.secondphase*info['microstructures']) > 0: - phase[0:int(options.secondphase*info['microstructures'])] += 1 - randomSeed = int(os.urandom(4).encode('hex'), 16) if options.randomSeed is None \ - else options.randomSeed # random seed for second phase + phase[0:int(options.secondphase*info['microstructures'])] += 1 # alter fraction 'options.secondphase' of used grainIDs + randomSeed = options.randomSeed if options.randomSeed \ + else int(os.urandom(4).encode('hex'), 16) # random seed for second phase np.random.seed(randomSeed) np.random.shuffle(phase) config_header += ['# random seed (phase shuffling): {}'.format(randomSeed)] @@ -312,7 +312,7 @@ for name in filenames: if hasEulers: config_header += [''] for ID in grainIDs: - eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id + eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id config_header += ['[Grain%s]'%(str(ID).zfill(formatwidth)), '(gauss)\tphi1 %g\tPhi %g\tphi2 %g\tscatter 0.0\tfraction 1.0'%tuple(eulers[eulerID]) ] From e1d4e51170f02c05498d40de9106e5aa81148a3f Mon Sep 17 00:00:00 2001 From: Franz Roters Date: Tue, 8 Mar 2016 10:54:06 +0100 Subject: [PATCH 052/134] updated version string for release --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 325c6feb2..46b105a30 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -revision3813-1056-g0c1fe23 +v2.0.0 From 26fa0fff72a6ebec33109ed0c9565c9dabea48d4 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 8 Mar 2016 16:13:40 +0100 Subject: [PATCH 053/134] updated version information after successful test of v2.0.0-3-g618e352 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 46b105a30..2bc4b2cfc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0 +v2.0.0-3-g618e352 From fa9411e998a4b93e4a70bc628ce46df9b1e8cdf0 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 8 Mar 2016 13:55:12 -0500 Subject: [PATCH 054/134] fixed mixed-up descriptions of relative and absolute tolerances in spectral part --- config/numerics.config | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/numerics.config b/config/numerics.config index 62adb552f..24241b8c4 100644 --- a/config/numerics.config +++ b/config/numerics.config @@ -54,12 +54,12 @@ discrepancyPower_RGC 5.0 fixed_seed 0 # put any number larger than zero, integer, if you want to have a pseudo random distribution ## spectral parameters ## -err_div_tolAbs 1.0e-3 # relative tolerance for fulfillment of stress equilibrium -err_div_tolRel 5.0e-4 # absolute tolerance for fulfillment of stress equilibrium -err_curl_tolAbs 1.0e-12 # relative tolerance for fulfillment of strain compatibility -err_curl_tolRel 5.0e-4 # absolute tolerance for fulfillment of strain compatibility -err_stress_tolrel 0.01 # relative tolerance for fulfillment of stress BC -err_stress_tolabs 1.0e3 # absolute tolerance for fulfillment of stress BC +err_div_tolAbs 1.0e-3 # absolute tolerance for fulfillment of stress equilibrium +err_div_tolRel 5.0e-4 # relative tolerance for fulfillment of stress equilibrium +err_curl_tolAbs 1.0e-12 # absolute tolerance for fulfillment of strain compatibility +err_curl_tolRel 5.0e-4 # relative tolerance for fulfillment of strain compatibility +err_stress_tolAbs 1.0e3 # absolute tolerance for fulfillment of stress BC +err_stress_tolRel 0.01 # relative tolerance for fulfillment of stress BC fftw_timelimit -1.0 # timelimit of plan creation for FFTW, see manual on www.fftw.org, Default -1.0: disable timelimit rotation_tol 1.0e-12 # tolerance of rotation specified in loadcase, Default 1.0e-12: first guess fftw_plan_mode FFTW_PATIENT # reads the planing-rigor flag, see manual on www.fftw.org, Default FFTW_PATIENT: use patient planner flag From 2296929344948406032843f030384ca4edd36286 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 8 Mar 2016 18:38:56 -0500 Subject: [PATCH 055/134] added symlink info for PETSC_DIR (if present) --- DAMASK_env.sh | 3 ++- DAMASK_env.zsh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DAMASK_env.sh b/DAMASK_env.sh index bfb5c12df..ad3c59dea 100644 --- a/DAMASK_env.sh +++ b/DAMASK_env.sh @@ -53,7 +53,8 @@ if [ ! -z "$PS1" ]; then [[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER" [[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING" echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" - [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" + [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" && \ + [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` [[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH" echo "MSC.Marc/Mentat $MSC_ROOT" echo diff --git a/DAMASK_env.zsh b/DAMASK_env.zsh index 521bfe8e1..5cf5b30f8 100644 --- a/DAMASK_env.zsh +++ b/DAMASK_env.zsh @@ -51,7 +51,8 @@ if [ ! -z "$PS1" ]; then [[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER" [[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING" echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" - [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" + [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" && \ + [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` [[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH" echo "MSC.Marc/Mentat $MSC_ROOT" echo From 69c1cb71de23f0fb1fc5b616fddedc05c3e11c05 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 9 Mar 2016 04:12:09 +0100 Subject: [PATCH 056/134] updated version information after successful test of v2.0.0-6-gb5302ec --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2bc4b2cfc..d9e8f873a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-3-g618e352 +v2.0.0-6-gb5302ec From 976803ba0b7d45557ff9df76d589f433c615aa88 Mon Sep 17 00:00:00 2001 From: Franz Roters Date: Wed, 9 Mar 2016 15:36:11 +0100 Subject: [PATCH 057/134] corrected error discovered by Haiming Zhang --- code/IO.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/IO.f90 b/code/IO.f90 index 1a36269c5..57eb23cb5 100644 --- a/code/IO.f90 +++ b/code/IO.f90 @@ -1237,8 +1237,7 @@ character(len=300) pure function IO_extractValue(pair,key) IO_extractValue = '' myChunk = scan(pair,SEP) - if (myChunk > 0 .and. pair(:myChunk-1) == key(:myChunk-1)) & - IO_extractValue = pair(myChunk+1:) ! extract value if key matches + if (myChunk > 0 .and. pair(:myChunk-1) == key) IO_extractValue = pair(myChunk+1:) ! extract value if key matches end function IO_extractValue From 849d487ab6de2f366ac9e716c405596fd3495166 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 9 Mar 2016 16:08:42 +0100 Subject: [PATCH 058/134] autogenerated file not needed in repository --- code/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/code/.gitignore b/code/.gitignore index 9467b3147..6184a3d0a 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -1 +1,2 @@ DAMASK_marc*.f90 +quit__genmod.f90 From bb9ee3910fac62010ab646cf3aaa841d0ccf6d7e Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 9 Mar 2016 16:12:54 +0100 Subject: [PATCH 059/134] updated version information after successful test of v2.0.0-7-g2296929 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2bc4b2cfc..4c6293bf0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-3-g618e352 +v2.0.0-7-g2296929 From 20fe46a030cbb424cbb833067571beef06238da4 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 9 Mar 2016 11:40:12 -0500 Subject: [PATCH 060/134] corrected logical mask for reporting stress in load cases --- code/DAMASK_spectral.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index 728b0fd6c..3f4d6764e 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -329,7 +329,7 @@ program DAMASK_spectral errorID = 838_pInt ! no rotation is allowed by stress BC write(6,'(2x,a)') 'stress / GPa:' do i = 1_pInt, 3_pInt; do j = 1_pInt, 3_pInt - if(loadCases(currentLoadCase)%deformation%maskLogical(i,j)) then + if(loadCases(currentLoadCase)%P%maskLogical(i,j)) then write(6,'(2x,f12.7)',advance='no') loadCases(currentLoadCase)%P%values(i,j)*1e-9_pReal else write(6,'(2x,12a)',advance='no') ' * ' From b933359f178bcc14de75b5fe95dfbe71e25ad4dc Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 9 Mar 2016 12:28:36 -0500 Subject: [PATCH 061/134] clarified text of error message complaining about wrong input dimension --- processing/post/addGrainID.py | 2 +- processing/post/addIPFcolor.py | 2 +- processing/post/addOrientations.py | 2 +- processing/post/addPole.py | 2 +- processing/post/imageDataRGB.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index 5443d1c70..7eb48f286 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -110,7 +110,7 @@ for name in filenames: remarks = [] if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) - if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim)) + if not np.all(table.label_dimension(label) == dim): errors.append('input {} does not have dimension {}.'.format(label,dim)) else: column = table.label_index(label) if remarks != []: damask.util.croak(remarks) diff --git a/processing/post/addIPFcolor.py b/processing/post/addIPFcolor.py index 24aeb3fa0..2a1a3581a 100755 --- a/processing/post/addIPFcolor.py +++ b/processing/post/addIPFcolor.py @@ -99,7 +99,7 @@ for name in filenames: # ------------------------------------------ sanity checks ---------------------------------------- if not np.all(table.label_dimension(label) == dim): - damask.util.croak('input {} has wrong dimension {}.'.format(label,dim)) + damask.util.croak('input {} does not have dimension {}.'.format(label,dim)) table.close(dismiss = True) # close ASCIItable and remove empty file continue diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index b806a56a0..f7519d92c 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -113,7 +113,7 @@ for name in filenames: errors = [] remarks = [] - if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim)) + if not np.all(table.label_dimension(label) == dim): errors.append('input {} does not have dimension {}.'.format(label,dim)) else: column = table.label_index(label) if remarks != []: damask.util.croak(remarks) diff --git a/processing/post/addPole.py b/processing/post/addPole.py index c8e3991ee..a57fef9eb 100755 --- a/processing/post/addPole.py +++ b/processing/post/addPole.py @@ -101,7 +101,7 @@ for name in filenames: errors = [] remarks = [] - if not np.all(table.label_dimension(label) == dim): errors.append('input {} has wrong dimension {}.'.format(label,dim)) + if not np.all(table.label_dimension(label) == dim): errors.append('input {} does not have dimension {}.'.format(label,dim)) else: column = table.label_index(label) if remarks != []: damask.util.croak(remarks) diff --git a/processing/post/imageDataRGB.py b/processing/post/imageDataRGB.py index ac51746ca..f706cb100 100755 --- a/processing/post/imageDataRGB.py +++ b/processing/post/imageDataRGB.py @@ -98,7 +98,7 @@ for name in filenames: errors.append('column{} {} not found'.format('s' if len(missing_labels) > 1 else '', ', '.join(missing_labels))) if table.label_dimension(options.label) != 3: - errors.append('column {} has wrong dimension'.format(options.label)) + errors.append('column {} does not have dimension'.format(options.label)) if errors != []: damask.util.croak(errors) From b0dedb8cbde2015aa3ad132f7b3f7a59b6bbad77 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 9 Mar 2016 19:02:28 +0100 Subject: [PATCH 062/134] =addOrientation can do the same (and more) --- processing/post/addQuaternions.py | 100 ------------------------------ 1 file changed, 100 deletions(-) delete mode 100755 processing/post/addQuaternions.py diff --git a/processing/post/addQuaternions.py b/processing/post/addQuaternions.py deleted file mode 100755 index fe0e3781f..000000000 --- a/processing/post/addQuaternions.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 no BOM -*- - -import os,sys,numpy as np -from optparse import OptionParser -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 [file[s]]', description = """ -Add Quaternions based on Crystal Frame Coordinates. - -""", version = scriptID) - -parser.add_option('-f','--frame', - dest='frame', nargs=4, type='string', metavar='', - help='heading of columns containing b* vector components and three frame vectors in that order') -parser.add_option('-s','--symmetry', - dest='crysym', nargs=1,type='string',metavar='', - help='crystal symmetry definition') -parser.set_defaults(frame = None) - -(options,filenames) = parser.parse_args() - -if options.frame is None: - parser.error('no data column specified...') - -datainfo = {'len':4, - 'label':[] - } - -if options.frame is not None: datainfo['label'] += options.frame - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) - - table.head_read() # read ASCII header info - -# --------------- figure out columns to process --------------------------------------------------- - active = [] - column = {} - - for label in datainfo['label']: - key = '1_'+label if datainfo['len'] > 1 else label # non-special labels have to start with '1_' - if key in table.labels: - active.append(label) - column[label] = table.labels.index(key) # remember columns of requested data - else: - damask.util.croak('column %s not found...'%label) - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['Q_%i'%(i+1) for i in xrange(4)]) # extend ASCII header with new labels [1 real, 3 imaginary components] - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - vec = np.zeros([4,3]) - for i,label in enumerate(active): - vec[i,:] = np.array(table.data[column[label]: - column[label]+3]) - - if sys.argv[1:][6]=='hexagonal': # Ensure Input matrix is orthogonal - M=np.dot(vec[0,:],vec[2,:]) - vec[1,:]=vec[1,:]/np.linalg.norm(vec[1,:]) - vec[2,:]=M*(vec[0,:]/np.linalg.norm(vec[0,:])) - vec[3,:]=vec[3,:]/np.linalg.norm(vec[3,:]) - else: - vec[1,:]=vec[1,:]/np.linalg.norm(vec[1,:]) - vec[2,:]=vec[2,:]/np.linalg.norm(vec[2,:]) - vec[3,:]=vec[3,:]/np.linalg.norm(vec[3,:]) - - - Ori=damask.Orientation(matrix=vec[1:,:],symmetry=sys.argv[1:][6]) - - table.data_append(np.asarray(Ori.asQuaternion())) - - - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output result ----------------------------------------- - outputAlive and table.output_flush() # just in case of buffered ASCII table - - table.close() # close ASCII tables From 6b0db40faf7bda9f717c50a5f6e26bc974589468 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 10 Mar 2016 04:20:21 +0100 Subject: [PATCH 063/134] updated version information after successful test of v2.0.0-12-ge933820 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2bc4b2cfc..f81643793 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-3-g618e352 +v2.0.0-12-ge933820 From 5249054d34fa6cf6eca7e63e2109f78aad0471ee Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 10 Mar 2016 16:13:09 +0100 Subject: [PATCH 064/134] updated version information after successful test of v2.0.0-13-g6b0db40 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index f81643793..65ea5b27b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-12-ge933820 +v2.0.0-13-g6b0db40 From 3898fb29a83ef2d4b9cae6a3b6dd908808c9d147 Mon Sep 17 00:00:00 2001 From: Test User Date: Fri, 11 Mar 2016 04:12:53 +0100 Subject: [PATCH 065/134] updated version information after successful test of v2.0.0-14-g5249054 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 65ea5b27b..d1397a0d1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-13-g6b0db40 +v2.0.0-14-g5249054 From 34b10b586a5d88bef132542aa8485d3d336cf07e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 11 Mar 2016 12:48:35 +0100 Subject: [PATCH 066/134] safe way of reporting --- DAMASK_env.sh | 6 ++++-- DAMASK_env.zsh | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/DAMASK_env.sh b/DAMASK_env.sh index ad3c59dea..16850d6b4 100644 --- a/DAMASK_env.sh +++ b/DAMASK_env.sh @@ -53,8 +53,10 @@ if [ ! -z "$PS1" ]; then [[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER" [[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING" echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" - [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" && \ - [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` + if [ "x$PETSC_DIR" != "x" ]; then + echo "PETSc location $PETSC_DIR" + [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` + fi [[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH" echo "MSC.Marc/Mentat $MSC_ROOT" echo diff --git a/DAMASK_env.zsh b/DAMASK_env.zsh index 5cf5b30f8..b4b2d6953 100644 --- a/DAMASK_env.zsh +++ b/DAMASK_env.zsh @@ -51,8 +51,10 @@ if [ ! -z "$PS1" ]; then [[ "x$SOLVER" != "x" ]] && echo "Spectral Solver $SOLVER" [[ "x$PROCESSING" != "x" ]] && echo "Post Processing $PROCESSING" echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" - [[ "x$PETSC_DIR" != "x" ]] && echo "PETSc location $PETSC_DIR" && \ - [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` + if [ "x$PETSC_DIR" != "x" ]; then + echo "PETSc location $PETSC_DIR" + [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` + fi [[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH" echo "MSC.Marc/Mentat $MSC_ROOT" echo From 344c6f6898f6cbe85bb667064bfbc83678fb1721 Mon Sep 17 00:00:00 2001 From: Test User Date: Fri, 11 Mar 2016 16:13:07 +0100 Subject: [PATCH 067/134] updated version information after successful test of v2.0.0-15-g3898fb2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d1397a0d1..99c96eda6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-14-g5249054 +v2.0.0-15-g3898fb2 From 167b2783276b23fdbd8526cbf4d74fc9012cd42b Mon Sep 17 00:00:00 2001 From: Test User Date: Sat, 12 Mar 2016 05:21:45 +0100 Subject: [PATCH 068/134] updated version information after successful test of v2.0.0-16-g344c6f6 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 99c96eda6..c02195acf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-15-g3898fb2 +v2.0.0-16-g344c6f6 From 2dbdf9a72f28f488746b598b9914ae008b03b455 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 13 Mar 2016 18:21:25 +0100 Subject: [PATCH 069/134] all symbols need to be representable in unicode --- lib/damask/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/damask/util.py b/lib/damask/util.py index 77bc30403..9ce42759a 100644 --- a/lib/damask/util.py +++ b/lib/damask/util.py @@ -104,7 +104,8 @@ class extendableOption(Option): class backgroundMessage(threading.Thread): """reporting with animation to indicate progress""" - choices = {'bounce': ['_','o','O','°','¯','¯','°','O','o',], + choices = {'bounce': ['_', 'o', 'O', u'\u00B0', + u'\u203e',u'\u203e',u'\u00B0','O','o','_'], 'circle': [u'\u25f4',u'\u25f5',u'\u25f6',u'\u25f7'], 'hexagon': [u'\u2b22',u'\u2b23'], 'square': [u'\u2596',u'\u2598',u'\u259d',u'\u2597'], From 80d2bdbfde1c55fbf3332eeedfd8565efa19de65 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 14 Mar 2016 04:12:59 +0100 Subject: [PATCH 070/134] updated version information after successful test of v2.0.0-18-g2dbdf9a --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c02195acf..6a337695e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-16-g344c6f6 +v2.0.0-18-g2dbdf9a From fdd4ab483e252895d06a00fdd4256c704e25ea55 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Mar 2016 05:51:52 +0100 Subject: [PATCH 071/134] core.so is not part of the repo --- lib/damask/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 lib/damask/.gitignore diff --git a/lib/damask/.gitignore b/lib/damask/.gitignore new file mode 100644 index 000000000..fd736fe35 --- /dev/null +++ b/lib/damask/.gitignore @@ -0,0 +1 @@ +core.so From b40e7a26124a59b8d38240d4b49a2012e0a42f3d Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 14 Mar 2016 16:11:55 +0100 Subject: [PATCH 072/134] updated version information after successful test of v2.0.0-19-g80d2bdb --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6a337695e..9f18a71da 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-18-g2dbdf9a +v2.0.0-19-g80d2bdb From 654e58faf28715172c1ce451de92dbd654e91b7b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 14 Mar 2016 22:30:55 +0100 Subject: [PATCH 073/134] integer overflow due do missing brackets, wrong forwarding for large files --- code/DAMASK_spectral.f90 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index 3f4d6764e..e72cd3dec 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -59,8 +59,6 @@ program DAMASK_spectral materialpoint_sizeResults, & materialpoint_results, & materialpoint_postResults - - use material, only: & thermal_type, & damage_type, & @@ -439,14 +437,14 @@ program DAMASK_spectral if (.not. appendToOutFile) then ! if not restarting, write 0th increment do i=1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output - outputIndex=[(i-1)*((maxByteOut/pReal)/materialpoint_sizeResults)+1, & - min(i*((maxByteOut/pReal)/materialpoint_sizeResults),size(materialpoint_results,3))] + outputIndex=int([(i-1_pInt)*((maxByteOut/pReal)/materialpoint_sizeResults)+1_pInt, & + min(i*((maxByteOut/pReal)/materialpoint_sizeResults),size(materialpoint_results,3))],pLongInt) call MPI_file_write(resUnit,reshape(materialpoint_results(:,:,outputIndex(1):outputIndex(2)),& [(outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults]), & (outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults,& MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) - fileOffset = fileOffset + sum(outputSize) ! forward to current file position enddo + fileOffset = fileOffset + sum(outputSize) ! forward to current file position if (worldrank == 0) & write(6,'(1/,a)') ' ... writing initial configuration to file ........................' endif @@ -646,14 +644,14 @@ program DAMASK_spectral call materialpoint_postResults() call MPI_file_seek (resUnit,fileOffset,MPI_SEEK_SET,ierr) do i=1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output - outputIndex=[(i-1)*maxByteOut/pReal/materialpoint_sizeResults+1, & - min(i*maxByteOut/pReal/materialpoint_sizeResults,size(materialpoint_results,3))] + outputIndex=int([(i-1_pInt)*((maxByteOut/pReal)/materialpoint_sizeResults)+1_pInt, & + min(i*((maxByteOut/pReal)/materialpoint_sizeResults),size(materialpoint_results,3))],pLongInt) call MPI_file_write(resUnit,reshape(materialpoint_results(:,:,outputIndex(1):outputIndex(2)),& [(outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults]), & (outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults,& MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) - fileOffset = fileOffset + sum(outputSize) ! forward to current file position enddo + fileOffset = fileOffset + sum(outputSize) ! forward to current file position endif if( loadCases(currentLoadCase)%restartFrequency > 0_pInt .and. & ! at frequency of writing restart information set restart parameter for FEsolving mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0_pInt) then ! first call to CPFEM_general will write? From 6197e839c942b5dc91fb7243bc0423fff39b3264 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 15 Mar 2016 14:52:10 -0400 Subject: [PATCH 074/134] fixed missing file extension when adding in-place --- processing/post/vtk_addRectilinearGridData.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index 922b4b696..3ca54d84e 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -151,7 +151,7 @@ for name in filenames: writer = vtk.vtkXMLRectilinearGridWriter() writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.splitext(options.vtk)[0]+('' if options.inplace else '_added.vtr')) + writer.SetFileName(os.path.splitext(options.vtk)[0]+('.vtr' if options.inplace else '_added.vtr')) if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(rGrid) else: writer.SetInputData(rGrid) writer.Write() From 9704eb6926f6be905128ae0552dec146fa811eb7 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 15 Mar 2016 17:23:01 -0400 Subject: [PATCH 075/134] small correction to variable declaration layout --- code/lattice.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lattice.f90 b/code/lattice.f90 index f5717e8e1..05a123125 100644 --- a/code/lattice.f90 +++ b/code/lattice.f90 @@ -2182,7 +2182,7 @@ pure function lattice_qDisorientation(Q1, Q2, struct) real(pReal), dimension(4) :: lattice_qDisorientation real(pReal), dimension(4), intent(in) :: & Q1, & ! 1st orientation - Q2 ! 2nd orientation + Q2 ! 2nd orientation integer(kind(LATTICE_undefined_ID)), optional, intent(in) :: & ! if given, symmetries between the two orientation will be considered struct From 93466273ffd03db9cc03e6fadf02727ba3967d19 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 16 Mar 2016 04:13:16 +0100 Subject: [PATCH 076/134] updated version information after successful test of v2.0.0-31-g6197e83 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9f18a71da..27bd816bb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-19-g80d2bdb +v2.0.0-31-g6197e83 From ce26ad06da8cbc945444412d42220b4755562730 Mon Sep 17 00:00:00 2001 From: Aritra Chakraborty Date: Wed, 16 Mar 2016 14:55:56 -0400 Subject: [PATCH 077/134] polishing and introduction of locally derived grid in FFT subroutine --- processing/post/addCurl.py | 39 +++++++++++++------------------- processing/post/addDivergence.py | 36 ++++++++++++----------------- 2 files changed, 31 insertions(+), 44 deletions(-) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index ac9715c36..6789b27d5 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -10,40 +10,35 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) def curlFFT(geomdim,field): + grid = np.array(np.shape(field)[2::-1]) N = grid.prod() # field size n = np.array(np.shape(field)[3:]).prod() # data size - if n == 3: - dataType = 'vector' - elif n == 9: - dataType = 'tensor' + if n == 3: dataType = 'vector' + elif n == 9: dataType = 'tensor' field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2)) curl_fourier = np.zeros(field_fourier.shape,'c16') # differentiation in Fourier space k_s = np.zeros([3],'i') - TWOPIIMG = (0.0+2.0j*math.pi) + TWOPIIMG = 2.0j*math.pi for i in xrange(grid[2]): k_s[0] = i - if(grid[2]%2==0 and i == grid[2]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[0]=0 - elif (i > grid[2]//2): - k_s[0] = k_s[0] - grid[2] + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif i > grid[2]//2: k_s[0] -= grid[2] for j in xrange(grid[1]): k_s[1] = j - if(grid[1]%2==0 and j == grid[1]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[1]=0 - elif (j > grid[1]//2): - k_s[1] = k_s[1] - grid[1] + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif j > grid[1]//2: k_s[1] -= grid[1] for k in xrange(grid[0]//2+1): k_s[2] = k - if(grid[0]%2==0 and k == grid[0]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[2]=0 + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order - xi = np.array([k_s[2]/geomdim[2]+0.0j,k_s[1]/geomdim[1]+0.j,k_s[0]/geomdim[0]+0.j],'c16') if dataType == 'tensor': for l in xrange(3): curl_fourier[i,j,k,0,l] = ( field_fourier[i,j,k,l,2]*xi[1]\ @@ -100,10 +95,8 @@ if options.vector is None and options.tensor is None: if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name,buffered = False) - except: - continue + try: table = damask.ASCIItable(name = name,buffered = False) + except: continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ @@ -161,9 +154,9 @@ for name in filenames: stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(curlFFT(size[::-1], # we need to reverse order here, because x - table.data[:,data['column'][i]:data['column'][i]+data['dim']]. # is fastest,ie rightmost, but leftmost in - reshape([grid[2],grid[1],grid[0]]+data['shape']))) # our x,y,z notation + stack.append(curlFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + table.data[:,data['column'][i]:data['column'][i]+data['dim']]. + reshape([grid[2],grid[1],grid[0]]+data['shape']))) # ------------------------------------------ output result ----------------------------------------- diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index 75708a603..99b56ead2 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -10,6 +10,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) def divFFT(geomdim,field): + grid = np.array(np.shape(field)[2::-1]) N = grid.prod() # field size n = np.array(np.shape(field)[3:]).prod() # data size @@ -18,27 +19,22 @@ def divFFT(geomdim,field): # differentiation in Fourier space k_s=np.zeros([3],'i') - TWOPIIMG = (0.0+2.0j*math.pi) + TWOPIIMG = 2.0j*math.pi for i in xrange(grid[2]): k_s[0] = i - if(grid[2]%2==0 and i == grid[2]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[0]=0 - elif (i > grid[2]//2): - k_s[0] = k_s[0] - grid[2] + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif i > grid[2]//2: k_s[0] -= grid[2] for j in xrange(grid[1]): k_s[1] = j - if(grid[1]%2==0 and j == grid[1]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[1]=0 - elif (j > grid[1]//2): - k_s[1] = k_s[1] - grid[1] + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif j > grid[1]//2: k_s[1] -= grid[1] for k in xrange(grid[0]//2+1): k_s[2] = k - if(grid[0]%2==0 and k == grid[0]//2): # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - k_s[2]=0 + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - xi=np.array([k_s[2]/geomdim[2]+0.0j,k_s[1]/geomdim[1]+0.j,k_s[0]/geomdim[0]+0.j],'c16') + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order if n == 9: # tensor, 3x3 -> 3 for l in xrange(3): div_fourier[i,j,k,l] = sum(field_fourier[i,j,k,l,0:3]*xi) *TWOPIIMG @@ -85,10 +81,8 @@ if options.vector is None and options.tensor is None: if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name,buffered = False) - except: - continue + try: table = damask.ASCIItable(name = name,buffered = False) + except: continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ @@ -140,16 +134,16 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings # ------------------------------------------ process value field ----------------------------------- stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(divFFT(size[::-1], # we need to reverse order here, because x - table.data[:,data['column'][i]:data['column'][i]+data['dim']]. # is fastest,ie rightmost, but leftmost in - reshape([grid[2],grid[1],grid[0]]+data['shape']))) # our x,y,z notation + stack.append(divFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + table.data[:,data['column'][i]:data['column'][i]+data['dim']]. + reshape([grid[2],grid[1],grid[0]]+data['shape']))) # ------------------------------------------ output result ----------------------------------------- @@ -158,4 +152,4 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) \ No newline at end of file + table.close() # close input ASCII table (works for stdin) From 3a267dc7ffc4f65d18bd30f9743c171e9d389d41 Mon Sep 17 00:00:00 2001 From: Aritra Chakraborty Date: Wed, 16 Mar 2016 15:02:38 -0400 Subject: [PATCH 078/134] FFT-based gradient calculation of scalar or vector field data (sibling of addCurl and addDivergence) --- processing/post/addGradient.py | 157 +++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100755 processing/post/addGradient.py diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py new file mode 100755 index 000000000..0d7caa829 --- /dev/null +++ b/processing/post/addGradient.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 no BOM -*- + +import os,sys,math +import numpy as np +from optparse import OptionParser +import damask + +scriptName = os.path.splitext(os.path.basename(__file__))[0] +scriptID = ' '.join([scriptName,damask.version]) + +def gradFFT(geomdim,field): + grid = np.array(np.shape(field)[2::-1]) + N = grid.prod() # field size + n = np.array(np.shape(field)[3:]).prod() # data size + if n == 3: dataType = 'vector' + elif n == 1: dataType = 'scalar' + + field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2)) + grad_fourier = np.zeros(field_fourier.shape+(3,),'c16') + +# differentiation in Fourier space + k_s = np.zeros([3],'i') + TWOPIIMG = 2.0j*math.pi + for i in xrange(grid[2]): + k_s[0] = i + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif i > grid[2]//2: k_s[0] -= grid[2] + + for j in xrange(grid[1]): + k_s[1] = j + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + elif j > grid[1]//2: k_s[1] -= grid[1] + + for k in xrange(grid[0]//2+1): + k_s[2] = k + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field order + + grad_fourier[i,j,k,0,:] = field_fourier[i,j,k,0]*xi *TWOPIIMG # vector field from scalar data + + if dataType == 'vector': + grad_fourier[i,j,k,1,:] = field_fourier[i,j,k,1]*xi *TWOPIIMG # tensor field from vector data + grad_fourier[i,j,k,2,:] = field_fourier[i,j,k,2]*xi *TWOPIIMG + + return np.fft.fftpack.irfftn(grad_fourier,axes=(0,1,2)).reshape([N,3*n]) + + +# -------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------- + +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +Add column(s) containing gradient of requested column(s). +Operates on periodic ordered three-dimensional data sets. +Deals with both vector- and scalar fields. + +""", version = scriptID) + +parser.add_option('-c','--coordinates', + dest = 'coords', + type = 'string', metavar='string', + help = 'column heading for coordinates [%default]') +parser.add_option('-v','--vector', + dest = 'vector', + action = 'extend', metavar = '', + help = 'heading of columns containing vector field values') +parser.add_option('-s','--scalar', + dest = 'scalar', + action = 'extend', metavar = '', + help = 'heading of columns containing scalar field values') + +parser.set_defaults(coords = 'ipinitialcoord', + ) + +(options,filenames) = parser.parse_args() + +if options.vector is None and options.scalar is None: + parser.error('no data column specified.') + +# --- loop over input files ------------------------------------------------------------------------- + +if filenames == []: filenames = [None] + +for name in filenames: + try: table = damask.ASCIItable(name = name,buffered = False) + except: continue + damask.util.report(scriptName,name) + +# ------------------------------------------ read header ------------------------------------------ + + table.head_read() + +# ------------------------------------------ sanity checks ---------------------------------------- + + items = { + 'scalar': {'dim': 1, 'shape': [1], 'labels':options.scalar, 'active':[], 'column': []}, + 'vector': {'dim': 3, 'shape': [3], 'labels':options.vector, 'active':[], 'column': []}, + } + errors = [] + remarks = [] + column = {} + + if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) + else: colCoord = table.label_index(options.coords) + + for type, data in items.iteritems(): + for what in (data['labels'] if data['labels'] is not None else []): + dim = table.label_dimension(what) + if dim != data['dim']: remarks.append('column {} is not a {}.'.format(what,type)) + else: + items[type]['active'].append(what) + items[type]['column'].append(table.label_index(what)) + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + +# ------------------------------------------ assemble header -------------------------------------- + + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) + for type, data in items.iteritems(): + for label in data['active']: + table.labels_append(['{}_gradFFT({})'.format(i+1,label) for i in xrange(3 * data['dim'])]) # extend ASCII header with new labels # grad increases the field dimension by one + table.head_write() + +# --------------- figure out size and grid --------------------------------------------------------- + + table.data_readArray() + + coords = [np.unique(table.data[:,colCoord+i]) for i in xrange(3)] + mincorner = np.array(map(min,coords)) + maxcorner = np.array(map(max,coords)) + grid = np.array(map(len,coords),'i') + size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) + +# ------------------------------------------ process value field ----------------------------------- + + stack = [table.data] + for type, data in items.iteritems(): + for i,label in enumerate(data['active']): + stack.append(gradFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + table.data[:,data['column'][i]:data['column'][i]+data['dim']]. + reshape([grid[2],grid[1],grid[0]]+data['shape']))) + +# ------------------------------------------ output result ----------------------------------------- + + if len(stack) > 1: table.data = np.hstack(tuple(stack)) + table.data_writeArray('%.12g') + +# ------------------------------------------ output finalization ----------------------------------- + + table.close() # close input ASCII table (works for stdin) From 36c703ecd34f0c9033f372e6799dd831b6daede7 Mon Sep 17 00:00:00 2001 From: Aritra Chakraborty Date: Wed, 16 Mar 2016 15:12:53 -0400 Subject: [PATCH 079/134] shortened excessively long lines --- processing/post/addCurl.py | 15 ++++++++------- processing/post/addDivergence.py | 25 +++++++++++++------------ processing/post/addGradient.py | 23 ++++++++++++----------- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index 6789b27d5..d8b1ee025 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -11,8 +11,8 @@ scriptID = ' '.join([scriptName,damask.version]) def curlFFT(geomdim,field): grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size + N = grid.prod() # field size + n = np.array(np.shape(field)[3:]).prod() # data size if n == 3: dataType = 'vector' elif n == 9: dataType = 'tensor' @@ -25,19 +25,19 @@ def curlFFT(geomdim,field): TWOPIIMG = 2.0j*math.pi for i in xrange(grid[2]): k_s[0] = i - if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif i > grid[2]//2: k_s[0] -= grid[2] for j in xrange(grid[1]): k_s[1] = j - if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif j > grid[1]//2: k_s[1] -= grid[1] for k in xrange(grid[0]//2+1): k_s[2] = k - if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order if dataType == 'tensor': for l in xrange(3): @@ -154,7 +154,8 @@ for name in filenames: stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(curlFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + stack.append(curlFFT(size[::-1], table.data[:,data['column'][i]:data['column'][i]+data['dim']]. reshape([grid[2],grid[1],grid[0]]+data['shape']))) diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index 99b56ead2..aadaceabf 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -11,34 +11,34 @@ scriptID = ' '.join([scriptName,damask.version]) def divFFT(geomdim,field): grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size + N = grid.prod() # field size + n = np.array(np.shape(field)[3:]).prod() # data size field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2)) - div_fourier = np.zeros(field_fourier.shape[0:len(np.shape(field))-1],'c16') # size depents on whether tensor or vector + div_fourier = np.zeros(field_fourier.shape[0:len(np.shape(field))-1],'c16') # size depents on whether tensor or vector # differentiation in Fourier space k_s=np.zeros([3],'i') TWOPIIMG = 2.0j*math.pi for i in xrange(grid[2]): k_s[0] = i - if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif i > grid[2]//2: k_s[0] -= grid[2] for j in xrange(grid[1]): k_s[1] = j - if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif j > grid[1]//2: k_s[1] -= grid[1] for k in xrange(grid[0]//2+1): k_s[2] = k - if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order - if n == 9: # tensor, 3x3 -> 3 + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field input order + if n == 9: # tensor, 3x3 -> 3 for l in xrange(3): div_fourier[i,j,k,l] = sum(field_fourier[i,j,k,l,0:3]*xi) *TWOPIIMG - elif n == 3: # vector, 3 -> 1 + elif n == 3: # vector, 3 -> 1 div_fourier[i,j,k] = sum(field_fourier[i,j,k,0:3]*xi) *TWOPIIMG return np.fft.fftpack.irfftn(div_fourier,axes=(0,1,2)).reshape([N,n/3]) @@ -76,7 +76,7 @@ parser.set_defaults(coords = 'ipinitialcoord', if options.vector is None and options.tensor is None: parser.error('no data column specified.') -# --- loop over input files ------------------------------------------------------------------------- +# --- loop over input files ------------------------------------------------------------------------ if filenames == []: filenames = [None] @@ -134,14 +134,15 @@ for name in filenames: maxcorner = np.array(map(max,coords)) grid = np.array(map(len,coords),'i') size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other spacings + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other ones # ------------------------------------------ process value field ----------------------------------- stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(divFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + stack.append(divFFT(size[::-1], table.data[:,data['column'][i]:data['column'][i]+data['dim']]. reshape([grid[2],grid[1],grid[0]]+data['shape']))) diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py index 0d7caa829..555e587de 100755 --- a/processing/post/addGradient.py +++ b/processing/post/addGradient.py @@ -11,8 +11,8 @@ scriptID = ' '.join([scriptName,damask.version]) def gradFFT(geomdim,field): grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size + N = grid.prod() # field size + n = np.array(np.shape(field)[3:]).prod() # data size if n == 3: dataType = 'vector' elif n == 1: dataType = 'scalar' @@ -24,24 +24,24 @@ def gradFFT(geomdim,field): TWOPIIMG = 2.0j*math.pi for i in xrange(grid[2]): k_s[0] = i - if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[2]%2 == 0 and i == grid[2]//2: k_s[0] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif i > grid[2]//2: k_s[0] -= grid[2] for j in xrange(grid[1]): k_s[1] = j - if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[1]%2 == 0 and j == grid[1]//2: k_s[1] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) elif j > grid[1]//2: k_s[1] -= grid[1] for k in xrange(grid[0]//2+1): k_s[2] = k - if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) + if grid[0]%2 == 0 and k == grid[0]//2: k_s[2] = 0 # for even grid, set Nyquist freq to 0 (Johnson, MIT, 2011) - xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field order + xi = (k_s/geomdim)[2::-1].astype('c16') # reversing the field order - grad_fourier[i,j,k,0,:] = field_fourier[i,j,k,0]*xi *TWOPIIMG # vector field from scalar data + grad_fourier[i,j,k,0,:] = field_fourier[i,j,k,0]*xi *TWOPIIMG # vector field from scalar data if dataType == 'vector': - grad_fourier[i,j,k,1,:] = field_fourier[i,j,k,1]*xi *TWOPIIMG # tensor field from vector data + grad_fourier[i,j,k,1,:] = field_fourier[i,j,k,1]*xi *TWOPIIMG # tensor field from vector data grad_fourier[i,j,k,2,:] = field_fourier[i,j,k,2]*xi *TWOPIIMG return np.fft.fftpack.irfftn(grad_fourier,axes=(0,1,2)).reshape([N,3*n]) @@ -79,7 +79,7 @@ parser.set_defaults(coords = 'ipinitialcoord', if options.vector is None and options.scalar is None: parser.error('no data column specified.') -# --- loop over input files ------------------------------------------------------------------------- +# --- loop over input files ------------------------------------------------------------------------ if filenames == []: filenames = [None] @@ -124,7 +124,7 @@ for name in filenames: table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) for type, data in items.iteritems(): for label in data['active']: - table.labels_append(['{}_gradFFT({})'.format(i+1,label) for i in xrange(3 * data['dim'])]) # extend ASCII header with new labels # grad increases the field dimension by one + table.labels_append(['{}_gradFFT({})'.format(i+1,label) for i in xrange(3 * data['dim'])]) # extend ASCII header with new labels table.head_write() # --------------- figure out size and grid --------------------------------------------------------- @@ -143,7 +143,8 @@ for name in filenames: stack = [table.data] for type, data in items.iteritems(): for i,label in enumerate(data['active']): - stack.append(gradFFT(size[::-1], # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation + stack.append(gradFFT(size[::-1], table.data[:,data['column'][i]:data['column'][i]+data['dim']]. reshape([grid[2],grid[1],grid[0]]+data['shape']))) From 36c88cde02a62a0e13961dcf0227907ee93e0a2f Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 17 Mar 2016 04:13:35 +0100 Subject: [PATCH 080/134] updated version information after successful test of v2.0.0-36-g2b7524e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 27bd816bb..09b18f22c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-31-g6197e83 +v2.0.0-36-g2b7524e From d42f8d5fd4958bbc1015f4db495995e814fbf823 Mon Sep 17 00:00:00 2001 From: Zhuowen Zhao Date: Thu, 17 Mar 2016 17:40:40 -0400 Subject: [PATCH 081/134] added possibility to read real numbers as microstructure indices (not only integers) --- lib/damask/asciitable.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 4abe4297d..5212ef00c 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -517,21 +517,25 @@ class ASCIItable(): # ------------------------------------------------------------------ def microstructure_read(self, - grid): + grid, + type = 'i'): """read microstructure data (from .geom format)""" - N = grid.prod() # expected number of microstructure indices in data - microstructure = np.zeros(N,'i') # initialize as flat array + def datatype(item): + return int(item) if type.lower() == 'i' else float(item) + + N = grid.prod() # expected number of microstructure indices in data + microstructure = np.zeros(N,type) # initialize as flat array i = 0 while i < N and self.data_read(): items = self.data if len(items) > 2: - if items[1].lower() == 'of': items = [int(items[2])]*int(items[0]) - elif items[1].lower() == 'to': items = range(int(items[0]),1+int(items[2])) - else: items = map(int,items) - else: items = map(int,items) + if items[1].lower() == 'of': items = np.ones(datatype(items[0]))*datatype(items[2]) + elif items[1].lower() == 'to': items = np.arange(datatype(items[0]),1+datatype(items[2])) + else: items = map(datatype,items) + else: items = map(datatype,items) - s = min(len(items), N-i) # prevent overflow of microstructure array + s = min(len(items), N-i) # prevent overflow of microstructure array microstructure[i:i+s] = items[:s] i += s From 0f78f1c74713b389462e2aa745a158c2cdcbfd45 Mon Sep 17 00:00:00 2001 From: Aritra Chakraborty Date: Thu, 17 Mar 2016 18:09:22 -0400 Subject: [PATCH 082/134] possibility to treat floating point numbers as microstructure indices --- processing/pre/geom_canvas.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/processing/pre/geom_canvas.py b/processing/pre/geom_canvas.py index 882f32c88..ec171f522 100755 --- a/processing/pre/geom_canvas.py +++ b/processing/pre/geom_canvas.py @@ -28,24 +28,32 @@ parser.add_option('-o', '--offset', help = 'a,b,c offset from old to new origin of grid [%default]') parser.add_option('-f', '--fill', dest = 'fill', - type = 'int', metavar = 'int', + type = 'float', metavar = 'float', help = '(background) canvas grain index. "0" selects maximum microstructure index + 1 [%default]') +parser.add_option('--float', + dest = 'real', + action = 'store_true', + help = 'input data is float [%default]') parser.set_defaults(grid = ['0','0','0'], offset = (0,0,0), fill = 0, + real = False, ) (options, filenames) = parser.parse_args() +datatype = 'f' if options.real else 'i' + + # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, labeled = False) + try: table = damask.ASCIItable(name = name, + buffered = False, + labeled = False) except: continue damask.util.report(scriptName,name) @@ -71,7 +79,7 @@ for name in filenames: # --- read data ------------------------------------------------------------------------------------ - microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure + microstructure = table.microstructure_read(info['grid'],datatype).reshape(info['grid'],order='F') # read microstructure # --- do work ------------------------------------------------------------------------------------ @@ -85,8 +93,8 @@ for name in filenames: else int(n) for o,n in zip(info['grid'],options.grid)],'i') newInfo['grid'] = np.where(newInfo['grid'] > 0, newInfo['grid'],info['grid']) - microstructure_cropped = np.zeros(newInfo['grid'],'i') - microstructure_cropped.fill(options.fill if options.fill > 0 else microstructure.max()+1) + microstructure_cropped = np.zeros(newInfo['grid'],datatype) + microstructure_cropped.fill(options.fill if options.real or options.fill > 0 else microstructure.max()+1) xindex = list(set(xrange(options.offset[0],options.offset[0]+newInfo['grid'][0])) & \ set(xrange(info['grid'][0]))) yindex = list(set(xrange(options.offset[1],options.offset[1]+newInfo['grid'][1])) & \ @@ -152,9 +160,9 @@ for name in filenames: # --- write microstructure information ------------------------------------------------------------ - formatwidth = int(math.floor(math.log10(microstructure_cropped.max())+1)) + format = '%g' if options.real else '%{}i'.format(int(math.floor(math.log10(microstructure_cropped.max())+1))) table.data = microstructure_cropped.reshape((newInfo['grid'][0],newInfo['grid'][1]*newInfo['grid'][2]),order='F').transpose() - table.data_writeArray('%%%ii'%(formatwidth),delimiter=' ') + table.data_writeArray(format,delimiter=' ') # --- output finalization -------------------------------------------------------------------------- From e39441f36bbff3d2dc4d63e42b2492bb6081c16a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 17 Mar 2016 19:02:30 -0400 Subject: [PATCH 083/134] corrected usage message to tell about string comparison in filter condition --- processing/post/filterTable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/post/filterTable.py b/processing/post/filterTable.py index d375785dc..6723d9faf 100755 --- a/processing/post/filterTable.py +++ b/processing/post/filterTable.py @@ -35,7 +35,7 @@ Filter rows according to condition and columns by either white or black listing. Examples: Every odd row if x coordinate is positive -- " #ip.x# >= 0.0 and #_row_#%2 == 1 ). -All rows where label 'foo' equals 'bar' -- " #foo# == \"bar\" " +All rows where label 'foo' equals 'bar' -- " #s#foo# == 'bar' " """, version = scriptID) From 2506667326235ed45fc461160fca211a80e4ef2c Mon Sep 17 00:00:00 2001 From: Test User Date: Fri, 18 Mar 2016 04:13:24 +0100 Subject: [PATCH 084/134] updated version information after successful test of v2.0.0-43-ge39441f --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 09b18f22c..690c6cb1d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-36-g2b7524e +v2.0.0-43-ge39441f From 6865987ea743fc5a2c0f92c42e37766b1ef90dea Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 20 Mar 2016 15:01:47 -0400 Subject: [PATCH 085/134] restored option to output microstructure indices as one-dimensional list (not clear why that got lost!) --- processing/pre/geom_unpack.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/processing/pre/geom_unpack.py b/processing/pre/geom_unpack.py index a07166cdd..85c60d6e5 100755 --- a/processing/pre/geom_unpack.py +++ b/processing/pre/geom_unpack.py @@ -18,6 +18,14 @@ Unpack geometry files containing ranges "a to b" and/or "n of x" multiples (excl """, version = scriptID) +parser.add_option('-1', '--onedimensional', + dest = 'oneD', + action = 'store_true', + help = 'output geom file with one-dimensional data arrangement') + +parser.set_defaults(oneD = False, + ) + (options, filenames) = parser.parse_args() # --- loop over input files ------------------------------------------------------------------------- @@ -69,7 +77,8 @@ for name in filenames: microstructure = table.microstructure_read(info['grid']) # read microstructure formatwidth = int(math.floor(math.log10(microstructure.max())+1)) # efficient number printing format - table.data = microstructure.reshape((info['grid'][0],info['grid'][1]*info['grid'][2]),order='F').transpose() + table.data = microstructure if options.oneD else \ + microstructure.reshape((info['grid'][0],info['grid'][1]*info['grid'][2]),order='F').transpose() table.data_writeArray('%%%ii'%(formatwidth),delimiter = ' ') #--- output finalization -------------------------------------------------------------------------- From a41cd3df4068af0cd752d72cc060f4d91204f470 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 20 Mar 2016 16:46:35 -0400 Subject: [PATCH 086/134] added "strict" option to reading microstructure from geom file. will now complain if data mismatches with grid. --- lib/damask/asciitable.py | 8 +++++--- processing/pre/geom_check.py | 27 +++++++++++++++------------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 5212ef00c..62d38e4dd 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -518,7 +518,8 @@ class ASCIItable(): # ------------------------------------------------------------------ def microstructure_read(self, grid, - type = 'i'): + type = 'i', + strict = False): """read microstructure data (from .geom format)""" def datatype(item): return int(item) if type.lower() == 'i' else float(item) @@ -537,6 +538,7 @@ class ASCIItable(): s = min(len(items), N-i) # prevent overflow of microstructure array microstructure[i:i+s] = items[:s] - i += s + i += len(items) - return microstructure + return (microstructure, i == N and not self.data_read() if strict # check for proper point count and end of file + else microstructure) diff --git a/processing/pre/geom_check.py b/processing/pre/geom_check.py index d607a1f73..518e8c3b0 100755 --- a/processing/pre/geom_check.py +++ b/processing/pre/geom_check.py @@ -54,12 +54,25 @@ for name in filenames: errors = [] if np.any(info['grid'] < 1): errors.append('invalid grid a b c.') if np.any(info['size'] <= 0.0): errors.append('invalid size x y z.') + +#--- read microstructure information -------------------------------------------------------------- + + if options.data: + microstructure,ok = table.microstructure_read(info['grid'],strict = True) # read microstructure + + if ok: + structure = vtk.vtkIntArray() + structure.SetName('Microstructures') + for idx in microstructure: structure.InsertNextValue(idx) + + else: errors.append('mismatch between data and grid dimension.') + if errors != []: damask.util.croak(errors) table.close(dismiss = True) continue -# --- generate VTK rectilinear grid -------------------------------------------------------------------------------- +# --- generate VTK rectilinear grid --------------------------------------------------------------- grid = vtk.vtkRectilinearGrid() grid.SetDimensions([x+1 for x in info['grid']]) @@ -72,18 +85,8 @@ for name in filenames: elif i == 1: grid.SetYCoordinates(temp) elif i == 2: grid.SetZCoordinates(temp) -#--- read microstructure information -------------------------------------------------------------- - if options.data: - microstructure = table.microstructure_read(info['grid']) # read microstructure - - structure = vtk.vtkIntArray() - structure.SetName('Microstructures') - - for idx in microstructure: - structure.InsertNextValue(idx) - - grid.GetCellData().AddArray(structure) + if options.data: grid.GetCellData().AddArray(structure) # --- write data ----------------------------------------------------------------------------------- if name: From 28259b2c46b805b66dcb14d95765feda18e1a7f4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 20 Mar 2016 23:20:58 +0100 Subject: [PATCH 087/134] switched dNeq and dEq to relative tolerance, removed single precision (makes things complicated and was never used anyway) --- code/crystallite.f90 | 46 ++++++++++++++++---------------------------- code/math.f90 | 31 +++++++---------------------- code/prec.f90 | 33 +++++++++++-------------------- 3 files changed, 35 insertions(+), 75 deletions(-) diff --git a/code/crystallite.f90 b/code/crystallite.f90 index 53378a70d..71a5e4743 100644 --- a/code/crystallite.f90 +++ b/code/crystallite.f90 @@ -3569,11 +3569,7 @@ logical function crystallite_integrateStress(& maxticks external :: & -#if(FLOAT==8) dgesv -#elif(FLOAT==4) - sgesv -#endif !* be pessimistic crystallite_integrateStress = .false. @@ -3756,11 +3752,7 @@ logical function crystallite_integrateStress(& - math_Plain3333to99(math_mul3333xx3333(math_mul3333xx3333(dLp_dT3333,dT_dFe3333),dFe_dLp3333)) dRLp_dLp2 = dRLp_dLp ! will be overwritten in first call to LAPACK routine work = math_plain33to9(residuumLp) -#if(FLOAT==8) call dgesv(9,1,dRLp_dLp2,9,ipiv,work,9,ierr) ! solve dRLp/dLp * delta Lp = -res for delta Lp -#elif(FLOAT==4) - call sgesv(9,1,dRLp_dLp2,9,ipiv,work,9,ierr) ! solve dRLp/dLp * delta Lp = -res for delta Lp -#endif if (ierr /= 0_pInt) then #ifndef _OPENMP if (iand(debug_level(debug_crystallite), debug_levelBasic) /= 0_pInt) then @@ -3849,31 +3841,27 @@ logical function crystallite_integrateStress(& math_mul3333xx3333(dT_dFi3333, dFi_dLi3333))) & - math_Plain3333to99(math_mul3333xx3333(dLi_dFi3333, dFi_dLi3333)) work = math_plain33to9(residuumLi) -#if(FLOAT==8) call dgesv(9,1,dRLi_dLi,9,ipiv,work,9,ierr) ! solve dRLi/dLp * delta Li = -res for delta Li -#elif(FLOAT==4) - call sgesv(9,1,dRLi_dLi,9,ipiv,work,9,ierr) ! solve dRLi/dLp * delta Li = -res for delta Li -#endif - if (ierr /= 0_pInt) then + if (ierr /= 0_pInt) then #ifndef _OPENMP - if (iand(debug_level(debug_crystallite), debug_levelBasic) /= 0_pInt) then - write(6,'(a,i8,1x,a,i8,a,1x,i2,1x,i3,a,i3)') '<< CRYST >> integrateStress failed on dR/dLi inversion at el ip ipc ', & - el,mesh_element(1,el),ip,ipc - if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & - .and. ((el == debug_e .and. ip == debug_i .and. ipc == debug_g)& - .or. .not. iand(debug_level(debug_crystallite), debug_levelSelective) /= 0_pInt)) then - write(6,*) - write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dR_dLi',transpose(dRLi_dLi) - write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dFe_dLi',transpose(math_Plain3333to99(dFe_dLi3333)) - write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dT_dFi_constitutive',transpose(math_Plain3333to99(dT_dFi3333)) - write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dLi_dT_constitutive',transpose(math_Plain3333to99(dLi_dT3333)) - write(6,'(a,/,3(12x,3(e20.7,1x)/))') '<< CRYST >> Li_constitutive',math_transpose33(Li_constitutive) - write(6,'(a,/,3(12x,3(e20.7,1x)/))') '<< CRYST >> Liguess',math_transpose33(Liguess) - endif + if (iand(debug_level(debug_crystallite), debug_levelBasic) /= 0_pInt) then + write(6,'(a,i8,1x,a,i8,a,1x,i2,1x,i3,a,i3)') '<< CRYST >> integrateStress failed on dR/dLi inversion at el ip ipc ', & + el,mesh_element(1,el),ip,ipc + if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & + .and. ((el == debug_e .and. ip == debug_i .and. ipc == debug_g)& + .or. .not. iand(debug_level(debug_crystallite), debug_levelSelective) /= 0_pInt)) then + write(6,*) + write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dR_dLi',transpose(dRLi_dLi) + write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dFe_dLi',transpose(math_Plain3333to99(dFe_dLi3333)) + write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dT_dFi_constitutive',transpose(math_Plain3333to99(dT_dFi3333)) + write(6,'(a,/,9(12x,9(e15.3,1x)/))') '<< CRYST >> dLi_dT_constitutive',transpose(math_Plain3333to99(dLi_dT3333)) + write(6,'(a,/,3(12x,3(e20.7,1x)/))') '<< CRYST >> Li_constitutive',math_transpose33(Li_constitutive) + write(6,'(a,/,3(12x,3(e20.7,1x)/))') '<< CRYST >> Liguess',math_transpose33(Liguess) endif -#endif - return endif +#endif + return + endif deltaLi = - math_plain9to33(work) endif diff --git a/code/math.f90 b/code/math.f90 index 2f76c1cb5..bf7460062 100644 --- a/code/math.f90 +++ b/code/math.f90 @@ -186,10 +186,6 @@ module math halton_seed_set, & i_to_halton, & prime - external :: & - dsyev, & - dgetrf, & - dgetri contains @@ -811,15 +807,13 @@ function math_invSym3333(A) integer(pInt), dimension(6) :: ipiv6 real(pReal), dimension(6,6) :: temp66_Real real(pReal), dimension(6) :: work6 + external :: & + dgetrf, & + dgetri temp66_real = math_Mandel3333to66(A) -#if(FLOAT==8) call dgetrf(6,6,temp66_real,6,ipiv6,ierr) call dgetri(6,temp66_real,6,ipiv6,work6,6,ierr) -#elif(FLOAT==4) - call sgetrf(6,6,temp66_real,6,ipiv6,ierr) - call sgetri(6,temp66_real,6,ipiv6,work6,6,ierr) -#endif if (ierr == 0_pInt) then math_invSym3333 = math_Mandel66to3333(temp66_real) else @@ -847,13 +841,8 @@ subroutine math_invert(myDim,A, InvA, error) logical, intent(out) :: error invA = A -#if(FLOAT==8) call dgetrf(myDim,myDim,invA,myDim,ipiv,ierr) call dgetri(myDim,InvA,myDim,ipiv,work,myDim,ierr) -#elif(FLOAT==4) - call sgetrf(myDim,myDim,invA,myDim,ipiv,ierr) - call sgetri(myDim,InvA,myDim,ipiv,work,myDim,ierr) -#endif error = merge(.true.,.false., ierr /= 0_pInt) ! http://fortraninacworld.blogspot.de/2012/12/ternary-operator.html end subroutine math_invert @@ -1937,16 +1926,13 @@ subroutine math_eigenValuesVectorsSym(m,values,vectors,error) real(pReal), dimension(size(m,1)), intent(out) :: values real(pReal), dimension(size(m,1),size(m,1)), intent(out) :: vectors logical, intent(out) :: error - integer(pInt) :: info real(pReal), dimension((64+2)*size(m,1)) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f + external :: & + dsyev vectors = m ! copy matrix to input (doubles as output) array -#if(FLOAT==8) call dsyev('V','U',size(m,1),vectors,size(m,1),values,work,(64+2)*size(m,1),info) -#elif(FLOAT==4) - call ssyev('V','U',size(m,1),vectors,size(m,1),values,work,(64+2)*size(m,1),info) -#endif error = (info == 0_pInt) end subroutine math_eigenValuesVectorsSym @@ -2135,16 +2121,13 @@ function math_eigenvaluesSym(m) real(pReal), dimension(:,:), intent(in) :: m real(pReal), dimension(size(m,1)) :: math_eigenvaluesSym real(pReal), dimension(size(m,1),size(m,1)) :: vectors - integer(pInt) :: info real(pReal), dimension((64+2)*size(m,1)) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f + external :: & + dsyev vectors = m ! copy matrix to input (doubles as output) array -#if(FLOAT==8) call dsyev('N','U',size(m,1),vectors,size(m,1),math_eigenvaluesSym,work,(64+2)*size(m,1),info) -#elif(FLOAT==4) - call ssyev('N','U',size(m,1),vectors,size(m,1),math_eigenvaluesSym,work,(64+2)*size(m,1),info) -#endif if (info /= 0_pInt) math_eigenvaluesSym = DAMASK_NaN end function math_eigenvaluesSym diff --git a/code/prec.f90 b/code/prec.f90 index 129681fd5..efa0c76a3 100644 --- a/code/prec.f90 +++ b/code/prec.f90 @@ -4,9 +4,9 @@ !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH -!> @brief setting precision for real and int type depending on makros "FLOAT" and "INT" +!> @brief setting precision for real and int type !> @details setting precision for real and int type and for DAMASK_NaN. Definition is made -!! depending on makros "FLOAT" and "INT" defined during compilation +!! depending on makro "INT" defined during compilation !! for details on NaN see https://software.intel.com/en-us/forums/topic/294680 !-------------------------------------------------------------------------------------------------- module prec @@ -18,18 +18,7 @@ module prec implicit none private -#if (FLOAT==4) -#if defined(Spectral) || defined(FEM) - SPECTRAL SOLVER AND OWN FEM DO NOT SUPPORT SINGLE PRECISION, STOPPING COMPILATION -#endif - integer, parameter, public :: pReal = 4 !< floating point single precition (was selected_real_kind(6,37), number with 6 significant digits, up to 1e+-37) -#ifdef __INTEL_COMPILER - real(pReal), parameter, public :: DAMASK_NaN = Z'7F800001' !< quiet NaN for single precision (from http://www.hpc.unimelb.edu.au/doc/f90lrm/dfum_035.html, copy can be found in documentation/Code/Fortran) -#endif -#ifdef __GFORTRAN__ - real(pReal), parameter, public :: DAMASK_NaN = real(Z'7F800001', pReal) !< quiet NaN for single precision (from http://www.hpc.unimelb.edu.au/doc/f90lrm/dfum_035.html, copy can be found in documentation/Code/Fortran) -#endif -#elif (FLOAT==8) +#if (FLOAT==8) integer, parameter, public :: pReal = 8 !< floating point double precision (was selected_real_kind(15,300), number with 15 significant digits, up to 1e+-300) #ifdef __INTEL_COMPILER real(pReal), parameter, public :: DAMASK_NaN = Z'7FF8000000000000' !< quiet NaN for double precision (from http://www.hpc.unimelb.edu.au/doc/f90lrm/dfum_035.html, copy can be found in documentation/Code/Fortran) @@ -188,29 +177,29 @@ logical elemental pure function prec_isNaN(a) end function prec_isNaN - !-------------------------------------------------------------------------------------------------- !> @brief equality comparison for double precision -! replaces "==" but for certain (absolute) tolerance. Counterpart to dNeq +! replaces "==" but for certain (relative) tolerance. Counterpart to dNeq +! http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm !-------------------------------------------------------------------------------------------------- logical elemental pure function dEq(a,b,tol) real(pReal), intent(in) :: a,b real(pReal), intent(in), optional :: tol - real(pReal), parameter :: eps = 1.0e-15_pReal - dEq = merge(.True., .False.,abs(a-b) < merge(tol,eps,present(tol))) + real(pReal), parameter :: eps = 2.2204460492503131E-16 ! DBL_EPSILON in C + dEq = merge(.True., .False.,abs(a-b) <= merge(tol,eps,present(tol))*maxval(abs([a,b]))) end function dEq - !-------------------------------------------------------------------------------------------------- !> @brief inequality comparison for double precision -! replaces "!=" but for certain (absolute) tolerance. Counterpart to dEq +! replaces "!=" but for certain (relative) tolerance. Counterpart to dEq +! http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm !-------------------------------------------------------------------------------------------------- logical elemental pure function dNeq(a,b,tol) real(pReal), intent(in) :: a,b real(pReal), intent(in), optional :: tol - real(pReal), parameter :: eps = 1.0e-15_pReal - dNeq = merge(.True., .False.,abs(a-b) < merge(tol,eps,present(tol))) + real(pReal), parameter :: eps = 2.2204460492503131E-16 ! DBL_EPSILON in C + dNeq = merge(.False., .True.,abs(a-b) <= merge(tol,eps,present(tol))*maxval(abs([a,b]))) end function dNeq end module prec From 8526d2f4958bf949e7ac6f243a2f448818f4919f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 20 Mar 2016 23:30:03 +0100 Subject: [PATCH 088/134] line feeds causing trouble on windows --- code/.gitattributes | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 code/.gitattributes diff --git a/code/.gitattributes b/code/.gitattributes new file mode 100644 index 000000000..8035e26a7 --- /dev/null +++ b/code/.gitattributes @@ -0,0 +1,8 @@ +# from https://help.github.com/articles/dealing-with-line-endings/ +# +# always use LF, even if the files are edited on windows, they need to be compiled/used on unix +* text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary From 01a5343ca20ec2c38449afc8137413b6a7135a62 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 20 Mar 2016 20:58:10 -0400 Subject: [PATCH 089/134] added another backgroundMessage animation. generally cleaned code a slight bit. --- lib/damask/util.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/damask/util.py b/lib/damask/util.py index 9ce42759a..c64a8cd00 100644 --- a/lib/damask/util.py +++ b/lib/damask/util.py @@ -106,6 +106,7 @@ class backgroundMessage(threading.Thread): choices = {'bounce': ['_', 'o', 'O', u'\u00B0', u'\u203e',u'\u203e',u'\u00B0','O','o','_'], + 'spin': [u'\u25dc',u'\u25dd',u'\u25de',u'\u25df'], 'circle': [u'\u25f4',u'\u25f5',u'\u25f6',u'\u25f7'], 'hexagon': [u'\u2b22',u'\u2b23'], 'square': [u'\u2596',u'\u2598',u'\u259d',u'\u2597'], @@ -229,7 +230,7 @@ def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0, return shape(res), dt def _int2extGrad(p_int, bounds): - """Calculate the gradients of transforming the internal (unconstrained) to external (constained) parameter.""" + """Calculate the gradients of transforming the internal (unconstrained) to external (constrained) parameter.""" grad = np.empty_like(p_int) for i, (x, bound) in enumerate(zip(p_int, bounds)): lower, upper = bound @@ -431,22 +432,20 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): else: pcov = np.inf - if return_full: - return popt, pcov, infodict, errmsg, ier - else: - return popt, pcov + return popt, pcov, infodict, errmsg, ier if return_full else popt, pcov -def execute(cmd,streamIn=None,wd='./'): +def execute(cmd,streamIn = None,wd = './'): """executes a command in given directory and returns stdout and stderr for optional stdin""" - initialPath=os.getcwd() + initialPath = os.getcwd() os.chdir(wd) - process = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr = subprocess.PIPE,stdin=subprocess.PIPE) - if streamIn is not None: - out,error = [i.replace("\x08","") for i in process.communicate(streamIn.read())] - else: - out,error =[i.replace("\x08","") for i in process.communicate()] + process = subprocess.Popen(shlex.split(cmd), + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + stdin = subprocess.PIPE) + out,error = [i.replace("\x08","") for i in (process.communicate if streamIn is None + else process.communicate(streamIn.read()))] os.chdir(initialPath) - if process.returncode !=0: raise RuntimeError(cmd+' failed with returncode '+str(process.returncode)) + if process.returncode != 0: raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) return out,error From 8cd1f027b303b9ca7ff8c8e03bcbcbdc04b2e167 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 21 Mar 2016 08:51:56 -0400 Subject: [PATCH 090/134] bug fixing. --- lib/damask/asciitable.py | 3 +-- lib/damask/util.py | 38 ++++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 62d38e4dd..f76cf6627 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -540,5 +540,4 @@ class ASCIItable(): microstructure[i:i+s] = items[:s] i += len(items) - return (microstructure, i == N and not self.data_read() if strict # check for proper point count and end of file - else microstructure) + return (microstructure, i == N and not self.data_read()) if strict else microstructure # check for proper point count and end of file diff --git a/lib/damask/util.py b/lib/damask/util.py index c64a8cd00..244aaa25c 100644 --- a/lib/damask/util.py +++ b/lib/damask/util.py @@ -58,6 +58,24 @@ def emph(what): """emphasizes string on screen""" return bcolors.BOLD+srepr(what)+bcolors.ENDC +# ----------------------------- +def execute(cmd, + streamIn = None, + wd = './'): + """executes a command in given directory and returns stdout and stderr for optional stdin""" + initialPath = os.getcwd() + os.chdir(wd) + process = subprocess.Popen(shlex.split(cmd), + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + stdin = subprocess.PIPE) + out,error = [i.replace("\x08","") for i in (process.communicate() if streamIn is None + else process.communicate(streamIn.read()))] + os.chdir(initialPath) + if process.returncode != 0: raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) + return out,error + + # ----------------------------- # Matlab like trigonometric functions that take and return angles in degrees. # ----------------------------- @@ -75,7 +93,7 @@ def gridLocation(idx,res): # ----------------------------- def gridIndex(location,res): - return ( location[0] % res[0] + \ + return ( location[0] % res[0] + \ ( location[1] % res[1]) * res[0] + \ ( location[2] % res[2]) * res[1] * res[0] ) @@ -432,20 +450,4 @@ def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): else: pcov = np.inf - return popt, pcov, infodict, errmsg, ier if return_full else popt, pcov - - -def execute(cmd,streamIn = None,wd = './'): - """executes a command in given directory and returns stdout and stderr for optional stdin""" - initialPath = os.getcwd() - os.chdir(wd) - process = subprocess.Popen(shlex.split(cmd), - stdout = subprocess.PIPE, - stderr = subprocess.PIPE, - stdin = subprocess.PIPE) - out,error = [i.replace("\x08","") for i in (process.communicate if streamIn is None - else process.communicate(streamIn.read()))] - os.chdir(initialPath) - if process.returncode != 0: raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) - return out,error - + return (popt, pcov, infodict, errmsg, ier) if return_full else (popt, pcov) From 1b22b6e4ee958d0eb67d4fc3f8e7f2416d184eae Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Mon, 21 Mar 2016 10:18:58 -0400 Subject: [PATCH 091/134] replaced variable interpolation into strings by "%" with .format() method --- lib/damask/test/test.py | 145 ++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/lib/damask/test/test.py b/lib/damask/test/test.py index 523f25d60..826b190c1 100644 --- a/lib/damask/test/test.py +++ b/lib/damask/test/test.py @@ -22,11 +22,11 @@ class Test(): logger = logging.getLogger() logger.setLevel(0) - fh = logging.FileHandler('test.log') # create file handler which logs even debug messages + fh = logging.FileHandler('test.log') # create file handler which logs even debug messages fh.setLevel(logging.DEBUG) full = logging.Formatter('%(asctime)s - %(levelname)s: \n%(message)s') fh.setFormatter(full) - ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level + ch = logging.StreamHandler(stream=sys.stdout) # create console handler with a higher log level ch.setLevel(logging.INFO) # create formatter and add it to the handlers plain = logging.Formatter('%(message)s') @@ -60,10 +60,10 @@ class Test(): try: self.postprocess(variant) if not self.compare(variant): - return variant+1 # return culprit + return variant+1 # return culprit except Exception as e : - logging.critical('\nWARNING:\n %s\n'%e) - return variant+1 # return culprit + logging.critical('\nWARNING:\n {}\n'.format(e)) + return variant+1 # return culprit return 0 else: if not self.testPossible(): return -1 @@ -74,13 +74,13 @@ class Test(): self.prepare(variant) self.run(variant) self.postprocess(variant) - if self.updateRequested: # update requested + if self.updateRequested: # update requested self.update(variant) - elif not (self.options.accept or self.compare(variant)): # no update, do comparison - return variant+1 # return culprit + elif not (self.options.accept or self.compare(variant)): # no update, do comparison + return variant+1 # return culprit except Exception as e : - logging.critical('\nWARNING:\n %s\n'%e) - return variant+1 # return culprit + logging.critical('\nWARNING:\n {}\n'.format(e)) + return variant+1 # return culprit return 0 def testPossible(self): @@ -94,13 +94,13 @@ class Test(): try: shutil.rmtree(self.dirCurrent()) except: - logging.warning('removal of directory "%s" not possible...'%(self.dirCurrent())) + logging.warning('removal of directory "{}" not possible...'.format(self.dirCurrent())) status = status and False try: os.mkdir(self.dirCurrent()) except: - logging.critical('creation of directory "%s" failed...'%(self.dirCurrent())) + logging.critical('creation of directory "{}" failed...'.format(self.dirCurrent())) status = status and False return status @@ -193,19 +193,19 @@ class Test(): try: shutil.copy2(self.fileInReference(file),self.fileInCurrent(targetfiles[i])) except: - logging.critical('Reference2Current: Unable to copy file %s'%file) + logging.critical('Reference2Current: Unable to copy file "{}"'.format(file)) def copy_Base2Current(self,sourceDir,sourcefiles=[],targetfiles=[]): - source=os.path.normpath(os.path.join(self.dirBase,'../../../'+sourceDir)) + source=os.path.normpath(os.path.join(self.dirBase,'../../..',sourceDir)) if len(targetfiles) == 0: targetfiles = sourcefiles for i,file in enumerate(sourcefiles): try: shutil.copy2(os.path.join(source,file),self.fileInCurrent(targetfiles[i])) except: logging.error(os.path.join(source,file)) - logging.critical('Base2Current: Unable to copy file %s'%file) + logging.critical('Base2Current: Unable to copy file "{}"'.format(file)) def copy_Current2Reference(self,sourcefiles=[],targetfiles=[]): @@ -215,7 +215,7 @@ class Test(): try: shutil.copy2(self.fileInCurrent(file),self.fileInReference(targetfiles[i])) except: - logging.critical('Current2Reference: Unable to copy file %s'%file) + logging.critical('Current2Reference: Unable to copy file "{}"'.format(file)) def copy_Proof2Current(self,sourcefiles=[],targetfiles=[]): @@ -225,7 +225,7 @@ class Test(): try: shutil.copy2(self.fileInProof(file),self.fileInCurrent(targetfiles[i])) except: - logging.critical('Proof2Current: Unable to copy file %s'%file) + logging.critical('Proof2Current: Unable to copy file "{}"'.format(file)) def copy_Current2Current(self,sourcefiles=[],targetfiles=[]): @@ -234,7 +234,7 @@ class Test(): try: shutil.copy2(self.fileInReference(file),self.fileInCurrent(targetfiles[i])) except: - logging.critical('Current2Current: Unable to copy file %s'%file) + logging.critical('Current2Current: Unable to copy file "{}"'.format(file)) def execute_inCurrentDir(self,cmd,streamIn=None): @@ -252,7 +252,7 @@ class Test(): def compare_Array(self,File1,File2): import numpy as np - logging.info('comparing\n '+File1+'\n '+File2) + logging.info('\n '.join(['comparing',File1,File2])) table1 = damask.ASCIItable(name=File1,readonly=True) table1.head_read() len1=len(table1.info)+2 @@ -270,8 +270,9 @@ class Test(): max_loc=np.argmax(abs(refArrayNonZero[curArray.nonzero()]/curArray[curArray.nonzero()]-1.)) refArrayNonZero = refArrayNonZero[curArray.nonzero()] curArray = curArray[curArray.nonzero()] - print(' ********\n * maximum relative error %e for %e and %e\n ********' - %(max_err, refArrayNonZero[max_loc],curArray[max_loc])) + print(' ********\n * maximum relative error {} between {} and {}\n ********'.format(max_err, + refArrayNonZero[max_loc], + curArray[max_loc])) return max_err else: raise Exception('mismatch in array size to compare') @@ -295,7 +296,7 @@ class Test(): absoluteTolerance=False,perLine=False,skipLines=[]): import numpy as np - logging.info('comparing ASCII Tables\n %s \n %s'%(file0,file1)) + logging.info('\n '.join(['comparing ASCII Tables',file0,file1])) if normHeadings == '': normHeadings = headings0 # check if comparison is possible and determine lenght of columns @@ -315,7 +316,7 @@ class Test(): for i in xrange(dataLength): if headings0[i]['shape'] != headings1[i]['shape']: - raise Exception('shape mismatch when comparing %s with %s '%(headings0[i]['label'],headings1[i]['label'])) + raise Exception('shape mismatch between {} and {} '.format(headings0[i]['label'],headings1[i]['label'])) shape[i] = headings0[i]['shape'] for j in xrange(np.shape(shape[i])[0]): length[i] *= shape[i][j] @@ -323,7 +324,9 @@ class Test(): for j in xrange(np.shape(normShape[i])[0]): normLength[i] *= normShape[i][j] else: - raise Exception('trying to compare %i with %i normed by %i data sets'%(len(headings0),len(headings1),len(normHeadings))) + raise Exception('trying to compare {} with {} normed by {} data sets'.format(len(headings0), + len(headings1), + len(normHeadings))) table0 = damask.ASCIItable(name=file0,readonly=True) table0.head_read() @@ -331,37 +334,34 @@ class Test(): table1.head_read() for i in xrange(dataLength): - key0 = {True :'1_%s', - False:'%s' }[length[i]>1]%headings0[i]['label'] - key1 = {True :'1_%s', - False:'%s' }[length[i]>1]%headings1[i]['label'] - normKey = {True :'1_%s', - False:'%s' }[normLength[i]>1]%normHeadings[i]['label'] + key0 = ('1_' if length[i]>1 else '') + headings0[i]['label'] + key1 = ('1_' if length[i]>1 else '') + headings1[i]['label'] + normKey = ('1_' if normLength[i]>1 else '') + normHeadings[i]['label'] if key0 not in table0.labels: - raise Exception('column %s not found in 1. table...\n'%key0) + raise Exception('column {} not found in 1. table...\n'.format(key0)) elif key1 not in table1.labels: - raise Exception('column %s not found in 2. table...\n'%key1) + raise Exception('column {} not found in 2. table...\n'.format(key1)) elif normKey not in table0.labels: - raise Exception('column %s not found in 1. table...\n'%normKey) + raise Exception('column {} not found in 1. table...\n'.format(normKey)) else: - column[0][i] = table0.labels.index(key0) # remember columns of requested data - column[1][i] = table1.labels.index(key1) # remember columns of requested data in second column - normColumn[i] = table0.labels.index(normKey) # remember columns of requested data in second column + column[0][i] = table0.labels.index(key0) + column[1][i] = table1.labels.index(key1) + normColumn[i] = table0.labels.index(normKey) line0 = 0 - while table0.data_read(): # read next data line of ASCII table + while table0.data_read(): # read next data line of ASCII table if line0 not in skipLines: for i in xrange(dataLength): myData = np.array(map(float,table0.data[column[0][i]:\ - column[0][i]+length[i]]),'d') + column[0][i]+length[i]]),'d') normData = np.array(map(float,table0.data[normColumn[i]:\ - normColumn[i]+normLength[i]]),'d') + normColumn[i]+normLength[i]]),'d') data[i] = np.append(data[i],np.reshape(myData,shape[i])) if normType == 'pInf': norm[i] = np.append(norm[i],np.max(np.abs(normData))) else: norm[i] = np.append(norm[i],np.linalg.norm(np.reshape(normData,normShape[i]),normType)) - line0 +=1 + line0 += 1 for i in xrange(dataLength): if not perLine: norm[i] = [np.max(norm[i]) for j in xrange(line0-len(skipLines))] @@ -370,12 +370,12 @@ class Test(): norm[i] = [1.0 for j in xrange(line0-len(skipLines))] absTol[i] = True if perLine: - logging.warning('At least one norm of %s in 1. table is 0.0, using absolute tolerance'%headings0[i]['label']) + logging.warning('At least one norm of {} in 1. table is 0.0, using absolute tolerance'.format(headings0[i]['label'])) else: - logging.warning('Maximum norm of %s in 1. table is 0.0, using absolute tolerance'%headings0[i]['label']) + logging.warning('Maximum norm of {} in 1. table is 0.0, using absolute tolerance'.format(headings0[i]['label'])) line1 = 0 - while table1.data_read(): # read next data line of ASCII table + while table1.data_read(): # read next data line of ASCII table if line1 not in skipLines: for i in xrange(dataLength): myData = np.array(map(float,table1.data[column[1][i]:\ @@ -384,21 +384,25 @@ class Test(): norm[i][line1-len(skipLines)]) line1 +=1 - if (line0 != line1): raise Exception('found %s lines in 1. table and %s in 2. table'%(line0,line1)) + if (line0 != line1): raise Exception('found {} lines in 1. table but {} in 2. table'.format(line0,line1)) logging.info(' ********') for i in xrange(dataLength): if absTol[i]: - logging.info(' * maximum absolute error %e for %s and %s'%(maxError[i],headings0[i]['label'],headings1[i]['label'])) + logging.info(' * maximum absolute error {} between {} and {}'.format(maxError[i], + headings0[i]['label'], + headings1[i]['label'])) else: - logging.info(' * maximum relative error %e for %s and %s'%(maxError[i],headings0[i]['label'],headings1[i]['label'])) + logging.info(' * maximum relative error {} between {} and {}'.format(maxError[i], + headings0[i]['label'], + headings1[i]['label'])) logging.info(' ********') return maxError def compare_TablesStatistically(self, - files = [None,None], # list of file names - columns = [None], # list of list of column labels (per file) + files = [None,None], # list of file names + columns = [None], # list of list of column labels (per file) meanTol = 1.0e-4, stdTol = 1.0e-6, preFilter = 1.0e-9): @@ -407,18 +411,18 @@ class Test(): threshold can be used to ignore small values (a negative number disables this feature) """ - if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested + if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested files = [str(files)] tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files] for table in tables: table.head_read() - columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files - columns = columns[:len(files)] # truncate to same length as files + columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files + columns = columns[:len(files)] # truncate to same length as files for i,column in enumerate(columns): - if column is None: columns[i] = tables[i].labels # if no column is given, read all + if column is None: columns[i] = tables[i].labels # if no column is given, read all logging.info('comparing ASCIItables statistically') for i in xrange(len(columns)): @@ -428,7 +432,7 @@ class Test(): ) logging.info(files[i]+':'+','.join(columns[i])) - if len(files) < 2: return True # single table is always close to itself... + if len(files) < 2: return True # single table is always close to itself... data = [] for table,labels in zip(tables,columns): @@ -443,16 +447,16 @@ class Test(): normedDelta = np.where(normBy>preFilter,delta/normBy,0.0) mean = np.amax(np.abs(np.mean(normedDelta,0))) std = np.amax(np.std(normedDelta,0)) - logging.info('mean: %f'%mean) - logging.info('std: %f'%std) + logging.info('mean: {:f}'.format(mean)) + logging.info('std: {:f}'.format(std)) return (mean0.0, maximum, 1) # do not devide by zero for empty columns + maximum = np.where(maximum >0.0, maximum, 1) # avoid div by zero for empty columns for i in xrange(len(data)): data[i] /= maximum mask = np.zeros_like(table.data,dtype='bool') for table in data: - mask |= np.where(np.abs(table) 1])) + logging.critical(('The test' if len(self.variants) == 1 else 'All {} tests'.format(len(self.variants))) + ' passed') logging.critical('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') return 0 if culprit == -1: logging.warning('Warning: Could not start test') return 0 else: - logging.critical(' ********\n * Test %i failed...\n ********'%(culprit)) + logging.critical(' ********\n * Test {} failed...\n ********'.format(culprit)) logging.critical('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') return culprit From 9cfadb251adbec996e5d531d8d03ace48c995175 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 22 Mar 2016 15:40:21 +0100 Subject: [PATCH 092/134] Initialize to J2 bevavior --- code/plastic_isotropic.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/plastic_isotropic.f90 b/code/plastic_isotropic.f90 index da4198007..563952122 100644 --- a/code/plastic_isotropic.f90 +++ b/code/plastic_isotropic.f90 @@ -55,7 +55,7 @@ module plastic_isotropic tausat_SinhFitC, & tausat_SinhFitD logical :: & - dilatation + dilatation = .false. end type type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance) From 0840a5f42e2424361888bbf22a032674f756263a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 22 Mar 2016 20:52:02 -0400 Subject: [PATCH 093/134] modernized orientation treatment and adopted slip systems from lattice.f90 --- processing/post/addSchmidfactors.py | 544 ++++++++++++---------------- 1 file changed, 222 insertions(+), 322 deletions(-) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index e4837d54b..2b9b4eeb1 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -9,363 +9,263 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -slipnormal_temp = [ - [0,0,0,1], - [0,0,0,1], - [0,0,0,1], - [0,1,-1,0], - [-1,0,1,0], - [1,-1,0,0], - [0,1,-1,1], - [-1,1,0,1], - [-1,0,1,1], - [0,-1,1,1], - [1,-1,0,1], - [1,0,-1,1], - [0,1,-1,1], - [0,1,-1,1], - [-1,1,0,1], - [-1,1,0,1], - [-1,0,1,1], - [-1,0,1,1], - [0,-1,1,1], - [0,-1,1,1], - [1,-1,0,1], - [1,-1,0,1], - [1,0,-1,1], - [1,0,-1,1], - ] - -slipdirection_temp = [ - [2,-1,-1,0], - [-1,2,-1,0], - [-1,-1,2,0], - [2,-1,-1,0], - [-1,2,-1,0], - [-1,-1,2,0], - [2,-1,-1,0], - [1,1,-2,0], - [-1,2,-1,0], - [-2,1,1,0], - [-1,-1,2,0], - [1,-2,1,0], - [-1,2,-1,3], - [1,1,-2,3], - [-2,1,1,3], - [-1,2,-1,3], - [-1,-1,2,3], - [-2,1,1,3], - [1,-2,1,3], - [-1,-1,2,3], - [2,-1,-1,3], - [1,-2,1,3], - [1,1,-2,3], - [2,-1,-1,3], - ] - -# slip normals and directions according to cpfem implementation -Nslipsystems = {'fcc': 12, 'bcc': 24, 'hex': 24} -slipnormal = { \ - 'fcc': [ - [1,1,1], - [1,1,1], - [1,1,1], - [-1,-1,1], - [-1,-1,1], - [-1,-1,1], - [1,-1,-1], - [1,-1,-1], - [1,-1,-1], - [-1,1,-1], - [-1,1,-1], - [-1,1,-1], - ], - 'bcc': [ - [0,1,1], - [0,1,1], - [0,-1,1], - [0,-1,1], - [1,0,1], - [1,0,1], - [-1,0,1], - [-1,0,1], - [1,1,0], - [1,1,0], - [-1,1,0], - [-1,1,0], - [2,1,1], - [-2,1,1], - [2,-1,1], - [2,1,-1], - [1,2,1], - [-1,2,1], - [1,-2,1], - [1,2,-1], - [1,1,2], - [-1,1,2], - [1,-1,2], - [1,1,-2], - ], - 'hex': [ # these are dummy numbers and are recalculated based on the above hex real slip systems. - [1,1,0], - [1,1,0], - [1,0,1], - [1,0,1], - [0,1,1], - [0,1,1], - [1,-1,0], - [1,-1,0], - [-1,0,1], - [-1,0,1], - [0,-1,1], - [0,-1,1], - [2,-1,1], - [1,-2,-1], - [1,1,2], - [2,1,1], - [1,2,-1], - [1,-1,2], - [2,1,-1], - [1,2,1], - [1,-1,-2], - [2,-1,-1], - [1,-2,1], - [1,1,-2], - ], - } -slipdirection = { \ - 'fcc': [ - [0,1,-1], - [-1,0,1], - [1,-1,0], - [0,-1,-1], - [1,0,1], - [-1,1,0], - [0,-1,1], - [-1,0,-1], - [1,1,0], - [0,1,1], - [1,0,-1], - [-1,-1,0], - ], - 'bcc': [ - [1,-1,1], - [-1,-1,1], - [1,1,1], - [-1,1,1], - [-1,1,1], - [-1,-1,1], - [1,1,1], - [1,-1,1], - [-1,1,1], - [-1,1,-1], - [1,1,1], - [1,1,-1], - [-1,1,1], - [1,1,1], - [1,1,-1], - [1,-1,1], - [1,-1,1], - [1,1,-1], - [1,1,1], - [-1,1,1], - [1,1,-1], - [1,-1,1], - [-1,1,1], - [1,1,1], - ], - 'hex': [ # these are dummy numbers and are recalculated based on the above hex real slip systems. - [-1,1,1], - [1,-1,1], - [-1,-1,1], - [-1,1,1], - [-1,-1,1], - [1,-1,1], - [1,1,1], - [-1,-1,1], - [1,-1,1], - [1,1,1], - [1,1,1], - [-1,1,1], - [1,1,-1], - [1,1,-1], - [1,1,-1], - [1,-1,-1], - [1,-1,-1], - [1,-1,-1], - [1,-1,1], - [1,-1,1], - [1,-1,1], - [1,1,1], - [1,1,1], - [1,1,1], - ], - } - -def applyEulers(phi1,Phi,phi2,x): - """transform x given in crystal coordinates to xbar returned in lab coordinates for Euler angles phi1,Phi,phi2""" - eulerRot = [[ math.cos(phi1)*math.cos(phi2) - math.cos(Phi)*math.sin(phi1)*math.sin(phi2), - -math.cos(phi1)*math.sin(phi2) - math.cos(Phi)*math.cos(phi2)*math.sin(phi1), - math.sin(Phi)*math.sin(phi1) - ], - [ math.cos(phi2)*math.sin(phi1) + math.cos(Phi)*math.cos(phi1)*math.sin(phi2), - math.cos(Phi)*math.cos(phi1)*math.cos(phi2) - math.sin(phi1)*math.sin(phi2), - -math.sin(Phi)*math.cos(phi1) - ], - [ math.sin(Phi)*math.sin(phi2), - math.sin(Phi)*math.cos(phi2), - math.cos(Phi) - ]] - - xbar = [0,0,0] - if len(x) == 3: - for i in range(3): - xbar[i] = sum([eulerRot[i][j]*x[j] for j in range(3)]) - return xbar - -def normalize(x): - - norm = math.sqrt(sum([x[i]*x[i] for i in range(len(x))])) - - return [x[i]/norm for i in range(len(x))] +slipSystems = { +'fcc': + np.array([ + # Slip direction Plane normal + [ 0, 1,-1, 1, 1, 1, ], + [-1, 0, 1, 1, 1, 1, ], + [ 1,-1, 0, 1, 1, 1, ], + [ 0,-1,-1, -1,-1, 1, ], + [ 1, 0, 1, -1,-1, 1, ], + [-1, 1, 0, -1,-1, 1, ], + [ 0,-1, 1, 1,-1,-1, ], + [-1, 0,-1, 1,-1,-1, ], + [ 1, 1, 0, 1,-1,-1, ], + [ 0, 1, 1, -1, 1,-1, ], + [ 1, 0,-1, -1, 1,-1, ], + [-1,-1, 0, -1, 1,-1, ], + ],'f'), +'bcc': + np.array([ + # Slip system <111>{110} + [ 1,-1, 1, 0, 1, 1, ], + [-1,-1, 1, 0, 1, 1, ], + [ 1, 1, 1, 0,-1, 1, ], + [-1, 1, 1, 0,-1, 1, ], + [-1, 1, 1, 1, 0, 1, ], + [-1,-1, 1, 1, 0, 1, ], + [ 1, 1, 1, -1, 0, 1, ], + [ 1,-1, 1, -1, 0, 1, ], + [-1, 1, 1, 1, 1, 0, ], + [-1, 1,-1, 1, 1, 0, ], + [ 1, 1, 1, -1, 1, 0, ], + [ 1, 1,-1, -1, 1, 0, ], + # Slip system <111>{112} + [-1, 1, 1, 2, 1, 1, ], + [ 1, 1, 1, -2, 1, 1, ], + [ 1, 1,-1, 2,-1, 1, ], + [ 1,-1, 1, 2, 1,-1, ], + [ 1,-1, 1, 1, 2, 1, ], + [ 1, 1,-1, -1, 2, 1, ], + [ 1, 1, 1, 1,-2, 1, ], + [-1, 1, 1, 1, 2,-1, ], + [ 1, 1,-1, 1, 1, 2, ], + [ 1,-1, 1, -1, 1, 2, ], + [-1, 1, 1, 1,-1, 2, ], + [ 1, 1, 1, 1, 1,-2, ], + ],'f'), +'hex': + np.array([ + # Basal systems <11.0>{00.1} (independent of c/a-ratio, Bravais notation (4 coordinate base)) + [ 2, -1, -1, 0, 0, 0, 0, 1, ], + [-1, 2, -1, 0, 0, 0, 0, 1, ], + [-1, -1, 2, 0, 0, 0, 0, 1, ], + # 1st type prismatic systems <11.0>{10.0} (independent of c/a-ratio) + [ 2, -1, -1, 0, 0, 1, -1, 0, ], + [-1, 2, -1, 0, -1, 0, 1, 0, ], + [-1, -1, 2, 0, 1, -1, 0, 0, ], + # 2nd type prismatic systems <10.0>{11.0} -- a slip; plane normals independent of c/a-ratio + [ 0, 1, -1, 0, 2, -1, -1, 0, ], + [-1, 0, 1, 0, -1, 2, -1, 0, ], + [ 1, -1, 0, 0, -1, -1, 2, 0, ], + # 1st type 1st order pyramidal systems <11.0>{-11.1} -- plane normals depend on the c/a-ratio + [ 2, -1, -1, 0, 0, 1, -1, 1, ], + [-1, 2, -1, 0, -1, 0, 1, 1, ], + [-1, -1, 2, 0, 1, -1, 0, 1, ], + [ 1, 1, -2, 0, -1, 1, 0, 1, ], + [-2, 1, 1, 0, 0, -1, 1, 1, ], + [ 1, -2, 1, 0, 1, 0, -1, 1, ], + # pyramidal system: c+a slip <11.3>{-10.1} -- plane normals depend on the c/a-ratio + [ 2, -1, -1, 3, -1, 1, 0, 1, ], + [ 1, -2, 1, 3, -1, 1, 0, 1, ], + [-1, -1, 2, 3, 1, 0, -1, 1, ], + [-2, 1, 1, 3, 1, 0, -1, 1, ], + [-1, 2, -1, 3, 0, -1, 1, 1, ], + [ 1, 1, -2, 3, 0, -1, 1, 1, ], + [-2, 1, 1, 3, 1, -1, 0, 1, ], + [-1, 2, -1, 3, 1, -1, 0, 1, ], + [ 1, 1, -2, 3, -1, 0, 1, 1, ], + [ 2, -1, -1, 3, -1, 0, 1, 1, ], + [ 1, -2, 1, 3, 0, 1, -1, 1, ], + [-1, -1, 2, 3, 0, 1, -1, 1, ], + # pyramidal system: c+a slip <11.3>{-1-1.2} -- as for hexagonal ice (Castelnau et al. 1996, similar to twin system found below) + [ 2, -1, -1, 3, -2, 1, 1, 2, ], # sorted according to similar twin system + [-1, 2, -1, 3, 1, -2, 1, 2, ], # <11.3>{-1-1.2} shear = 2((c/a)^2-2)/(3 c/a) + [-1, -1, 2, 3, 1, 1, -2, 2, ], + [-2, 1, 1, 3, 2, -1, -1, 2, ], + [ 1, -2, 1, 3, -1, 2, -1, 2, ], + [ 1, 1, -2, 3, -1, -1, 2, 2, ], + ],'f'), +} # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add columns listing Schmid factors (and optional trace vector of selected system) for given Euler angles. +Add RGB color value corresponding to TSL-OIM scheme for inverse pole figures. """, version = scriptID) +latticeChoices = ('fcc','bcc','hex') parser.add_option('-l','--lattice', - dest='lattice', type='choice', choices=('fcc','bcc','hex'), metavar='string', - help="type of lattice structure [%default] {fcc,bcc',hex}") -parser.add_option('--direction', - dest='forcedirection', type='int', nargs=3, metavar='int int int', - help='force direction in lab coordinates %default') -parser.add_option('-n','--normal', - dest='stressnormal', type='int', nargs=3, metavar='int int int', - help='stress plane normal in lab coordinates ') -parser.add_option('--trace', - dest='traceplane', type='int', nargs=3, metavar='int int int', - help='normal (in lab coordinates) of plane on which the plane trace of the Schmid factor(s) is reported') + dest = 'lattice', type = 'choice', choices = latticeChoices, metavar='string', + help = 'type of lattice structure [%default] {}'.format(latticeChoices)) parser.add_option('--covera', - dest='CoverA', type='float', metavar='float', - help='C over A ratio for hexagonal systems') -parser.add_option('-r','--rank', - dest='rank', type='int', nargs=3, metavar='int int int', - help="report trace of r'th highest Schmid factor [%default]") + dest = 'CoverA', type = 'float', metavar = 'float', + help = 'C over A ratio for hexagonal systems') +parser.add_option('-f', '--force', + dest = 'force', + type = 'float', nargs = 3, metavar = 'float float float', + help = 'force direction in lab frame [%default]') +parser.add_option('-n', '--normal', + dest = 'normal', + type = 'float', nargs = 3, metavar = 'float float float', + help = 'stress plane normal in lab frame [%default]') parser.add_option('-e', '--eulers', - dest='eulers', metavar='string', - help='Euler angles label') + dest = 'eulers', + type = 'string', metavar = 'string', + help = 'Euler angles label') parser.add_option('-d', '--degrees', - dest='degrees', action='store_true', - help='Euler angles are given in degrees [%default]') -parser.set_defaults(lattice = 'fcc') -parser.set_defaults(forcedirection = [0, 0, 1]) -parser.set_defaults(stressnormal = None) -parser.set_defaults(traceplane = None) -parser.set_defaults(rank = 0) -parser.set_defaults(CoverA = 1.587) -parser.set_defaults(eulers = 'eulerangles') + dest = 'degrees', + action = 'store_true', + help = 'Euler angles are given in degrees [%default]') +parser.add_option('-m', '--matrix', + dest = 'matrix', + type = 'string', metavar = 'string', + help = 'orientation matrix label') +parser.add_option('-a', + dest = 'a', + type = 'string', metavar = 'string', + help = 'crystal frame a vector label') +parser.add_option('-b', + dest = 'b', + type = 'string', metavar = 'string', + help = 'crystal frame b vector label') +parser.add_option('-c', + dest = 'c', + type = 'string', metavar = 'string', + help = 'crystal frame c vector label') +parser.add_option('-q', '--quaternion', + dest = 'quaternion', + type = 'string', metavar = 'string', + help = 'quaternion label') -(options,filenames) = parser.parse_args() +parser.set_defaults(force = [0.0,0.0,1.0], + normal = None, + lattice = latticeChoices[0], + CoverA = math.sqrt(8./3.), + degrees = False, + ) -options.forcedirection = normalize(options.forcedirection) -if options.stressnormal: - if abs(sum([options.forcedirection[i] * options.stressnormal[i] for i in range(3)])) < 1e-3: - options.stressnormal = normalize(options.stressnormal) - else: - parser.error('stress plane normal not orthogonal to force direction') -else: - options.stressnormal = options.forcedirection -if options.traceplane: - options.traceplane = normalize(options.traceplane) -options.rank = min(options.rank,Nslipsystems[options.lattice]) - -datainfo = { # list of requested labels per datatype - 'vector': {'len':3, - 'label':[]}, - } - -datainfo['vector']['label'] += [options.eulers] +(options, filenames) = parser.parse_args() toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians -# Convert 4 Miller indices notation of hex to orthogonal 3 Miller indices notation -if options.lattice=='hex': - for i in range(Nslipsystems[options.lattice]): - slipnormal[options.lattice][i][0]=slipnormal_temp[i][0] - slipnormal[options.lattice][i][1]=(slipnormal_temp[i][0]+2.0*slipnormal_temp[i][1])/math.sqrt(3.0) - slipnormal[options.lattice][i][2]=slipnormal_temp[i][3]/options.CoverA - slipdirection[options.lattice][i][0]=slipdirection_temp[i][0]*1.5 # direction [uvtw]->[3u/2 (u+2v)*sqrt(3)/2 w*(c/a)] , - slipdirection[options.lattice][i][1]=(slipdirection_temp[i][0]+2.0*slipdirection_temp[i][1])*(0.5*math.sqrt(3.0)) - slipdirection[options.lattice][i][2]=slipdirection_temp[i][3]*options.CoverA - for i in range(Nslipsystems[options.lattice]): - slipnormal[options.lattice][i]=normalize(slipnormal[options.lattice][i]) - slipdirection[options.lattice][i]=normalize(slipdirection[options.lattice][i]) +force = np.array(options.force) +force /= np.linalg.norm(force) -# --- loop over input files ------------------------------------------------------------------------- +if options.normal: + damask.util.croak('got normal') + normal = np.array(options.normal) + normal /= np.linalg.norm(normal) + if abs(np.dot(force,normal)) > 1e-3: + parser.error('stress plane normal not orthogonal to force direction') +else: + normal = force + +input = [options.eulers is not None, + options.a is not None and \ + options.b is not None and \ + options.c is not None, + options.matrix is not None, + options.quaternion is not None, + ] + +if np.sum(input) != 1: parser.error('needs exactly one input format.') + +(label,dim,inputtype) = [(options.eulers,3,'eulers'), + ([options.a,options.b,options.c],[3,3,3],'frame'), + (options.matrix,9,'matrix'), + (options.quaternion,4,'quaternion'), + ][np.where(input)[0][0]] # select input label that was requested + +c_direction = np.zeros((len(slipSystems[options.lattice]),3),'f') +c_normal = np.zeros_like(c_direction) + + +if options.lattice in latticeChoices[:2]: + c_direction = slipSystems[options.lattice][:,:3] + c_normal = slipSystems[options.lattice][:,3:] +elif options.lattice == latticeChoices[2]: + # convert 4 Miller index notation of hex to orthogonal 3 Miller index notation + for i in xrange(len(c_direction)): + c_direction[i] = np.array([slipSystems['hex'][i,0]*1.5, + (slipSystems['hex'][i,0] + 2.*slipSystems['hex'][i,1])*0.5*np.sqrt(3), + slipSystems['hex'][i,3]*options.CoverA, + ]) + c_normal[i] = np.array([slipSystems['hex'][i,4], + (slipSystems['hex'][i,4] + 2.*slipSystems['hex'][i,5])/np.sqrt(3), + slipSystems['hex'][i,7]/options.CoverA, + ]) + +c_direction /= np.tile(np.linalg.norm(c_direction,axis=1),(3,1)).T +c_normal /= np.tile(np.linalg.norm(c_normal ,axis=1),(3,1)).T + +# --- loop over input files ------------------------------------------------------------------------ if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name,buffered = False) - except: - continue + try: table = damask.ASCIItable(name = name, + buffered = False) + except: continue damask.util.report(scriptName,name) - table.head_read() # read ASCII header info - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) +# ------------------------------------------ read header ------------------------------------------ - key = '1_%s'%datainfo['vector']['label'][0] - if key not in table.labels: - file['croak'].write('column %s not found...\n'%key) + table.head_read() + +# ------------------------------------------ sanity checks ---------------------------------------- + + if not np.all(table.label_dimension(label) == dim): + damask.util.croak('input {} does not have dimension {}.'.format(label,dim)) + table.close(dismiss = True) # close ASCIItable and remove empty file continue - else: - column = table.labels.index(key) # remember columns of requested data + + column = table.label_index(label) # ------------------------------------------ assemble header --------------------------------------- - table.labels_append(['%i_S(%i_%i_%i)[%i_%i_%i]'%(i+1, - slipnormal[options.lattice][i][0], - slipnormal[options.lattice][i][1], - slipnormal[options.lattice][i][2], - slipdirection[options.lattice][i][0], - slipdirection[options.lattice][i][1], - slipdirection[options.lattice][i][2], - ) for i in range(Nslipsystems[options.lattice])]) - - if options.traceplane: - if options.rank > 0: - table.labels_append('trace_x trace_y trace_z system') - else: - table.labels_append(['(%i)tx\tty\ttz'%(i+1) for i in range(Nslipsystems[options.lattice])]) + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) + table.labels_append(['{id}_S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]({normal[0]:.1g}_{normal[1]:.1g}_{normal[2]:.1g})'\ + .format( id = i+1, + normal = theNormal, + direction = theDirection, + ) for i,(theNormal,theDirection) in enumerate(zip(c_normal,c_direction))]) table.head_write() # ------------------------------------------ process data ------------------------------------------ + outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table - [phi1,Phi,phi2] = Eulers=toRadians*np.array(map(\ - float,table.data[column:column+datainfo['vector']['len']])) - S = [ sum( [applyEulers(phi1,Phi,phi2,normalize( \ - slipnormal[options.lattice][slipsystem]))[i]*options.stressnormal[i] for i in range(3)] ) * \ - sum( [applyEulers(phi1,Phi,phi2,normalize( \ - slipdirection[options.lattice][slipsystem]))[i]*options.forcedirection[i] for i in range(3)] ) \ - for slipsystem in range(Nslipsystems[options.lattice]) ] - table.data_append(S) - if options.traceplane: - trace = [np.cross(options.traceplane,applyEulers(phi1,Phi,phi2,normalize(slipnormal[options.lattice][slipsystem]))) \ - for slipsystem in range(Nslipsystems[options.lattice]) ] - if options.rank == 0: - table.data_append('\t'.join(map(lambda x:'%f\t%f\t%f'%(x[0],x[1],x[2]),trace))) - elif options.rank > 0: - SabsSorted = sorted([(abs(S[i]),i) for i in range(len(S))]) - table.data_append('\t'.join(map(str,trace[SabsSorted[-options.rank][1]])) + '\t%i'%(1+SabsSorted[-options.rank][1])) + if inputtype == 'eulers': + o = damask.Orientation(Eulers = np.array(map(float,table.data[column:column+3]))*toRadians,) + elif inputtype == 'matrix': + o = damask.Orientation(matrix = np.array(map(float,table.data[column:column+9])).reshape(3,3).transpose(),) + elif inputtype == 'frame': + o = damask.Orientation(matrix = np.array(map(float,table.data[column[0]:column[0]+3] + \ + table.data[column[1]:column[1]+3] + \ + table.data[column[2]:column[2]+3])).reshape(3,3),) + elif inputtype == 'quaternion': + o = damask.Orientation(quaternion = np.array(map(float,table.data[column:column+4])),) + + rotForce = o.quaternion.conjugated() * force + rotNormal = o.quaternion.conjugated() * normal + table.data_append(np.abs(np.sum(c_direction*rotForce,axis=1) * np.sum(c_normal*rotNormal,axis=1))) outputAlive = table.data_write() # output processed line -# ------------------------------------------ output finalization ----------------------------------- +# ------------------------------------------ output finalization ----------------------------------- - table.close() # close input ASCII table (works for stdin) + table.close() # close ASCII tables From 143a868dada09d816fdf661468edc9f2af19f19e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 23 Mar 2016 11:05:00 +0100 Subject: [PATCH 094/134] files resulting from compilation should not be part of the repository --- code/.gitignore | 1 + lib/damask/.gitignore | 1 + 2 files changed, 2 insertions(+) diff --git a/code/.gitignore b/code/.gitignore index 6184a3d0a..bc33403b4 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -1,2 +1,3 @@ DAMASK_marc*.f90 quit__genmod.f90 +*.marc diff --git a/lib/damask/.gitignore b/lib/damask/.gitignore index fd736fe35..00feaa11f 100644 --- a/lib/damask/.gitignore +++ b/lib/damask/.gitignore @@ -1 +1,2 @@ core.so +corientation.so From 900d2f7bf28758199f96579e903a8c38c64e5b74 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 23 Mar 2016 11:05:36 +0100 Subject: [PATCH 095/134] output follows damask.croak syntax --- processing/pre/seeds_fromDistribution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/processing/pre/seeds_fromDistribution.py b/processing/pre/seeds_fromDistribution.py index dd813e334..5d443a7f9 100755 --- a/processing/pre/seeds_fromDistribution.py +++ b/processing/pre/seeds_fromDistribution.py @@ -135,8 +135,8 @@ class myThread (threading.Thread): bestSeedsUpdate = time.time() # save time of better fit damask.util.croak('Thread %i: Better match (%i bins, %6.4f --> %6.4f)' %(self.threadID,i+1,target[i]['error'],currentError[i])) - damask.util.croak(' target: ',target[i]['histogram']) - damask.util.croak(' best: ',currentHist[i]) + damask.util.croak(' target: %s'%np.array_str(target[i]['histogram'])) + damask.util.croak(' best: %s'%np.array_str(currentHist[i])) currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier) perturbedSeedsVFile.reset() bestSeedsVFile.close() From d1dc976eda1ecade2904d7d216e8d9605f83b7aa Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 23 Mar 2016 12:15:03 +0100 Subject: [PATCH 096/134] missing initializers (Intel compiler does not initialize to 0) --- code/plastic_isotropic.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/plastic_isotropic.f90 b/code/plastic_isotropic.f90 index 563952122..81d3055cf 100644 --- a/code/plastic_isotropic.f90 +++ b/code/plastic_isotropic.f90 @@ -50,10 +50,10 @@ module plastic_isotropic a, & aTolFlowstress, & aTolShear , & - tausat_SinhFitA, & - tausat_SinhFitB, & - tausat_SinhFitC, & - tausat_SinhFitD + tausat_SinhFitA=0.0_pReal, & + tausat_SinhFitB=0.0_pReal, & + tausat_SinhFitC=0.0_pReal, & + tausat_SinhFitD=0.0_pReal logical :: & dilatation = .false. end type From 809f03bef555b061333d30b6f3a65f2e9c88d297 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 23 Mar 2016 17:02:51 +0100 Subject: [PATCH 097/134] new printing for python3 and corrected help --- processing/post/addSchmidfactors.py | 4 ++-- processing/pre/seeds_fromDistribution.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 2b9b4eeb1..71040cbdc 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -104,7 +104,7 @@ slipSystems = { # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add RGB color value corresponding to TSL-OIM scheme for inverse pole figures. +Add columns listing Schmid factors (and optional trace vector of selected system) for given Euler angles. """, version = scriptID) @@ -152,7 +152,7 @@ parser.add_option('-q', '--quaternion', type = 'string', metavar = 'string', help = 'quaternion label') -parser.set_defaults(force = [0.0,0.0,1.0], +parser.set_defaults(force = (0.0,0.0,1.0), normal = None, lattice = latticeChoices[0], CoverA = math.sqrt(8./3.), diff --git a/processing/pre/seeds_fromDistribution.py b/processing/pre/seeds_fromDistribution.py index 5d443a7f9..d2b51519d 100755 --- a/processing/pre/seeds_fromDistribution.py +++ b/processing/pre/seeds_fromDistribution.py @@ -133,10 +133,10 @@ class myThread (threading.Thread): break elif currentError[i] < target[i]['error']: # better fit bestSeedsUpdate = time.time() # save time of better fit - damask.util.croak('Thread %i: Better match (%i bins, %6.4f --> %6.4f)' - %(self.threadID,i+1,target[i]['error'],currentError[i])) - damask.util.croak(' target: %s'%np.array_str(target[i]['histogram'])) - damask.util.croak(' best: %s'%np.array_str(currentHist[i])) + damask.util.croak('Thread {:d}: Better match ({:d} bins, {:6.4f} --> {:6.4f})'\ + .format(self.threadID,i+1,target[i]['error'],currentError[i])) + damask.util.croak(' target: '+np.array_str(target[i]['histogram'])) + damask.util.croak(' best: '+np.array_str(currentHist[i])) currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier) perturbedSeedsVFile.reset() bestSeedsVFile.close() @@ -149,7 +149,7 @@ class myThread (threading.Thread): for j in xrange(nMicrostructures): # save new errors for all bins target[j]['error'] = currentError[j] if myMatch > match: # one or more new bins have no deviation - damask.util.croak( 'Stage %i cleared'%(myMatch)) + damask.util.croak( 'Stage {:d} cleared'.format(myMatch)) match=myMatch sys.stdout.flush() break @@ -164,8 +164,8 @@ class myThread (threading.Thread): target[j]['error'] = currentError[j] randReset = True else: #--- not all grains are tessellated - damask.util.croak('Thread %i: Microstructure mismatch (%i microstructures mapped)' - %(self.threadID,myNmicrostructures)) + damask.util.croak('Thread {:d}: Microstructure mismatch ({:d} microstructures mapped)'\ + .format(self.threadID,myNmicrostructures)) randReset = True @@ -243,7 +243,7 @@ if os.path.isfile(os.path.splitext(options.seedFile)[0]+'.seeds'): else: bestSeedsVFile.write(damask.util.execute('seeds_fromRandom'+\ ' -g '+' '.join(map(str, options.grid))+\ - ' -r %i'%options.randomSeed+\ + ' -r {:d}'.format(options.randomSeed)+\ ' -N '+str(nMicrostructures))[0]) bestSeedsUpdate = time.time() @@ -279,7 +279,7 @@ if options.maxseeds < 1: else: maxSeeds = options.maxseeds -if match >0: damask.util.croak('Stage %i cleared'%match) +if match >0: damask.util.croak('Stage {:d} cleared'.format(match)) sys.stdout.flush() initialGeomVFile.close() From c24a9f824440aa5eacc8279339a2b433f5bcf44e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 25 Mar 2016 12:47:58 +0100 Subject: [PATCH 098/134] should be in the root directory --- .gitattributes | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..8035e26a7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# from https://help.github.com/articles/dealing-with-line-endings/ +# +# always use LF, even if the files are edited on windows, they need to be compiled/used on unix +* text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary From da89da6c21ce5ddf7003789a15b51b6c8a70d120 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 26 Mar 2016 19:55:44 +0100 Subject: [PATCH 099/134] checking for MPI errors --- code/DAMASK_spectral.f90 | 16 +++++++++++++--- code/IO.f90 | 4 +++- code/prec.f90 | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index e72cd3dec..22c825bd3 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -13,7 +13,8 @@ program DAMASK_spectral pInt, & pLongInt, & pReal, & - tol_math_check + tol_math_check, & + dNeq use DAMASK_interface, only: & DAMASK_interface_init, & loadCaseFile, & @@ -339,7 +340,7 @@ program DAMASK_spectral reshape(spread(tol_math_check,1,9),[ 3,3]))& .or. abs(math_det33(loadCases(currentLoadCase)%rotation)) > & 1.0_pReal + tol_math_check) errorID = 846_pInt ! given rotation matrix contains strain - if (any(loadCases(currentLoadCase)%rotation /= math_I3)) & + if (any(dNeq(loadCases(currentLoadCase)%rotation, math_I3))) & write(6,'(2x,a,/,3(3(3x,f12.7,1x)/))',advance='no') 'rotation of loadframe:',& math_transpose33(loadCases(currentLoadCase)%rotation) if (loadCases(currentLoadCase)%time < 0.0_pReal) errorID = 834_pInt ! negative time increment @@ -431,9 +432,13 @@ program DAMASK_spectral MPI_INFO_NULL, & resUnit, & ierr) + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_open') call MPI_file_get_position(resUnit,fileOffset,ierr) ! get offset from header + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_get_position') fileOffset = fileOffset + sum(outputSize(1:worldrank)) ! offset of my process in file (header + processes before me) + write(6,*) fileOffset call MPI_file_seek (resUnit,fileOffset,MPI_SEEK_SET,ierr) + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_seek') if (.not. appendToOutFile) then ! if not restarting, write 0th increment do i=1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output @@ -443,8 +448,10 @@ program DAMASK_spectral [(outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults]), & (outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults,& MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_write') enddo fileOffset = fileOffset + sum(outputSize) ! forward to current file position + write(6,*) fileOffset if (worldrank == 0) & write(6,'(1/,a)') ' ... writing initial configuration to file ........................' endif @@ -643,15 +650,18 @@ program DAMASK_spectral write(6,'(1/,a)') ' ... writing results to file ......................................' call materialpoint_postResults() call MPI_file_seek (resUnit,fileOffset,MPI_SEEK_SET,ierr) + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_seek') do i=1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output - outputIndex=int([(i-1_pInt)*((maxByteOut/pReal)/materialpoint_sizeResults)+1_pInt, & + outputIndex=int([(i-1_pInt)*((maxByteOut/pReal)/materialpoint_sizeResults)+1_pInt, & min(i*((maxByteOut/pReal)/materialpoint_sizeResults),size(materialpoint_results,3))],pLongInt) call MPI_file_write(resUnit,reshape(materialpoint_results(:,:,outputIndex(1):outputIndex(2)),& [(outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults]), & (outputIndex(2)-outputIndex(1)+1)*materialpoint_sizeResults,& MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_write') enddo fileOffset = fileOffset + sum(outputSize) ! forward to current file position + write(6,*) fileOffset endif if( loadCases(currentLoadCase)%restartFrequency > 0_pInt .and. & ! at frequency of writing restart information set restart parameter for FEsolving mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0_pInt) then ! first call to CPFEM_general will write? diff --git a/code/IO.f90 b/code/IO.f90 index 57eb23cb5..576514d81 100644 --- a/code/IO.f90 +++ b/code/IO.f90 @@ -1669,7 +1669,9 @@ subroutine IO_error(error_ID,el,ip,g,ext_msg) msg = 'unknown filter type selected' case (893_pInt) msg = 'PETSc: SNES_DIVERGED_FNORM_NAN' - + case (894_pInt) + msg = 'MPI error' + !------------------------------------------------------------------------------------------------- ! error messages related to parsing of Abaqus input file case (900_pInt) diff --git a/code/prec.f90 b/code/prec.f90 index efa0c76a3..e099c8964 100644 --- a/code/prec.f90 +++ b/code/prec.f90 @@ -113,7 +113,9 @@ module prec public :: & prec_init, & - prec_isNaN + prec_isNaN, & + dEq, & + dNeq contains From 0b1cd70e3336b6dd876617a80317389680cb9392 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 27 Mar 2016 09:15:47 +0200 Subject: [PATCH 100/134] size needs to use larger integer --- code/DAMASK_spectral.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index 22c825bd3..45451df08 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -148,7 +148,9 @@ program DAMASK_spectral MPI_file_seek, & MPI_file_get_position, & MPI_file_write, & - MPI_allreduce + MPI_abort, & + MPI_allreduce, & + PETScFinalize !-------------------------------------------------------------------------------------------------- ! init DAMASK (all modules) @@ -424,8 +426,9 @@ program DAMASK_spectral !-------------------------------------------------------------------------------------------------- ! prepare MPI parallel out (including opening of file) allocate(outputSize(worldsize), source = 0_MPI_OFFSET_KIND) - outputSize(worldrank+1) = int(size(materialpoint_results)*pReal,MPI_OFFSET_KIND) + outputSize(worldrank+1) = size(materialpoint_results,kind=MPI_OFFSET_KIND)*int(pReal,MPI_OFFSET_KIND) call MPI_allreduce(MPI_IN_PLACE,outputSize,worldsize,MPI_INT,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process + if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_allreduce') call MPI_file_open(PETSC_COMM_WORLD, & trim(getSolverWorkingDirectoryName())//trim(getSolverJobName())//'.spectralOut', & MPI_MODE_WRONLY + MPI_MODE_APPEND, & @@ -436,7 +439,6 @@ program DAMASK_spectral call MPI_file_get_position(resUnit,fileOffset,ierr) ! get offset from header if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_get_position') fileOffset = fileOffset + sum(outputSize(1:worldrank)) ! offset of my process in file (header + processes before me) - write(6,*) fileOffset call MPI_file_seek (resUnit,fileOffset,MPI_SEEK_SET,ierr) if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_seek') @@ -451,7 +453,6 @@ program DAMASK_spectral if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_write') enddo fileOffset = fileOffset + sum(outputSize) ! forward to current file position - write(6,*) fileOffset if (worldrank == 0) & write(6,'(1/,a)') ' ... writing initial configuration to file ........................' endif @@ -661,7 +662,6 @@ program DAMASK_spectral if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_file_write') enddo fileOffset = fileOffset + sum(outputSize) ! forward to current file position - write(6,*) fileOffset endif if( loadCases(currentLoadCase)%restartFrequency > 0_pInt .and. & ! at frequency of writing restart information set restart parameter for FEsolving mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0_pInt) then ! first call to CPFEM_general will write? @@ -708,7 +708,7 @@ program DAMASK_spectral enddo call utilities_destroy() - call PetscFinalize(ierr); CHKERRQ(ierr) + call PETScFinalize(ierr); CHKERRQ(ierr) if (notConvergedCounter > 0_pInt) call quit(3_pInt) ! error if some are not converged call quit(0_pInt) ! no complains ;) From 0d93a47c71be883c27afbeb518fd84f2a2d24d00 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 27 Mar 2016 13:32:08 -0400 Subject: [PATCH 101/134] Generate histogram of N bins in given data range. --- processing/post/histogram.py | 128 +++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 processing/post/histogram.py diff --git a/processing/post/histogram.py b/processing/post/histogram.py new file mode 100755 index 000000000..102170c86 --- /dev/null +++ b/processing/post/histogram.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 no BOM -*- + +import os,sys +import numpy as np +from optparse import OptionParser +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 [file[s]]', description = """ +Generate histogram of N bins in given data range. + +""", version = scriptID) + +parser.add_option('-d','--data', + dest = 'data', + type = 'string', metavar = 'string', + help = 'column heading for data') +parser.add_option('--range', + dest = 'range', + type = 'float', nargs = 2, metavar = 'float float', + help = 'data range of histogram [min - max]') +parser.add_option('-N', + dest = 'N', + type = 'int', metavar = 'int', + help = 'number of bins') +parser.add_option('-l', '--logarithmic', + dest = 'log', + action = 'store_true', + help = 'logarithmically spaced bins') +parser.set_defaults(data = None, + range = None, + N = None, + log = False, + ) + +(options,filenames) = parser.parse_args() + +if not options.data: parser.error('no data specified.') +if not options.N: parser.error('no bin number specified.') + +if options.log: + def forward(x): + return np.log(x) + def reverse(x): + return np.exp(x) +else: + def forward(x): + return x + def reverse(x): + return x + + +# --- loop over input files ------------------------------------------------------------------------ + +if filenames == []: filenames = [None] + +for name in filenames: + try: table = damask.ASCIItable(name = name, + buffered = False, + readonly = True) + except: continue + damask.util.report(scriptName,name) + +# ------------------------------------------ read header ------------------------------------------ + + table.head_read() + +# ------------------------------------------ sanity checks ---------------------------------------- + + errors = [] + remarks = [] + + if table.label_dimension(options.data) != 1: errors.append('data {} is not a scalar.'.format(options.data)) + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + +# --------------- read data ---------------------------------------------------------------- + + table.data_readArray(options.data) + bincenter = np.zeros(options.N,'f') + +# --------------- auto range --------------------------------------------------------------- + + if options.range is None: + rangeMin,rangeMax = min(table.data[:,0]),max(table.data[:,0]) + else: + rangeMin,rangeMax = min(options.range),max(options.range) + +# --------------- bin data ---------------------------------------------------------------- + + count,edges = np.histogram(table.data[:,0], + bins = reverse(forward(rangeMin) + np.arange(options.N+1) * + (forward(rangeMax)-forward(rangeMin))/options.N), + range = (rangeMin,rangeMax)) + bincenter = reverse(forward(rangeMin) + (0.5+np.arange(options.N)) * + (forward(rangeMax)-forward(rangeMin))/options.N) # determine center of bins + +# ------------------------------------------ assemble header --------------------------------------- + + table.info_clear() + table.info_append([scriptID + '\t' + ' '.join(sys.argv[1:]), + scriptID + ':\t' + + 'data range {} -- {}'.format(rangeMin,rangeMax) + + (' (log)' if options.log else ''), + ]) + table.labels_clear() + table.labels_append(['bincenter','count']) + table.head_write() + +# ------------------------------------------ output result ----------------------------------------- + + table.data = np.squeeze(np.dstack((bincenter,count))) + table.data_writeArray() + +# ------------------------------------------ output finalization ----------------------------------- + + table.close() # close ASCII tables From 73640587d5df82af84df7f8321374c8fc89a3c18 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 27 Mar 2016 16:26:51 -0400 Subject: [PATCH 102/134] fixed buggy query-by-label-index --- lib/damask/asciitable.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index f76cf6627..8ec355400 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -272,7 +272,7 @@ class ASCIItable(): for label in labels: if label is not None: try: - idx.append(int(label)) # column given as integer number? + idx.append(int(label)-1) # column given as integer number? except ValueError: try: idx.append(self.labels.index(label)) # locate string in label list @@ -283,7 +283,7 @@ class ASCIItable(): idx.append(-1) # not found... else: try: - idx = int(labels) + idx = int(labels)-1 # offset for python array indexing except ValueError: try: idx = self.labels.index(labels) @@ -293,7 +293,7 @@ class ASCIItable(): except ValueError: idx = None if labels is None else -1 - return np.array(idx) if isinstance(idx,list) else idx + return np.array(idx) if isinstance(idx,Iterable) else idx # ------------------------------------------------------------------ def label_dimension(self, @@ -312,7 +312,7 @@ class ASCIItable(): if label is not None: myDim = -1 try: # column given as number? - idx = int(label) + idx = int(label)-1 myDim = 1 # if found has at least dimension 1 if self.labels[idx].startswith('1_'): # column has multidim indicator? while idx+myDim < len(self.labels) and self.labels[idx+myDim].startswith("%i_"%(myDim+1)): @@ -331,7 +331,7 @@ class ASCIItable(): dim = -1 # assume invalid label idx = -1 try: # column given as number? - idx = int(labels) + idx = int(labels)-1 dim = 1 # if found has at least dimension 1 if self.labels[idx].startswith('1_'): # column has multidim indicator? while idx+dim < len(self.labels) and self.labels[idx+dim].startswith("%i_"%(dim+1)): @@ -345,7 +345,7 @@ class ASCIItable(): while idx+dim < len(self.labels) and self.labels[idx+dim].startswith("%i_"%(dim+1)): dim += 1 # keep adding while going through object - return np.array(dim) if isinstance(dim,list) else dim + return np.array(dim) if isinstance(dim,Iterable) else dim # ------------------------------------------------------------------ def label_indexrange(self, @@ -363,7 +363,7 @@ class ASCIItable(): return map(lambda a,b: xrange(a,a+b), zip(start,dim)) if isinstance(labels, Iterable) and not isinstance(labels, str) \ else xrange(start,start+dim) - + # ------------------------------------------------------------------ def info_append(self, what): From 7c72ede29d317831fe9e514baa90411f25fd0341 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 27 Mar 2016 16:29:45 -0400 Subject: [PATCH 103/134] now works properly for labels specified as index (instead of string) --- processing/post/reLabel.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/processing/post/reLabel.py b/processing/post/reLabel.py index b1f8b898b..e70a1166e 100755 --- a/processing/post/reLabel.py +++ b/processing/post/reLabel.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys +import os,sys,re import damask from optparse import OptionParser @@ -32,14 +32,17 @@ parser.set_defaults(label = [], (options,filenames) = parser.parse_args() +pattern = [re.compile('^()(.+)$'), # label pattern for scalar + re.compile('^(\d+_)?(.+)$'), # label pattern for multidimension + ] + # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) + try: table = damask.ASCIItable(name = name, + buffered = False) except: continue damask.util.report(scriptName,name) @@ -63,8 +66,9 @@ for name in filenames: for i,index in enumerate(indices): if index == -1: remarks.append('label {} not present...'.format(options.label[i])) else: + m = pattern[dimensions[i]>1].match(table.labels[index]) # isolate label name for j in xrange(dimensions[i]): - table.labels[index+j] = table.labels[index+j].replace(options.label[i],options.substitute[i]) + table.labels[index+j] = table.labels[index+j].replace(m.group(2),options.substitute[i]) # replace name with substitute if remarks != []: damask.util.croak(remarks) if errors != []: From fcddf9345ef41a42b889950ab2208740e85d55d2 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Sun, 27 Mar 2016 17:54:49 -0400 Subject: [PATCH 104/134] added option for non-uniform weights --- processing/post/histogram.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/processing/post/histogram.py b/processing/post/histogram.py index 102170c86..4ba5f97bd 100755 --- a/processing/post/histogram.py +++ b/processing/post/histogram.py @@ -22,6 +22,10 @@ parser.add_option('-d','--data', dest = 'data', type = 'string', metavar = 'string', help = 'column heading for data') +parser.add_option('-w','--weights', + dest = 'weights', + type = 'string', metavar = 'string', + help = 'column heading for weights') parser.add_option('--range', dest = 'range', type = 'float', nargs = 2, metavar = 'float float', @@ -34,10 +38,11 @@ parser.add_option('-l', '--logarithmic', dest = 'log', action = 'store_true', help = 'logarithmically spaced bins') -parser.set_defaults(data = None, - range = None, - N = None, - log = False, +parser.set_defaults(data = None, + weights = None, + range = None, + N = None, + log = False, ) (options,filenames) = parser.parse_args() @@ -77,7 +82,9 @@ for name in filenames: errors = [] remarks = [] - if table.label_dimension(options.data) != 1: errors.append('data {} is not a scalar.'.format(options.data)) + if table.label_dimension(options.data) != 1: errors.append('data {} are not scalar.'.format(options.data)) + if options.weights and \ + table.label_dimension(options.data) != 1: errors.append('weights {} are not scalar.'.format(options.weights)) if remarks != []: damask.util.croak(remarks) if errors != []: @@ -87,8 +94,7 @@ for name in filenames: # --------------- read data ---------------------------------------------------------------- - table.data_readArray(options.data) - bincenter = np.zeros(options.N,'f') + table.data_readArray([options.data,options.weights]) # --------------- auto range --------------------------------------------------------------- @@ -102,7 +108,9 @@ for name in filenames: count,edges = np.histogram(table.data[:,0], bins = reverse(forward(rangeMin) + np.arange(options.N+1) * (forward(rangeMax)-forward(rangeMin))/options.N), - range = (rangeMin,rangeMax)) + range = (rangeMin,rangeMax), + weights = None if options.weights is None else table.data[:,1], + ) bincenter = reverse(forward(rangeMin) + (0.5+np.arange(options.N)) * (forward(rangeMax)-forward(rangeMin))/options.N) # determine center of bins From 0738684361e5a029d72e55ceeabeb1addbfc7122 Mon Sep 17 00:00:00 2001 From: Franz Roters Date: Tue, 5 Apr 2016 11:39:30 +0200 Subject: [PATCH 105/134] new QR-code as website is now https://damask.mpie.de --- misc/DAMASK QR-Code.png | Bin 81990 -> 35096 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/misc/DAMASK QR-Code.png b/misc/DAMASK QR-Code.png index 28a82c5cf9aa2bb0042bda86b2d1e56f449d80a6..8fb9bace98ecef7a8d7d1c7f937353c5f3159c1f 100644 GIT binary patch literal 35096 zcmeEt_g7O#NEK0#-fJL1Q3)U*N|UPeBA_Cj5R|4= z={2DfB#_VpgphYY?|t|E0q=)5z6S#`LOA>Ez1CcF&9(ME5%+b~8BcSZ27y3~ni^08 z5a^`9;Sc>W;4haqK1~8Ir#v(sc!NL;XAgg9`Y`Z);3JSG^tMqz+A^l&-Q(eqDbl1Y z3ELU8b$O)vJ%{fj1IY>S;ir z54_Wiz#GO>?!fP-8vp;2|A#I15#E2v1C840D^A6p2v|g|uQQ}#U!1cwoGjBF+ko|9 z*@2fjL2J`YSN@gVmu$LYBu2jfR9sN zDQ5+zBkLGDj9)sCag0qOH}$+Dg@gY?BjpfXDi&f5n@f4p)6jpG3TaC)y$p6qhbsznQ@k5EJ zHQcs86~v6vp~wgQ#ZqceJ^u=MP!k51-U`r5dAGfv@r`&X^^tNDzeDqXXr3>a+@wuo z{mV-<+(D^({+sO`VlH!VJ&qnR5tpUitp+^?Ytz-$n=}8RN+;f_Bo#{wQfmDhY$1n9 z&kLRE)wjKo$4$%&P()Owf5Wi{1YBJE50!^Y(kPl>sedAXyp)h+GxC!%)|2UKZAxl8 zanODbN zim@`btwf%tb%W%yk=nF(N|47oVJIm!vvQnzeP(m%G6dokf&3|{8qFG~J;za#lg(d~ zhfLvv%5Gtz*W~0l49XO3IZH$2Hf7w)~H7l^Bn_nWCTiFgJU^exK#029M54ZHV6Z zaS;FeRoW@hd1Ur1OnYxNg~QW%wVaa�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 literal 81990 zcmeFXcTiMow)KaRvY|pZ>b;0FqOm0{|Gx*5cwSDpnvDkh2xYfm~KxoZP_) zWMTc*902f`NmIAfP~X58LctEj&7|;J@j+VEFnZgA zNAWTos$2n&3dKlq=Yx7WyBC&OUk74PI{vy?haR{diL>N&ikj@SQf7XkPgT0nY%hy*`QM0bWbp2}nz%RR?6=1-$7uHCY0v zumIlB`LB)w0@6;Byzc~zm0naStJNW=pEP$7? zKnoc_IRwx)go9ZLc<>1DQuRX!1K_SV;LUd`Di1(#65yHCK2UIvsT608@kUZfm4fxu ze3F5B4_F-0fk0ML`XN~Yrf1y7e;6mfW^MOOB4iKbd^~?J003l09VyL4!X z`%^8p5zA)l{cB1SlclSbVX(t%0ARtz@8=aWTNP1&!2JNbt8AK`yH;~TcI*Cd>6s#fn~9I#p2HS4g293Gz;KS=*Z-xT=puITp% zPmL*NKHM=0*QWaPfFLR4gyNgb-6s*$uBsZz>EbIH6?3)djmlp)y{a{7ZWR9~tg zTHrf?{oTd;Ch1qPft9L4V~=XY>kD{@f~B%Cf0((vN{+(MO!?tdO(gV@J8SI+*y{02 zl(2Zu%eM9B=p3DIU$S<0h*j`1Ka4T$ub?b`1nwp(*D6M93_CI%u5iEmBv7*LA@^N( zF>+&4Q5kIoZKWxh0`eEsoVYU&c^;w#tG3fo#uUg`(>CCqc0M;@e-)}N!%Q{tBp{qGVwCSz8*%J$!o{2C+dszYJE0xgey2JoGbUu6WK*IbCT8O3bHhCxuSH%O0sIz z%2Y!Oo^rY-^9=^!%gX1LWXFvXSrJ&FtjpG28gS?0NR<+P07v>aq}LPH(GJ}oVZFx- z>iJ+vPnhx?{kbKf`}49yg*?L12*MtXmprew64#O*CxJAz8EYAR@S^)L;^g9JUng^Qw8c~IY>b|8?njGp&g%8K#!J0*BDqHHr>XwB91))Wj1t1NPuYNk0 zVfS@96grf}zp7?d7%eq*lVh3^R(UW}*kXa-y9RP~(pC&k`?xVSCSH;>MhF!ZX7P!0 z$Z-Ix)DB`TM9`NK9ZynSlpe0p=O-Nag~Og985S9c^EegiUzzLM7R4vTYlCILs$l7@ zX6{l%ep+6$WTVb`Ahu|a9GyO$v}M%Ly|gv;Y4y2$jC_1WA^xLM)*{-JP(IAFdF||lFWaTYrQKQnk@O?&`&Eyq??WFAJs0faas&yIu=POqRK*QC zUW?}%#~CLq1V`8Z6wDcyij;c%(YjlIiF(Pd+par@_C75It-Ru<;!d)fVtpP%o`8aY zLeJp9VD{id5?6}Qt4a2?l(m$}6gcFKu7@sjZ9#3FxoqXKZl2CgZIgY7E}u@Wwx+H@ zl~hSu3C%=fNn<{4e!WtR5;%RrvZH*jwzswrLRh{sbst(CL#&57$Y7gTKPjM{OKJ91dv`$k` z8I`squ&j3uI`|L~CjYLVH9?p)g}8g}d-JlK%aNnOg4f7VT1r()JE8zuw!^(+y%Rc{ zF~FI@kgmhw{G;Q$_`K@MPZ7+FxR@I%dyE2j~nA2aJk@kFEEmAqT|RzhL*efx6>1!^sED0;{mJ4D5Aec}hY@v3n| zhunzDnS7|2Zq}43{{Qh?jt+SiVx`D`S!4ViYc7wGo`*Y2a)S z>1MUi85q}2)0TZJ|ALQ|v6S2XZ43MYaS*zgwurgpO_0d;-N3;!YpDG&Bp<(!^$9b7 z{A+~|O1!bVqBx8N_#bKZpSsh0!tiV-X}6?g`^o+D!<4u_BdOB945Omgm+j~#E>G$% zj$G!I`e3@k&rJ$g3Uev^>G;WRr{LQa|zC?d^6f2@ojH$KUv|P1t>n}DBsl4j4 zkASd|#-aDxR(&qMr^A9#E0(vep-Vr>h+b)F4zy?;4C~{I2d6U)A_l7Zpr3hCkr~&B zC+$xbzSQQvmj|+tXsdEre~_L;9Av)qhm=ZTf!hcv@xhwygsK@ zu&&8GzjtU*Kt$uK#-YZU2KUa$T#fPMiT%$VV(+G7&h2riUK8q4xVHtWc}G)m++y7P zT=u*QB~ltzv~d!DZf8)UWao(JK^sB4M5n^8ova@lCm9jaP>Y&i+LFfZA#1rxL%OqI zabsylrgkqGj1Qfix<#G$=paRN!V<}lJ}FPQq+^r^-S~{lm~== zPHe)wE~KGkk5f4Xbv)$`GAscX9 z7DgnmBi00(1cvnY>s(48gC2K z25~yi(A;6O=N|s`#CSTN&|LF@7YNmbI)dZR`8m;D4)r%qyVLEIG$}V39ll10PK(cl zj*IAB%}ya_{cYOZGY@{wN~7+F1PxzBA4NSDzZaDh)&Cyr{Z=}!FdyHdh|}f9MZWm3 z*)VN7!BzHEe<=Yzo8QU!*5uI7#GhFS`w20vc0Re6n{8W!Wzg>SZqk-s4~|!chg#=| zZ|<}1B*+~2W94NZa)0`3tJ8`j^&k1?F@!NO*LTqp4=zkOSfIbkPE#2*MF7By1^@^M z0sv00Z@xDG0N0lQz~&nOfIkrcAOL+a>XHK7;c}Ff5Y_OQ*}k+ccinJ>hnBb^eS6ZS zIi>!%D;quk=DnGOOtyk(R5!O$%Y;Qubuw-UN#=>HX_|H;s;r2j87 zeJi0`hHlN{-(tF{iq8w;JFo1s&!O)c0E$ue-&{f#A=xq#{6(sUia7wSbazfr2M{#E z|MM1lyOn=awpDlkYdqvXyZ(R5^=}vZt+xPofHd>Bj)l>TGu{XQ+);S1cewn)g?G?! zKkCDIxW7oNZL9Q!_mhBYY`?PC-T$wK85|h%-$Ci0QRV-SFn250f6Ive8Jp)x+HmD} zhgP3vTs(@{#W^|57apPnz>Qj@^^JDG?ug3)fAmun-mcI)yYIh)|397b-(up{asMf~ z+xPsF(c8HGzmjgsO^W^VbNlXF9&ew!efKTRf8F}Ot@KtazpedW`?zK3mgb)fHKFmE zJOs>phx`gp@VF(v#h46Fpf3!GkF0gQviF6#6Z`nz0nD@iw_p74)cqew_f`Y{G>Lzy z>350nr(Xa7<%9VmM~?UlBm;E9r%CSPzFli8eyi|d0N^nh`+rfz@}Fb*KeS?thkyIS z?YnOc^7gq~aop1U(;#nY{wcEC_xzW6(d}Zl3?TuZwBNaNXIzc-=-l<_*$q?nTQxWm zI+^r^=7*0splowb{go@2|G0+D`(2S5ShlnRcANkBZ+G}h*Z+>NZ;j^vi-r8<4gx8^ z4iwDo;`2Av>`CM1nIA-$Z8E|2CP5T)WF(x2!})xo>dNZMS_mkX{^xV@e|-S`ox1?H zhWOii|Fxxm2H6Lo_`ig8({=fudHmONx9|Q<^H1CSS0eZ~*Z+I@TY>zO$6MXp()??& z-wf?yzaHE+I0_WGIZ!l#g^@Rjd(VBG-yb53Y>ae=qSoiS8xe5gVvcJ+i?q|LeI!=t zjjpa)1+D(Ou>DH||Fo7{t^ZpZ{in8?&{Q}~@#Y1F{;HzZE^m$*SEagZ$cZ&y9@wx& zc7s22_Cd(0w1;rBfy9#1kWc?aFEgyh+pp;@ zio2mG0xS1tu4{r??yV7{bmrIf?fJ)R<#6Sb2l+@>WaZ`09#}V_oM5j5E=z{2M`dZ1 zh-M1iY81PYX-(phSVl`f8CaNM@6jb`d-GnvWYRV3u0SXpc+v8%AN?lm2K4vE-k~*7 z&BPzK(`?x>Qe(iF*pF}YcUx2W#DEW(q{bL;?(gG6Do^%5s;bYmxsu?=e)TnOTLS`2 zEjmR*Dw+B-J3}9(J*}N?6{6pCw8#I%#Tt1EUXm!YIXxtLmfR|}FjLF4K|LM2gQ+Bv zXY*lfAQ#5gWzW$YVX=dje2>txh^-x>D=gFc8Zl6kh;$yXCC2c z6Ip4Kf55Wr*VXK}`WU4<=N~_pu@e-k8D99dg7z*B20rtH6VE_S=ASAlesM)wsi!`u zFtzY0%+`9IEh_e_?($~t2@g?sWotefe^pKx+LMXt*~ny(=%KpqCg5CBii^{n^_Z$S z1^47M<|@$$k>|!7dNu6>b4QM<`uju)j`}8^^jnVre}<~M%zfCk0vW%JKp_`b7+0@_ zqi4HTcbVH;Svsp9bn5cm!Bv}r3*<;wx{6|OE~>sS^{qw%59z%TZ@ZYIrWgganpAl> zIKuX;&1sU=cxK+Jw{6lMzbJp-mkzO9|Arc_eoJARRBno(IZ22|ZlB57!C|kOqpd(^ ztL%?bb+Jh$bWGep7ZwZIc0=P&Ugy+tC5?MNLY@V8e=1qe=&yMe9c8e-U$jMb5rAyz zL!M7|UDVV*#|vNN4{0N9=fA;Te)%G-^bdEDX4i3R7E!Y^!Tb_#wtGQ}UM9?Fs=0(ds9)jWVy}DwQKIdWNgW^j84_0g*-QR@db25{ zV5Oor1SX*JxkxjTg{X&$A4bkQzK_Xkph^~Gl>N90+f;tQ-*DstuRh8KxewanA81@Y&F3Z6OQAtwlBnqJ!dB} zgLS3~9XcU;V&dH1)bZmbpquih?ElxkaMVm9qyHz=7vqb0Xc1P6=te7bHsC= z^7!*>iW~3{@GE1@FD5dH)sCocKgw43t;drjV$3eFIorI__sFQTD?KK3RPM>{b3A+IQ#;LpON;4aOf3 zk;B@W;MJ5fH&#S%0EMs2d}!W(38Xq_)>nK)d;03jKtAG!)=+0gJ!&>xvUS3{1pNNO zVrZJSilPh@gJY$F&2K0rKj?MvuvS${!ZzCL3&$XoHXf~8mYI-2I$@%bn*4c?Vg zUO~9b@$-bSD!VMGK7RVam!0_P6*R+}U{x3UqT&V{O-P#v6^v>-R*vue?l)FjZ$0Jw zB#}k(WNKh6uBibssk+c2I5n9IcI_DCOm&+Yf8L&|-&Yes)%hdHy0#trX$i9ouQO2| zA^i%zy6K*O4ViMEM`|lRVQOg7*7oDa$sAf^YwkK4Cr9g>Vx+8;F%vraA#OyMnonC7 zJ~1YAFmGLtOQ4?XIMGc+4&g_3L2Kph&v8DES34MVm;qOJnmyaQt6N9w14eD;q%^oKwYO76dXhQsQc2qCCL zE;~{s_gjA7#UlqSlArL%rv&GCujDxj#-(VHIAvX_%UiJl2f>crnY?L2e^h3ya3gUr$vFJmM$})D z%!g+gG)|wqY;hK)ezcB3H$Su8fwRw>rPzPBWt#SlWkZRcad!CK0Xu^eE;#)X(^`~Q(O)h96CAGWaAiL zgYvH8o$Xg9;+aETdPQ+sGv0KSxh<15g$ia>722)r!|2Ip&fp8l(ipyG~4fOv|~C-#2-_;6qdv%ktD2F#%bMNP zJiAGawBp3_$~noPbNuNg5lPrinRUl?0F}&GP>@5eSOZEfu|5{uWlpo>&nOVID%F!Uc{tasdgLN_OvFGMCUV>lQra_v@;g!R;uY+gmSbNy6>@6??qNcv&(gR%< z_>6u1#^{3RhC{8Jn@baoQ|#-;@hUzaR%!ZdvpAD$7;LDU}?`44T4I4B*|!D40!DD>C_pt}-^^F>VN%IpHU@0yoW(jed{b!nT%94n2E znfgj=K^j@K=B2MZdQ59Yr9J#9%yJ1!4AvUK(||HPpnTNDhqtZF41;wiB8J8xM6|XOA(>&>hFG*Q|XqDT?~%SQ;oqDYlz&`t+%g^zkZt?nl%Ht zX3X?a>NU~BzPG_or#U)X|vKx_b>^?kW8GezDEmY`2t&(l7PpgC6syZ)3+YeWL(>!hV#;52+I4ZQH z63%lPYx)wpS7**RUHdG~SCXsBigA+`X5SX}Fmn$;REgQ{U3MMuJ4;CU;02v#4sXN= zx8Xi*s`&7&hQ5dPdW9~|xoaoCmwfOss-&sN6vFv2uAAAje5Hvz z0bO-WrwzP}3>niicTgVJcAl7RHPDtSp}GW>=P6jPyDUxRYLJa=*MJMyIex8TF6yM2h_~&#FA$vtW4B?83kr@}sgyMt z#DG0#-@RI6DEJIZsfLhszUV72Q5bg1u>Xiv<+87ZvB3ov5V@Y#mE9UC|5h@{BJCA_IyR!4k+Pf6z&nkxafG!0U{cy3veMGIGM>!X?~ezmMl zrcueqrpVI&R^<7B(Wg=BT5AP4+Y{Xlm6IoyVLfb0$?wvoA9iXThqnH?nP13(gLRmN z=|+OD-_W~bm9_74bc>u*MTIW)`(F&7Moic7b}KBsWnlxV3DtUFZHH%b;ipE0!Hd3W z%5x2~JaxB^U-gj8<&=Cg2Hf0?=dxh9)aNl;Ayw)=OKk#Pi9bk&>nS)SFE@nXDyU9A zBiEA9C4fYmMB6=4YUw@e&az!poaYSoV4jJilT6-k)J0F!)3&VAA+$GW?a;P#RWDO_ z5tskL=;PqNK9Th%SaNJJq+B@R?JF4dp7(+`2I=ZeC~eCPzQG3D%;RC_68Z%Jzn7s{6OD=2Oc)5aPIUNHBPs~YHYVfBOpn`ca!T<>w`b$@|^9T7h;W2!HGw@ zRy$LSa4^N&H5-Su^P-1UB!OWFpp<-U=VbL-c(A>d4uN$q%hsY-IZYf>53Vg&6+-e& z-D_b@+sLSdT=r1yAL%8l#bq8D5fgJGN1}7G{_hLLz8TpMG8GqI!;hX7cvJYKTmTi; zhj`HAH8&$7f!6Kc{vYSMJQvsGeFZg>P`dh@`k@{j)3@>mOr&Jw=|7X-56g zl-VWSP$TY|@f03Gcz-ZUj1NgnSTaHBQjCoOP4BRFYJestYg34K%b`Jx*rp9WUjn-J zes=#BXw>yBB=@*uv+ALaH@Gu~2b4s6;5}Jf)oNM%UgDi)ihuW_)!9M|x81lwR(NDt zNtXa6?Csz>@9)E1d2K%bCds&tEOG3?4}hVo#Hn$~jEl`+)1K2dxu*MbSM24SG(Aq+ ztFQ1cc+R`Yl@^QD^>@CDgV$Gu)xmc0p)=^%onT=)u#$2cHIR9DPl>40SSZr-kL0q- zl4^Iyk^{|YHR2|gyR^)OMiJa|=XcBMyxuYuj%hI|r9k*I?V05X+g7g+qp4!F13_5{ zP`yveDFC1^NuJFqrk!z3K23W3J(PIAOS+WP>j$hW_<3+0!XGRQSoV%y^}$f_8U{Q* ztXJC&VlJ%jq;eG-ZjML4pdb(#OGqad*%mspr!S@T@wl+^dKXNATuF#gLM*N>qNwUEin2hhDW9 z$d)xO5>;Os2uMqICgtSE^k@ZyT{*Xm3#Muw%G>7I-FQ(X{DXsupM$|6ZnZ|M%Kiew z)U&q>G{Xfc?w`0yZ$^dwEXu1Y7*F~z{ix%{$>6d$4Y95hyF_u_FipMi4VUt;N{e=# z=j8_M;m#Nk?gkCcRk|AY2T+C=NfYW8qT$-r+8n(WGgsda=HvU1Xu27wkHftmTKj!ckquxyTvwp&!tfG@9xoc}}lKujb&3i2|@TM}uSorvf zP;u0=v=_>~YktjKGuo8n+hDq%{H%i91Y$NVx{9ES)Db*PvUYx3hkeu@Ll}l2r_(w1 zhaL4v9Y?KfMq!!iErD`gDN+D{l^_v(2cWMtbb&=8QT8-R(>?UGQ_C=d-7szb;gA_V zQTcgl(Xe5j!|Pa^jdk78uet->W13!iAO7$t1erUkQI1_?ZoiV$e}_Nf!Rs27cKKo3 zjFp9<(2%*sf(6p4kjHd`4Jeqx4FSD&3KO%}F-B-A*bT@1UL}VV?Cd(tEZz5a& zzGjf!&{Bme>Yclvg|OV0ct;q-v19g#P%dLX{>EabgDl&A==Aie`3B>MWBo!C^-Ts`nSlpijq8_%3Yt!e zT}$v0oq6mPYWGNnjjsxTzUL&G7W5pg`rzZ1hl`Qd%ZcgX@B^L0ijK@RUv=N&hp1c}V;TZu7FVoO z%0151&KmlwQR?~`a&lpMoO9gG*_M}Kz6D--7tq)8#Gc9QZLOSl{wxU`UX3GGBGm;% z1NfS=Bmv5Ime{>(uZ?hOH-lsDrsc3Ac#D$NSs?s6=6-$EL(a9l8@l}$EdCF|rssYH z*=4!=#(JjQ8x)j`Rx+@gpwD%j!58^Jw!dr}H~P#zEV&2zRfoIvlf_)}noP)S*_N?V zIAfQQPxpA!W)&^Q=OVPG?g?H0vgWOH8sF#W`NQ#k8|Ka@`ZS*?Xedei- ziM~FLJ2sk|8#&m#80TcEw&-_(huE`+E)T94@Rpt?8Lzgy_rrL@u2O)&@cVY7vtMC@ zfQoZ4*$hb?@ubid5wF(iy;-)(^tR^>V;ZscK8JhhsOdk+UHcf zX_zZ#Z$ioW1{af;J1w*mhTbVfY>s}3!=lxel$SqBE9F{deNkTAhGNj#V6#e`B~|Y; zTq;~;LLjCUzm^#~{KPug*m*|lAc?4N@Y5*i+4k*QkWbDmef4N;x+>DFjMg7nCnp=Y z)!xZk>|BWfc@p-cFi<_=i2i7p;xS9d_}r=d3y$<~MbdZPf;V-i@cOSaz1e%hZx%B|qow_E z9B9t(a-zb2wQF*x>7rW*m+w`*`}K0CgoKjP_Ri%~+3QjCGrse6V0GY^YmVNatBvkPRL`{X)%!u zsYi}usZB=BIA;uwcbPy6*UymcIKw46=)Y6b^Lr3oO?NNZd@DlV$<5;Ql;EkB1wJne z*<-7HIhYBfvgGn+Tu_vt|B|%G;Z%r7YEsb|`o`(uz~<>FI^`F)%1Ke(s4bU_2@V}Z zZF*Z08Nv=U?Uy~CR4wppL%BRVb1m+al#m@#|AXCRr?>^TNBLgT1^)ZeI;9rYkaIfDD%0mw2w;0#TABL;@xC+YB0AHeKR}o3vRCi zoV`+sJm*cm7O0QFCQ)EmQV9H2sBgZT3v-o=cF0 zC;!|IYI<|rt8P!h%bF&AOLz;Ljj?Jgt4Er2t#;3N3-$^7NJ!Z*MY)BIY;or@1_*C* z-`eRVh9Fxn&YGbpB}3n>D<%-kduig5&F|nC41!(HFhPu3T~qrLw@&l7A#%8zhWM;a z->9{!EOD)?7!7kc;ED5i?gW}%(GyF=73X57$mp1!UKJr1eRnTd#PV{6|ICTqS^3=3 z-wtINqi4**3)VSYtmX9XO^Q^^#YL9`lcDXnMiA>WJ9^Zlc6|0>!5luTo50vdq&*U9 zrAUEP{jdy2jB{@s+7Q7bHskcmGAi&EOdo>&V+hU0pV*f}l=Ng<= z*Il&D`&!`Req~~w(xyR5uQS68&5$C(C6qBTEBQ2O^VOSZVX?S9o!20DB9MHl!ThH1rK0-aGTLH=vHo2ofpR}l!*zhLU5KTGh|4oW+bha zKxGC3LCd+rPcgL-)EgIA^*hRJcICcA#Bs|^70q6L0)DC@b2Uupz^KEYThdFt8E5NH z=`7qRdn_`pyY*VnS0H|COrWbFAk5=5@*J}B0^Z{8B@P$f*)rT7AZ zOl%$;7P;dl=zp2p{x+SZOtLk$?|_`d$?Iz-&LWfu3YdIl$jZ2^@4@Da^0wM?KIzwD*Sd*)f0j*X^6`^1E)L0%kKyedmbf*KIOXzGJW;E6rTWmN?x~HXB@{1ZjA(kD z1Gg-oCR3o)qRQqv#ok>kzO*X^^e?PSLfFylBTNqs(C%uIPC~wN$f|zyY9|)Z7gB16 zArD?}zt+TF4quP*nXe!_Z7WT>Mzvl|fP5B?;Fo>e`5jrqd{$T;k z_nXY-BLWfF>?*Xxqn2*eRkmvVB!TuX^qf`hyQM9uI(1iKUn*nzldg7Ck-G0>;?21+ zJ8H8wO1XLisgvq&otjE$55H877l7k8Vw>!q)`MRh6&YL%z?|5=43GY7ep0PjT4v_v zOch&t5*atGz3h@?gMEE5x!y4hKl$!$pPtx!(cR4EdvJ{OJsO0c?x(cwb@8;EjUZw; zn`Red_c>1txFGZ?kGHg+V*^p-)>gG}=H{;KXUIprK1i2xXQt9^{1Pl;%){ErvxT~z zzoGvYG@IF#>D9McoCbw1L2LEWhHkuspCjI0!n!G#Aqg3ptp;&6DSE;jruvFMFEY5! z4Fpnioz3;|OzFZJOAhp+XLs@yt1|K#e5nL0!UL*@>|{%~bhJEOt44d!i-rZ=jy9yr zE~ZdI$1{2;BOk=hTFdb&{4z4ZA8}CD?6}4IU~aixXa_bMUpy`74@*5yt?#;WkTv+h z8dp+r<>Q5($Ly8-FvI6*_EYFoD;W;X?Bu}oi!*))1cox{=U)lxPmny7(>bxpi`7j< z*4sOzqy}w_3xpi8T9Mo%6vO2HX`@+WN589~yd&vk7i@1gP;2RHC%>XqljojhDK+W# zT9j4z&^G7jY~aw<)fOZ&#ArsIGJXd<|J?=`TQlA3uunb8@N^xM$N#D)-ScShy!B!l zc-3!ox{CC_EP?E#ew5nv)jX~VCLO zVEM*gGhD!bA7^l%dueg)u0&Rg4nHgWA&-@4F8@_(t~l?Z-;e60c8>!aukz!>yk~BDXC>oYQZ{-Y8dT2)MuLpmaCiUXs1P( zm)VO(4Hh07jF?(S7sPAK23dh{#6lpf&dXzIb0On033X8=a(N+gk_PnKgBYF;vNi9m zfabimhGY}x$!3~=u(-M)GSh5G3{vvP$Se|QLRVHu1Xwr+U?)%**HcX zVhNZ-owz_pZUQ|5g)3O64O!L0qb|)~P*A#zkAr4a1%Bq;>3w&!Lg1B&3bi8_vVi{V z5??A|N?X$=tmxLcG+{%2mCF+{ug!dsvrYoTrXyk_k0k>C^A-P#E*?Yg1H;r3mfZQ- z$bB_;AUYW+AEFr4;h%hu^@@r7TY~~Md{;I}zAy9fofnpgr`-Ez_l8^#$8}h~AMem0 z^ZZC}brSM2a&u-8@RDZ?Xkh;X?078z({E8K9-doCAK^U{2)Ud61h%_A^Zc<^MEB@+ z#rS6gN6li^EF1@3Ip*L-Rj6uZHC>*GasF2sTpgdX{A$f zIYCh^sOVpp$c4D_6$}W!5NN#`VY^tBhwP*)XeLR35NS#|^_Ry>m}+aTsJSKkVOr14 zM7W1WbpE3%2~)8ui&Y~#m0{d~DLnT4WXb;Oy*VC7#0u*vyy3T_vt~EQ;}(}Ob7i0< zsA=wmydJsR_ppjr-(8Cck!1bCurG95z@2fm+S?obl zqd`fBR0_%_V~r2XSFc@Rxbla`8syQN!CG$V>@o3EWoeO<4hix-Hr5l@$^ zp!2V5`UeL_Y0l{%{Z~(>{E%SKRn3i4i=1tPjXd_^xs3C^C>(PfymO07J+gZ`)Z0Cv zh6x#5_N;sgBFbm6$cMg~Us(<{F*=Rco1`i2B{7J1Jvu@lv0-+tWdS!+Ix+CZzxpqn zl=l5Xaf7Ip#=B^xb-4(_~Mv} zt<@1!X3BCgN}$Ta(Y@%y7HN2yW7BZ~5RAaKag=I1v3yBhTm)^*jQhE`DrJ{4(1#29 zQ4TF@$V|NNYDe^kou5zg% zRf9gHj@BMrE(`&yd@Vk?G=l0|8WzNB)w)VrnpGC6C1MUZA}59fRlpXb$Ck9&t%I(H zNx5m3VjfImTl}EZ@$sA>vh$W6;gi{;jLR&#>rFP_C7>{Brum%iswG*M)9k&gR#=KF zE`8*aNoypo*uLjJ?N48?7-|2b*hTJ#RCT@%eT~JoNtE$wvxP0b?}@W3QoBGV4w}Wn zyT5slF6s#itwKWFL>4>DXzZNKDdN`TemF;h@73T`yFa*7Y~gM<$xW9wVeddHR9_-E zN-?BSRattd^v97x0&iH!s-3fkD;0>q>?n+TH9Ku%aVPhjPtw~i3ze`x;GHSdL1%Ax zS|25J83VsQfu9d1T&F4fpAwhB_=IIK_~Z4!#EJR#FCf|utk2J;`{#64n=`tETBTN7 zxLD1FX7b%P=fomTK4_Y&J4e<~eChFx+IwSeG~K1Lm5E$fZ+Xo0G4fYMpAd(3GfOr9 z1Z?lDrCduu{KUTu>Du)J&F}l?9ZVe-*>|Uv@`?G|v%*X*qr^GDCT#_z>ljX{>_cx^ zt%K5|NJF&Awaa6}JEcQCWcD(hMUh}8Z~kU4lMQ;)wcd{`48xH+`j)zlc5iF>CD<)Q z4sbRuwx0B6uQwY&9A_iVP8I@%9S{0M4%CM)iLaN)E-^*U+nts5g;d-pBTZ~Ez1+$| z4L#^zqjRmmgYtoX)rAY+zZZotEhz(%k7!QqtgMjBnq=TA$`xab zA&kcmpUe4w&Sa?J4U}By+39dJ5EFUiJP~+!J~3PU2?;xXZ72R1dN928X7^w$31sxZ ze+WFfOEs-lZC*Su8fAD%cDeERYWQk4^!oc_5my(Na)Ow13yT`hr>l2N&tJGUv8?g3 zZrS@OR_(+z26nO9qt-ThwP&+rpYO#z8m{pv8|5e( zJ~qeV>)R-MFo*>gMIFgrl2D;#Tr5j9d%3Bg{I+#h!~d=bhm=nuOC!h*OHU63mEKlS z&M9tc_12CM*+Jcsq|yqHB)z!JwPFtCK-2Nxz)Blhl9Q{u2rYyr+)3#4SX1Z3Z_>5E z-#*otf4mxs__Px_bP!3nT5@3zhjFjvX9sZOtFYO6<7q7WDjQuB`0X^4ozLf7ALq9o zMz!vChm}2iY`^9WX~l7^9MP_TclUip;7TTAFU&ze?^CNeZ94(+WQ8P^aKq069ksYB z#2HKxZq6<1YArKF_oH$e{<5ZB63VOg^wth8A};6{MIj#7gGaVf81g0WkI<5+v0fF4 z*YZeALioaLsE`fO;)XO9xn@ze_$WcyIgL@+eOxW9kr6C_JZ@-YjKW>Fe;WWck8f z(6HS~aV<;9D1)c3VVCDoTcg{`yrtiK7?}^8>U#M441As8f4JBWnsrvX%i7v3@MV>= zt~-Hw@Dc_;SY7o)P?;|)TOxC?=^T8zWBwj4{3yvr`SR_u{iAOidSB^<$40{GD{Ar)r1#sJsm1> zP?WMQxvS_s_1Uvz-pE=vObBWnsu?Q>oJ)JQku+qHPcaZG_~Z2C_7fRAKT2I z33S^i5=niA)`XZ6JNbV_>N)K;cPmMb(T=cAbLHQi{0iaEaTNYLXOeu+ ziPM&^6h2|EWL$v+QQJ$v>l~w#O*a4Inx&_D)t*4>%`WF@*lb3}((Bn5plke?Z66D9 zkw&z95gN}#+vnSBzF3xy;lUp-9|d=9y7)hf@lm+}Q+)o+;sZpDGWOS_vlqiIn9lD9 ziP`lMxj7B@xi(FK+{}YZIHn@jy+lIl2dPY&wQ5mzj5S4vk>bS`A2sj5CrlyggWQML zMd?jQJwx#HL|_y4`u^%JG5!`*61|e10fboJlGYo)_x3KXRzjh$jQczIbzt9(bBA4b zWn6#1sn*v@4fqlv6&dX`_;gb#&L>gAYZQuhJLA4TLlLc*_$d5$Mzr|0a~)u!7TQ&X zN%gzr+BvolD{=+B51n|DdVQi_R^Lpl{hGJjb)!B>J%j4zoyNNM1@T!6HKldK^1R$T z8fXaR__!!n{Z=e%l8WkV6>FXmY#pB#fgqNS@`nas&uy$+gT^#l-8#Eadm8s6AV_ni z7H^snzdZRhZA8|}hPb9Qr%vn-V07y7bg9&(%hjxn>t)ew+i))NFd6Ckd3wuL!u5sp z)tdiKhq92HdBS9AUeFi)ANnIFhotGI4JcipZ)|_$(G!R{P8&C-RFg;T41nEcNnYLS z>go*b6#3@a+NN*~0z4=^EBXqE2B>TLGvk!}aiu&hU z9p)Kz#RV>~!?@<&>V|xz6ByfggvJR>t4!RVhngyKYYf7*y2x?)LFPVq~q+8*VZ@Z=g|8DH*i=VSAKJZpWyA#yZ(Q;ET^ zhk#e}U3zmU$t6XmZzPH(Uo-m;cO1NXHtorBN3<1$X+0uhzAYAybt#j_Br-;sBdmjV zKX#uk&_oRJzWTer|2)DuNb+5{)*vCb;-;>+P(55GLVu62weUqZwrj@HF-Rn*v_??} zBIeGu1)j?)Uh}9qvx~bga$u&lUm3SfJmUu~vZH$BnC>h?=0FoA=tZ!h`t!AyF zFKQn3kojsm>0UCrJPQ((Y>xksV#^LGHTV5QBkp?Bj8LQJLI>0>&p?Udwo3YyjrJo8 z`5W}?`p}437V-VZqDn!E%EQvev`GRL>^*u77zoCo;q5$O^Ky^9~&I12VfqTbugrAHeM*BVsB{haBp=GKW#F2lETy}B9(OQVZi zqA6dkTpvsOEp|l7I}j&Km9s=v&2XY6{NRu7ERM5O<5fttTcDR1rYJwD*{9%`^H(+} zqfG(r!Cm?vo}Plxm>P3?{_gA%#Lw=aE>A-2@IS^%)t_8!kj2$(yjT~)?C-g|)QneU z{hUkC?|aJm+74kv+Jc^LwM~9>fWf%D{N$QGYLwelo@WtEltpuXIF`U_z~5lU3=$Xt zrY)2(G<5o{@>?r3)NZ;RX*I8GL~iJg(MzS2DfQSXZqHZ*j$1jm))ViRUc#&QcGge><$d(6A!Iw8LdT0alck|?;2weuu-@0 zF!D$zj<}e=!Q2>Z$Y!GF2`k#Gjq^PpcH2)X2LFJ1Z>)}Y_^%B6!0G%hlD2@4XVb`@ z{uHL=IxH&ON+7MO8N@oAkRr`^U*K}xcATuE=2$m$=3K$M({I8*C&sDx87eEe=r^(D*ZI@LNLVt>c5*3|`ueqcyJ8UgWC{Pm#7pMF zLN}$U(})Hj-k9BnhpT>>O;e2!6u%eIV{O*}<ILCh5YEV+}Aq6xQPO-5LJS6$h}JAn|ip{3-BAyPfUCJ5E27TdV^m@~M@5PxGO^1Dpq zgQF+;)7F&*Yz1f|(B-CQQ~}4e*3PTHFa-ajVc(lFYHAet3A_CQ0dr^RGlG6}TWSA% zg3n@HoEf!v`IoD}}c*5W<*Lg$HA=aKhDMj;MG>~PlaJCuYQI@vLBmm)lLt#mHr<%-xxhoPJ zdOa#~zL0TUVOdH_5}d;4Z=Q{n;y(^j-yh0_K^e@Pk2a^HROC#Wj^szD?vI2(rHn6L z%Ebz&VE>K&^YHumBUvU~G?I2mhQ`_@Ds)mdVZw)14V2@%n6NyA`Wc0Y`;M6u_l*?U zn`K=g>@}KN&}k&~7*xcZ!?`6o63!Y3`%y8HlnU%JR6f7JcPUvlBFrjdydE~fF%0^n za)Sl3PnYne0R-I!t9ubUe(v(A8|}G4XII#K7cWH)(3D@0N(i8FOh!{Qf(8#+w%)&i zw});j7Y7?blL0-^OHL8iOYuaW^pdOyPki zm2*q73W6yW%D!)>4yny-nDb~%^`ok3tkhOkjfyk%-272$;)h4CGhJTO;!>H2G-&M1 zwQW@=Atc7v0XCbfG&YLv+vMfLsg6C^?HE-J{x%pLhPy3ok` zILKmQ3^g|-7pjTFeiuo!^vJ?NG3|Q-j;Q?g&7|+2V|E|2oM;-vPd7w2y=n*RUquY5 zc2FVknMaTL_#GLz2%mnW<`p@IEIY#Gt;bq4MzgMRYr`69W{R>aN{r)6vl})0p~v$j zQbMgIXN(Ri!+iJHW^67Z8P+S0-@rfkzSXZJ`Y4l9b9!-BhrolMNHE~2SZ38EY`i`~ zhoin5T^*45ZT@5$vU*u-5~^R_TFB+`REbNtPgXx7bXvg$U7+J6q|&ScKWeeneX-gl zQU7K8U2apu(U5OE)j2nV0)G~G+yy21>ZS=m=_&}auQpn(>htu|xiIvIm<~1Ny2wbD z0r6VK=3yK^S)0=2)ZG4rQrf_hXUL+5O|;!SpNEQkJ0yKpUb7m258ktQ+JX&fE~RRX z8ZZtb<*sV^{7sF`ox4xEDIp0<1FnX1Vu;FA8)TI4?$1A?{|!){B>94D1&nNQM zYJNV!(B&Hi`DnPK>ce`@>NxnW^Q#9tRM2XwJ`InD7s{%qPjPr`whToUa2J>IS-Gh1rz%FNuED|cmT=E}Xb zawUr9o=C%-ndQt~ZbifiF0^tFGzTsOa-tx(K}F?D&%5XI`~ATm{^bi^_kG>xI@dYp z@;lEHmt+vSy*x#sr1aU5rgJJhl>8*7V1}L!B3AbX5uZQ)X`~N2)c1boE3g&ctox;s z-QsH88Nc8f#u+&AJp-n(w7+(F)iD<13a?Y<${jNoYipEvw8XSG{X63_3@jFyP(FI+ zF3!YMyRBw@zfwqm&1JW7{@Wv?Drc}r{76DRWH(ZAEFIM-wp~AC-*SD$Vsa6Eg;H=6 zaT&^!TL|s)?D_yp4#=!GFm4F1l|N093s5EOxsrdVjXd|vKMYg;UCsTy#k){mWyais zF_rQTOfAl3n5eI>FljV9koHIou!C%ieO9>?TomdXv65Ed+nXkv7qseYAF4IH0<>w$ z?|A&WqliuOzt@#KH|&Rt(3yR9XVcIsfKNav_~X&d%{SRMuX6PI-bqAp{Twm1au;;V z6oe*K$&Zc#CMHDNmIb^JPB7bFW&F4=b3%4D8|kV<9wNv__Q{G<>aeUmEjMunGKeu? zaqmi@BX&yKBeQT6o;1z8P@$hm7PfYTG1`FF+Pt7Pc-gR-k+8p(bef1R?fi#2)ME?e zc;{3st8o7NzD%l1gfs1dehn@0fks$d0OQgbHtg^3ScEZQi#Z1V*F^N*KX4~FyZnP( z{~ov1J@mcmZi}*}>3XYATP`)9wzqCuHyXNXL*^%Sv;92eQVdHx6WrAXg+x4HFR$vrtYuk?o_}M>^P% zwi~2TQtB5=e$0w7t@D3Iy%Xl9OcTKgr0RZ8)Kzl}tqQupR^B&T6`{S+?YOaEO>(;I zE<(IEtYaf+TTho9uMz-lu}@D$$n}ezhB@ixoNywoqD2jti@;uDZLC~UEV>O!X%PNE z<@U-9fq){%UBDzrGX&FW=k?)c>j*ZHy8*);8z5Yrvv=zT^OYq#9D0G4+EyDBy_{i2 zsEm&v8{Ui{#zdY;P~2w$L;fGmrmbaXm)W;Hd&L0A+zC5@?Pq1@;qn*Z|4%k1QjF4Z(`$OC!o0-pSy9vvv47bj(@S4Dttk?+|3MWR>W%-LJ`LY7LkB%&`BpKXUr|vQ z#@lN;eEMok;P%D4e^1NqdTXnu1_CY~dBjj+j3ZrOE`izFO})FKZ8mgStNPEnX=!R;1^v)T|$ei|DBd}r`nFYWOcuCW$7 z_on)G>F`vV!*N%k9CnQ(>$*zDl*NSZR)xQ0==A{osfyxJwu7?P>cG~Gxeqrm#n@3Q zmyAU>!04Iqt}0V*nBZyu$YZJJ+uMB^a1MTaepY{@M;FO{Tu+hHgNX`n3w~bC~^8%`e=NkycSQ zUctMco*R6~#`t~tv}imy=x`(hcQ!`zw|UE%RQb64hC+x1f|r#Ae{VB;esM9DK6J`+ z_Nw#ZU+u{qWx?9JW|msjjVYwNNgfYQmzC(p`D{B^EZ5H_y2(ee$MM|cm(vj|z;HV* zm*p4geNVjWQZMAXb~&eE3LDF{Gx< zz+roMT*31SM!3|Wja4qB`tCCau#q48)_Q2r#%D3cz5sZ2lc`hjbTuZm359zD>@jA= zHf7ed>!NW65wkAdT?kWB1lNO_XIozl@CuGBAN-gt)4xWz9IAcmymBLo8zYl@Bn{Nr z-+Nmy>3v!T=dMAB?p_Tirg}1c8vONrvOcI83eb=B+{OhwwNhq+#S(Gn75Ab*^yi$2 zC9R;m9F0(OvfiqxdTy<^F}!7`Ima+_&|v}M?(stIBrr4}(5~N1q`j9_(r(N286yhE zSW>5H+egb`2HvP-<~HzvEDwsMTz81%lWT7AJ&!-Qdr(s?B`FI0Lz1g$6yexn1S$Nd zz#`y(zj;vR{FD*wg6ty6?|D)Yg|oR|0)*cwu~v{80xFe+UiLSW&Q?@Vwb3kYTre*- zTWIJFFkhHF|5Zt*uvwZv4DFtMC4A!{BxY#~kl9orzXIG1JSgy|PIMlrDf1!$9``U1 z*CXRI7{s`MMbphI`8t4xior5&hcVyZzAN|V4H@$_;H{|Ka}F14)0OtyPX^wYEc|+q+~V{}Ek}-l_I)m= zkGUt@@%fooh=y@D^ZoyWw_b(!$GCE7Lb(fS(8o-D|B*&5EL zZin@#wDB5s8;&m>vS{qV@XXcUG#7#CO-;$TWur;DJRxYv4?j5hNM&-tHk-9TojID0 z7^N&JrQ5y$`DYTnP@RQhwhmm)bwx{12asJJuts*W-20_=(fFmUDf6f9Ck&YSgoORc z++fNODavFEAgwzx``j}zn+2)Sxa$>bP`sY}-kft{s@I_DaP6WDq;uKVQTC5?o)FCp zIjS#+SZ^?<$a`&V9InPyfqSYxp5ddpLKhVO`CM7eH%1)$8ts|Np7 z6qizNO|C)R@#?2>d``1(r8(^9bGGiFZ1B)NdUsu0u|U(5{TrIP@4?b5TJOx8meq7p zae|k>y!8uf`pvUrP3YK2LJ z_mw)sfg0AjTu04x>o9?4t&}l?e)o=Erf!-sv)Z!Zo(l#s9w7I;6Gc?L8o`~hPk8!- zzR6F(s1=5mn&h?nFkY&^E3fdZND?m#r)iwir<&G2`6 zSH(UHcpuby_+G(2{D9IQ6cs>{b&;y*jDGKC+E=p?R#4h?wbfg>;pet&*|oS$OK^CI zLmdLww1XeSLmB5=Fo&V-t2$~@ctK{b^Ie&f?}mP3m1cGB03XZKuGjdLHK*{y@fBM$ zT4p$5&`H{xAp1J)b6h`06w;6_2z38a*cT7WNs|OiW^(-&FWkS;f6kS70)CK6F{}A? z-J{3S-8T84(DdTSoTH+e+H!3YQx7@2k)_#~89jYA#K9?R%~9baj)vk596zrR(yd@!P1=Ba)OI0sR^qAKreiHro4qn#nCq)sx&Mxf z4%D~bFxtS>U3!=Swx;80s-T0IOl?6fNxLq8 zvA_{|$gWeho7K4drUiIs?14nKhJGZ1*4e4O!-V?%cm~6Q#@04X4Mcu7h}-!_Q{R}w(`1_k^xz-;a+$+q%ei3Ey`hQp=?BnbfQQkkf+@ zD=m^Dah~@w|B{DqcN}n4#ma|afl{olF6ghldK>oTTM>P@VOtXi$om@@Z%=!iM6F+l zo8XXy9fJyg2x+Tw#>%#+Xl!#m=5&8r{3a^M;3NaL9P%>AA#e3^=Hy$k?z(y;TXwRD zNzEu;;ih{f{<72=?OIKyw(xLz9KX-}s3@rft?bP(+u(y=n+oC7)4BV?;FV<_3$}rk zikt-o^k>GSI@GKyJ`tb>BJ%I;YFLGZ z7=11utus00dWtoKP*ad!=8zV64D$=;%8%gN%Rcok1w9d3Os*bL>VV5tMdtO&Iw*rL z7NhD0?OjY(g3IqzO(LsE=gy$^8Wt=!9joYF)QwD=P^CJ%xns4wtzq1MD>gXafr1UH*um@89NvYP~%75_(<626yj_(#8ZIDOfIsavUi3I+iu1l%&4rm`*L5{buDo zdzu(|V-7GBl=#@Ooyo-}aA$ScX2@fWzCg!ot6{5Jtd;DjMc8UZ^?lbof z6NZL*u7dX^{jSpeB&WlNo8CwFD>xwOxs2gB#uRvO7kmKQKLl^2!;m|~Y*sVgu~#N4 zUV{|=0-k(qYpY?|OG6;e73Z;;_Up~zpSM}n(9XALp)F2L-X{v@<;`g@t;DuWf!BPS z=?k=U?C%3VN4+&^JJ&}SbCH7XAMCO6ff?H0n0 z<~|(=(Oo*J`J89C@hlc7ohoZg-rnvUC)-v95XkZkPpyEb1Z9_2Dmp@>a$VpfdDDC> zUefayVHpkDj*2M0pHDJWw|3o20BX?K@oF#z+~~b*_70aC76QXIGFV!7Hy8^r@Vdi6 zf*L&#JXe@>0B|Vz4fb~&jk6RK6zs5zimyYMhpJ%|Fc%1O{xt%m>|C?8?Vt&nodpwO`n49^2Gf*tuWPdJ8(1v=RD zs4Pns%E84wAG|-@c_R8)UZHch7G!br_Wa0%_FYX*mRYcUi;;xa=3IY2R5!uq!}%53 z#v*yn;b7XGk;&*0ie78$gpm=8O)aC7TCeLu&sg%w+&Ex!KOvQlYyWHZjON42-D)Pg%|I)r@LWP z^6}EKclKpg5&2I9qQ|c?iOqT5ZQ67wrJXlwL16ZUcV~Y zEqi}+vmg^y2eWTe9euV(HJ@Uw(rCELPpPGa0TdD^!GbEPwXCRcFem=;dcWM zscDQl#?~fy&Z0G#aWjqG6pDE=jot<@$_?CrvC5?f8SPYMm65{L-}f0Y2`Y#A0%5h~ zHFR8QK=x>(N8BX zFaFLeuTcvdl|ZOZfU?OIiDUk9X%4%u}t+}DG#nDl@8 z&AYAK*?85>NY| zyvQBL)9h*=?yAxlPTCG-;Ftyy#v!x33N#0iZi-_3jI7<)$@ZRLth*Og>x_$BmWOiK zNKV_(%#XptUrFkF-?TI1B*{t;7Q>gXPOmxi%O-iq@;%w|KIAfWT}#=OvM|4+abxng+!djrxrjV_ADf7W3rBf|_{iA7!qOSO8l$ ziZ(@~eW`cHTUBxHbMf@)y1*v_!Yf`!VtfW>{g%RPSsFlc7n_(C8inv}8%7gjoDhD% zX0N`S3@ig#a*fi9NN{^>-!i(g3Y~-W^Ac39zPc}YLrTS;ObFj%`UC_T{Xe=Krg~f% zR-(htvoaUwBz>392R@iFr1`MQo$ryypX>R1SP_~fe(|_D4XnW0R6aHk%QLh44idv^trcWF6=>6iejjD z7(QLp=)Khygq?Ixk5D0e83ztbx*M3#>XwuwD34;<14N^LEiF1XX;FSLRy}3BYsxja zL1`ujb$IZB14AsA(bT#=oE<7m_EUhxL;4M@5%w8l=&%)Nz~#plHb%k`h-?BHdO!%D zFBLfap8u`>prJ4M_eH=v)(S@%P2l zk3DBDVP(;$0e$Q0v&ZMv&}12FW0Odm>jL$D?8NW5O_{LI6PDpnH{#7vQj(aAd@gR< zph5fkLLJ1JL98qpGCbS@=Ud;aqZetAJIk6LzMDkC>}MkHp2pvT0F?UB;BGnlL!itn zNUB1Sj@e0jf~j0cKQ+~~O`tE0BQr2z5WW#=@yb81d$+%@1$Qq+EYlZ#$s$Pw`3w82 z+Q{$s!63nHW$?#vyBmw|6pBEWxY<}-D--BR6d#KkdcFEw{xY5E5jsRMEj6thY^~mO ziZ|v~W!Wi*hGaxi4?wRtfOWLbI&;uM>o}0L!w|%{%n#! z{f42e52Wa8%tcJWu1_bN z8M}8^iAx+Z5}T3OVw3;P`g6^<2@r#*cIjxTiieUmCazQ#6QwPR@)(?WqnqZYDJ zC_A3u6|UCD;Vuie+o&RWvyg zV-Ox1v%|EvF)+-g6u)2R#g{8f%8D$>?Q#GLPE|AWNaB-1@M~lqUOr;(ZaRUj^Q4)2 zeIILR+U*35aVDHrlGmuP^C*>ret*Ev zZ>636L?b@c^H3Ba5q#Z(VO3vNh@3o+rOoh!3}3u1b*}(r88#mpWdRJ4+xVdn`-ypF6NK z7NK+CO(v$}4BsrAyR2)5N1ucmm>4cBiN*PVEk=i9;_D5G>M$s4&ttI1W|BbgK2scma^_6N!w}I5OwymYA`zJ{7(z{;qrHaCUp zF;Ai;<+z3Lby?9@<5yQsCrE@ZAR=AOjEWKEr$P__(Or+i$eB@7aUta?uFSOEd4Qxc zdG<=YEcH1Hiv7fcboz#mTVf%3_oeCTF0V0XNG~K{ZqoNhv&%_IXMv7WY9)RtX}Ef3 z6M~XD*l=}FjuBZXNF6K>Tr1k*IS(*)>43Ss)2-EkUF5P#$ObdXv_ER7emQ|2aJ<1P zyk2NO`Y2xi8o?(aFzJj(2C+03?|EG%PwmBDsumW1gOUXD6o_ zJO@a@cfbs@PqcP<;EBYJBGBqvN%$`Uhkt!!@XDNQn8nYP85pMn&z!0V|EkH`Q`(e4 z@Z4DI?s)4CvjJ@Mw*dHi6`Wm5W=p%v7ADuEtZJ33zIk5Hri_?B&ITsZ1;EUTvP=Bn z&mWi3xYtIr*bE}a)ps>Xt=9XtZ;KT0pnc|;_v_#1-9yVc=rQuiPESr)HH#ft zK^lvT)~#_*uJ7F(oq{UTtxckCpE~|-hHhm-5LIoTEDV?i+1)|R|jT>#N z;G1mZnh9NXO6t%B&jHKlVKMt4pNq5|EW*sOM95TfM`XRA>A!*g9k;txYJ5;`Q|53j zK*ZC3+1p#Wr(s%pO>t2ZZdMz!o1`xT9BU#%|%n@17ScwwEwH#Aa-Gmv^$%5uy7Ya{~O~%MPbG+N2|?e``mF zDWVUGVlLvzw9St&N4+mM5p7>tx~-hcKb5~@Yo`q9oWxRY14_l}pKx0_6}ZzY7&3*b z$oSyQi~4yLWwZ?c!DBF&v+lX@30d~E+ucG$!i{H5FQ2GTE2X_;TNk`381IY}w&?(y z&;uD-KxXLO0UkVGAZ`AS#R^OsZxL}t`6qe)3^-d|Ta_t4CsFtc2~_$tv4O?q9@?EQ zQ{Q}Nr~*=dV{P)L9qy+Qe-aCZ7jxmgq`*hz*q^ z1K>-^skv!cspSvHZO@w&sKnz=mj%DV~R zb@$eT1qFCo6Vge{NTSN*S-xKw6OLqCv5_@S34|Xm{+U(pEneXh;qg!lvZ1V_3SkoG zoc6ZSQa8K6dn4qLKDxAZzZ2axT;jMraEzFnO!lBv za-X$B*2ANc-W!&gDJBRZw6@9uhNoT>2bSLC^wM{o%*Lro_gyGU-w&eSro(a;7CrfO zxs};_`Zg}uw}m!sm5J)N&-*%rlGJya91g}vG^X;LjKK$m&s{?JU#RoEVb(m(w?{y- zwWjm&cjwaERuz?gRenjm@uDMnpfRW`h=B1=7_|7Y>d^G;;(zddXV&=hOZgVh<#PGa z+3X4^{w{9^y~O7657xelx>KpB{&`V8to(FQd(b6ENQ}wwwtpaDS;-O2(@o;-&O)19 zQlB#1O}y8rICzCeqct0|d*(F__dM8Q8N6A_5JGKTDz2|DkD`?jnv8)ffzQvVRw0>Lvb z=Q4Ksz6E>tBV2Y?ms`Me%&UYzRUFprg5dIhjo1@Umb-ek4fWO@YpLQF(U^Oz>x=zW z#K*4cBpZLCPR&>L{A6_#aWfEFw2+)`2+R$D)I~-Eii3p_WRXhb_|!@_TEq(VR?2Qe zbCY8>@kH?QIoixQsOED1%jStz9d2G|-xpmO;bz|s&UDHVowfIDB^@824HbvDpiSyJ zcq7h%&LlI-8m;B~`kaRbvYj^5wU)?d)~zpmrsPdMm%I^m`d`9Q&4f>HK<>o7P7b2$ zDyWIF?)|;Vg$@#2`1?&*Og?lSe4yNsop^|;%UzaO?^)-u%WltTEAcyjohL+`tCF>$ z#3U|9@yrvYdSGRgEGgPKSHfDEa4fiKHlphXmE+>VLHq@a;C8Ip_ zfj=vG1y1f8M;2zH5V@j|ui?5*?M)fl*VVi(<>qWdv15g{2N&eTs9wg$PSc|t_QuEz z5`Jg4r^s!$%=9_kP~c;!nLu5L+O*G%V!`0M{R0J-UW0?ci(Qym}lf4J!@ zca!$kRS^^4q)L2Ld#`5@*V`6+~$lsX~rGD&Tg39>s)QX+S``x?+RBOPA90TdeNV^d?NoE zwPX3`q#%0rPUrX8K;~uMSxNY!q4pQ>#1U6NrT9rK3e^5Y@HjzN1GX*LZ^DZ@dwaZBr z%jua2+`t#K%gyp`2Os11IwE0hZTI1th%_n(kVjGa7#s8Q>e%gi({;+-+L?Wc)Y;X; z)%izo8~# z`A1GMV$}#?IrDHNtG^FrB5btIP9k-QbP?m9=Lk zeoczTEt#Wbq!fc6w~VYI9O}eI)N)0?6)+*yRG}MCjIK+!S&2aP7B)*PK#7gO$?Z!@ zs??KYp1CgLm(NPWN3J*nI}(AVi{UhGTsZvE@X`>vY^wf^e12!f$lBRS4h+n=G&p>F zFNqSo4W+lP*+_v&bxk}#-16|KSlzm-TqBM4U33VUakW+HQ#x{WnIsTC$O_~jsNiRr zu@6zxbFN_$PTilGtC0U4HeHDC_x@*1C0>#E9Q~d>HSKc-s&=ue*22<7SBmUEQU|up zu1LIUBXq}k=u+1C+5xvHRLIF3y`MkxgvP7hXHGq7ihOaD{O;PJ>{Ns+x@U?tHuVOM zIOBq^moTf<1mQReb@>n+jC-FQ4v`k%WtzQe)uE5aJfu)8`=wMMP^<*;Lu(|6N99Rq zy*GKyQ6P+YQnX1OF@uo#x0`CVH}D@r!*&LU?;k$+->E;sXu^m;c2;-vpt@nQ_QeMZ z!wjy}?9Ln9v3%8*b4*<6;jWHLem6WhOL(D~`?xvA+d}kZApsLspOX^dQ4FS$RCQ@W zLEqf&el^E`L@Id<&G^rb604bwoJ$WP;5vI>hD6;d%dCuB75uooSGAVpte?`$8woeU z!1*6fnug9X3+^t2nU_-6gh6Nn`yA}>PU&!9Uce%&mGEGUSpFK<#vgrUF+cLsc(7M@ znpAqggR_J;jBMY8!L%=L|D%6Cm|pheaQYU=nd|@i@O0>w==cWV>6wfy#7$GF%+A~2 zm9W+Y$((nf5uWIeoSK*VUb_eH2ICT|(-g6Mk3KDe;cSVL)jmik$C8bo0(}EvUKYA5 zr{AFsPJr*Bp@}{+uK7@BValsAR5}E#X2T>02o4N->*f>SZ$nzYR@?(pmW7ZXvSm5a zV@x)+$ZLr~QwJR|?PG(RxT&qJAY4;d-#ed#gv*OP%p|LSG5f=tZDrE!FAKzKc;Gzs zWaS8mR9Qb?%i;IwnQ9p*{9R3?JMqmLB6E#tZ_=G7f&_GXwCSQktkb z6Sf6J$cK8`NQ87^3I~CU`VvKkb?RPVZit4H_e-NnH(x5p;6od!1GDz$u6nN+6Nh*( z!yWy-{G$!+`j@S+#yDbp8h<%)(BfOJ*$};+2gbW>7|xiBI-Q+hZBICeUw=A1=SKRA zQxR_lU4rWz)fOyCsV3$!Wyk7fJJ9-fHhRI`t67F7!qc_-%CJjcjEVggb1h}^%7*Zo z0e)SawbgYt&OnD)7d;C8l_b*0kePf5 z9bUd$2-L;K5Fm0E3yuq1Y;?_6};SRBM9Q=CQ@# zO^f?p(%1Ac(67UGeSYBZz#Y$nKn9i?j0d)ob`H+1-uyQp&XcU_{@NW{d4enpP0632 zs`eQpIj0He(tU58X4c5@dX-oU#{0}*Vmekj0x~4@Xthb6wo7mDG^D9&N z{1Y6ebN@mQpuuK^Im=U^#E2YY3lVUkma$v$+~vz7ug&bB%4S26kJi~Z+!#(S(@wx+ zYufW1*uWaXKV@v_Zz%wbw88AiVcF;C1lDxDNt$T{rYI z5$uyH0_`2rif#P;;s7sJ0}na_8BE_108!BvxO(AC$v`tNL^`1$58`8BMgo2+c|tQw z3|k=x4&uWWtHgdR4V0a z-c{;SV$AqU`|Nxu=uM;95Q)7n@_gF1DNrgZY_IBL%EmEqp-#-Y>D0h+T}7? z*qF7=%iSCZf-}3+MtQZJ3Pf|?q%Cnz6iRCs*S157zMXmDv7+A^*=>QPd3BAfrO{=* zm7+oeQS%KVSRv~=mZNS#+cgd#QeexTi*mKQ8L*{MW1ykXFNTy-e82Je)Y5m9dzAWC zi#9b4V|N}a^$hT0B85Nb&B52{Ip*Z@-@H0)x!bA|tZm;4ri;vB@1lz?JvG8kdK;45 zvRU);n^o9!hLs#x!p;mM^~=p_TLzMBn6srEX7jDm5Cx)!9bl?>viWbE@szgrk~ z!4EIOSCv&O(iTSp8(TEg-D`bEUdZL{AvC<;EU=Y|l?ieF?$+_F^QM76%M@w+kG{%- zem7u|5pSq4@ElsXb^ZM~Q(U2=@WGG$H*ls6kQ~@3WSyig!f_m;45v6X`yCK}u(hmy z4w9QYHlSHq9kTJ28G`l~i3Bxm*yQ=vwL4${M#mI2>HzTh&R*^uOHmt8S+;K5tyGKw+q z+1^A*#F#OP**~vT{{UP+;E8w&oRknN(&R6e+!I-p$O4YkdaYCMq_vG}+O(Wv$j1wq zk34GJQ1cxC>s$VG^|L$OwB!}O9xoNPX|7y}^sh8Tu~biD9Gn9%9lvnr2-D;@#L%2Z zYD+OJWqaI~|3;`yki+%acoGPQu|4|!CT*vxqNeJ(JT>Yp%a3P&lfXEILNwS69nqx~ za${^3SV@rwW!`G(7#+&=*dp>$;Z6g1VO-pqJb+F8u>W7%#6S9S0wnWlY@=h@sWd?qs<=tRa5oOdJN;E9E<{7rj5O~!kb z{7$kA%Y9dW_J8?59saZ(XJn11&#h4nTdPYLC6cMHyuXM1hU3s~n0c8p+SPMV(A_nj z0tGeH#f+<$2xhy70&!PVCm2zO`(dXir9(TT& zV{VxrRu^9xt)J}yG(pNsjMzU#Z#;`P@VI4Tl7U7FSpwX5UpGpH!VRk317B2=boh;* zO2nc-NEqjg1Q5+jN^gCt!zoxXr^RuG7hl--Eo{4UyoMtgc*JbC@3&M^%7GFKx8o!w4 zubK}&PWz$eOD`)#Xy30hhQ;Y4AD$>X7q{8-mb!T=)HBWsvNFA|rz>fzjD#xQahi*e2*+W+ zftgWWYHDs%C(7b>dK;T>^(Qfc%{GQpvSC^%wB#xLg~J~NPnGbwl9=()l8D@e!^;0F z{RE5Ys@}k{BI{Z>+@*I*_OWj4Z5RK8BWusE%GdlJx{p!F0Az`^q-j8^o{L~sHfKsV znq3|^1HZ$cIPT%FjrzZK&De$isU4XZKn)}&6J<9mw687in$GcM_xK#G*Jm!Ym&3z1 z_GVt?t2IklPJk>iK$-GBl=DiIVirK=35w&PVV?^8sWRWV)wY-v_HfZXuyD&_JjBQ9 zT&|5i!Jf(Z`>gK`r=Gm8(iq)L=y5kx@ezu4s#(lTYS%z7l+D#y`*T)yd&!Dkb+v=3!r7~?&Ba!M zrEast&*5v6q|FIpK2nqBCL(W7SPq>XTR~@FH)xcYHSk5 z9<#RAV@=R_6Y@05fSqn07IR6FL*$D9icgHQ-)-erFa;oFK8G5Xmbg`CqQ3ihZcuRQ z+<~dgTW{@biaBsP!V9Z(~0x#cQ z-xZ6}Q?})&1o^-GFFy98<*_5Lbz>U)7Dagw4G-Ejjn9EW(4~8>r1$m!!gsPl4>DQ{k`SBvd z^;}Cde(+GQ-SF1Pr#A^@YgB9!o=&t0q-5K+hD_L#${H<>e=l$EOrqI2Tn(7^UU+dfst~8eZT=CT}l)2?b_tgIub$vN;3uo4M z;CoZ1tEAE?B2_unKcg^SLi?D$P;wn6k7^0uh^Q{%$A^~&%y@Pej|xc^4vj0U7xf3H z0O&*z>Y=sq-sIvrc`%<=nT(ILlSl94<)WQhlRk;~x6O1i3Zgd~PvehP+>jGc zH`(Jh90cJM%_MD`cZ&5FmN@~V58S(Zz;ks?_@HeH;8#d|=4hkeD$6yyK!o3UDpYw7 zF#M%FY68iW;Au6B(3+N*c;NXJup_3;6{Bvn~ef1`To#GuN;rm*sT9D#Mlhns?hI2(b4d!Whk5%rAIe$Lnh zV-ot*V51vzxY+L3>4GM+*f=`HJO;h3BN~P1e7+hCt~$Ja@4J<4TLXrP z$!Vx@O40A=Z6j%$?lqHUF2&e?hlIJHeZYsIiE~cfEr($rj$9o$ z!#4f@eS;p=lMiIC1|HNpHhyV*@Z+1zB-yDxe-&5ZX(6ouDO?XqyQwg~f_;fCXe+FJ zWq~g*@J-B4@sK~b)nl63h71Et!~3@%$B`m(g+}JM;#D^__x2d2sNUz33J={sV~bP$ zjWZy~NCDx}Huk}yb0&f0MKO6p!}6?eec|+r&L+aeHQc2hnMV8yq7p$v@oW_o%h~cB z8c%Bg=}^~e+J-erm-9fS(YmpEO`gB@5(awlnY&>nk0^D;Kky%qUN?rbEN900`{Qf_ z|M#7ah5>_zJ@SWxdNo;J_$=LtquPZpjg}}1w9=5=X-nB^EM?irvDPI41h|gwvS@#y ztPf%vSxq@wagrdHk82LR_Z?&DS{&_>8=pL}$=g3q6YUP$aa`$oNUGn7fSc%+U9SUj zXY?Pa0lkDkwo0;9XaudPwm{cKbl|5D5!>;|BTDDukigf^~G>8my=t~-MHMD(>+J+&$}i+l3P&`;)*47Ppt-HwCQl&i ziy(36l7>&hUoErk3HK*oHHdY$P`0@hnz`h%c{w6vQqk7G<(|;8UO_AcsyZ=jWemG@ z2XRcNvDUTMDc}u@ep{ZCnQw)@?2lytisDC1X-Mj7E0QD&b9u4?Q%|O_e2lhO-u<~4 z3B!ZgVC+6}Y?Pnv>q6V2=!C<{FEF zvMa15z%RWj(GVa232K=-I{FP?tjt*3RMPFYQ~-g^)a_oEWGo6!OWjC z_YZwvqIuGuzEQ<|H5J(ioA7JH`fvE_ma0&psiQ8FwwJL`9&>&EF=5Qx&6`=~ zj(O%vfN#ibRA|o0!am*0$1Y5*0&MTBewKId>oOaA`LN=LqpdM+YW9Oaiy7M@OG@2H zg!g{RBlR%-pQ>XrbUwhvtR@*m)^BrlHIxgssW%RW1Cc1+$Ydy6a1)AnUPs|O;Kd{r zbc2)=JtCYNHs70+z>nNmJh)|Fq)1&DlfyY?WITG(7g#ay%A)z7;q_I0W{p1kr$+0> zMc%UUI;$G>rXg=+%}FN+AmT+OPtORqWSXU(zql2QpTok9Lrb%o#}YX7NFl^P7(XGaaWseokrBxyjE8_S(r--?Q@O@BY3(kTek|L|_hlypN&sh%{tvJG zOH3c@&l@@L3Q=dh*We2ArEUc1FETsJUL$dP*29VLt10!~FIZ3wsd_qXwTr_dwEF74 zvQrk2p{F`uvP&m2*%oyF8Cd#SC$5#&Wi7q~&tW^sGUdLlbl&>OtLqJ8#X1&a9lZOG z0i|kw1G6oPVyvC3*isNVMY+dF%5G%yRB3NLOn#{bNw7A<8BqBZ=4ZaCZBC%KBPwV4 zS1r~aH2oLpIv{fE=b)dM#E)=}&mAW+EUY#WP4Cw&%uapjuMYTJbPy^HE8*}*=uer= zJWfAvX7bTKYy2Bt2WO!pRcKRhgetWNkR19l4y_mtg$jbCE0bNY-WO3i=HA;l-R$Kj z{OudKVUb-x0LehZ_I_9BRB?EOwUVT{R;0TcA>`|N4%a^!u<+$fgrPxd-L!~S&3ahk zG#U7m_R0FDagGY`De_3d`9HEwip0Vb{n)~_$-~gS@Beq83EKW26EoN%uYGV^Q-SnA zs+Y=Cn_7}K1N!}=_Th>`tqYg!H{&4zo+7Cp=I zJ2>(VBG+a&ke)CDb$u^HYnRlS; zzFTe!_4s$Wc#zM>r!T%qqh&39^`Cp0{VK|OF4k>QW_6ezrYMzOCN8B9Mk>Z-J#);FRJ1B)cyNv9FgT)lFMfFMlkE!bnWOMENJ>5MmZMC#^TUE7N z8ftgZqNo`w)UFY+B8bt2)~vm$8AR*|kx;vKjR+!%JsX?Y-kfLjdB5cIo%_D7|NM>5 z+tSZbw;|Ho?|$mFlg# z<{CF*0$1=`hX9Km#F`}0tx zR)=r-<}L2MRzg#oGuN_sS){Yq{@#4fDq~3b-+Ai~m8R0=4v(f+rOEV&QyGMdRaq@< z{tna7cp7K-3akFhMPDFUi9~!DTUb}CCqAXHi+eY>+h?0s90rT$GO-e zX{vH?XL)e0N&opLOmkECl#vKwXzPcIa7=qMeG#!?uhm34*Sv`?ND)_%CoSO}Hq6N3 zc^jGROiNsg5}PR{fVfh3y$YX%UTHlSf%d2caOz!4=|Om6ExI17 zMh#DL0bfC=IP`+E1>ySZjVUHG+d7(b;t}h2X-U0g|OAX_lW}E#6S9%`?P-07Ih>uA19QBQ> zqk(DOE4EWW3eLR5OW1E9W5LYWs04LsL;B#1PUwz9G%g7wC(Br3-zurNEc>oz_Hx6Y zw{GTP%@Mo@HJX<(G;v43-hABO#6WH{+f(kBHM&SZ@iV!(Mn!6Tkfd4jLO1NaGU=Rh zkL<==B-6I&B=YI6i-%(xZ;JsF=;tIUm<}S3)BzXK(4{lj?oV`EYMULSBAwM0Os}D^ z%vbdQ_Z{0FN6maGUk<1G92UolEe)E3O2%8?Kjb~JZj4P%Qs2D(4&H*qXVlXf1|fTK zP38CEp%o(sVoLA+T-m^fc9O-RMtYJ=&S_(#k-Qas@~{CK^l>f*6uekgxAcVY93DMBFph4`6UU+k|fl-^-bELYz6 z^6+E#KAyR-htmJaMyM7mOmI(pYpsj)!aU&drNH|h{{WV*c+MQ0d2Qx%=*;=t-n|F? z+`?)b&eTvjGf8vKt!5o0rz`qT?@bW+!re?NI{ob5ejy&nE&VBB-cM6Zv?5=l8TiwB z;!BI&S3&1W(0H9x(Y#sX=Gxydz@fo~sg6e%e_CH7FPbfImFk$okZ5CSk;6n)@-1{9 z5AH?V6|{)7m2%m%>%4aJ%5k~h%tydEi6y$c2DyuT!d{(;ZBm)fa}lO(Tms07F>VIU z`oQkBED0+J0Wm7MN!hycfV6>a?h zPtXeoaoym&kK3`V=7RT+!-|V~%1<0_+wr$qW2??iRXN=vx^X_rOgcP5hkbEm^^$dt zsQ68v19z@7sISFbsM;|CfARCv zQy>2KZ1=}Z7hhY-&0o<&ufcPL^iw|Pg-8l-XpG=HEk;BmcmC>^>~nzwt3YgHIu%bU6i>sw>Q59`HVvrwV>vz&pvr2|ett z8&MMlnUy&Umc7RB#h09QCHi^^*8tP-7rW<~io5h@9S?CAp#+6&n?U9D*mC{AZKt{I zA=qN0Sk=vyv3cT=HLAiQ04@XOOuM?qFg~HEzF_T}y5>DKw8jt(Kn^KvJS%Zdq`}8i z#Zf)C!Q1oUO^msDqng>c;)qKmU3&V=*wpTd`0?RPef^IueCodxYp4575K#m!jz_JI zh;vgQDMqBQF_zn?IWJ1Rlo}Fq_{rTXY#(StJ`!E}%L<)ts^*|zkE#q0fS~PSX67o4 zE)*fZT5?bbNK>jfEjX*q`CwqK8|(AAkchjtLSgZY`@L*6^X&dpag7#=$e}!XTS_r% z`=XpBd&LQoX4f)BNtLd%b(i`jrO0-W|Ebv0&@!PF@JtWp#xUGjeN*vQI<$d#B(|3- z_$N%9c|bH$_#DEzv`!f@Z1OM{JymUIPCwEzx!8B>k_hvO-u_o=8#EPm7yX5W-Mhbg zi+CvvZwLo~`72Yh>0c?pHgk~zL7Q%!u}32f=Lp7tMEh*eoVjeqqq&bfo;LW|iaRJR zrRun!ABW^BQor66sOqsKKO$;|rYGW{bHlYmi1(pI`&dV~XIho$l5v>lWjBK~@94=$ zGbNml#}&3_+&+F*ocPJ}&&1-jcVy4vghO7BGZ=Wx1qJCC@pUe8h9P9CuFV;J12VmF z$n4$AtQV4_UTH`9j_P!V&MjS;J^IDg5{7;7xhBZusaM*C=BCr`jEZWKrpkLJxb_66Tk+tBVtK7T^?{H=tjmxIV$yHga({PkwZ;NoZnXxiQ0lg8WzNJ5Uqh z8aK?v5Rmp?Ogudxvf_i^KTabjyqiDdNe+lO$NRDpL`K_i5BnshnM(;=MRR20MAr`| z3YkolR$qsDj3g0~Hfp2S4cEV{EU3&PgiTWC4T@VTbE+ifg~KD<{rYPC97ld|H_)%| zWK#J&zpIV`OQ0EFL8@&QbQ|&ml=a;zsz38*ptjt@T0gqA=~`Ty*V4BPv3zNKLNWFB z!mg~hX2*4`4;+z3#rb&6yaM%jH=)f^#CO87t~1u3R`^+Qx~k$y+h?Khq~ZQq z@Rn_yOYHT|Z#jgv^}?joZ7(1zEv~fw`w_G1TC%5rSudvbFOqhq(C@=qMsgf~D;_te zr0ZSZ0)?Odv*B_-D(2zoV{=Djzc9t2bruh|FAR&pl7l`Vc$fV-V&!NaV!a8wV54$50mrU<{f|yOF{!gVORoHnrkhY^v$Pz_)rC4cg%aAoOlkvzsGO($Nb>3b13_qyWyoVR%{VxGyP)2gM zfn0Y$gvAtUD$IuedgN?h2lJSA6P1$)b~Tus9#eELzBeR*2O1cvS^=X(Qnsg1Fdwq_ z{-Rr>`-4{%zb2g(Be^9hidKT{DxJv+aH>efgDfM_M7J|-5-A%^1hh`1drIyV?MbZ! zx0GW0+VPKY)k%%$-;*yawLSz&o#Rz59UOf-;0N~ojIDBhs5O@MW`&*lMl`q7a-V|S z1uv{qXjdJ7+&iel2%bUy+}v7J zOh~`Jv!LFxVjplm+`IOkIE_`^ug*EcEk!j1lZKxXRb;9we6%eW*2xN9^zdEn^TS8# z=6CB=DATMp)wKlE^@)^E-R5sD_&fQd@KNY$e|xB+cXUTw+F3=gLB>hSY))Bh%GN$F zOFhl@MgoKvA^TBrQFaI4sPJP){66iWM>)VN+XX!rEI+cKh2s5~MqVBloYGVud zTNjdD%>lQQE@k0gKwA2DD&o5Jp(UmRB+c<6nqTey&gZ-eEX8EV-l>*2ZQ@r5fv!9> zJ0}N!DVvrY@Y@J4LL9bRPAMiRE0~UwaU8^7`6UwSlXDxzU*D#GVhAS33vc{rNvOSn zw(Hk3KnC5mb57IhVz}SoScZ|NFznK3=9=OaU3W4ky!fT6nw;tyBc}~&aXo;w;Pq=d z{@-Bu32Z+JU!E}X{IPfEJ9D4HWjYpe!9bw6@{4rnMwzX~zT$@k{&*~I`HrNKO~1pF zLA7_eqR4Oq(%4dl`BpgnSzG^o$c6R*Scpvig!&;S>wca1+hZqEYRbo36&l}Te#}B^ zAJ+mpcQ=G+h5qUY3$nv!h1fa$@&x}{%36iqM#c7!+RQv*v51?4N{KzPgDRf5^K`4OR#7`; zd*XCGt54k_|FCiBwj=h%oS}@GH+{4ax2582`3Hh>7mxc(Y9W2 zDZ|ln+fvd)E5bO6gb3A0)E$o>YwX?G#P^FW*1>hVLJFlIBNCJS=*CE^IjN4s0jrEs z^vyG+$`Q|XU0eRzFnp+bbzU?#IED6K~8RRnc2c}^3av5}cY#!V zNzIQ*R4w?K9PZR?>qK(adTVt@57XNpjdV?{k@I}>vfzY85&&Zh3>7<=5A}@qr3;CL zxroPI6~Y66x(z%q;oNwCWT{cM;9GLNu+2)A6u@UPrdPNLmmKO`K~)WbjA5b2oW=^p z)|Zy`qH7q>2)79@P zn1-Fotunw7td5cfEfjkYqn7(@#uy*e-{m5~2aRfp`3jw(x2);E z^sWt)CAd*6aPYw!pQ$P7NM`1PIYJ9DN7!&D;?Mk9?8m#=SP8<2-E}`^$$Y+q{_FNZ zqUvf1_C2ciP;vev;;jYJ_75@rikxkRfvypwy}mdRfUUp~S0Jy@+1Z=awBICB*KRrJ^m@!HEi zuy|6cd)^E*v{)3soJ2^A?-17UZ8Is*H!5}%ZeUp|oqzH8?-i@L##8@WFW!XMh$Qpt z?%6B)FOkf+_QYleEXV~Q@9I11_EyEgH&3D;BY_)pOkmSCi8O={E~L0H$~Y7tm|YmM zu4U68!Cikf($|UOSIg?Z~MJGwg?*WmnpT$q0Ci>&YgaU$Z95bD=Wos)oNkpSGIJhyp%uO7=3xE~4XQClCPR{-Q5Hf=F%7z!~?yPWmqKANFcn!ql>kZ(*# z{APsS8^Ay6G2RJWxmE+98HC0RoL)%g(kDLQQMs0(J#TWxrJF5%j=cl}TpUgKz8??z znzZW==t5P*9c{~Gb}!8pPY+vamDDHu+i2`DJrXh#Bx-gXAwlMKrknrw(}cz&Q#-bJm=3GZ;4A6HsDhMT=5=Nj6}<%g zVJQ0D5VW~B?I1A{v||qSnX6XCe(aa+Ht7jLKr1SRLtBF>%XJ6v6F_&y3HjIVwNtd_ zB?!ZN)yXwF#_0aDs(y8+9#hd2H&PwVV63dD?@|-HW9${j_=bM|+kSK>G{X5@kbYWf zbK-TYDt*mzheDeq*Fuq1!4a-^UkdC^Uh8eESTYhIM+KTbxqhP$_7d@2U6o^BBKSL0 z*C)XDhxV0;V87f86AzD-?uZ+B-rqWnA{naLw=P`zof_&ahxa>@saXPt?H58yrA8nAb-clq%>Q~jN41<^U*Tz-F&y-EK!Ggbk z8j$z4#?a3W5f!ZV}8@T)I0DDtZ8wsA|?t<6IJRkqjI29C3p2i85`=HsElo zqM^Nvezi7hN%umr+hNCq=c)~>w-KvuQ3yxjd99I^p$e2ST6E~P=UWqS6)|}FUrGJ4 z&p!vcW^;SsQ?n7fI*(SITaN5KsTLJ;@kmWre~KiDYbRDX-d%lFXyiV*sHD($u@!k( zH2WD7IFB5duhcb4D)T^_)D;anU(Re$TQ?vd9Db-PZ$#}F} zMn!B%eDO%FLt)NGslBG9)H$En%BN(f%w*A`*M=@h7mFDJ6%c)}nBIh361`TUJC`Y$|{H;WQlK-vuhS4%b%s8zEK+9lI0P4wA2t- z7ttAS*z?Uiw}Af#>C`y!Op!4#id?zVH4I9 zr#xBkdIF~fN_P=bDRH5~W&Rd~UTTo>V)$J2gfiBe$F!Qj#Hr; zuFyrt412E&xTmJ33Ac)N=a>X(6_{*n2CF|?cA7xX-%mkPZDnjm zxQe?bJ6gxlKJr3H9JnL9wE=R}`zEVs=}BbIWgG8#)1Dvj59F~Qp(oy~J)_fAkPzMD zfYI-$oOdsO<&yZw8K~KWK;r0dy9p*zv}S&HFVHD!b^K4Gb)%1>ZQAWg9ToH`jPiwU z&ew1&;IsQYzMLkW7AxxmrX6p`ejKe_P@&xgP0-aUe>Nt`6XG!&sRnW*3_AXi4Q7Xf zHCsx7!r|9cnZrk7_RYXoDoZ`4UKq{Dsa{+TR~W3aa11nt&FbQj$S*@G{=}BDDjE6d z#mkpBqn3hIIT2+RU?Qf-&Y8%vrXQAPU|nf7XHugW;dWd-rk%I{N&`;d$@zmmwah;nSHad6x8TinJqcoKn7!wbm znjr(lOLv}9rjN+DB%^G2|Knv9fKlmb^Olp9_}Kn=>!oddeWN$~pcPlpX_RzCx)oDx z;xm`o7~$YuGc~631=5+VJ`T+Y&!CcIj{c{;VdGAQCuSkee>W!r)EDdDQ?LFx%7IBk zLzN_4IdOl~}Ni7%(HulzC+70GS)k!O}L1G!>nr1ScmpCVc;AZECv%dugv zLP#a7WM>wU&1dWtTUfGj6vQq4mx^g`c9Z-gXIB1^;i7w4x>laFcf+Nd$jnq(CV!kq zwCr}v9?~F&0?6-UJHK;3EN;HDAHo=y{p$!3F)u38K^S$QaICLx!G{6yWb|b z`t7BAEqC6lw$+BexknapBfhcC3&PMN;v$_3(Y!mb(VGG*P4L#`|1dXz(7)r*7sIht zQ+<14==9}hIac*CO{W+d^`-dD1tB6sDdkF?58B}MpzVso!kqg!AYfT*rCSc6K#}UE z`Ce}xla;^p&nKu3d%!Tz8ZV!m^Jm)4b``^TON-DinuQ9)=g`Q8<<5&s?=%}`EX%^ zVVaHpEU8mdsv;m2BN2ut8(QsRWtCB`8C%!dv*JLr@7C77>f8>(f&ef3T0!P7UNAFn z7Twh2gB{{;)JxaY-ljEBc^2|CMr(c2G4zAOeGAIr0RlT5vQv_N{IQlTnw|VBZ!i}c zNjLZI|ECDN`L9wiP6kYxV@dOhe>^7FF{c6z#Tb&*KlVL$=Gbd*B0&wR=2QobLhgRR zCm-qa?+L|$x^wwwyYP%9obaJhPBJYwVg~E%s*C=3xPRr8mnh<*XntwQ{MHx_uF<0SbJEThP-|dxoAASm^>VeQBomptAgGUQaI#)P z>NnWX@*<-K_rr8`SPXoBmD?o)>?V)nxr8QI>SyNLcmgj(OGSiupFZiU=o=sCIOryO zoB+pxAoa~y58f9yc}-Q)Dr7Vs-_31}>GM0^&aJKgnwfdJZ|UV$e@-(LbyrLJHGv}d zy@D2HcCpiuysy^Y8;04-JHg}{<1=xPHlA_Z^S=cJ5+5TIqoL#u-SCHv0Npj!IqOr=yE%Oz5#gO6{f37=Udq846oHiq#Pi zc7wD^(cjiEK+t2QexCRgId*#o(9J@1p(O*v2mVw<_1>IA35ZX^p__!3;|-si=Hs0G z_;g`jsL;o2xHrpWCQH|eUnXWBUQ(x?)j7Hy4un(;ar;rHL^a(UizKzKqE+6jV|^@0 zn2G;xjvrsPxYJj+;v+5nDos<7wOv*>O1C&NoUU8f;7Gyx zx6Zs7%YNoBF&vAc4Orz>fWvw8rFJ_8B0hIFQMg@Nt2t?U?krs9O^x@~gPP^sx=#k0 zM3bz=={-AC^y*nBQlwGND^2OJ zAhM!o<(*oD#5DTR`NDZr%_@pd8E+S;%|$rDUDNRNrO5Qd({qGcRL+>DvZrk z1z%EMh37r})qN*}BVD8RLCW)*W?MY{TXlbKo${y4yIk_N#dSX#tHm`WNX{>rJi>3zQD${?q6{;EMHw&EB9N&r3FqYgAU|w|8B0j zb8BV(m}gBc_;|TKW_b=qqR*4J<=7YuNEiFQx1e;jwBTuV%Ip@Vju_m~E1w(>Keu&H z%W(pO2P`b-xI4gLa`VVIX@VUlwv3KF*UYTD3rUm|k5Rw8he0=!sh|SF+ z&~&0Gi@>hvaOCpf+Q6x}6iqK60i+DUUOPac&zF4hNV^D7;R|Jlf<+cK8`j#}+f|_= zkqyl5<_fTJpO6UyZ}>mMXcxiEK`us!X7M*s{~3EvRo?bRI4#(uJZym~yH!Q2NO&IJ zJGy1)$>T(Nq0gLw&R+zw*8Miwck_Ott-Hr!R~v3ue}Yy;W&Tu%FISR`Cq zH=vetHC-)RKOvJp>J(uK$PDDGjp;HYvj95D5dpltId?WTbvWrpMkgqBFt_98#+ma= z3;T*X3%j5Gv@$sET~Wm(TO(kvg9Xs4Xt6)i_;rO^`_fL!O85YwkrSr&L=IF35OA`= z#_Q=irW#a?2p{Sy2c)>87nB`9apyQq!zD%>)=oWXHh#|pWeXgKN$a7W8 z*?+ExqUnEpbOl0Dtb?yKqZ~p+=ED-@@BS%Mc9XJEPSUF*S(kTT#oMx8x6}1L6Q`T7 z%>NbLq3=VBraZU&>_0_YC+joqswtIlAxzE{$%+;&mU({E%a#%aomiUjypqLX>za|| zI=Glt912>Y*RzD61p*YQMtRa9qihYQV_N++Kdq&UWL*i*@P;+Q8IA*b>MX|K)Q+E+ zP`=SldP6KhnBL}jciM5o8zu3k>nNG>YWLhPn3T%(9o^m@sf3iMAJpfZ$0n64;5ovlft9d zvBv{I82gHmz2zN}A2IpdR`{7-V%g#rw6sY|ZSOzOI&~2a%Q)+Vk_Cchr2wLGeD!*F zzOvi0Q?evd_aX~dx<}^?jiIKDQEzPm)|XFM%&~XlZhW*;C%Lhr=$6=uVZN?o+3gBH zI<)$1OO#ki9HcSh;`Px|-9;0Sja${DP{dWe^w3VP;|kd@yv9pn*5=!X2{RLwm;nnr1p+Fp((q)zMc#a8>{QOH;Hm=L6%f8`93ydiP`NV^u%BJ3f88 zJp1Qp|L%p=x*5H2$+G8>eqEUNF`vQ`fLO@goS1Rixxq-bI)H{sZw(VhwwoZBx|C01 zPmbpl$AI;P5kOlY3S&T6)t4Y#`$jS9?z|c5ZJTzjFE@{ez_hyk)no2-x=(30VA}C@ zP^i-KFlyz-eVeYjttV=B==y+0Q&__M5QnExK1S~<1lhfLX;&IdQht%{v#C}-WU?EB zxls(^y00-_zEGTC*55tox=62s(x)kh*X&L|cy@^+)WD+(?0CVw>&n;J8fue3?@MV< zb1j9H*UIGnv_x3oHADQ3=zJuG-xtXA;CP=jRFJ>={tY~6RdOyRqUB@DJC zI8HrcK!f0PQe1hf#d7V`e-pPM5+jK6b1jb(d~tN+AYXvjDm(D{AN5t@n zjX+h}!SE{m)N9X#71z*gIIfSK!_v zB{8jkjG3CpzhDR_9?H?RCiNp8-XQq@#hd!4RXf0vWZoumvgGL=6;vo>sFB7h?Oaif z*@>o2IOJvwbb8+RGg*e7=plaTU-oCk@QWMyWK4T>=EUlwh6qqz2=$CpD>P!T~X_+4Ps%GZ~5=6hHVzPucEmzXhws!srIj$Adl0 zzfStUDKk5iV_)h%&%QZL@thnf46q4LnbGqk#G<1?BJWC*@9KqC8JW0O*l2IUd5#O? z+_ws+VEW#5sRnU-)^m3l+`noXIe$Y+>9<0w%|j(8n7!}IACupwjth{FS8Xl=0EMBQ z0-#eh%4rZVx_awbKRqduQzupTeZ;Hgo%8qZ{NqEN9j=7ttgM@~uV6Y92{rpPJwHTA zDxe*BRFLQq)M}_wQI+wR+20>6r7p6yW^i01*QNXzgK9jCDnqh6t6NFbJ11bnmcJy9EkM+$Nwnt`kc~dqg{y=ZCB>0$ck~jZw;%!7TFN*7Dg_j~`Xy*mH}Z~GQad@z8ZS}qtm@0#CR?7d>$!wnJ*C`xLAT|K=t z^j*Vo|3rAp^WU{R>HeD?K|Gp0-e5NqZo%<>$~W-U7XT?O7?k@=Ng-w>ogu0H*nfHy zojEcJ0=b!5x#U12i92SzmIEBW8FKFbNb#m-4D!h`=xt-SM78$h4J$~Q*^^T$f&TY z&nZsUa}{5SxH$6IYjt;Y96nI^W+(sb!bqJ@qkaAK4*}QW>YVxaEqe8VRokUGnc#^e zfnrk``Qa~pmGoY^>Q(%Vfy%8=-R@p7b2h|3umfk1R2#Au3734zd8QO*;*4FG)L!nEMvdmPbr^n zu{Ukd_#}e^h;5X)4L_U0tH3Z`!a0?B?J{kPCRZ$#q6|y%rC1ON8GK|wB0To4x=wg}dV!WXPGy>SCU#w2_uEqCmQV0{HZgl6= zMA6fTvzbe^v5q$W8W-u^zw|dCe+z^B@cUn*Xn^mU>dig1f?V`8EF&f)H6#~e!=tcU)*E0 ze{+vfc$lRLJcg#duD}vTaqSj%Q9o;+t7^y)a1@1%L^4siF}=^3<7&0p%>Wx!iKRJW9N6C%+_aEjKkQDOM| z&~D2uk2mh!=g|cw(bWCfHq5%&g2OuK;qke2yyqL!jzfJ%NTCM`81G+D^F6+tSUV$s zHEZqQ&K&J*>>xxxYbK={mo*v_4T(r4Oa#&Ck`-@}OldNY4MdF6MM z2q3M{#M&o)#XkZb>OkKhtBut7D6k2@SJr9ISrSF=eL(+RqiGwDt}ym7C67uadzswW zlvV5SMWTkhom|ncZErSSp4?VGQnl`RT@qwk8H-)Aekxw(WrEU+u2nl1j@oHB8ck~* zetgE`k;>I)4HdK!Hx`1X7UEkt)u^z#=ge^J!NG@)4J}h$P(*@Bi)%lj$lo3XHFr#^ z!-tC$j%iV$zLw(k-jI0Cy8_;{j}QMJcKxrSOVpt|oi;Yksg;{%7j|&;SLTk%(8_>Y z+G!E3>jODHU2ON-K?+D?$4c7Y8yoxa7-&oTNd>@KdfB?gY3y{nmf+_Jw1LLOl&#yW zAdjc}(kT_EAqSs(Ux9V;$c%%twsmsqw#0 z_E`2j0S73lOPd@@o_SX^R>`2E2b5yV+WeP!Gkj??auZ83!9Qy66I>z_f+zo57F2&< zU(WH`gHn*X+q+?S`w4w+%L}3$NFR z-WFI8ZUq#=XwH4xDgf`jGGSr~mqF7mVRid%i{lxuj<*QKKx}squB5|Mjkbrk+V4=u zOc5)(HV6D_8=5@+yZ^yy?50J7reHXF8;_fD8risGx#w=7@QaLc-}}wsJ8|io{WkH?X8h_3zs6CQo1KEPZUyjf)vGq$PHu{d%j6x>Stwm!%S(-Efch z(qv8fybjF(S6$sHHL_biv--0u1u4su)m<(B0t1E|2(l06FB?dyrVQd?CcMQJ>m zRzl+P-e7B7OPqYzxdmqXm*oiAjq3vi5p?JsSjRVvv|*u}(%}Z>Fs7u=L*TTL=BY=s zvz585e((Okt1f<7Hm!vhj-?K&lIAUEzrE;l7V89SV@$YIiVALz(G1`%Bx6I=b!f_M zt)yP#!zF}g$ytE<+AlQ;C;!i5=({W4@2K2=ivM-tauyB8_Ye=viz>?VKQ zOh_Rz2kZ4bjAGEBoY?cfE{!glo75d1{^BX_4n{og^V&y3$N_8US~$!T%lUO0+5Dxw^UUnt^K^=ffLJ4hEoz5lr0H0K`gjh3+ zX98ebe12rqcegN&)%?qx&t4{@Ki?eW0~*kKRVZ>Gx@=T2p4UK*>JMbPyvuYn&WTaG zaxvHX>nyzV5RQC5+vFdV^mZ%AjE3RgQTeei-OIZ-cY>Y> zJ5M9Kjg!cG+L#qkcSN+ZqC4x&`+EawEhSI~-5dSJ?qwL|L-xO`$eUYtd za{<-&BfA%B*k7|3GsHE-nJ4(pV+$%#h9&KdUqRCh|LVG8xSdvnAIsA8r%DP{lT&$# z0iFPlHin+<+}w$0_))I^o&o}4ogHUxDby$bWw3(5x;pxch03f#f#P_7I)efSRrCaH zT2$Y@SGY;{dVj10KOS{-^dtwTxu?4?HWpe&u?TA45Q=A2jYxYEJ686jI{dMR zWz&<*l-#=>z7Ota3O+GzL16n- ztL0sd{^eZ@ZNk*r_aoRFUC|YhKMzI9iah;#B+K00hgIdIOE_56+gl^!{Aah<^@SG)W?~ZF}oE?EP+dl$c*h zkpE>@pJlxCv286~JYXMHQQ_5?#k&l61drsuv=HoA-QmJlcGtpJw`FddOl*~tyoW{1eiMIz72Eg*OxzjTJpt*`7ck1^bc5CiXM2q!U(Z_yJ3HA#|Jk;^unUs@B zK)D~mN=Iwblxo<}I_z1I<@`~VUnI8e)Ge=5F8Xr-%KjZsjXHEf^z{(fRu?owi}1{D zz1qEY6FmT!UBn8|`nUT>>|3D2*G$+h676S=2wA<_GAR4{M>*XIkTpYeqSBHXfE?6H zw!d6e1%$QLjCjjc?#KoOIoKF>P|Rw<9;P&D`Zld->eU=-F*Dwe-f+b)7<8B$CcJGj z;U`L-UPalP(@ek#LrP)EMY;6dgRgDH$G;<$WN-epPd#< zz=9^9|8OQRPqO4iwFnRS5}jqndKB8yy}!Z%+xFGV-$MKSjon3kD8Esfp#x~!?tBF3 z*TWNN31|h9>|;Cn2`dL>S3^-~)jW&x_x>gKc9`sPLH#+xu*B5|v#1QK#;;-L@CY0YB2g>ZbRmq^X zpt)T0T_@7bib@+FRpH=BjA3uVJ*HLrwA}}HouDrlDC^5ZvnNIxEy8qv(PKD9dijT} zFn4<~n^KNcgeVzC#xBn{bPKS69?Z+((Oz;*;*Kb)@66B=guD`Q{02g8yih)|fLXZI z@(b%*ttQ&}%dBZ@K;_a2`A0=wr{pU$<+`FqgT3OMed)iRAWb^SlWV^sed@Y)HPB)| zh@*B#iuX0SYYk$4bX0aI++FlAf{Ou^UJ)0fZIk{EO8~68XP1vchPbWtIf-5y%0EXz zd6)KcZ?FrJe<(pt^eiLbpPSs1cpVmMt%+NWTP_!^N>djpoqL{|$A^JR^vy+@>jPdf zznX#VodvnY9gWAAF01qQSFIk6bz;oxp%7mq$EsOs9`nT&PexmQ8ghb19*+4%f4nJ6 zsR|&n)kQ!y@*RH;gUwGxa^hk}#&wyzFA6#%pP9F%JUn3wZVkSe1Iiu?OXbeBzD z&;QgG6I@xDpf5P^Yn@S1{!WkH1YC|XRtWPj-5xtEwnbH`sa9oQhG8&M4xzu(x1j3q zDzyF2kpsjLEYh^3{$PXgw6My}GoY;|PJbmFf6#=*22-&?V{pe8f@mswJr070Zgj&B z8353L5DHpIuCI8Qkt(!xZrqNL|B<B{=j=B=rrO#|_- z5xECrTJpOMmrccuD)vOzm?4>jPP_vw!|WlYC3hvb^2OwVbP3L%&M8inU2=m2xJ=G} zC=)p*ukc)cKhE@n)K0PaNkAjzd2hTWnYmN)d=`>L2~{+e@>Wngf14rnLAB$T=S?=u zwqbECVq=M+24GSUyaX7=zmYsKRPIbFl7nPXm^FYO(*aVPe-j-u@+Su|Qldd^FQmo& z+Ke}==KbsI>zZT|7Qk1i#&b13&WTDnKSa%joSuLJ*v79Z9d15|f`6$lBadG30RkpA ziho-y?YP{z=X{daUzZJfjdaR?0WH^y_eCmgeao1bzvIdsTw8DQpOAC{75H$}FV0Jl zJY86I{xdXR^YVg#SVzkxww1Eh$?5p8D;al|Q*~w~)-AZ<1Ua8-^h9vxgU3=c#-cHK z7+)XR5ea|PLJTd&dI>Xlf1siUmSF^h0GqIMWFi8;WkTI{))eYd7_ z_wH}{jjMI0n}ZZX4b()54!h00zN^M~U#$k0j(cYQTSG!4%R##$TBCBe6gp#=S>bE5 zX>(?E3by3T=^Pu2>Y)|o|J(pmrswZ5fdd?#u5_zhESux)6KJVJ-*nEYORM%j^e_1J z(X;4+*_uW+JoUa~kAx4q587m0yOGK6R*O@8lW_B8Pg#?zMCcN3ow|1(FS0c~kDj`T)_t7a!Yl; zOmH|yV^ED+FE`k#L_dikh zbT*_Cc*U#i+Vlqu=sxQxjx3F*(m_?DD=ZMB`pq@`K!*7jnD%pc728~R@TtLYYZ7md z`2piU`K-5^KJnk$tQ8X1()HQvFG;2#D0we;Pham^&Af?iLxd7mbQs@+ zM{VW*So#)!ru+B*?z-<(LU-L!l-->VP9^8Vc9&176x|6iETnRnCFZ=XQdG)1Ipnld zh?zOf*vyJp&T<-NTaLrb%-GoRx9;!nPk24v@7MLZuIqUsTeC3ojw4hPv9#C)By5Ol z;9Iisbg>jp1yb4MQD)j9y1l3$nIN=CiGPyBIXg`NkbN8)v4XiNe-upS3u)qgJG*l1 zum(9Q*$UB`C5&_xb~}WD?l5Yg!!L%B@T#?Asn#zuVivW^hD2EpV-Aw@geii6rsowS zF5FZ-DmQ4Vszy%v;RX5_AAjJ{alx2hY3i3K=OWDqAl6w1eJ**J+0?U2LT4i91YFeE zgbOe{>!C;a-rF1 zxdJ;D2%SwarSv8Bo#Rt~Ux?RifCv&BpILrsD#<<5&hoX5VwJ?Vm*I31xpap#<4ntXfWRoV`;~eT;s*@iHyWwjS3X zT5+x?F&_g zvxL;ga+d2ye$-{VS0c8IY4Pv<-z6){tZ$;v4bkIFd)jJBm4)2rZ4f3ZSG1k3_*t#c=R}w|;8zf*8^{uZ7jof9o-6_+ zd2sLg>In`n_NsU>@12u=(&n+*t&6YCK`zp=X2#lWlq6WMu&vqhpLR_?a@eX;%AEhd z67A;mT)ku>IBMklnoK>$GGM;?A5ziB2FsPvsko!?hD{8DfnHf(Ek6hk&%!3(B#;K{ z$?*hPX4vT7meU$V8(!0*PHvcguM^#_D1jg7;d7xLA3iujD8*OUAfB}a28TA-6H=1B-f${SYKS+nLd8!;pUdcK0cy=b^@e6R zb5b?ddcWJ#CK4AASWk8nq4$trj1nhZ80KIQ1Y7mNk)BhrSl?5{SEr=+|Ts z15Y-Tyd4V0ZdS@?Y0< zjsWMX(KhMpyyv^1YkT-4n=8=L1DPg+mAok^>0=gUSNje%qw1-Uwd~^>9KlJ#N~S;+ z4nkg?!YCJ$F$p(g^!B_x`?mPSn)mLL5G%!D-skAqp~bO3TZnBSm0`K`Hlj*gUEsZE z$)n17#XRIq4IB-?$It15A|q2w96MQh>+CN5>Ki*6w*+xd#aiPo4chRDz(77Sx4Ne6 zUF>`;D@oo`guph{R@%T$J3nkYjhand{p-!p=*xuj%mRqm_fWM{vIW{Uora?~O-`nV zma(Ldhz1AO_6@h}e>jMJc(zR7^fCInU$1DdP>wnq*IA;<<$Q_09>2ef8ul(FA=;)bn z_PfJgJnWfU9vA(8^W)Eo5}7eCIpX@p_BsrK2U9OW#)7)t!m_U=63%mJGVc{xdjpBV88@T zW#SWU`AK}U53Ua0FlXhCKqhy96ByTi5BKGtC?zj&yuC6Q;uOM^XsH+9mabU0;1Ptj zzsG~g#~q0}M|q(b&6nA~%9ZrCZGV*R;Zp?5CtxQlMw0MaswHxXiMWz;KrI*gl? zVnRFzbBU&O&F7sAFLp(};rhF_D;@yM4-qY{qLTUgyd_KG+vZEQzAkuG{d!Nedy(tr z6^J||Pf~|TFugnykzGC3>00PEv$|j3MLl~Wn)EfkizT$>P0<&C(osDkKNn7mW%-`~ zyv#Z~6I~TwkFxsJ^XOl($DNDX+s^Q{wmXR3XXO(Kgh_$DP}k_uf9sFT4KlCo&8kQ% zGq@hjX|JxD3vTcl$WeRhGv(X%VPI|BNPw5#j$6Ae7K~d?cREl_y4-WdT@6p}ayRMw zbHJ>I2y=FIVYR*b>6cMaeW@6x#V6Gr`x%8ZL2x^7W8y!CoC5w81HfC*cG&)U zDV4$NRiljEmAM7+4ai%2dIc!fDLOsLeUbosT~9cPp(Wx)Pg?#M3w`7^0x-}x5jfJ8 ztvTvTXuPNc>T@*37Ze%H6;*8>>o_yKF^%{#$c4JQ#g?F|0U0k}jrYtOZP5yu6>787 zwc#}NqJSnTsM?ejWS^^h6w3Y#qMxT9yWS->*Yt1y5L4R*krfvK1$}^eB(AHI!_f&h zPC455_rh4|WzyM%RhVIFCR-o7FvB1$jE10A33RG_F1Nx>YPYepqbPL5Mja4|?)H}r z{Qqn8cTLICzFD}R;iK8X!aBA*iIMo@EAG*LVIQPgF_?7a$4Kx~6KJqoyxP9t&*zL? z*|UkBfear0oc)oN7U`AcN@6?d``My6skZx?N=bK;9F}|s(CuEt3L4w`J@{ixt~2>< zB~>GRwk+y5B%@Z}(PhB!9DS{3E|XZ5z|4)@<=*dLEdQcfBCTBYD6?my<{>bJHOlc z{Z{o)g!pqzi>14og`&;(!d|+ckud-R{uKyACN;)YzN!UM(3J%AXf4tR5tyuly@^|G zGpn@49RwYJOfAVUnB@zmAbLx#AhUX{_Qg zyu*j_SS(o!`VenxkICOdQe|rmp6;)!uSZWc9lIZQ5;L!|aux0X$e#j`p+k``7et_$ zOL@Mx!m5ZR;YU4Bu6g(6hf(1_f45AiY5t$c&jAG-Q(yC=StsC$t*t`}|@t1NTI zD1&QrU%z;IG2&Vrzi3r=(151P?>)p5vVJlJn`28JZ_^=-in0h#Pug2Yq7(+;LHkr7tMONwLo0fVH&~p^rBTj)OsKtG%Jz z4*08YbIT_#&Oh@IPHJ~Q@86f57A}f8mJeKuOe3wdc55#>#bgOTRWG282G4^8Lo3R5 zsz5aZA>~#9TFf6wRR^0w;(|O^6XtHOgk6Fip-ifBD$?j|5+--xIMW(G0{L5kyuQK2 z@0xVi2%R|*qKwU{(VV9N?kB(A3A>+c9h*Gn8~-vzNOB2zj)U)P=b-i`CquKFLI7)C zkO`7cA!C@~qBO2(b=}?DRo{T9ceE_CDU1*Ec-$62Up6jTwuEO^7N+(U&BnX+XCE}j|P(&|GweXB{K%Mhu&Gt>#{HiG_i6aClQbh z-UbC}E{exmN-jt`R?S4{W+v-TA7XrZX`EJ+k6<13t(;C!(-`Pt)-ix$HT>2$6C}S- z_}sr96M7$)F}2aScv&;Jzw*DTVXOX=c?s{gB^oDHrqzbkARN&KK?J~VADXdeg`)nF zQ7zHpUjp~Lc}7%`4=tI%b<=mYgm=f+_tjIFjRmJLMFtt+q1U%wBBVZzI%>#&wwRpt zaBxaUd6o}9hFy6DybuXZ(EHT)DOf4GBWxIp@;ZyZ@ISPWK^*8GWFy~wm{ypzyCh6j zP~{n@Ne35JCPd=qR9`)?7W}4hF1LKHfcR`&@LISb1cw-Fw^S~#Stb#`TfL1pY1iVX zr$bXr)XEBWD1Tm$KGf@|_yUunjHPct_4 zsbKxoh~`Q}qq*IEU4YAO_QodU1n$1I_8BeprNHC&VPj~hje4I%49+zM<*LUlRp_BO z86eS9kaC&Od_z=MpJ4oC7t0zeG@MN#$93fpE>7*HuI9?aB1H3xQ!{pu# zK3qdK82jIa?C$2b0uJw|79Zm#UVRjiW!Z3*nve(25E5nsBI&3V}kD>+8j zNLz#+zrq$(LBLaNRA%ZIqJzJ+Ih>@zK}tZZZS zSyc?)?rP8)UX1HMrZX_R(gx`?vR%Qxoejrw_fO_4-E;M?bhcB)GrrQ)xbSjM-K95% z*FB21A}41Zl@yfl2x>JE-F4d`^#}z*D$H&0n?7Y)0MmZS>gsX7p+Fp)5;3dT^0rPq zb=7@odlBbi(q205dFR~4p(~5OPC-1o%s>3!V?3Om!LS3zOUoc{KGD-sh<#6rd;W&1 zcjH!0mckLuqE!EI+4amVzOMyNL5=TR`}U-_^(%shcH|wF`Pua6(5A_G`fht8{tbzL zXcWk9v~S6e!QK55ki*K@?*Lx%dTq@LS4R+yKq*iu*S1K^+X&9Qz>;`Q6@U-A#24~l zR8t_{YRt}iwnC4t;G={^iYY+6ztwz@tE6rqAwjRyLicU4D}r?0-bLg~0Zbc9IIz47 z2vwL3k##YpP&?gLgYAx$&4)J?s1He>R(W}W#>q*dr9c~wX_Vg`>DGrfD?zRinv3PX zFq8ZN{@T2DK}g2$qP$=nTiaJG^R7z2(FAGcYF?;JD)um1P#8s|UR3)ZE&|s3BQCAS z-Dh~3Sub?!odo2qR^Oz+Zj?=&D5~Avkn}<s(^y`*>LiT#MB;mTg*D*LxGzGc4 zUgVO`aA?py<4zWLN9NByee@uL0RDm+uLw~p*sH4$B^`LrZbK;Y?6jeM{X*c$N1-b% zR;yEEL1hc}YmY(XH7O((YWL1upTnafl#dtocyf!r2JY>0+AZ$Qup*Vt!@f_7+L5n6 zKVz=bGBIGS(}FE5AU~&AI8_MUz0C|%-pld2XxoO? z7*O35=zrB_Ag3@GVluGe6*hcXwAW)pW-lTa=H zp>)|I31?&{26l=~K`Fu+lBM>s1M ze^9jZ{r-f*%!8?8LfbTR^9**k{@eUv<(ejubgiqG#FJA zT3CAY49U`@UQ3VKw{MKo&Q$(H#VQn@LpvbJ8?IMTHUvHDEn=l$MkyP%J%(DJt% z8)sj-pPXT@`u!pnGnPwSpyXy=na=#Q>+L=-dnw)$#ya)C)k{?CkuiiVq(q#WM5uTh3x>TSRru%s#>Xuwugzgf&wW) zC{`~fFQKljaKVi%t+V|CTKkxR61Q8Lv<|2xM*{O!e)3tj#H)+KMC$H!Dr9)3;X39v z|Kwgm*q-H{&X7AEzS4U8gdZ@~I{`ih9h-yJ%6EOwXiD+V=ZDY6SkI%U}C={ysjH z3}4EIv7{K3a>|2U8y#sJir)&UzvN?xHa{jma#B(GSPLHg%t&veum1$4XVOKq@fYHK zLkH48jEVC4A1>v>jSDOTAIxMeIsSV<1;sU&-VlFr5=by_}Uuz`()xB78J-Uap7Z{QBS`{wIxw9Yus zhiB7EH1psTN7Z)xntv5AMwv@X#G!>3;zF8_#8b_k}z7+zm*Z*~ZDwMCl=|Q*}UwdO){U^`Y z@R6wUb4>Ux?#R=#;#*Mpt5A{ZDsB8!^!} z1o^VpnNMKf0M-8mgiKjz3U}oQ zaUzQQE8k?|s-iPKQBZm{{O~voVa%<#bm%R81OQdqD zk8ozEII6cqlNK9-DmQ1P;54f87Jb71$93A*YqeLb3THqqSgreSO%_xDeq1I@<-Rt2 zPq2xil=2lGn@pZzHi#WjA&jY{kaRmsu6aZ50a7k-I{1!B+FPba*$n2}*Mj)M|w|z2_yC1pJ z8_ndAZ!38)du0nw+GjD}+#%9lA7Qhl;T9)~wEszv?D~c1*yUI8Wly&e|3e5H{PN9> zUoL38YwO=(@OB5^yu;}ECgXsYdS^T~??98xYobo_V!P)vwyw+0!1vV*M8w$6pz=h= zAqA4^ui(AvhzZej=><3M7{hQ!#NYraFZJs4C3F3O+QHnZYQH}I=?Fq)i4VFiPV+I8 zT@6a75i2m>MrhDIxeij2h*GhYCh>~LfVgo1x5)rpX+6}p_TVE$B7|t*N4^elYJsr7 zU7Yq!Z+QZejf7C;^H}DQ{hdS{sH*_~*U^>NhdHp1@d??$i9@j`(O#v$AdT{V98COR zald>}wLHCK^eTWj=@&ZGzth_I4s4*j;^{TZ1grj0(S_niU%%5RwDy6KqUH-f1ztfO zH3KYW<>yO4o2l?ctluPDJ@8Aw**J~0gftAJe3uQbW-!n$1W_dz3rlwE3;z?IwH3hU zF1Mo*t3Q-|5V?RV%0SLIf|iF?Lg4VEf=k?PHMg0jkyRNnXc9Q{1UdQvmNqmo1!G!E z$yCK?E*WQAqvo~|E501kdP6jJDE{SwfLUA}IM-FPZ{07>(!eTR0ux5~%{2fBhSM8p z#W(WFaPbsUH!$+}iG{`{;O_>@>$oFbBw7Uk9D?is~M{!I%2uTP0R3Ga66fnxS~oH3#JIV~nor4GRrD_#`$ zyo7lP4J28m%AcYYoeR*YCjg`|LMo!(`^o3U@*+Omkg-LoNgpyouXR}BF2TrHd4 z!nu?gy3A9B3N0LL9&%{7Ov{f7Aa!LBCcYC_+nQetGGjPbE?=2wQRLsT8(lpyWecpA zKQ=Ca;^BLXTp(sXSh@CcoIGxArVp)Z^H7Vf)Wug2$-5#R={HM{#4!{m*;f60CDZJ>+&Gc|9%8E7$ij) zUl6a3@!lW~x~2bj$OxQPj0ylSDR8=95Q*zDv6yKw^q~R$z|~K7H-yCaN^-IJ-J&?h z+29XLIq%y@Qv=7lGeTcf-%P=%?WGq=vn0=WDbL32&b}MmMeZaT{iRI)%ZK}6(zYy_ z=24%T-9cQeA5dy#YZ@C{q#dQP>BaW(qZn_lD;lB{f<)gSlHwxdSP@3it^(R7(7rA% zDW8&~S)mYP>~_dw(LOz`BkpbfU+Zu7wO<^}gCd<&#>xtqY^)t6l4VcKQz~cBJ%wdU z@pHz~?EIG08PB35RlcSipXB0sFX?k6pmjus-TWVvNV2%)*@T1Q$l%VrtQ%S>EGVmw z(MT8jv4cP->c8PWwKi~_HV9u<`rpX5RM~)xB#^(9KqMvklALi;(e)~$LFte75$|r> zih%P5DTRF#>C8yGn9?2i3)5)uvd80=ro6>5e?r<-K>VbnTd}$WvpQR(j0Q>b(LnhO z+D<;BI-Zl>&jO<{5k+-Wb5bVy;0DV>pPkQ6){vORJt@jaJ*m z!rtE8J{09}p-J{}K_H!}d~JaRQH*MqSw=rh&h`999en97dNEwE+)nrNA+^7BsEbji zA+B4q6a6uZ$-2{Jx4}--;Ua8L&d@4*7gMtkriRKhWcHy=8}foiCs+ocD^mQiPn`fSS+&E;*qTvjD}< zkH3(f3db`0@4NHWHg$N^cPv$ZABSH8w0vcl$ftf)`z9Dl8e%efyzgn@Bu=mnkL0=6 zB=3KGR=nzJ9XHE@wa(rz?;}4JJrh`{1`;YCxH5aYK}Dz-?oQ|pM`{5$Vg^@=jE5iq z5#nPTG!tvVpT))j>eaibWIh+s8DSa}staK9?&i^FUdMpmrgj&67iu!{@6_FN8f8WV=_6rFLNoAv6e4&rPq-f?kZO*ca8lMd5OY z``@AT==!MT5m!L1pnrmnQG9uUQMMjIDUM(y!vNHHa$elzNT5b<+XvLDn=ZYRTJIF_MiTJ=j_66=SGyj%n{j}Mw)5-Bwfw*!@P(xMj39VlGxMG2?;8eAO9=tlrl z!S@%E$pE@XvkcqzaLiN~^mgEZeT;P~pWCMQTU&xnq2U%lYPWih@-Am#7$n2N6SQAhgr|d^5JgE@MC7_j)&qBskP9 zgqMton^el^$Z`L#Lbb0eAuAF>%=@+jbZ*Hc^7@KVN;A*RE)NfX`I%#Df4(cotubLK z5Kg+e>%0ZKs~n%dj94|^a_Hh34z$(vcu+M4C5D!}R zv7!#s@?FCZM27yp(*RRceJZ&iHk^FZr_uy^$-dhUn7On!V9ft-_q8v@iQ>63kKI7# z2XAd~1_x}VS*BHuMx>GYpdvL|owr|ZEHH@?uHSWkEB~2+raX@yVji_{<7va5uz#$m zLv-KT6}FvFMr??{hD4okzT9oWpxda3k7X0@YY{t61Kv)ItX{F$j=9#Jq&_+8-Uab zJFCJ$w6g2I+u5%Q0UqRa?%5P{^iM5%7J5LCl6g)gu^z!A#+upEwh*S{`=szV@C_Ca z5sq3xUNp$jF@V~+Y6G7YT+(?GAstsM*BbG#H6lt5tb1s=&Z8QxiV zP@D-D_XErF3H13+c~;pZd}e7{I@W!}G)cW%&CmRat-ffYI8^9l*AJ(q;GDN~z%tiP z;z@-Xj)pu6aipigXBFL`7y(ImFg7LHq5(tZ>A@?$dy{`~!GBz|zq}rs4=hMSa2@rs zhA91|jaqkK-@EkWvVb%qGjm_E|Q0>cHJx#A(hH*q*5z6vN<>H)iTOhem z>neAVc=8%P>?Sf4yN7&n727!=%(}Z3+m!Ewj!39*e=)^*F*xhGs|(#B{UfP9mqmXm znrN3Vg+wbpLe@qM@Jvb!2FC3M<5t&_L!^74e3=jv(4+#h2(AH-Ym6e32j=4xCpRCd zs(HGufM2N1n5So%+^3(o@?Os_U7on^i$jaP3j48*KJxKFh)12S&eZs4p7G`8HX+hj zEOWDua<#=>zJF7Wo9f>=4HKRF)^LnRs_k+9N zUq)T0m4WuP?G%j+J>_u$ipFu%Mz(6dTGHWXX-S``GNPy#?{|$ zsL%qnuMOsA%X+W~_0Lg%qQ$05+B7IcW|>}-4jr>G4ADB(QiJW^R;R`FLaW&p5oWN1 zGl3QB>m{AX4{4sZ$L&H(%Txh?y|$NagS5!C$*kSn zcU9tH$>+8YpAxK2zq~a&(I$&2!fr`fr4biKl>ijy@omMbt+>0;eN%H&bY~2d_p;7PgHjv~5U|ICKG?Ute`WpGv&#FK#)Iz|u`^J_ z#-s5!jKlly?xn?P^)(xBhw}!TCP>~n2JVe!l|17R@YG!0z;Lil|7kp74aSjPtnwUz z#@7xCI!fG$<6rg3D(-r<7zt^+pF7b=vXcK-tCGWYePhiP*-t!$4cT% z%-zvm+>*eHhM3R{6W#b2Q{Pdt%P+N$=5i46S*^|n%85!S*>C^!u8O9voWg^|qfSI; zdB^xq$smu*ayg%d7>k=RtW~wSrt&r?c%o!PIsqbyx?Ar_Mu;Z zc@w!w*u)AqE!{9q@M7fI;7IAx1sq&G zN1fON)fd3;MyocHb;ChsKK38?UDr2MFOq-Zq~OjdymP2=!D^gMy?+Ka?Xb%PN6m75 z2f-WL{DURn=q?4h8^x`nO0Qyw?Pn+TyKWL*B172!gKlbxKa7_aeN0CjT&+2-e`I|q zad2dLjc04Pb;Xd;iXSTUgM5bNpCm(Bza9!LZ4y`v2Z?N0v^YYa3V-=WN8Qz=7ykKQ zc7vF35rALOgMg_fyj!U>$<7&gS%?*pjY>?fJx=}`gbn1aslH=O|_xP$lnzfh&+1a6b z97KAk#U;>cCx_2M@0=ijUCLaCqpZXB>{8kJk*$O2H^&l+qF;y^qH8EYU0D9@vDxSU z+?&Qef3d4A$lcS_wwh9V}Lw~V8R z#BL7a!u)gs+W}dg6zkobd+Uc;E8gYG9=NAoSa4>$x#M{L9?AQNp|AS0`z!#Vf4T^R z;~;@2U)lld>)L+aAg>(Xj=#F>c3j4psJE#wCB6r*G=X#D&L=nVk|}RZ64s{K@)cNp zq_8Un$lYI?*Sp$7y|HPm0MlrHkXOd{((UCoxZRY#=Xq@2oB%5W$_`v1$k-*)WBga;6;;FHmJu&XOK>8?Xqru$>>*7B^=(#2@pymlyx3 z8$k=Z>G5_ zYJpyxUC=xtgd$W*l!z&;$>@md z@*Zby&symUYUkX=w$n4v30y91HcUHukA08UbXb!b?qE@CTk(oSfgPM$<2}RqH0=BR zSDStE9?kcT`LdgF{xL6JMrp`up|8|;N(x*Y)R$P#}PE+wZ)yTJBMB&Col|tQ-PlT8@!*BAzj8guKVJsZ>-=g}OgVv<65ymuP zYb%b2W$Qqexr!;IlP=+fTPf}!v!Hip&ogX}0CYs9l zkseW!)js_Z>=(PD@iDV+vcEaIP>bi=21HF-yz%J>wL{>CK>fblys*q}+i#k}Lm?(0 z5E)x$EwC zL^nN7mX)JTbvZHJr^BvaGWOJ|Fx42m2)lXy4%T{LD)GqR_=PCxr;;wupxqtebO zm+1`xwz3MwuA`%Vzxe$#vuuupi65C}5C`F&43+Skeegw3)8(|Rgw#F^IX_VKTP@=> zq^H(1_73D1ZTPREW|0HliS_d*NRiy>dl0UuFuRv-=yDJMdItfk@cs@ zR%Z38e%zgc;uylIwZAuZ8x#Z`shK$DPZO54$Gu;k`?^)fIsP@C^dA3AsMQN^ZOQB2 z+tu!es&r!XckW!xU`>BLSm)Hf+J{N@wzn%E`(Cedq*2NMC^advLja^~5V5C)??xs3Oni5puIS)lqs{>fwV0Vf&5W-3;%{y&~+e}jW< zjcki~VGB%VD>H=>v|;pZ!J@V)EC1e zb}5EV^UQ)XRY_S;!5#S@HAh)+SK^Gu;-abZ)}Q;jSpf&EpDpv)@xU38EOKe5P~vljb>;hn4slPT)^*~>7=a2uf!X+360VB(vGK^Ut+sf84- zDW~6Y_!x~BJ;7{Zf@IBK8P!>o(EMR}Y)AFLXZqk-Nmg#z7L(T69G3m-bi3EMj!(`- zjfJm}qF*HWUrhN@ucJ4a=?%oT#Szg>)*17ddVj+VC^W~S8h#jNG}}?lJ`Z|X`t2d( zqiUNG{}gwTkPJxrT%+5U>uc~L*TGG+*c5Dz>?(-ZhahpKKmYotwXMp7*Va}Y5l^_6 zm&eRJ6*2OOvau<|Cg*}R@O$9M4y3o|3D~(z;^QKt4ZiiUVvs_W7aWa}*U`h6XjorQ zeCSX%6DBIFP}n_Uyw(^u9$T-2q3PP>1VaD3=zRhs{j)}92$mI#I!C8Bvv5aE)nZmv zn(CPERndEskv`X2231K%%~Qn7C5&71+pf6`+m23`16E}IgcY$bZE2(zDg?4(>}XZ_ zDKVaCJfok!eNTG)U!cqh7@8F94?0X>iP z*%j7=l4iY)J#EVhs~q(q9p*Ism6$^7N!35`>mob)qpQ8hkT7=5gw6s5a*crphxD43 zXpjlgmRYcXCz?`>N7Y#TfSXj>+XTI&#}}=PWu#xvC>@galJjo61428DhtCKS&i!o^ z2pRCwG8l^39B1QYXOF(S*gl5WOl@7<#G%>Img+`iKizDP#zAuLALX776rNvVrK_n6jOpb`Ck~1Xs{j)6=Dh-A1FUqM&E; z0kU)GA?#~5aFw@wg&P!0ZTqjw;~zw3oUkW99^f0kA(k&wrjo-fW4IfS75p3JvZ<;5 zgGIHQok!bAFi}h7%lxTIdWsDkFPeaK51n#F(#oNN!CSLK)5%;8*XBU zX&DgcMGRW>b@!XfJQoYlGTy5b0BP3&yES3VwT4;~UdxK_q*G?DG-2 zo8Dd=?KR(IR$9j+e`|`C)I5GxiO167=fRfv>G-r_Y}9k8AbG7Z=)L_=f3EYuaqixq zSa;Uc-J>45rXHQGoWuy(%Oq~sTGVxg53_3lP4`nGy~wYajH!wFGC3VC+ZA>@cl?9c z;^GbVRejhoRtyi+E#wD_v)9TPvkwMFK=sGr8|-BN-RSYd3uBy=EsOT0k$&;MgIEMB z%xG;Y)^s=wN-mcBw=eXlRekF{`@@M&(Mq@RkbcqX9r@aHtw#MacHIzYUtvia`l(gv8LScr3))ar{MZF=ut~S7jABnBcDE5?G+3dy(mPH=0yS z58kwkq3F*1?aYDCL+gX7cwEu7OFHnJ3+|0!1HGLBebXVqP``>oOa6@oIDSY=HJEP{AozBv&Z%TSFIB%m;qSzh0~> z_JsoX#_81Z+n<~PGQ?go#2W4TEx@B@C{N?RF3*WI`|$d_ukX0=g7#AEa8uN~^%1ku z<1k{67jb;At7GU(U;i!_|FPqPh3~9=?p&tFd!$rH{NrPO1k=Zt(cF%~Jq_=46HhG1 zIQ88koujl7v8(ogN7YQpoS-O07EvL-o9C}!Ovo_$4+fspu5Ik@8d1qnlpa*UC`!Br zql9yjAp#9d)Lv{~cavE|@x^$^2^Rw@QR^(v9hbbqStSy*)^J+9aHq93`9gHAeaTqP z8TIIq!WP)z|MeD^o^Pq3#mLf`2ws`rJDch&EQd3Oh9>b9+@TU9XH5eit(ug_3#Q$B zfI~4khZohd{zS~);jWP)mVMG9GMYXJ63b>iVr8`3TT%_m&_%&T;&|D-=5$W?u;PYj zRdB%WPPAo4akoR`IDkz;D8&tu5w>#FQn{AlYfpwW_LMeT7l-BBMjb;DQU48jG!UwLYoy2T*;vaKNmR!lPR zMz=@%9kVrl$_IaQL4}5+R+qp?uQTe>>|K8PlnYe=Y1DQrJ?KWOuX*8O4J53oJo?7#6-mhCT@hZIHl;X)FDk0!0JanN?! zRn_()V$2y_^XU!0=xp96BZ*<#qItLfBsN5QT`D)~81-H8a;nL!0j_%lZ%!Eu;xMS4u&R zFfwB$=YdB=S8v4UoGsh4YkGlG)rr*GD)(W|1D?b&Xpj15(wk}e-X?+ zlb|(ZRPD@d_vV(TYSRbjkQIX@m`EDdt3CZcLzdd&VaABkTT_;eKQGiIL74a4MFe#T1}IExCc-;kQUYAz8#xG5wA z=yFn(_3J5Bc|9svFgr208_BW7v!N3?^~fn}i#eDa_{8{e^5q>BT?w_t#-GIwvXQ^K zh}CwFI76TAri{i<2o#?EV}epWDxv%X&=5g$_%yQT*Oc>sFeZ&OBp6B0Etp2ThNy&+ zu!?z~_ux&FI>R@dq!piPV4)3!C~ohShOUGh!g#}!+edspQfif~b@CorR*;>}F=|t( zk^(8;_M$T5^NQ-0j~C1a)x}6oXa@iEa14rxqH%@7y4Pz{4db^I*7tsGSQI>uRoT%jqy3r6RV#2&M{Rp;? zu=Vza@yfNx^!L()W^-Ydkt);4_mBU|QMuau>q~n^B>OUY&11s?F(7a0-kKX<_*my5ufAxpY`_{Rxg7n@=8Z=5HSLtSrV?q%D{xkPU-C&1 zyRvMvi>n|Qy(}Qf-Lkq14sD$EL??!Hwku}6iEeB1WwUlm-#D&N^(i7yi*0=5+O+2- zsssNEFQa09zky(Z)q=y@QLpdPVs7zLzAMRR*~-srzM+tlM@Saa1~6G_c$bq$XHH?-}cN(E=)^~0ERqlY@$7o*Q=5X$nX6pT7W1kW^}|MirLkMa6Cn88JdURPj42CRKMs*dSCP-b;v; z1ds{GO*Uaxo;V?#(sOW(n=UH(O< zZy@wjvp<8QTY}mBxoHu!mQd#5RNZq4ft|WZcDXJl?J6^q21T~lfW8Sl}Vk+bqE|70Jkm{^XvGLZ063x74C;n~+i+-dm#>+ZXQ zn%uU&?bsmbQBT^^WG6Z@AmE@l)h)oOfSWVe_3@^gaEHn%>wE813aVM zQ_bu;BLn_yK!LbVz0HwXV5rzjCXNotnMX7j{2|b`~c-(JwVkHJ%2@0dy961Yt*5CZFQm^lB?6yW+n7-RTj)Sh{JklFHhl`xsj)@ z`(eZuZ;wG7PRUog+oOTJp5I};eSR1+-eH^ZqPc^wvjjF4{b7FgA{TZLgab{YF<&1?4L#8|}AS5IgWLB*bdD>wSscIu^Z$HKG-Sd`uA6zc@G zZcKPfms-+pbLyzkEv?s$TJKtWz1R`&Ak-NHbJlp>Gz&ocA+ygMY!Q}xGZ4L{Wq(sB z!rL({5mcN2mOc>Y~x%&mBtZkQ+= zF7G6pX*|Ua6#Jzv87mItYH0qD_gq}MgM4P3t7=ET{d(g47*Zio987nx-@U=neX=*- z*)Wl%=8eo_+xA~H29Kg>{8gajeN|)&7O>Dnk!L$`31!Q1no7KpYaE|8jQePl&GU(XZ64y71Fl?B^;G>rq9+ zSpk%J-N)~~tj5_L&aG}KRVX60BlBdkqRi7S?4ibrC;XKVW#B$1A0KD(#TFAZ=E!D+ z_$JLL5F#E?(V|8aRv_nc?PCE)9 z3%bQ#Pb68X&aXUVHCFb?BI zI%M118PLiNh8Az{*0Ro}zz`L$}^(&MBoZX{|VXLK> z%Jee%qBG^cMdi>|xHokT+m~IOeOK?1WBh&;+qBHNP&N1ZJt4U@hF|qaC0TE{rykf{ zVQN&;{S-R)X8z{pwK4#)8o|Cw?07%dg&gu6k3Cr7K1UTx>%uz9g>~!azT$WAgULi(Gjmx1fy(xf= zciA4N&*ABfj?ig5JJnAqo=Cm z@ImpiNz$41eYXVDdH4J7W92sl8|j0YiwtfJ1fM;s$}v%l+7+Rno(~0~1Rrv3j1UB5 zf5D#FH^xh!Zt$L+j*r)5hT9`7i-f)1i?Gwq(c#a;QX(+EIHl&sl)#g)VWjougv%~2 zA0q_7R!PJ|j;-Rk^{x8AGUu+G!ZJU?jLnMZt+8O@S)h2F8#1Ai7@0M-gB?OlpVriDsR(6o}&yO()p z2J46Wcad6C8M$fJQCzC>eG-PG;`jL$+fQ${ z=VZ9y*5h5l85Op2^f)7i`}K|R{)88SSR;9iq32vkY{l^S^z6KMp#W!Fun6U3TZtCFnz}1 zY>!oL7+Ejp+Rz~1IYmTG?&_Sa_m@z%R`xy79XB&Mrh@N*H~2jfL+y^h+!a=_6ylXz z#pLS7m|!(|1y#8s(3?`|eemF|X8vPD>7Rnzy|C@W+yE|_N*Ayq61l5TzDNk8!GW{1 z>}=xYX}}v73=pDtz&r)g4Fwas0`YJ*V;8fAOLgQEcta?iK=5RTk?+)GX*MSB;M*zj z2FF#2L((~ouW*JXHY9tnmgeF27~eYZ0iX;DINAy@FwVdE!jMio^j5dy6ztpAex$ZU zze^f~v=Z$dyAoouG?OmvGT0~;fa+Ou)dc;~txd{RliA-`Gv#*AqfYvu^2UQ@RBUhs zm0eBEy^Afb5#?1k*qOk|2UnFIy|hs4f`rllx=NtSoB_+WT?VVoC>pe_IswKiaP&m2 zjb_LfI?d3}+;#yA|1m!k62HI4;8@(2TJ$zh;}~qO{I4SnW1_`YX?Flb&hXgVXxT=a zW}hmz7NGQFda~8MuBu&`%56J$jWHKtK({KwEzcgiXzuVKtxnu2r-6F~{bhacnEm5} z$*wf)5q)Q+jx<=l_in>rkrmSUsmeX4V&R-yOo|&ES@7~eAY;iAzQCqGk{tzsfMW5t zSAM$~>vg?(IR%BhAs=auUBH*BUkiC%dVy$eQiPU{aj13;mo9^cHa7n1&%Yf0p$O#gai&vpeBP)zQenvOGp!f?O+lWC2R0_$z@F7*Uk>?11;>cbc|uq^8#2&Bu@tic_K}6NhNAo zS#U<4@v7Hx6>F=vBMsj?6}m0YU3DP(GLo3&+|hL-0f?`ma_bp6<)fsMI2k{7r96EH z0s#Gx9A9K_AQ``2BNL|^?X`H4XnAC3ciNrC5PfGj_$-_2=wuM+x&ym_`JpCijQFnA zV=(5MmuGm(-?=}iG(sL*-?TJ1dmY>THo%W%F!f#8J*&^)9m4L&fHILHj8~UK+3+s+ zo)7V{J{;&C>7!M{RFAI`#ZOi9Ol)zck5OYbiDXO?=^ons{Z;G?Rjihp+v+V8PbSsL zxzFL=hyFfz^E$6A>%;WYslGzJCtaWsY5BV+#%tl>4-3K`eHs%RIKPRbZCy26I8oPL z=e}Q3F*Gt${;rJAp@|UROOX$YwPo-da@p(>k#22wZ}o6w^dtA+&Qnguu9j%2))0rU%ZdCW^ICFm z!|umdESsyBL@u1Cm<2!R}(05l`A(U8m@%K9nv1+~*3Sly;_ac5NwbrQi zPpe(1!7tF?`Vf!E>PoRq3E=-Byu6R*a3#7D3Vkas@@zB-N#edy#XeaZ$y&xBa6gOb z;tlp<^M>x6w{51EH zV{0Q0lX&lyDfqF1#-P!FKIE0}S2K;3nuYEX*65Pi@%I>|Ac|`wcgD&$#Nyq&@&?oK zZJ8i$I}1fIvLcTUn~je-kRD6~D|{XZH})qoha?w1W*^D2C`r&b(_kN$PLy9l_BP-A z(P=z~gNu=X1=r41Jias9g_BXD zDFY;)Jg!EVf{Js!_G6Vt633xK#kuOS3{et}Nb>nY!!X-U%Z`bXZqoWL8q2?(wYF;L ze~d$)!NPY!k{XXLgi?f0CU4*lRHcneIq0OLTO1=bGu=SBN|Dpm^Gy2)}YlDlSf_iw!u3iF5ejfO~P+|LMco z4G=lekVc8yHkF2*(Y4{;xX*n}ELr|3(yb9;QfKbwlh(-98+;|{lzZa#*rvOVmSV?b z$NHpP4Md7NR+O{+sC++)P_ox5`#PIHqq|nyGb5224jzRq57C?ZRt(w%DF61Sv$die z*JYVR3jHn1MHin|%QqXYh&%I#8mukxR2W9$!CNrJFg6{wl>i=}$_Yy>#ngV9e(P@u zQ{1xnD#;A|iDvrxVf%@e?75lf3fOC%#Iy)+lRiCH24q5Sup@6`Hl?zdn{EER3aV9^niHv!zqg2+$svqjX%H zYw#FPQlpJHi?zGzSPS>~dWlkvUhqdS*|?T)fqTh2RM@wJU(ZiVhDcpU73`@=tZk;f za!x*f+u86LRkgz7YO#loxE&Nha9-SEbk?jmsUo%=_OM>Hgye9Jx9IWf~F8}YI7z`ybe{XQQQsKHoO*>e528^ zDszX7cT{aoT>?4*p!UD%9L6ZiDqblZkZ+vBd~a~!~p^kt%)d~38` zew$@YjGceLO|k-4sLL1MlgjESEUGai^7Zk6l7DHee%UqUT1H23 zU`&qQx1MsbkJWhmQuWo^Ozght0^Sav?RZDV6I#709KRoLX-;9En7~F*pySAnh9?+l z_A{DYvwi^D-!1NsU%p_a1zow)UR<`i(yO9Vqo{-@Zp%Kb(G{tWtvt)Gjv8 zuwT1LpqF*RE5TFKojUdITW9%v_jsDL{-&PtP-c^kt3jIyLa?;oZ%`LYR(*vX_Pceh zhBXIYyigT%zGUGS!NkD1!&#U9h~3ff=_*qhrIf)X?jjvpkFc~ely|E=Ek3$CmP$;f zsJx!^?QsWxX56tAAS)P&E(J&M=?o zTP6ckM03lB+d6b(gKBgO&xdlN9Z}P3&$L3x+PZuCx8q_vCYuEhr+RGtK3;33hK7MY znv+f%d$8EFA#a3s@*#z7cPM$A?OQ=6;-s1;s5d(~h;7+gHJIH$nonDm%skO!Mt&d9 zm1BLu5j2>R^+d71I)Cbq=V9My6&~Rk+L{PSEIEl@66UuIQ#%_)O_8pRrcf6ge7Wb{ z%{`>w7cf$`a>14SRL>NQq|=UqiaO z_0tiQ!9!JquS?`0!Z95!X5+ycHe8h!@gjXH-$H-`=?}k1njaj#vRo}|@vE$6r!TBE z2Abu|A60^FULA~cusc-d#=Ktv>>S^*5q|LFpF1}z=hQCc$a=1A5E&Lc6_c_u=aGnF zp>){6Gy|ow>eR&GlX+IrKX_R#AqrdM+IIO(Aspo_554qmtzLktm6}n?HR?V?I@DCi z0ciyD;?k^>Pu-@en>-VQ6U$+OsdV4h6NBCIe*Wm`QHoYnN$57yc|)I5IuU8S>I? z^Ot_;yxfD!wU{tgSDf0fkjy=;`^LkX>_EN}U26KCbte1BO(ODtOsT`+U_RaU4@8%H zUA3KYsYzJmH;{jwDN3NiJ{Ugq=+I86t#|?Lri-Iv`1>M;A4W0Zt%*!cp0bnwktNkp z_|!s^@}Zi2FWRm88KZyNq=p+Hys(lb@g%jxKaw9*%4|Qdeyu{h^|9`+&%=k=P8JFZ z5E&DP8&InkkDZ1J=QB!W5DlF+VT?xug^LcgI`=562J@>jE}y!Z9Ixcg`j~$dZ=^Mh z=ZOf^$UMS3PegN{-gH#Zy5A2E(kfjJxPGj3H)vxidttx2sc(0C5t$iPggmh`z5J|$ z;8KTk8mH%WX}Xb=Wp)+GnIxR7co$$$n2bX^v=`U%{NKAZln8HL)MnON+#)E`VrX&4 zbLclShrk2Z6{0GkBfG<#tg@k%pj*w}7p|GTR5jgJukr|p&-``-|JblEn7LSP7X8Bj zT*y_8paD1XN!BKSxWjx;fGOI{%+`~59CIV!IMDr0GWNr+wa2^f z!FFA?E0V227hqd-+=>EUM~3@#(~1*VP6BI?7>JM#zd~Eac#Wj$oOKX$DJ=GAVbz7Z zxO-*BEbs@RtTj){#q$9=a@OIxco2@=Me zh+s5lj`=mx{;iRoXNcXC=y7oatCz562X4=vmN&rlD!gjv+**Z}6S|Kt8m;nouIm4Y zQj)dykpS*^1h&u{*3kZjH5Q7$PnH1gG5o7p008|z5*4+|#XMDS`rG%-h&VH*w}7c|c^?Sc zPS7zDytdTa9!-G(hOfJQX7loyNTQJQFa|w?msmB@Z{v)y{2JHhdwn9-wfECR{pYgW zCZO$qPRdV@`ODV+`Plzd{;AvHppS!+b=beg%-pOL z9$kkH9|I11{{`2qV~?Kz!+#=UO#qw!Z^0*^<^Ov(IU6yU(cgi;|E&G|^dHde@5WSz z!}YfS&-h6_>j?3`BLAeqzk3)zsqpVcxId|49YOy;WKQrZZNtnis`%WKt_VP@8?Iio LxKMWf_QU@JwZ}Sf From da29b1a36152a5e2c7047990cca55cfc412d7634 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 5 Apr 2016 12:33:14 -0400 Subject: [PATCH 106/134] removed line continuation characters (not needed within parentheses) --- lib/damask/asciitable.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 8ec355400..fddd21f42 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -25,7 +25,7 @@ class ASCIItable(): readonly = False, # no reading from file ): self.__IO__ = {'output': [], - 'buffered': buffered, + 'buffered': buffered, 'labeled': labeled, # header contains labels 'labels': [], # labels according to file info 'readBuffer': [], # buffer to hold non-advancing reads @@ -35,18 +35,18 @@ class ASCIItable(): self.__IO__['inPlace'] = not outname and name and not readonly if self.__IO__['inPlace']: outname = name + self.tmpext # transparently create tmp file try: - self.__IO__['in'] = (open( name,'r') if os.access( name, os.R_OK) else None) if name else sys.stdin + self.__IO__['in'] = (open( name,'r') if os.access( name, os.R_OK) else None) if name else sys.stdin except TypeError: self.__IO__['in'] = name try: - self.__IO__['out'] = (open(outname,'w') if (not os.path.isfile(outname) \ - or os.access( outname, os.W_OK) \ - ) \ - and (not self.__IO__['inPlace'] \ - or not os.path.isfile(name) \ - or os.access( name, os.W_OK) \ - ) else None) if outname else sys.stdout + self.__IO__['out'] = (open(outname,'w') if (not os.path.isfile(outname) or + os.access( outname, os.W_OK) + ) and + (not self.__IO__['inPlace'] or + not os.path.isfile(name) or + os.access( name, os.W_OK) + ) else None) if outname else sys.stdout except TypeError: self.__IO__['out'] = outname From e9ec497da666c9ba015f926b8f43f095942be37c Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 5 Apr 2016 16:17:55 -0400 Subject: [PATCH 107/134] fixed bug preventing files specified with full path to be treated properly --- processing/post/averageTable.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/processing/post/averageTable.py b/processing/post/averageTable.py index edb0a0661..4a2f1eca6 100755 --- a/processing/post/averageTable.py +++ b/processing/post/averageTable.py @@ -37,10 +37,14 @@ if options.label is None: if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = options.label+'_averaged_'+name if name else name, - buffered = False) + damask.util.croak(name) + + try: table = damask.ASCIItable(name = name, + outname = os.path.join( + os.path.split(name)[0], + options.label+'_averaged_'+os.path.split(name)[1] + ) if name else name, + buffered = False) except: continue damask.util.report(scriptName,name) From 3e6d2710a3b4b7a8ce7ad459158e0b2855dd819a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 5 Apr 2016 16:18:34 -0400 Subject: [PATCH 108/134] added option to report probability density --- processing/post/histogram.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/processing/post/histogram.py b/processing/post/histogram.py index 4ba5f97bd..d5d4cd185 100755 --- a/processing/post/histogram.py +++ b/processing/post/histogram.py @@ -34,7 +34,11 @@ parser.add_option('-N', dest = 'N', type = 'int', metavar = 'int', help = 'number of bins') -parser.add_option('-l', '--logarithmic', +parser.add_option('--density', + dest = 'density', + action = 'store_true', + help = 'report probability density') +parser.add_option('--logarithmic', dest = 'log', action = 'store_true', help = 'logarithmically spaced bins') @@ -42,6 +46,7 @@ parser.set_defaults(data = None, weights = None, range = None, N = None, + density = False, log = False, ) @@ -110,6 +115,7 @@ for name in filenames: (forward(rangeMax)-forward(rangeMin))/options.N), range = (rangeMin,rangeMax), weights = None if options.weights is None else table.data[:,1], + density = options.density, ) bincenter = reverse(forward(rangeMin) + (0.5+np.arange(options.N)) * (forward(rangeMax)-forward(rangeMin))/options.N) # determine center of bins From e0d209d87b9fbe5c4d21786d7f8792ba21808218 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 5 Apr 2016 16:19:14 -0400 Subject: [PATCH 109/134] exchanged "readlink -f" for (hopefully) more portable python call --- DAMASK_env.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/DAMASK_env.sh b/DAMASK_env.sh index 16850d6b4..535708ed4 100644 --- a/DAMASK_env.sh +++ b/DAMASK_env.sh @@ -2,7 +2,7 @@ # usage: source DAMASK_env.sh if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == 'linux' ]; then - DAMASK_ROOT=$(readlink -f "`dirname $BASH_SOURCE`") + DAMASK_ROOT=$(python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "`dirname $BASH_SOURCE`") else [[ "${BASH_SOURCE::1}" == "/" ]] && BASE="" || BASE="`pwd`/" STAT=$(stat "`dirname $BASE$BASH_SOURCE`") @@ -18,11 +18,11 @@ fi SOLVER=`which DAMASK_spectral 2>/dev/null` if [ "x$SOLVER" == "x" ]; then - export SOLVER='Not found!' + SOLVER='Not found!' fi PROCESSING=`which postResults 2>/dev/null` if [ "x$PROCESSING" == "x" ]; then - export PROCESSING='Not found!' + PROCESSING='Not found!' fi # according to http://software.intel.com/en-us/forums/topic/501500 @@ -55,7 +55,8 @@ if [ ! -z "$PS1" ]; then echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" if [ "x$PETSC_DIR" != "x" ]; then echo "PETSc location $PETSC_DIR" - [[ `readlink -f $PETSC_DIR` == $PETSC_DIR ]] || echo " ~~> "`readlink -f $PETSC_DIR` + [[ `python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "$PETSC_DIR"` == $PETSC_DIR ]] \ + || echo " ~~> "`python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "$PETSC_DIR"` fi [[ "x$PETSC_ARCH" != "x" ]] && echo "PETSc architecture $PETSC_ARCH" echo "MSC.Marc/Mentat $MSC_ROOT" From 6f1dbbe011e6f3e0d6db969e6870f1a8fd65b5c3 Mon Sep 17 00:00:00 2001 From: Franz Roters Date: Thu, 7 Apr 2016 09:13:54 +0200 Subject: [PATCH 110/134] removed config file as the model was removed; use dislo_UCLA instead --- config/Phase_DisloKMC_Tungsten.config | 37 --------------------------- 1 file changed, 37 deletions(-) delete mode 100644 config/Phase_DisloKMC_Tungsten.config diff --git a/config/Phase_DisloKMC_Tungsten.config b/config/Phase_DisloKMC_Tungsten.config deleted file mode 100644 index 799c80e61..000000000 --- a/config/Phase_DisloKMC_Tungsten.config +++ /dev/null @@ -1,37 +0,0 @@ -### $Id$ ### - -[Tungsten] -elasticity hooke -plasticity dislokmc - -### Material parameters ### -lattice_structure bcc -C11 523.0e9 # From Marinica et al. Journal of Physics: Condensed Matter(2013) -C12 202.0e9 -C44 161.0e9 - -grainsize 2.0e-5 # Average grain size [m] 2.0e-5 -SolidSolutionStrength 0.0 # Strength due to elements in solid solution - -### Dislocation glide parameters ### -#per family -Nslip 12 0 -slipburgers 2.72e-10 # Burgers vector of slip system [m] -rhoedge0 1.0e12 # Initial edge dislocation density [m/m**3] -rhoedgedip0 1.0 # Initial edged dipole dislocation density [m/m**3] -Qedge 2.725e-19 # Activation energy for dislocation glide [J] -v0 3560.3 # Initial glide velocity [m/s](kmC) -p_slip 0.16 # p-exponent in glide velocity -q_slip 1.00 # q-exponent in glide velocity -u_slip 2.47 # u-exponent of stress pre-factor (kmC) -s_slip 0.97 # self hardening in glide velocity (kmC) -tau_peierls 2.03e9 # peierls stress [Pa] - -#hardening -dipoleformationfactor 0 # to have hardening due to dipole formation off -CLambdaSlip 10.0 # Adj. parameter controlling dislocation mean free path -D0 4.0e-5 # Vacancy diffusion prefactor [m**2/s] -Qsd 4.5e-19 # Activation energy for climb [J] -Catomicvolume 1.0 # Adj. parameter controlling the atomic volume [in b] -Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b] -interaction_slipslip 0.2 0.11 0.19 0.15 0.11 0.17 From 8ebc5982e458434aab4283d1c59c39959f5041bd Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 8 Apr 2016 11:16:20 -0400 Subject: [PATCH 111/134] fixed wrong sign of deviation comparison between existing phase constituent distribution and target values. --- code/material.f90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/material.f90 b/code/material.f90 index 1afbbed28..b274cfabf 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -1280,7 +1280,7 @@ subroutine material_populateGrains integer(pInt) :: t,e,i,g,j,m,c,r,homog,micro,sgn,hme, myDebug, & phaseID,textureID,dGrains,myNgrains,myNorientations,myNconstituents, & grain,constituentGrain,ipGrain,symExtension, ip - real(pReal) :: extreme,rnd + real(pReal) :: deviation,extreme,rnd integer(pInt), dimension (:,:), allocatable :: Nelems ! counts number of elements in homog, micro array type(p_intvec), dimension (:,:), allocatable :: elemsOfHomogMicro ! lists element number in homog, micro array @@ -1407,8 +1407,11 @@ subroutine material_populateGrains extreme = 0.0_pReal t = 0_pInt do i = 1_pInt,myNconstituents ! find largest deviator - if (real(sgn,pReal)*log(NgrainsOfConstituent(i)/myNgrains/microstructure_fraction(i,micro)) > extreme) then - extreme = real(sgn,pReal)*log(NgrainsOfConstituent(i)/myNgrains/microstructure_fraction(i,micro)) + deviation = real(sgn,pReal)*log( microstructure_fraction(i,micro) / & + !-------------------------------- & + (real(NgrainsOfConstituent(i),pReal)/real(myNgrains,pReal) ) ) + if (deviation > extreme) then + extreme = deviation t = i endif enddo From 2354cd609a992abe0d0009fb94d4ad7ec276fa51 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 8 Apr 2016 17:46:06 -0400 Subject: [PATCH 112/134] small polishing of help. added option to change output number format. --- processing/pre/seeds_fromRandom.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/processing/pre/seeds_fromRandom.py b/processing/pre/seeds_fromRandom.py index 29bf85712..f0a3b81df 100755 --- a/processing/pre/seeds_fromRandom.py +++ b/processing/pre/seeds_fromRandom.py @@ -48,8 +48,11 @@ parser.add_option('-m', '--microstructure', parser.add_option('-r', '--rnd', dest = 'randomSeed', type = 'int', metavar = 'int', help = 'seed of random number generator [%default]') +parser.add_option('--format', + dest = 'format', type = 'string', metavar = 'string', + help = 'number format of output [auto]') -group = OptionGroup(parser, "Laguerre Tessellation Options", +group = OptionGroup(parser, "Laguerre Tessellation", "Parameters determining shape of weight distribution of seed points" ) group.add_option('-w', '--weights', @@ -70,8 +73,8 @@ group.add_option('--sigma', help='standard deviation of normal distribution for weights [%default]') parser.add_option_group(group) -group = OptionGroup(parser, "Selective Seeding Options", - "More uniform distribution of seed points using Mitchell\'s Best Candidate Algorithm" +group = OptionGroup(parser, "Selective Seeding", + "More uniform distribution of seed points using Mitchell's Best Candidate Algorithm" ) group.add_option('-s','--selective', action = 'store_true', @@ -103,6 +106,7 @@ parser.set_defaults(randomSeed = None, force = False, distance = 0.2, numCandidates = 10, + format = None, ) (options,filenames) = parser.parse_args() @@ -215,7 +219,7 @@ for name in filenames: # --- write seeds information ------------------------------------------------------------ table.data = seeds - table.data_writeArray() + table.data_writeArray(fmt = options.format) # --- output finalization -------------------------------------------------------------------------- From b0496f20ca2e0cbdc48cd1f4cbe10ac3d6c353c2 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 8 Apr 2016 17:47:02 -0400 Subject: [PATCH 113/134] grouped command line options. removed functionality to add random second phase. --- .../pre/geom_fromVoronoiTessellation.py | 147 +++++++++--------- 1 file changed, 72 insertions(+), 75 deletions(-) diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index c7a860e79..569c181c5 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -4,7 +4,7 @@ import os,sys,math import numpy as np import multiprocessing -from optparse import OptionParser +from optparse import OptionParser,OptionGroup from scipy import spatial import damask @@ -109,71 +109,83 @@ Generate geometry description and material configuration by standard Voronoi tes """, version = scriptID) -parser.add_option('-g', '--grid', - dest = 'grid', - type = 'int', nargs = 3, metavar = ' '.join(['int']*3), - help = 'a,b,c grid of hexahedral box [auto]') -parser.add_option('-s', '--size', - dest = 'size', - type = 'float', nargs = 3, metavar=' '.join(['float']*3), - help = 'x,y,z size of hexahedral box [auto]') -parser.add_option('-o', '--origin', - dest = 'origin', - type = 'float', nargs = 3, metavar=' '.join(['float']*3), - help = 'offset from old to new origin of grid') -parser.add_option('-p', '--position', - dest = 'position', - type = 'string', metavar = 'string', - help = 'column label for seed positions [%default]') -parser.add_option('-w', '--weight', - dest = 'weight', - type = 'string', metavar = 'string', - help = 'column label for seed weights [%default]') -parser.add_option('-m', '--microstructure', - dest = 'microstructure', - type = 'string', metavar = 'string', - help = 'column label for seed microstructures [%default]') -parser.add_option('-e', '--eulers', - dest = 'eulers', - type = 'string', metavar = 'string', - help = 'column label for seed Euler angles [%default]') -parser.add_option('--axes', - dest = 'axes', - type = 'string', nargs = 3, metavar = ' '.join(['string']*3), - help = 'orientation coordinate frame in terms of position coordinate frame') -parser.add_option('--homogenization', - dest = 'homogenization', - type = 'int', metavar = 'int', - help = 'homogenization index to be used [%default]') -parser.add_option('--crystallite', - dest = 'crystallite', - type = 'int', metavar = 'int', - help = 'crystallite index to be used [%default]') -parser.add_option('--phase', - dest = 'phase', - type = 'int', metavar = 'int', - help = 'phase index to be used [%default]') -parser.add_option('-r', '--rnd', - dest = 'randomSeed', - type = 'int', metavar='int', - help = 'seed of random number generator for second phase distribution [%default]') -parser.add_option('--secondphase', - dest = 'secondphase', - type = 'float', metavar= 'float', - help = 'volume fraction of randomly distribute second phase [%default]') -parser.add_option('-l', '--laguerre', + +group = OptionGroup(parser, "Tessellation","") + +group.add_option('-l', '--laguerre', dest = 'laguerre', action = 'store_true', help = 'use Laguerre (weighted Voronoi) tessellation') -parser.add_option('--cpus', +group.add_option('--cpus', dest = 'cpus', type = 'int', metavar = 'int', help = 'number of parallel processes to use for Laguerre tessellation [%default]') -parser.add_option('--nonperiodic', +group.add_option('--nonperiodic', dest = 'nonperiodic', action = 'store_true', help = 'use nonperiodic tessellation') +parser.add_option_group(group) + +group = OptionGroup(parser, "Geometry","") + +group.add_option('-g', '--grid', + dest = 'grid', + type = 'int', nargs = 3, metavar = ' '.join(['int']*3), + help = 'a,b,c grid of hexahedral box [auto]') +group.add_option('-s', '--size', + dest = 'size', + type = 'float', nargs = 3, metavar=' '.join(['float']*3), + help = 'x,y,z size of hexahedral box [auto]') +group.add_option('-o', '--origin', + dest = 'origin', + type = 'float', nargs = 3, metavar=' '.join(['float']*3), + help = 'origin of grid') + +parser.add_option_group(group) + +group = OptionGroup(parser, "Seeds","") + +group.add_option('-p', '--position', + dest = 'position', + type = 'string', metavar = 'string', + help = 'column label for seed positions [%default]') +group.add_option('-w', '--weight', + dest = 'weight', + type = 'string', metavar = 'string', + help = 'column label for seed weights [%default]') +group.add_option('-m', '--microstructure', + dest = 'microstructure', + type = 'string', metavar = 'string', + help = 'column label for seed microstructures [%default]') +group.add_option('-e', '--eulers', + dest = 'eulers', + type = 'string', metavar = 'string', + help = 'column label for seed Euler angles [%default]') +group.add_option('--axes', + dest = 'axes', + type = 'string', nargs = 3, metavar = ' '.join(['string']*3), + help = 'orientation coordinate frame in terms of position coordinate frame') + +parser.add_option_group(group) + +group = OptionGroup(parser, "Configuration","") + +group.add_option('--homogenization', + dest = 'homogenization', + type = 'int', metavar = 'int', + help = 'homogenization index to be used [%default]') +group.add_option('--crystallite', + dest = 'crystallite', + type = 'int', metavar = 'int', + help = 'crystallite index to be used [%default]') +group.add_option('--phase', + dest = 'phase', + type = 'int', metavar = 'int', + help = 'phase index to be used [%default]') + +parser.add_option_group(group) + parser.set_defaults(position = 'pos', weight = 'weight', microstructure = 'microstructure', @@ -181,26 +193,20 @@ parser.set_defaults(position = 'pos', homogenization = 1, crystallite = 1, phase = 1, - secondphase = 0.0, cpus = 2, laguerre = False, nonperiodic = False, - randomSeed = None, ) (options,filenames) = parser.parse_args() -if options.secondphase > 1.0 or options.secondphase < 0.0: - parser.error('volume fraction of second phase ({}) out of bounds.'.format(options.secondphase)) - # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.splitext(name)[-2]+'.geom' if name else name, - buffered = False) + try: table = damask.ASCIItable(name = name, + outname = os.path.splitext(name)[-2]+'.geom' if name else name, + buffered = False) except: continue damask.util.report(scriptName,name) @@ -294,20 +300,11 @@ for name in filenames: config_header = [] formatwidth = 1+int(math.log10(NgrainIDs)) - phase = options.phase * np.ones(NgrainIDs,'i') - if int(options.secondphase*info['microstructures']) > 0: - phase[0:int(options.secondphase*info['microstructures'])] += 1 # alter fraction 'options.secondphase' of used grainIDs - randomSeed = options.randomSeed if options.randomSeed \ - else int(os.urandom(4).encode('hex'), 16) # random seed for second phase - np.random.seed(randomSeed) - np.random.shuffle(phase) - config_header += ['# random seed (phase shuffling): {}'.format(randomSeed)] - config_header += [''] for i,ID in enumerate(grainIDs): config_header += ['[Grain%s]'%(str(ID).zfill(formatwidth)), 'crystallite %i'%options.crystallite, - '(constituent)\tphase %i\ttexture %s\tfraction 1.0'%(phase[i],str(ID).rjust(formatwidth)), + '(constituent)\tphase %i\ttexture %s\tfraction 1.0'%(options.phase,str(ID).rjust(formatwidth)), ] if hasEulers: config_header += [''] From b76f499c45d595641238bd034c4dcb6cc60ecef9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 10 Apr 2016 15:52:43 +0100 Subject: [PATCH 114/134] Li and its tangent in isotropic returned undefined values for (default) J2 behavior, set mandatory parameters to NaN when initializing for faster dying --- code/plastic_isotropic.f90 | 45 +++++++++++++++++++------------------- code/plastic_j2.f90 | 13 ----------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/code/plastic_isotropic.f90 b/code/plastic_isotropic.f90 index 81d3055cf..132a0abb1 100644 --- a/code/plastic_isotropic.f90 +++ b/code/plastic_isotropic.f90 @@ -7,14 +7,11 @@ !! untextured polycrystal !-------------------------------------------------------------------------------------------------- module plastic_isotropic -#ifdef HDF - use hdf5, only: & - HID_T -#endif use prec, only: & pReal,& - pInt + pInt, & + DAMASK_NaN implicit none private @@ -40,20 +37,20 @@ module plastic_isotropic integer(kind(undefined_ID)), allocatable, dimension(:) :: & outputID real(pReal) :: & - fTaylor, & - tau0, & - gdot0, & - n, & - h0, & - h0_slopeLnRate, & - tausat, & - a, & - aTolFlowstress, & - aTolShear , & - tausat_SinhFitA=0.0_pReal, & - tausat_SinhFitB=0.0_pReal, & - tausat_SinhFitC=0.0_pReal, & - tausat_SinhFitD=0.0_pReal + fTaylor = DAMASK_NaN, & + tau0 = DAMASK_NaN, & + gdot0 = DAMASK_NaN, & + n = DAMASK_NaN, & + h0 = DAMASK_NaN, & + h0_slopeLnRate = 0.0_pReal, & + tausat = DAMASK_NaN, & + a = DAMASK_NaN, & + aTolFlowstress = 1.0_pReal, & + aTolShear = 1.0e-6_pReal, & + tausat_SinhFitA= 0.0_pReal, & + tausat_SinhFitB= 0.0_pReal, & + tausat_SinhFitC= 0.0_pReal, & + tausat_SinhFitD= 0.0_pReal logical :: & dilatation = .false. end type @@ -474,7 +471,8 @@ subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dTstar_3333,Tstar_v,ipc,ip,e implicit none real(pReal), dimension(3,3), intent(out) :: & Li !< plastic velocity gradient - + real(pReal), dimension(3,3,3,3), intent(out) :: & + dLi_dTstar_3333 !< derivative of Li with respect to Tstar as 4th order tensor real(pReal), dimension(6), intent(in) :: & Tstar_v !< 2nd Piola Kirchhoff stress tensor in Mandel notation integer(pInt), intent(in) :: & @@ -484,9 +482,7 @@ subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dTstar_3333,Tstar_v,ipc,ip,e real(pReal), dimension(3,3) :: & Tstar_sph_33 !< sphiatoric part of the 2nd Piola Kirchhoff stress tensor as 2nd order tensor - real(pReal), dimension(3,3,3,3), intent(out) :: & - dLi_dTstar_3333 !< derivative of Li with respect to Tstar as 4th order tensor - real(pReal) :: & +real(pReal) :: & gamma_dot, & !< strainrate norm_Tstar_sph, & !< euclidean norm of Tstar_sph squarenorm_Tstar_sph !< square of the euclidean norm of Tstar_sph @@ -523,6 +519,9 @@ subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dTstar_3333,Tstar_v,ipc,ip,e dLi_dTstar_3333 = gamma_dot / param(instance)%fTaylor * & dLi_dTstar_3333 / norm_Tstar_sph endif + else + Li = 0.0_pReal + dLi_dTstar_3333 = 0.0_pReal endif end subroutine plastic_isotropic_LiAndItsTangent diff --git a/code/plastic_j2.f90 b/code/plastic_j2.f90 index 4d247677b..4138aea25 100644 --- a/code/plastic_j2.f90 +++ b/code/plastic_j2.f90 @@ -207,9 +207,6 @@ subroutine plastic_j2_init(fileUnit) phase = phase + 1_pInt ! advance section counter if (phase_plasticity(phase) == PLASTICITY_J2_ID) then instance = phase_plasticityInstance(phase) -#ifdef HDF - outID(instance)=HDF5_addGroup(str1,tempResults) -#endif endif cycle ! skip to next line endif @@ -226,21 +223,11 @@ subroutine plastic_j2_init(fileUnit) plastic_j2_outputID(plastic_j2_Noutput(instance),instance) = flowstress_ID plastic_j2_output(plastic_j2_Noutput(instance),instance) = & IO_lc(IO_stringValue(line,chunkPos,2_pInt)) -#ifdef HDF - call HDF5_addScalarDataset(outID(instance),myConstituents,'flowstress','MPa') - allocate(plastic_j2_Output2(instance)%flowstress(myConstituents)) - plastic_j2_Output2(instance)%flowstressActive = .true. -#endif case ('strainrate') plastic_j2_Noutput(instance) = plastic_j2_Noutput(instance) + 1_pInt plastic_j2_outputID(plastic_j2_Noutput(instance),instance) = strainrate_ID plastic_j2_output(plastic_j2_Noutput(instance),instance) = & IO_lc(IO_stringValue(line,chunkPos,2_pInt)) -#ifdef HDF - call HDF5_addScalarDataset(outID(instance),myConstituents,'strainrate','1/s') - allocate(plastic_j2_Output2(instance)%strainrate(myConstituents)) - plastic_j2_Output2(instance)%strainrateActive = .true. -#endif case default end select From 63386ed732795beb1b3be08b053bebbac43577d0 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 11 Apr 2016 04:20:06 +0200 Subject: [PATCH 115/134] updated version information after successful test of v2.0.0-93-g0ddc29d --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 690c6cb1d..7d1fa0440 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-43-ge39441f +v2.0.0-93-g0ddc29d From d278d86f9d5e8ff1d8d8428dc793d51cac527a50 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 11 Apr 2016 13:24:43 +0200 Subject: [PATCH 116/134] long line --- processing/post/addSchmidfactors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 71040cbdc..5a08024fc 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -239,7 +239,9 @@ for name in filenames: # ------------------------------------------ assemble header --------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{id}_S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]({normal[0]:.1g}_{normal[1]:.1g}_{normal[2]:.1g})'\ + table.labels_append(['{id}_' + 'S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]' + '({normal[0]:.1g}_{normal[1]:.1g}_{normal[2]:.1g})'\ .format( id = i+1, normal = theNormal, direction = theDirection, From c8b3f08743c433c93bb15f14ef4ea74a413742c9 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 12 Apr 2016 04:20:06 +0200 Subject: [PATCH 117/134] updated version information after successful test of v2.0.0-95-gd278d86 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7d1fa0440..03f85d164 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-93-g0ddc29d +v2.0.0-95-gd278d86 From 8b27de7d163e0da8075e1dd6e1e441b7c6a86364 Mon Sep 17 00:00:00 2001 From: Pratheek Shanthraj Date: Tue, 12 Apr 2016 11:05:01 +0200 Subject: [PATCH 118/134] fix bug in MPI output --- code/DAMASK_spectral.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DAMASK_spectral.f90 b/code/DAMASK_spectral.f90 index 45451df08..e999bf5dc 100644 --- a/code/DAMASK_spectral.f90 +++ b/code/DAMASK_spectral.f90 @@ -427,7 +427,7 @@ program DAMASK_spectral ! prepare MPI parallel out (including opening of file) allocate(outputSize(worldsize), source = 0_MPI_OFFSET_KIND) outputSize(worldrank+1) = size(materialpoint_results,kind=MPI_OFFSET_KIND)*int(pReal,MPI_OFFSET_KIND) - call MPI_allreduce(MPI_IN_PLACE,outputSize,worldsize,MPI_INT,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process + call MPI_allreduce(MPI_IN_PLACE,outputSize,worldsize,MPI_LONG,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process if(ierr /=0_pInt) call IO_error(894_pInt, ext_msg='MPI_allreduce') call MPI_file_open(PETSC_COMM_WORLD, & trim(getSolverWorkingDirectoryName())//trim(getSolverJobName())//'.spectralOut', & From 284c2783e2ee10413d887d751978c0f6480cf38c Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 12 Apr 2016 16:19:57 +0200 Subject: [PATCH 119/134] updated version information after successful test of v2.0.0-97-g8b27de7 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 03f85d164..c271e0939 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.0-95-gd278d86 +v2.0.0-97-g8b27de7 From 6e2ca7d59579d7e3ddfd166615db22cab461ed2d Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 17:48:17 -0400 Subject: [PATCH 120/134] Removed hard requirement of 3D dataset. Fills in necessary dimensions. --- processing/post/vtk_rectilinearGrid.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/processing/post/vtk_rectilinearGrid.py b/processing/post/vtk_rectilinearGrid.py index a00d60185..38deabf3a 100755 --- a/processing/post/vtk_rectilinearGrid.py +++ b/processing/post/vtk_rectilinearGrid.py @@ -38,9 +38,9 @@ parser.set_defaults(position ='ipinitialcoord', if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, readonly = True) + try: table = damask.ASCIItable(name = name, + buffered = False, + readonly = True) except: continue damask.util.report(scriptName,name) @@ -48,10 +48,13 @@ for name in filenames: table.head_read() - errors = [] - if table.label_dimension(options.position) != 3: - errors.append('coordinates {} are not a vector.'.format(options.position)) + remarks = [] + errors = [] + coordDim = table.label_dimension(options.position) + if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.position)) + elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.position)) + if remarks != []: damask.util.croak(remarks) if errors != []: damask.util.croak(errors) table.close(dismiss=True) @@ -60,6 +63,11 @@ for name in filenames: # --------------- figure out size and grid --------------------------------------------------------- table.data_readArray(options.position) + if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape + if table.data.shape[1] < 3: + table.data = np.hstack((table.data, + np.zeros((table.data.shape[0], + 3-table.data.shape[1]),dtype='f'))) # fill coords up to 3D with zeros coords = [np.unique(table.data[:,i]) for i in xrange(3)] if options.mode == 'cell': From feae2164fc18bbbe04decb616b998055b151edf0 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 17:48:49 -0400 Subject: [PATCH 121/134] polishing and now explicitly closing input table. --- processing/post/vtk_addRectilinearGridData.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index 3ca54d84e..6b78950c7 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -83,9 +83,9 @@ damask.util.croak('{}: {} points and {} cells...'.format(options.vtk,Npoints,Nce if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, readonly = True) + try: table = damask.ASCIItable(name = name, + buffered = False, + readonly = True) except: continue damask.util.report(scriptName, name) @@ -133,6 +133,8 @@ for name in filenames: elif datatype == 'vector': VTKarray[me].InsertNextTuple3(*map(float,theData)) elif datatype == 'scalar': VTKarray[me].InsertNextValue(float(theData[0])) + table.input_close() # close input ASCII table + # ------------------------------------------ add data --------------------------------------- for datatype,labels in active.items(): # loop over scalar,color From 0b09ce31db22b9f50280fecbb35a4366fad04fff Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 17:49:48 -0400 Subject: [PATCH 122/134] changed coordinate option to be consistent with rectilinearGrid. --- processing/post/vtk_pointcloud.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/processing/post/vtk_pointcloud.py b/processing/post/vtk_pointcloud.py index 7701421fc..f35911135 100755 --- a/processing/post/vtk_pointcloud.py +++ b/processing/post/vtk_pointcloud.py @@ -18,12 +18,12 @@ Produce a VTK point cloud dataset based on coordinates given in an ASCIItable. """, version = scriptID) -parser.add_option('-d', '--deformed', - dest = 'deformed', +parser.add_option('-c', '--coordinates', + dest = 'pos', type = 'string', metavar = 'string', - help = 'deformed coordinate label [%default]') + help = 'coordinate label [%default]') -parser.set_defaults(deformed = 'ipdeformedcoord' +parser.set_defaults(pos = 'pos' ) (options, filenames) = parser.parse_args() @@ -46,9 +46,9 @@ for name in filenames: errors = [] remarks = [] - coordDim = table.label_dimension(options.deformed) - if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.deformed)) - elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.deformed)) + coordDim = table.label_dimension(options.pos) + if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) + elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.pos)) if remarks != []: damask.util.croak(remarks) if errors != []: @@ -58,7 +58,7 @@ for name in filenames: # ------------------------------------------ process data --------------------------------------- - table.data_readArray(options.deformed) + table.data_readArray(options.pos) if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape if table.data.shape[1] < 3: table.data = np.hstack((table.data, From ea0bc80af997a3cf7df5df0af43100b9b7f5c201 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 18:03:40 -0400 Subject: [PATCH 123/134] modernized to reflect rectilinearGrid processing. Now supports vector data and in-place adding. --- processing/post/vtk_addPointcloudData.py | 211 ++++++++++++++--------- 1 file changed, 125 insertions(+), 86 deletions(-) diff --git a/processing/post/vtk_addPointcloudData.py b/processing/post/vtk_addPointcloudData.py index 95b91d8ee..602e69307 100755 --- a/processing/post/vtk_addPointcloudData.py +++ b/processing/post/vtk_addPointcloudData.py @@ -1,8 +1,9 @@ #!/usr/bin/env python # -*- coding: UTF-8 no BOM -*- -import os,sys,vtk +import os,vtk import damask +from collections import defaultdict from optparse import OptionParser scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -17,125 +18,163 @@ Add scalar and RGB tuples from ASCIItable to existing VTK point cloud (.vtp). """, version = scriptID) -parser.add_option('-v', '--vtk', dest='vtk', \ +parser.add_option( '--vtk', + dest = 'vtk', + type = 'string', metavar = 'string', help = 'VTK file name') +parser.add_option( '--inplace', + dest = 'inplace', + action = 'store_true', + help = 'modify VTK file in-place') +parser.add_option('-r', '--render', + dest = 'render', + action = 'store_true', + help = 'open output in VTK render window') parser.add_option('-s', '--scalar', dest='scalar', action='extend', \ help = 'scalar values') +parser.add_option('-v', '--vector', + dest = 'vector', + action = 'extend', metavar = '', + help = 'vector value label(s)') parser.add_option('-c', '--color', dest='color', action='extend', \ help = 'RGB color tuples') -parser.set_defaults(scalar = []) -parser.set_defaults(color = []) +parser.set_defaults(scalar = [], + vector = [], + color = [], + inplace = False, + render = False, +) (options, filenames) = parser.parse_args() -datainfo = { # list of requested labels per datatype - 'scalar': {'len':1, - 'label':[]}, - 'color': {'len':3, - 'label':[]}, - } - -if not os.path.exists(options.vtk): - parser.error('VTK file does not exist'); sys.exit() +if not options.vtk: parser.error('No VTK file specified.') +if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(options.vtk) reader.Update() -Npoints = reader.GetNumberOfPoints() -Ncells = reader.GetNumberOfCells() +Npoints = reader.GetNumberOfPoints() +Ncells = reader.GetNumberOfCells() Nvertices = reader.GetNumberOfVerts() -Polydata = reader.GetOutput() +Polydata = reader.GetOutput() if Npoints != Ncells or Npoints != Nvertices: - parser.error('Number of points, cells, and vertices in VTK differ from each other'); sys.exit() -if options.scalar is not None: datainfo['scalar']['label'] += options.scalar -if options.color is not None: datainfo['color']['label'] += options.color + parser.error('Number of points, cells, and vertices in VTK differ from each other.') -# ------------------------------------------ setup file handles --------------------------------------- +damask.util.croak('{}: {} points, {} vertices, and {} cells...'.format(options.vtk,Npoints,Nvertices,Ncells)) -files = [] -if filenames == []: - files.append({'name':'STDIN', 'input':sys.stdin, 'output':sys.stdout, 'croak':sys.stderr}) -else: - for name in filenames: - if os.path.exists(name): - files.append({'name':name, 'input':open(name), 'output':sys.stderr, 'croak':sys.stderr}) +# --- loop over input files ------------------------------------------------------------------------- -#--- loop over input files ------------------------------------------------------------------------ -for file in files: - if file['name'] != 'STDIN': file['croak'].write('\033[1m'+scriptName+'\033[0m: '+file['name']+'\n') - else: file['croak'].write('\033[1m'+scriptName+'\033[0m\n') +if filenames == []: filenames = [None] - table = damask.ASCIItable(file['input'],file['output'],False) # make unbuffered ASCII_table - table.head_read() # read ASCII header info +for name in filenames: + try: table = damask.ASCIItable(name = name, + buffered = False, + readonly = True) + except: continue + damask.util.report(scriptName, name) -# --------------- figure out columns to process - active = {} - column = {} +# --- interpret header ---------------------------------------------------------------------------- - array = {} + table.head_read() + + remarks = [] + errors = [] + VTKarray = {} + active = defaultdict(list) - for datatype,info in datainfo.items(): - for label in info['label']: - foundIt = False - for key in ['1_'+label,label]: - if key in table.labels: - foundIt = True - if datatype not in active: active[datatype] = [] - if datatype not in column: column[datatype] = {} - if datatype not in array: array[datatype] = {} - active[datatype].append(label) - column[datatype][label] = table.labels.index(key) # remember columns of requested data - if datatype == 'scalar': - array[datatype][label] = vtk.vtkDoubleArray() - array[datatype][label].SetNumberOfComponents(1) - array[datatype][label].SetName(label) - elif datatype == 'color': - array[datatype][label] = vtk.vtkUnsignedCharArray() - array[datatype][label].SetNumberOfComponents(3) - array[datatype][label].SetName(label) - if not foundIt: - file['croak'].write('column %s not found...\n'%label) - + for datatype,dimension,label in [['scalar',1,options.scalar], + ['vector',3,options.vector], + ['color',3,options.color], + ]: + for i,dim in enumerate(table.label_dimension(label)): + me = label[i] + if dim == -1: remarks.append('{} "{}" not found...'.format(datatype,me)) + elif dim > dimension: remarks.append('"{}" not of dimension {}...'.format(me,dimension)) + else: + remarks.append('adding {} "{}"...'.format(datatype,me)) + active[datatype].append(me) + + if datatype in ['scalar','vector']: VTKarray[me] = vtk.vtkDoubleArray() + elif datatype == 'color': VTKarray[me] = vtk.vtkUnsignedCharArray() + + VTKarray[me].SetNumberOfComponents(dimension) + VTKarray[me].SetName(label[i]) + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + # ------------------------------------------ process data --------------------------------------- - while table.data_read(): # read next data line of ASCII table + while table.data_read(): # read next data line of ASCII table - for datatype,labels in active.items(): # loop over scalar,color - for label in labels: # loop over all requested items - theData = table.data[column[datatype][label]:\ - column[datatype][label]+datainfo[datatype]['len']] # read strings - if datatype == 'color': - theData = map(lambda x: int(255.*float(x)),theData) - array[datatype][label].InsertNextTuple3(theData[0],theData[1],theData[2],) - elif datatype == 'scalar': - array[datatype][label].InsertNextValue(float(theData[0])) + for datatype,labels in active.items(): # loop over scalar,color + for me in labels: # loop over all requested items + theData = [table.data[i] for i in table.label_indexrange(me)] # read strings + if datatype == 'color': VTKarray[me].InsertNextTuple3(*map(lambda x: int(255.*float(x)),theData)) + elif datatype == 'vector': VTKarray[me].InsertNextTuple3(*map(float,theData)) + elif datatype == 'scalar': VTKarray[me].InsertNextValue(float(theData[0])) table.input_close() # close input ASCII table # ------------------------------------------ add data --------------------------------------- - for datatype,labels in active.items(): # loop over scalar,color + damask.util.croak('adding now...') + for datatype,labels in active.items(): # loop over scalar,color + damask.util.croak('type {}'.format(datatype)) + if datatype == 'color': - Polydata.GetPointData().SetScalars(array[datatype][labels[0]]) - Polydata.GetCellData().SetScalars(array[datatype][labels[0]]) - for label in labels: # loop over all requested items - Polydata.GetPointData().AddArray(array[datatype][label]) - Polydata.GetCellData().AddArray(array[datatype][label]) + Polydata.GetPointData().SetScalars(VTKarray[active['color'][0]]) + Polydata.GetCellData().SetScalars(VTKarray[active['color'][0]]) + for me in labels: # loop over all requested items + damask.util.croak('label {}'.format(me)) + Polydata.GetPointData().AddArray(VTKarray[me]) + Polydata.GetCellData().AddArray(VTKarray[me]) + + damask.util.croak('...done.') Polydata.Modified() - if vtk.VTK_MAJOR_VERSION <= 5: - Polydata.Update() + if vtk.VTK_MAJOR_VERSION <= 5: Polydata.Update() # ------------------------------------------ output result --------------------------------------- -writer = vtk.vtkXMLPolyDataWriter() -writer.SetDataModeToBinary() -writer.SetCompressorTypeToZLib() -writer.SetFileName(os.path.splitext(options.vtk)[0]+'_added.vtp') -if vtk.VTK_MAJOR_VERSION <= 5: - writer.SetInput(Polydata) -else: - writer.SetInputData(Polydata) -writer.Write() + writer = vtk.vtkXMLPolyDataWriter() + writer.SetDataModeToBinary() + writer.SetCompressorTypeToZLib() + writer.SetFileName(os.path.splitext(options.vtk)[0]+('.vtp' if options.inplace else '_added.vtp')) + if vtk.VTK_MAJOR_VERSION <= 5: writer.SetInput(Polydata) + else: writer.SetInputData(Polydata) + writer.Write() + +# ------------------------------------------ render result --------------------------------------- + +if options.render: + mapper = vtk.vtkDataSetMapper() + mapper.SetInputData(Polydata) + actor = vtk.vtkActor() + actor.SetMapper(mapper) + +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. + + ren = vtk.vtkRenderer() + + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + + ren.AddActor(actor) + ren.SetBackground(1, 1, 1) + renWin.SetSize(200, 200) + + iren = vtk.vtkRenderWindowInteractor() + iren.SetRenderWindow(renWin) + + iren.Initialize() + renWin.Render() + iren.Start() From 1994b5a4c12955a030651e567a5b02b4f8cd4054 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 19:29:04 -0400 Subject: [PATCH 124/134] removed debug messages --- processing/post/vtk_addPointcloudData.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/processing/post/vtk_addPointcloudData.py b/processing/post/vtk_addPointcloudData.py index 602e69307..58190de27 100755 --- a/processing/post/vtk_addPointcloudData.py +++ b/processing/post/vtk_addPointcloudData.py @@ -123,20 +123,14 @@ for name in filenames: # ------------------------------------------ add data --------------------------------------- - damask.util.croak('adding now...') for datatype,labels in active.items(): # loop over scalar,color - damask.util.croak('type {}'.format(datatype)) - if datatype == 'color': Polydata.GetPointData().SetScalars(VTKarray[active['color'][0]]) Polydata.GetCellData().SetScalars(VTKarray[active['color'][0]]) for me in labels: # loop over all requested items - damask.util.croak('label {}'.format(me)) Polydata.GetPointData().AddArray(VTKarray[me]) Polydata.GetCellData().AddArray(VTKarray[me]) - damask.util.croak('...done.') - Polydata.Modified() if vtk.VTK_MAJOR_VERSION <= 5: Polydata.Update() From 170d377092b749a460bbbde1c3cfb5b73c0b5e5a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 13 Apr 2016 19:33:46 -0400 Subject: [PATCH 125/134] much improved algorithm to speed up grain identification. --- processing/post/addGrainID.py | 118 +++++++++++++--------------------- 1 file changed, 44 insertions(+), 74 deletions(-) diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index 7eb48f286..a250c197c 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -5,7 +5,6 @@ import numpy as np import damask from optparse import OptionParser from scipy import spatial -from collections import defaultdict scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -23,7 +22,7 @@ parser.add_option('-r', '--radius', parser.add_option('-d', '--disorientation', dest = 'disorientation', type = 'float', metavar = 'float', - help = 'disorientation threshold per grain [%default] (degrees)') + help = 'disorientation threshold in degrees [%default]') parser.add_option('-s', '--symmetry', dest = 'symmetry', type = 'string', metavar = 'string', @@ -61,7 +60,8 @@ parser.add_option('-p', '--position', type = 'string', metavar = 'string', help = 'spatial position of voxel [%default]') -parser.set_defaults(symmetry = 'cubic', +parser.set_defaults(disorientation = 5, + symmetry = 'cubic', coords = 'pos', degrees = False, ) @@ -86,17 +86,16 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') (options.matrix,9,'matrix'), (options.quaternion,4,'quaternion'), ][np.where(input)[0][0]] # select input label that was requested -toRadians = np.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians -cos_disorientation = np.cos(options.disorientation/2.*toRadians) +toRadians = np.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians +cos_disorientation = np.cos(np.radians(options.disorientation/2.)) # cos of half the disorientation angle # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) + try: table = damask.ASCIItable(name = name, + buffered = False) except: continue damask.util.report(scriptName,name) @@ -109,8 +108,10 @@ for name in filenames: errors = [] remarks = [] - if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) - if not np.all(table.label_dimension(label) == dim): errors.append('input {} does not have dimension {}.'.format(label,dim)) + if not 3 >= table.label_dimension(options.coords) >= 1: + errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) + if not np.all(table.label_dimension(label) == dim): + errors.append('input {} does not have dimension {}.'.format(label,dim)) else: column = table.label_index(label) if remarks != []: damask.util.croak(remarks) @@ -122,8 +123,10 @@ for name in filenames: # ------------------------------------------ assemble header --------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append('grainID_{}@{}'.format(label, - options.disorientation if options.degrees else np.degrees(options.disorientation))) # report orientation source and disorientation in degrees + table.labels_append('grainID_{}@{:g}'.format('+'.join(label) + if isinstance(label, (list,tuple)) + else label, + options.disorientation)) # report orientation source and disorientation table.head_write() # ------------------------------------------ process data ------------------------------------------ @@ -162,7 +165,7 @@ for name in filenames: time_delta = (time.clock()-tick) * (len(grainID) - p) / p bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...'\ - %(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) + %(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),np.count_nonzero(memberCounts))) if inputtype == 'eulers': o = damask.Orientation(Eulers = np.array(map(float,table.data[column:column+3]))*toRadians, @@ -179,84 +182,51 @@ for name in filenames: o = damask.Orientation(quaternion = np.array(map(float,table.data[column:column+4])), symmetry = options.symmetry).reduced() - matched = False + matched = False + alreadyChecked = {} + candidates = [] + bestDisorientation = damask.Quaternion([0,0,0,1]) # initialize to 180 deg rotation as worst case -# check against last matched needs to be really picky. best would be to exclude jumps across the poke (checking distance between last and me?) -# when walking through neighborhood first check whether grainID of that point has already been tested, if yes, skip! - - if matchedID != -1: # has matched before? - matched = (o.quaternion.conjugated() * orientations[matchedID].quaternion).w > cos_disorientation - - if not matched: - alreadyChecked = {} - bestDisorientation = damask.Quaternion([0,0,0,1]) # initialize to 180 deg rotation as worst case - for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points - gID = grainID[i] - if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested? - alreadyChecked[gID] = True # remember not to check again - disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation - if disorientation.quaternion.w > cos_disorientation and \ - disorientation.quaternion.w >= bestDisorientation.w: # within threshold and betterthan current best? + for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring points + gID = grainID[i] + if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested? + alreadyChecked[gID] = True # remember not to check again + disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation + if disorientation.quaternion.w > cos_disorientation: # within threshold ... + candidates.append(gID) # remember as potential candidate + if disorientation.quaternion.w >= bestDisorientation.w: # ... and better than current best? matched = True matchedID = gID # remember that grain bestDisorientation = disorientation.quaternion - if not matched: # no match -> new grain found - memberCounts += [1] # start new membership counter + if matched: # did match existing grain + memberCounts[matchedID] += 1 + if len(candidates) > 1: # ambiguity in grain identification? + largestGrain = sorted(candidates,key=lambda x:memberCounts[x])[-1] # find largest among potential candidate grains + matchedID = largestGrain + for c in [c for c in candidates if c != largestGrain]: # loop over smaller candidates + memberCounts[largestGrain] += memberCounts[c] # reassign member count of smaller to largest + memberCounts[c] = 0 + grainID = np.where(np.in1d(grainID,candidates), largestGrain, grainID) # relabel grid points of smaller candidates as largest one + + else: # no match -> new grain found orientations += [o] # initialize with current orientation + memberCounts += [1] # start new membership counter matchedID = g g += 1 # increment grain counter - else: # did match existing grain - memberCounts[matchedID] += 1 - grainID[p] = matchedID # remember grain index assigned to point p += 1 # increment point - bg.set_message('identifying similar orientations among {} grains...'.format(len(orientations))) - - memberCounts = np.array(memberCounts) - similarOrientations = [[] for i in xrange(len(orientations))] - - for i,orientation in enumerate(orientations[:-1]): # compare each identified orientation... - for j in xrange(i+1,len(orientations)): # ...against all others that were defined afterwards - if orientation.disorientation(orientations[j],SST = False)[0].quaternion.w > cos_disorientation: # similar orientations in both grainIDs? - similarOrientations[i].append(j) # remember in upper triangle... - similarOrientations[j].append(i) # ...and lower triangle of matrix - - if similarOrientations[i] != []: - bg.set_message('grainID {} is as: {}'.format(i,' '.join(map(str,similarOrientations[i])))) - - stillShifting = True - while stillShifting: - stillShifting = False - tick = time.clock() - - for p,gID in enumerate(grainID): # walk through all points - if p > 0 and p % 1000 == 0: - - time_delta = (time.clock()-tick) * (len(grainID) - p) / p - bg.set_message('(%02i:%02i:%02i) shifting ID of point %i out of %i (grain count %i)...' - %(time_delta//3600,time_delta%3600//60,time_delta%60,p,len(grainID),len(orientations))) - if similarOrientations[gID] != []: # orientation of my grainID is similar to someone else? - similarNeighbors = defaultdict(int) # frequency of neighboring grainIDs sharing my orientation - for i in kdtree.query_ball_point(kdtree.data[p],options.radius): # check all neighboring point - if grainID[i] in similarOrientations[gID]: # neighboring point shares my orientation? - similarNeighbors[grainID[i]] += 1 # remember its grainID - if similarNeighbors != {}: # found similar orientation(s) in neighborhood - candidates = np.array([gID]+similarNeighbors.keys()) # possible replacement grainIDs for me - grainID[p] = candidates[np.argsort(memberCounts[candidates])[-1]] # adopt ID that is most frequent in overall dataset - memberCounts[gID] -= 1 # my former ID loses one fellow - memberCounts[grainID[p]] += 1 # my new ID gains one fellow - bg.set_message('{}:{} --> {}'.format(p,gID,grainID[p])) # report switch of grainID - stillShifting = True - + grainIDs = np.where(np.array(memberCounts) > 0)[0] # identify "live" grain identifiers + packingMap = dict(zip(list(grainIDs),range(len(grainIDs)))) # map to condense into consecutive IDs + table.data_rewind() outputAlive = True p = 0 while outputAlive and table.data_read(): # read next data line of ASCII table - table.data_append(1+grainID[p]) # add grain ID + table.data_append(1+packingMap[grainID[p]]) # add (condensed) grain ID outputAlive = table.data_write() # output processed line p += 1 From dbfd107b480e135cdfdea50661002b69ee27da36 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 14 Apr 2016 17:43:19 -0400 Subject: [PATCH 126/134] Add deformed configuration of given initial coordinates. Operates on periodic three-dimensional x,y,z-ordered data sets. Replaces 3Dvisualize..! --- processing/post/addDisplacements.py | 222 ++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100755 processing/post/addDisplacements.py diff --git a/processing/post/addDisplacements.py b/processing/post/addDisplacements.py new file mode 100755 index 000000000..3c3456b91 --- /dev/null +++ b/processing/post/addDisplacements.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 no BOM -*- + +import os,sys,math +import numpy as np +import scipy.ndimage +from optparse import OptionParser +import damask + +scriptName = os.path.splitext(os.path.basename(__file__))[0] +scriptID = ' '.join([scriptName,damask.version]) + + +#-------------------------------------------------------------------------------------------------- +def cell2node(cellData,grid): + + nodeData = 0.0 + datalen = np.array(cellData.shape[3:]).prod() + + for i in xrange(datalen): + node = scipy.ndimage.convolve(cellData.reshape(tuple(grid)+(datalen,))[...,i], + np.ones((2,2,2))/8., # 2x2x2 neighborhood of cells + mode = 'wrap', + origin = -1, # offset to have cell origin as center + ) # now averaged at cell origins + node = np.append(node,node[np.newaxis,0,:,:,...],axis=0) # wrap along z + node = np.append(node,node[:,0,np.newaxis,:,...],axis=1) # wrap along y + node = np.append(node,node[:,:,0,np.newaxis,...],axis=2) # wrap along x + + nodeData = node[...,np.newaxis] if i==0 else np.concatenate((nodeData,node[...,np.newaxis]),axis=-1) + + return nodeData + +#-------------------------------------------------------------------------------------------------- +def displacementAvgFFT(F,grid,size,nodal=False,transformed=False): + """calculate average cell center (or nodal) displacement for deformation gradient field specified in each grid cell""" + if nodal: + x, y, z = np.meshgrid(np.linspace(0,size[0],1+grid[0]), + np.linspace(0,size[1],1+grid[1]), + np.linspace(0,size[2],1+grid[2]), + indexing = 'ij') + else: + x, y, z = np.meshgrid(np.linspace(0,size[0],grid[0],endpoint=False), + np.linspace(0,size[1],grid[1],endpoint=False), + np.linspace(0,size[2],grid[2],endpoint=False), + indexing = 'ij') + + origCoords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) + + F_fourier = F if transformed else np.fft.rfftn(F,axes=(0,1,2)) # transform or use provided data + Favg = np.real(F_fourier[0,0,0,:,:])/grid.prod() # take zero freq for average + avgDisplacement = np.einsum('ml,ijkl->ijkm',Favg-np.eye(3),origCoords) # dX = Favg.X + + return avgDisplacement + +#-------------------------------------------------------------------------------------------------- +def displacementFluctFFT(F,grid,size,nodal=False,transformed=False): + """calculate cell center (or nodal) displacement for deformation gradient field specified in each grid cell""" + integrator = 0.5j * size / math.pi + + kk, kj, ki = np.meshgrid(np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2])), + np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1])), + np.arange(grid[0]//2+1), + indexing = 'ij') + k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3) + k_sSquared = np.einsum('...l,...l',k_s,k_s) + k_sSquared[0,0,0] = 1.0 # ignore global average frequency + +#-------------------------------------------------------------------------------------------------- +# integration in Fourier space + + displacement_fourier = -np.einsum('ijkml,ijkl,l->ijkm', + F if transformed else np.fft.rfftn(F,axes=(0,1,2)), + k_s, + integrator, + ) / k_sSquared[...,np.newaxis] + +#-------------------------------------------------------------------------------------------------- +# backtransformation to real space + + displacement = np.fft.irfftn(displacement_fourier,grid,axes=(0,1,2)) + + return cell2node(displacement,grid) if nodal else displacement + + +# -------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------- + +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options file[s]', description = """ +Add deformed configuration of given initial coordinates. +Operates on periodic three-dimensional x,y,z-ordered data sets. + +""", version = scriptID) + +parser.add_option('-f', '--defgrad', + dest = 'defgrad', + metavar = 'string', + help = 'column label of deformation gradient [%default]') +parser.add_option('-c', '--coordinates', + dest = 'coords', + metavar = 'string', + help = 'column label of coordinates [%default]') +parser.add_option('--nodal', + dest = 'nodal', + action = 'store_true', + help = 'output nodal (not cell-centered) displacements') + +parser.set_defaults(defgrad = 'f', + coords = 'ipinitialcoord', + nodal = False, + ) + +(options,filenames) = parser.parse_args() + +# --- loop over input files ------------------------------------------------------------------------- + +if filenames == []: filenames = [None] + +for name in filenames: + try: table = damask.ASCIItable(name = name, + outname = (os.path.splitext(name)[0]+ + '_nodal'+ + os.path.splitext(name)[1]) if (options.nodal and name) else None, + buffered = False) + except: continue + damask.util.report(scriptName,name) + +# ------------------------------------------ read header ------------------------------------------ + + table.head_read() + +# ------------------------------------------ sanity checks ---------------------------------------- + + errors = [] + remarks = [] + + if table.label_dimension(options.defgrad) != 9: + errors.append('deformation gradient "{}" is not a 3x3 tensor.'.format(options.defgrad)) + + coordDim = table.label_dimension(options.coords) + if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) + elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.coords)) + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) + table.close(dismiss=True) + continue + +# --------------- figure out size and grid --------------------------------------------------------- + + table.data_readArray([options.defgrad,options.coords]) + table.data_rewind() + + if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape + if table.data[:,9:].shape[1] < 3: + table.data = np.hstack((table.data, + np.zeros((table.data.shape[0], + 3-table.data[:,9:].shape[1]),dtype='f'))) # fill coords up to 3D with zeros + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + +# --------------- figure out size and grid --------------------------------------------------------- + + coords = [np.unique(table.data[:,9+i]) for i in xrange(3)] + mincorner = np.array(map(min,coords)) + maxcorner = np.array(map(max,coords)) + grid = np.array(map(len,coords),'i') + size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings + + N = grid.prod() + + if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid)) + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + +# ------------------------------------------ process data ------------------------------------------ + + F_fourier = np.fft.rfftn(table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),axes=(0,1,2)) # perform transform only once... + + displacement = displacementFluctFFT(F_fourier,grid,size,options.nodal,transformed=True) + avgDisplacement = displacementAvgFFT (F_fourier,grid,size,options.nodal,transformed=True) + +# ------------------------------------------ assemble header --------------------------------------- + + if options.nodal: + table.info_clear() + table.labels_clear() + + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) + table.labels_append((['{}_pos' .format(i+1) for i in xrange(3)] if options.nodal else []) + + ['{}_avg({}).{}' .format(i+1,options.defgrad,options.coords) for i in xrange(3)] + + ['{}_fluct({}).{}'.format(i+1,options.defgrad,options.coords) for i in xrange(3)] ) + table.head_write() + +# ------------------------------------------ output data ------------------------------------------- + + zrange = np.linspace(0,size[2],1+grid[2]) if options.nodal else xrange(grid[2]) + yrange = np.linspace(0,size[1],1+grid[1]) if options.nodal else xrange(grid[1]) + xrange = np.linspace(0,size[0],1+grid[0]) if options.nodal else xrange(grid[0]) + + for i,z in enumerate(zrange): + for j,y in enumerate(yrange): + for k,x in enumerate(xrange): + if options.nodal: table.data_clear() + else: table.data_read() + table.data_append([x,y,z] if options.nodal else []) + table.data_append(list(avgDisplacement[i,j,k,:])) + table.data_append(list( displacement[i,j,k,:])) + table.data_write() + +# ------------------------------------------ output finalization ----------------------------------- + + table.close() # close ASCII tables From 01ba11448c5e991378e1ce4039fec3cc651ca181 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 07:41:24 -0400 Subject: [PATCH 127/134] small polishing of remark output regarding <3D vectors --- processing/post/addDisplacements.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/processing/post/addDisplacements.py b/processing/post/addDisplacements.py index 3c3456b91..98d5c3291 100755 --- a/processing/post/addDisplacements.py +++ b/processing/post/addDisplacements.py @@ -139,8 +139,12 @@ for name in filenames: errors.append('deformation gradient "{}" is not a 3x3 tensor.'.format(options.defgrad)) coordDim = table.label_dimension(options.coords) - if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) - elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.coords)) + if not 3 >= coordDim >= 1: + errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) + elif coordDim < 3: + remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim, + 's' if coordDim < 2 else '', + options.coords)) if remarks != []: damask.util.croak(remarks) if errors != []: From f040842ed4418bf5776747090548282906f9964e Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 07:41:55 -0400 Subject: [PATCH 128/134] superseded by addDisplacements --- processing/post/addDeformedConfiguration.py | 164 -------------------- 1 file changed, 164 deletions(-) delete mode 100755 processing/post/addDeformedConfiguration.py diff --git a/processing/post/addDeformedConfiguration.py b/processing/post/addDeformedConfiguration.py deleted file mode 100755 index 3fb39ee0d..000000000 --- a/processing/post/addDeformedConfiguration.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 no BOM -*- - -import os,sys,math -import numpy as np -from optparse import OptionParser -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -#-------------------------------------------------------------------------------------------------- -def deformedCoordsFFT(F,undeformed=False): - - wgt = 1.0/grid.prod() - integrator = np.array([0.+1.j,0.+1.j,0.+1.j],'c16') * size/ 2.0 / math.pi - step = size/grid - - F_fourier = np.fft.rfftn(F,axes=(0,1,2)) - coords_fourier = np.zeros(F_fourier.shape[0:4],'c16') - - if undeformed: - Favg=np.eye(3) - else: - Favg=np.real(F_fourier[0,0,0,:,:])*wgt -#-------------------------------------------------------------------------------------------------- -# integration in Fourier space - k_s = np.zeros([3],'i') - for i in xrange(grid[2]): - k_s[2] = i - if(i > grid[2]//2 ): k_s[2] = k_s[2] - grid[2] - for j in xrange(grid[1]): - k_s[1] = j - if(j > grid[1]//2 ): k_s[1] = k_s[1] - grid[1] - for k in xrange(grid[0]//2+1): - k_s[0] = k - for m in xrange(3): - coords_fourier[i,j,k,m] = sum(F_fourier[i,j,k,m,0:3]*k_s*integrator) - if (any(k_s != 0)): - coords_fourier[i,j,k,0:3] /= -sum(k_s*k_s) - -#-------------------------------------------------------------------------------------------------- -# add average to scaled fluctuation and put (0,0,0) on (0,0,0) - coords = np.fft.irfftn(coords_fourier,F.shape[0:3],axes=(0,1,2)) - - offset_coords = np.dot(F[0,0,0,:,:],step/2.0) - scaling*coords[0,0,0,0:3] - for z in xrange(grid[2]): - for y in xrange(grid[1]): - for x in xrange(grid[0]): - coords[z,y,x,0:3] = scaling*coords[z,y,x,0:3] \ - + offset_coords \ - + np.dot(Favg,step*np.array([x,y,z])) - - return coords - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options file[s]', description = """ -Add deformed configuration of given initial coordinates. -Operates on periodic three-dimensional x,y,z-ordered data sets. - -""", version = scriptID) - -parser.add_option('-f', '--defgrad',dest='defgrad', metavar = 'string', - help='heading of deformation gradient columns [%default]') -parser.add_option('--reference', dest='undeformed', action='store_true', - help='map results to reference (undeformed) average configuration [%default]') -parser.add_option('--scaling', dest='scaling', action='extend', metavar = '', - help='scaling of fluctuation') -parser.add_option('-u', '--unitlength', dest='unitlength', type='float', metavar = 'float', - help='set unit length for 2D model [%default]') -parser.add_option('--coordinates', dest='coords', metavar='string', - help='column heading for coordinates [%default]') - -parser.set_defaults(defgrad = 'f') -parser.set_defaults(coords = 'ipinitialcoord') -parser.set_defaults(scaling = []) -parser.set_defaults(undeformed = False) -parser.set_defaults(unitlength = 0.0) - -(options,filenames) = parser.parse_args() - -options.scaling += [1.0 for i in xrange(max(0,3-len(options.scaling)))] -scaling = map(float, options.scaling) - - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) - -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - - if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) - else: colCoord = table.label_index(options.coords) - - if table.label_dimension(options.defgrad) != 9: errors.append('deformation gradient {} is not a tensor.'.format(options.defgrad)) - else: colF = table.label_index(options.defgrad) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - - coords = [np.unique(table.data[:,colCoord+i]) for i in xrange(3)] - mincorner = np.array(map(min,coords)) - maxcorner = np.array(map(max,coords)) - grid = np.array(map(len,coords),'i') - size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings - - N = grid.prod() - - if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid)) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for coord in xrange(3): - label = '{}_{}_{}'.format(coord+1,options.defgrad,options.coords) - if np.any(scaling) != 1.0: label+='_{}_{}_{}'.format(scaling) - if options.undeformed: label+='_undeformed' - table.labels_append([label]) # extend ASCII header with new labels - table.head_write() - -# ------------------------------------------ read deformation gradient field ----------------------- - centroids = deformedCoordsFFT(table.data[:,colF:colF+9].reshape(grid[2],grid[1],grid[0],3,3), - options.undeformed) -# ------------------------------------------ process data ------------------------------------------ - table.data_rewind() - for z in xrange(grid[2]): - for y in xrange(grid[1]): - for x in xrange(grid[0]): - table.data_read() - table.data_append(list(centroids[z,y,x,:])) - table.data_write() - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables \ No newline at end of file From 3474800db1241a22fb99213d6d30e3409594f961 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 14:04:10 -0400 Subject: [PATCH 129/134] switched coordinates default from "ipinitialcoords" (ugh) to "pos" --- processing/post/vtk_rectilinearGrid.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/processing/post/vtk_rectilinearGrid.py b/processing/post/vtk_rectilinearGrid.py index 38deabf3a..6f1228ad8 100755 --- a/processing/post/vtk_rectilinearGrid.py +++ b/processing/post/vtk_rectilinearGrid.py @@ -24,11 +24,11 @@ parser.add_option('-m', '--mode', type = 'choice', choices = ['cell','point'], help = 'cell-centered or point-centered coordinates ') parser.add_option('-c', '--coordinates', - dest = 'position', + dest = 'coords', type = 'string', metavar = 'string', help = 'coordinate label [%default]') -parser.set_defaults(position ='ipinitialcoord', - mode ='cell' +parser.set_defaults(coords = 'pos', + mode = 'cell' ) (options, filenames) = parser.parse_args() @@ -50,9 +50,9 @@ for name in filenames: remarks = [] errors = [] - coordDim = table.label_dimension(options.position) - if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.position)) - elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.position)) + coordDim = table.label_dimension(options.coords) + if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) + elif coordDim < 3: remarks.append('appending {} dimensions to coordinates "{}"...'.format(3-coordDim,options.coords)) if remarks != []: damask.util.croak(remarks) if errors != []: @@ -62,7 +62,7 @@ for name in filenames: # --------------- figure out size and grid --------------------------------------------------------- - table.data_readArray(options.position) + table.data_readArray(options.coords) if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape if table.data.shape[1] < 3: table.data = np.hstack((table.data, @@ -109,7 +109,7 @@ for name in filenames: writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() writer.SetFileName(os.path.join(directory,os.path.splitext(filename)[0] \ - +'_{}({})'.format(options.position, options.mode) \ + +'_{}({})'.format(options.coords, options.mode) \ +'.'+writer.GetDefaultFileExtension())) else: writer = vtk.vtkDataSetWriter() From cbe9afb2b3b1f8353842d6233f1d2043be4c7026 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 14:06:01 -0400 Subject: [PATCH 130/134] removed --mode option. script figures on its own. --- processing/post/vtk_addRectilinearGridData.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index 6b78950c7..d54bb4cf4 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -30,10 +30,6 @@ parser.add_option('-r', '--render', dest = 'render', action = 'store_true', help = 'open output in VTK render window') -parser.add_option('-m', '--mode', - dest = 'mode', - type = 'choice', metavar = 'string', choices = ['cell', 'point'], - help = 'cell-centered or point-centered data') parser.add_option('-s', '--scalar', dest = 'scalar', action = 'extend', metavar = '', @@ -56,7 +52,6 @@ parser.set_defaults(scalar = [], (options, filenames) = parser.parse_args() -if not options.mode: parser.error('No data mode specified.') if not options.vtk: parser.error('No VTK file specified.') if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') @@ -124,8 +119,11 @@ for name in filenames: # ------------------------------------------ process data --------------------------------------- + datacount = 0 + while table.data_read(): # read next data line of ASCII table - + + datacount += 1 # count data lines for datatype,labels in active.items(): # loop over scalar,color for me in labels: # loop over all requested items theData = [table.data[i] for i in table.label_indexrange(me)] # read strings @@ -133,17 +131,25 @@ for name in filenames: elif datatype == 'vector': VTKarray[me].InsertNextTuple3(*map(float,theData)) elif datatype == 'scalar': VTKarray[me].InsertNextValue(float(theData[0])) - table.input_close() # close input ASCII table + table.close() # close input ASCII table # ------------------------------------------ add data --------------------------------------- + if datacount == Npoints: mode = 'point' + elif datacount == Ncells: mode = 'cell' + else: + damask.util.croak('Data count is incompatible with grid...') + continue + + damask.util.croak('{} mode...'.format(mode)) + for datatype,labels in active.items(): # loop over scalar,color if datatype == 'color': - if options.mode == 'cell': rGrid.GetCellData().SetScalars(VTKarray[active['color'][0]]) - elif options.mode == 'point': rGrid.GetPointData().SetScalars(VTKarray[active['color'][0]]) + if mode == 'cell': rGrid.GetCellData().SetScalars(VTKarray[active['color'][0]]) + elif mode == 'point': rGrid.GetPointData().SetScalars(VTKarray[active['color'][0]]) for me in labels: # loop over all requested items - if options.mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[me]) - elif options.mode == 'point': rGrid.GetPointData().AddArray(VTKarray[me]) + if mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[me]) + elif mode == 'point': rGrid.GetPointData().AddArray(VTKarray[me]) rGrid.Modified() if vtk.VTK_MAJOR_VERSION <= 5: rGrid.Update() From 8ac40ced5a3b355db1fb4099c94b4f24fb478576 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 18:23:35 -0400 Subject: [PATCH 131/134] coordinates of nodal or cell-centered values are always labelled "pos" --- processing/post/postResults.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/processing/post/postResults.py b/processing/post/postResults.py index baa306003..95b9eabf8 100755 --- a/processing/post/postResults.py +++ b/processing/post/postResults.py @@ -1003,11 +1003,8 @@ fileOpen = False assembleHeader = True header = [] standard = ['inc'] + \ - {True: ['time'], - False:[]}[options.time] + \ - ['elem','node','ip','grain'] + \ - {True: ['1_nodeinitialcoord','2_nodeinitialcoord','3_nodeinitialcoord'], - False:['1_ipinitialcoord','2_ipinitialcoord','3_ipinitialcoord']}[options.nodalScalar != []] + ['time'] if options.time else [] + \ + ['elem','node','ip','grain','1_pos','2_pos','3_pos'] # --------------------------- loop over positions -------------------------------- From 7567aae7c08da7763fa71e05f1e308ffdfdcb1ac Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 18:25:56 -0400 Subject: [PATCH 132/134] now deals with 1D, 2D, 3D. speed up of grid detection. "pos" as default coordinate label. --- processing/post/addEuclideanDistance.py | 51 +++++++++++++------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/processing/post/addEuclideanDistance.py b/processing/post/addEuclideanDistance.py index 7f32abb6b..5299c4d27 100755 --- a/processing/post/addEuclideanDistance.py +++ b/processing/post/addEuclideanDistance.py @@ -89,19 +89,20 @@ Add column(s) containing Euclidean distance to grain structural features: bounda """, version = scriptID) parser.add_option('-c','--coordinates', dest='coords', metavar='string', - help='column heading for coordinates [%default]') + help='column label of coordinates [%default]') parser.add_option('-i','--identifier', dest='id', metavar = 'string', - help='heading of column containing grain identifier [%default]') + help='column label of grain identifier [%default]') parser.add_option('-t','--type', dest = 'type', action = 'extend', metavar = '', help = 'feature type {%s} '%(', '.join(map(lambda x:'/'.join(x['names']),features))) ) parser.add_option('-n','--neighborhood',dest='neighborhood', choices = neighborhoods.keys(), metavar = 'string', help = 'type of neighborhood [neumann] {%s}'%(', '.join(neighborhoods.keys()))) -parser.add_option('-s', '--scale', dest = 'scale', type = 'float', metavar='float', +parser.add_option('-s', '--scale', dest = 'scale', type = 'float', metavar = 'float', help = 'voxel size [%default]') -parser.set_defaults(coords = 'ipinitialcoord') -parser.set_defaults(id = 'texture') -parser.set_defaults(neighborhood = 'neumann') -parser.set_defaults(scale = 1.0) +parser.set_defaults(coords = 'pos', + id = 'texture', + neighborhood = 'neumann', + scale = 1.0, + ) (options,filenames) = parser.parse_args() @@ -125,10 +126,8 @@ for i,feature in enumerate(features): if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, buffered = False) - except: - continue + try: table = damask.ASCIItable(name = name, buffered = False) + except: continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ @@ -141,9 +140,11 @@ for name in filenames: remarks = [] column = {} - if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) + coordDim = table.label_dimension(options.coords) + if not 3 >= coordDim >= 1: + errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.coords)) else: coordCol = table.label_index(options.coords) - + if table.label_dimension(options.id) != 1: errors.append('grain identifier {} not found.'.format(options.id)) else: idCol = table.label_index(options.id) @@ -164,18 +165,20 @@ for name in filenames: table.data_readArray() - coords = [{},{},{}] - for i in xrange(len(table.data)): - for j in xrange(3): - coords[j][str(table.data[i,coordCol+j])] = True - grid = np.array(map(len,coords),'i') - size = grid/np.maximum(np.ones(3,'d'),grid-1.0)* \ - np.array([max(map(float,coords[0].keys()))-min(map(float,coords[0].keys())),\ - max(map(float,coords[1].keys()))-min(map(float,coords[1].keys())),\ - max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\ - ],'d') # size from bounding box, corrected for cell-centeredness + coords = [np.unique(table.data[:,coordCol+i]) for i in xrange(coordDim)] + mincorner = np.array(map(min,coords)) + maxcorner = np.array(map(max,coords)) + grid = np.array(map(len,coords)+[1]*(3-len(coords)),'i') - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings + N = grid.prod() + + if N != len(table.data): errors.append('data count {} does not match grid '.format(N) + + 'x'.join(map(str,grid)) + + '.') + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue # ------------------------------------------ process value field ----------------------------------- From 81f6530f5254bb98c044c8ac5b9dabe0a58ea51a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 18:27:23 -0400 Subject: [PATCH 133/134] changed default label of coordinates to "pos" --- processing/post/addCurl.py | 10 +-- processing/post/addDisplacements.py | 5 +- processing/post/addDivergence.py | 8 +-- processing/post/addGradient.py | 14 +++-- processing/post/averageDown.py | 15 ++--- processing/post/blowUp.py | 95 ++++++++++++++--------------- 6 files changed, 73 insertions(+), 74 deletions(-) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index d8b1ee025..683fc0631 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -71,18 +71,18 @@ Deals with both vector- and tensor-valued fields. parser.add_option('-c','--coordinates', dest = 'coords', - type = 'string', metavar='string', - help = 'column heading for coordinates [%default]') + type = 'string', metavar = 'string', + help = 'column label of coordinates [%default]') parser.add_option('-v','--vector', dest = 'vector', action = 'extend', metavar = '', - help = 'heading of columns containing vector field values') + help = 'column label(s) of vector field values') parser.add_option('-t','--tensor', dest = 'tensor', action = 'extend', metavar = '', - help = 'heading of columns containing tensor field values') + help = 'column label(s) of tensor field values') -parser.set_defaults(coords = 'ipinitialcoord', +parser.set_defaults(coords = 'pos', ) (options,filenames) = parser.parse_args() diff --git a/processing/post/addDisplacements.py b/processing/post/addDisplacements.py index 98d5c3291..b73994bde 100755 --- a/processing/post/addDisplacements.py +++ b/processing/post/addDisplacements.py @@ -88,8 +88,9 @@ def displacementFluctFFT(F,grid,size,nodal=False,transformed=False): # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options file[s]', description = """ -Add deformed configuration of given initial coordinates. +Add displacments resulting from deformation gradient field. Operates on periodic three-dimensional x,y,z-ordered data sets. +Outputs at cell centers or cell nodes (into separate file). """, version = scriptID) @@ -107,7 +108,7 @@ parser.add_option('--nodal', help = 'output nodal (not cell-centered) displacements') parser.set_defaults(defgrad = 'f', - coords = 'ipinitialcoord', + coords = 'pos', nodal = False, ) diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index aadaceabf..8d58367ac 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -58,17 +58,17 @@ Deals with both vector- and tensor-valued fields. parser.add_option('-c','--coordinates', dest = 'coords', type = 'string', metavar = 'string', - help = 'column heading for coordinates [%default]') + help = 'column label of coordinates [%default]') parser.add_option('-v','--vector', dest = 'vector', action = 'extend', metavar = '', - help = 'heading of columns containing vector field values') + help = 'column label(s) of vector field values') parser.add_option('-t','--tensor', dest = 'tensor', action = 'extend', metavar = '', - help = 'heading of columns containing tensor field values') + help = 'column label(s) of tensor field values') -parser.set_defaults(coords = 'ipinitialcoord', +parser.set_defaults(coords = 'pos', ) (options,filenames) = parser.parse_args() diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py index 555e587de..4d136c8b9 100755 --- a/processing/post/addGradient.py +++ b/processing/post/addGradient.py @@ -9,7 +9,9 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) +#-------------------------------------------------------------------------------------------------- def gradFFT(geomdim,field): + grid = np.array(np.shape(field)[2::-1]) N = grid.prod() # field size n = np.array(np.shape(field)[3:]).prod() # data size @@ -17,7 +19,7 @@ def gradFFT(geomdim,field): elif n == 1: dataType = 'scalar' field_fourier = np.fft.fftpack.rfftn(field,axes=(0,1,2)) - grad_fourier = np.zeros(field_fourier.shape+(3,),'c16') + grad_fourier = np.zeros(field_fourier.shape+(3,),'c16') # differentiation in Fourier space k_s = np.zeros([3],'i') @@ -61,17 +63,17 @@ Deals with both vector- and scalar fields. parser.add_option('-c','--coordinates', dest = 'coords', type = 'string', metavar='string', - help = 'column heading for coordinates [%default]') + help = 'column label of coordinates [%default]') parser.add_option('-v','--vector', dest = 'vector', action = 'extend', metavar = '', - help = 'heading of columns containing vector field values') + help = 'column label(s) of vector field values') parser.add_option('-s','--scalar', dest = 'scalar', action = 'extend', metavar = '', - help = 'heading of columns containing scalar field values') + help = 'column label(s) of scalar field values') -parser.set_defaults(coords = 'ipinitialcoord', +parser.set_defaults(coords = 'pos', ) (options,filenames) = parser.parse_args() @@ -96,7 +98,7 @@ for name in filenames: items = { 'scalar': {'dim': 1, 'shape': [1], 'labels':options.scalar, 'active':[], 'column': []}, - 'vector': {'dim': 3, 'shape': [3], 'labels':options.vector, 'active':[], 'column': []}, + 'vector': {'dim': 3, 'shape': [3], 'labels':options.vector, 'active':[], 'column': []}, } errors = [] remarks = [] diff --git a/processing/post/averageDown.py b/processing/post/averageDown.py index f77914374..0af56e176 100755 --- a/processing/post/averageDown.py +++ b/processing/post/averageDown.py @@ -22,7 +22,7 @@ Average each data block of size 'packing' into single values thus reducing the f parser.add_option('-c','--coordinates', dest = 'coords', type = 'string', metavar = 'string', - help = 'column heading for coordinates [%default]') + help = 'column label of coordinates [%default]') parser.add_option('-p','--packing', dest = 'packing', type = 'int', nargs = 3, metavar = 'int int int', @@ -39,7 +39,7 @@ parser.add_option('-s', '--size', dest = 'size', type = 'float', nargs = 3, metavar = 'float float float', help = 'size in x,y,z [autodetect]') -parser.set_defaults(coords = 'ipinitialcoord', +parser.set_defaults(coords = 'pos', packing = (2,2,2), shift = (0,0,0), grid = (0,0,0), @@ -59,11 +59,10 @@ if any(shift != 0): prefix += 'shift{:+}{:+}{:+}_'.format(*shift) if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.join(os.path.dirname(name), - prefix+os.path.basename(name)) if name else name, - buffered = False) + try: table = damask.ASCIItable(name = name, + outname = os.path.join(os.path.dirname(name), + prefix+os.path.basename(name)) if name else name, + buffered = False) except: continue damask.util.report(scriptName,name) @@ -75,7 +74,6 @@ for name in filenames: errors = [] remarks = [] - colCoord = None if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) else: colCoord = table.label_index(options.coords) @@ -86,7 +84,6 @@ for name in filenames: table.close(dismiss = True) continue - # ------------------------------------------ assemble header --------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) diff --git a/processing/post/blowUp.py b/processing/post/blowUp.py index 725e623b4..7b8c9bd15 100755 --- a/processing/post/blowUp.py +++ b/processing/post/blowUp.py @@ -19,83 +19,82 @@ to resolution*packing. """, version = scriptID) -parser.add_option('-c','--coordinates', dest='coords', metavar='string', - help='column heading for coordinates [%default]') -parser.add_option('-p','--packing', dest='packing', type='int', nargs=3, metavar='int int int', - help='dimension of packed group [%default]') -parser.add_option('-g','--grid', dest='resolution', type='int', nargs=3, metavar='int int int', - help='resolution in x,y,z [autodetect]') -parser.add_option('-s','--size', dest='dimension', type='float', nargs=3, metavar='int int int', - help='dimension in x,y,z [autodetect]') -parser.set_defaults(coords = 'ipinitialcoord') -parser.set_defaults(packing = (2,2,2)) -parser.set_defaults(grid = (0,0,0)) -parser.set_defaults(size = (0.0,0.0,0.0)) +parser.add_option('-c','--coordinates', + dest = 'coords', metavar = 'string', + help = 'column label of coordinates [%default]') +parser.add_option('-p','--packing', + dest = 'packing', type = 'int', nargs = 3, metavar = 'int int int', + help = 'dimension of packed group [%default]') +parser.add_option('-g','--grid', + dest = 'resolution', type = 'int', nargs = 3, metavar = 'int int int', + help = 'resolution in x,y,z [autodetect]') +parser.add_option('-s','--size', + dest = 'dimension', type = 'float', nargs = 3, metavar = 'int int int', + help = 'dimension in x,y,z [autodetect]') +parser.set_defaults(coords = 'pos', + packing = (2,2,2), + grid = (0,0,0), + size = (0.0,0.0,0.0), + ) (options,filenames) = parser.parse_args() - options.packing = np.array(options.packing) -prefix = 'blowUp%ix%ix%i_'%(options.packing[0],options.packing[1],options.packing[2]) +prefix = 'blowUp{}x{}x{}_'.format(*options.packing) # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.join(os.path.dirname(name), - prefix+ \ - os.path.basename(name)) if name else name, - buffered = False) + try: table = damask.ASCIItable(name = name, + outname = os.path.join(os.path.dirname(name), + prefix+os.path.basename(name)) if name else name, + buffered = False) except: continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ table.head_read() - errors = [] # ------------------------------------------ sanity checks ---------------------------------------- - if table.label_dimension(options.coords) != 3: - damask.util.croak('coordinates {} are not a vector.'.format(options.coords)) + errors = [] + remarks = [] + + if table.label_dimension(options.coords) != 3: errors.append('coordinates {} are not a vector.'.format(options.coords)) + else: colCoord = table.label_index(options.coords) + + colElem = table.label_index('elem') + + if remarks != []: damask.util.croak(remarks) + if errors != []: + damask.util.croak(errors) table.close(dismiss = True) continue - else: - coordCol = table.label_index(options.coords) - - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) # --------------- figure out size and grid --------------------------------------------------------- - table.data_readArray() - - coords = [{},{},{}] - for i in xrange(len(table.data)): - for j in xrange(3): - coords[j][str(table.data[i,coordCol+j])] = True - grid = np.array(map(len,coords),'i') - size = grid/np.maximum(np.ones(3,'d'),grid-1.0)* \ - np.array([max(map(float,coords[0].keys()))-min(map(float,coords[0].keys())),\ - max(map(float,coords[1].keys()))-min(map(float,coords[1].keys())),\ - max(map(float,coords[2].keys()))-min(map(float,coords[2].keys())),\ - ],'d') # size from bounding box, corrected for cell-centeredness - - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings + table.data_readArray(options.coords) + coords = [np.unique(table.data[:,i]) for i in xrange(3)] + mincorner = np.array(map(min,coords)) + maxcorner = np.array(map(max,coords)) + grid = np.array(map(len,coords),'i') + size = grid/np.maximum(np.ones(3,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) + size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 set to smallest among other spacings packing = np.array(options.packing,'i') outSize = grid*packing -# ------------------------------------------ assemble header --------------------------------------- +# ------------------------------------------ assemble header -------------------------------------- + + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.head_write() # ------------------------------------------ process data ------------------------------------------- + table.data_rewind() data = np.zeros(outSize.tolist()+[len(table.labels)]) p = np.zeros(3,'i') @@ -107,15 +106,15 @@ for name in filenames: table.data_read() data[d[0]:d[0]+packing[0], d[1]:d[1]+packing[1], - d[2]:d[2]+packing[2], + d[2]:d[2]+packing[2], : ] = np.tile(np.array(table.data_asFloat(),'d'),packing.tolist()+[1]) # tile to match blowUp voxel size elementSize = size/grid/packing elem = 1 for c in xrange(outSize[2]): for b in xrange(outSize[1]): for a in xrange(outSize[0]): - data[a,b,c,coordCol:coordCol+3] = [a+0.5,b+0.5,c+0.5]*elementSize - data[a,b,c,table.label_index('elem')] = elem + data[a,b,c,colCoord:colCoord+3] = [a+0.5,b+0.5,c+0.5]*elementSize + if colElem != -1: data[a,b,c,colElem] = elem table.data = data[a,b,c,:].tolist() outputAlive = table.data_write() # output processed line elem += 1 From 24d029c7ed51bab68c21cfd4954d5bf19eec3ebb Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 15 Apr 2016 18:54:09 -0400 Subject: [PATCH 134/134] speed up (x 5 to 10) identification of most frequent microstructure index --- processing/pre/geom_clean.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/processing/pre/geom_clean.py b/processing/pre/geom_clean.py index 18caf68b9..2bef9dc08 100755 --- a/processing/pre/geom_clean.py +++ b/processing/pre/geom_clean.py @@ -6,15 +6,12 @@ import numpy as np import damask from scipy import ndimage from optparse import OptionParser -from collections import defaultdict scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) def mostFrequent(arr): - d = defaultdict(int) - for i in arr: d[i] += 1 - return sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0][0] # return value of most frequent microstructure + return np.argmax(np.bincount(arr)) #-------------------------------------------------------------------------------------------------- @@ -43,10 +40,9 @@ parser.set_defaults(stencil = 3, if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, - labeled = False) + try: table = damask.ASCIItable(name = name, + buffered = False, + labeled = False) except: continue damask.util.report(scriptName,name) @@ -72,7 +68,7 @@ for name in filenames: # --- read data ------------------------------------------------------------------------------------ - microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure + microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure # --- do work ------------------------------------------------------------------------------------