From 40d38ebf55f38c65f81548645b5b213459e055b1 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 08:02:55 +0100 Subject: [PATCH 01/97] added rotation conversions modified versions from 3Drotations code (available on GitHub) by Marc De Graef --- src/CMakeLists.txt | 22 +- src/Lambert.f90 | 213 +++++++ src/commercialFEM_fileList.f90 | 3 + src/prec.f90 | 4 +- src/quaternions.f90 | 433 +++++++++++++ src/rotations.f90 | 1088 ++++++++++++++++++++++++++++++++ 6 files changed, 1757 insertions(+), 6 deletions(-) create mode 100644 src/Lambert.f90 create mode 100644 src/quaternions.f90 create mode 100644 src/rotations.f90 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e4462243..4210a79b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,18 +49,30 @@ add_library(FEsolving OBJECT "FEsolving.f90") add_dependencies(FEsolving DEBUG) list(APPEND OBJECTFILES $) -add_library(DAMASK_MATH OBJECT "math.f90") -add_dependencies(DAMASK_MATH FEsolving) -list(APPEND OBJECTFILES $) +add_library(MATH OBJECT "math.f90") +add_dependencies(MATH DEBUG) +list(APPEND OBJECTFILES $) + +add_library(QUATERNIONS OBJECT "quaternions.f90") +add_dependencies(QUATERNIONS MATH) +list(APPEND OBJECTFILES $) + +add_library(LAMBERT OBJECT "Lambert.f90") +add_dependencies(LAMBERT MATH) +list(APPEND OBJECTFILES $) + +add_library(ROTATIONS OBJECT "rotations.f90") +add_dependencies(ROTATIONS LAMBERT QUATERNIONS) +list(APPEND OBJECTFILES $) # SPECTRAL solver and FEM solver use different mesh files if (PROJECT_NAME STREQUAL "DAMASK_spectral") add_library(MESH OBJECT "mesh.f90") - add_dependencies(MESH DAMASK_MATH) + add_dependencies(MESH ROTATIONS FEsolving) list(APPEND OBJECTFILES $) elseif (PROJECT_NAME STREQUAL "DAMASK_FEM") add_library(FEZoo OBJECT "FEM_zoo.f90") - add_dependencies(FEZoo DAMASK_MATH) + add_dependencies(FEZoo ROTATIONS FEsolving) list(APPEND OBJECTFILES $) add_library(MESH OBJECT "meshFEM.f90") add_dependencies(MESH FEZoo) diff --git a/src/Lambert.f90 b/src/Lambert.f90 new file mode 100644 index 000000000..ab939bcc6 --- /dev/null +++ b/src/Lambert.f90 @@ -0,0 +1,213 @@ +! ################################################################### +! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without modification, are +! permitted provided that the following conditions are met: +! +! - Redistributions of source code must retain the above copyright notice, this list +! of conditions and the following disclaimer. +! - Redistributions in binary form must reproduce the above copyright notice, this +! list of conditions and the following disclaimer in the documentation and/or +! other materials provided with the distribution. +! - Neither the names of Marc De Graef, Carnegie Mellon University nor the names +! of its contributors may be used to endorse or promote products derived from +! this software without specific prior written permission. +! +! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! ################################################################### + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +! +!> @brief everything that has to do with the modified Lambert projections +! +!> @details This module contains a number of projection functions for the modified +!> Lambert projection between square lattice and 2D hemisphere, hexagonal lattice +!> and 2D hemisphere, as well as the more complex mapping between a 3D cubic grid +!> and the unit quaternion hemisphere with positive scalar component. In addition, there +!> are some other projections, such as the stereographic one. Each function is named +!> by the projection, the dimensionality of the starting grid, and the forward or inverse +!> character. For each function, there is also a single precision and a double precision +!> version, but we use the interface formalism to have only a single call. The Forward +!> mapping is taken to be the one from the simple grid to the curved grid. Since the module +!> deals with various grids, we also add a few functions/subroutines that apply symmetry +!> operations on those grids. +!> References: +!> D. Rosca, A. Morawiec, and M. De Graef. “A new method of constructing a grid +!> in the space of 3D rotations and its applications to texture analysis”. +!> Modeling and Simulations in Materials Science and Engineering 22, 075013 (2014). +!-------------------------------------------------------------------------- +module Lambert + use math + use prec + + implicit none + + real(pReal), private :: & + sPi = sqrt(PI), & + pref = sqrt(6.0_pReal/PI), & + ! the following constants are used for the cube to quaternion hemisphere mapping + ap = PI**(2.0_pReal/3.0_pReal), & + sc = 0.897772786961286_pReal, & ! a/ap + beta = 0.962874509979126_pReal, & ! pi^(5/6)/6^(1/6)/2 + R1 = 1.330670039491469_pReal, & ! (3pi/4)^(1/3) + r2 = sqrt(2.0_pReal), & + pi12 = PI/12.0_pReal, & + prek = 1.643456402972504_pReal, & ! R1 2^(1/4)/beta + r24 = sqrt(24.0_pReal) + + private + public :: & + LambertCubeToBall, & + LambertBallToCube + private :: & + GetPyramidOrder + +contains + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief map from 3D cubic grid to 3D ball +!-------------------------------------------------------------------------- +function LambertCubeToBall(cube) result(ball) + use, intrinsic :: IEEE_ARITHMETIC + + implicit none + real(pReal), intent(in), dimension(3) :: cube + real(pReal), dimension(3) :: ball, LamXYZ, XYZ + real(pReal) :: T(2), c, s, q + real(pReal), parameter :: eps = 1.0e-8_pReal + integer(pInt), dimension(3) :: p + integer(pInt), dimension(2) :: order + + if (maxval(abs(cube)) > ap/2.0+eps) then + ball = IEEE_value(cube,IEEE_positive_inf) + return + end if + + ! transform to the sphere grid via the curved square, and intercept the zero point + center: if (all(dEq0(cube))) then + ball = 0.0_pReal + else center + ! get pyramide and scale by grid parameter ratio + p = GetPyramidOrder(cube) + XYZ = cube(p) * sc + + ! intercept all the points along the z-axis + special: if (all(dEq0(XYZ(1:2)))) then + LamXYZ = [ 0.0_pReal, 0.0_pReal, pref * XYZ(3) ] + else special + order = merge( [2,1], [1,2], abs(XYZ(2)) <= abs(XYZ(1))) ! order of absolute values of XYZ + q = pi12 * XYZ(order(1))/XYZ(order(2)) ! smaller by larger + c = cos(q) + s = sin(q) + q = prek * XYZ(order(2))/ sqrt(r2-c) + T = [ (r2*c - 1.0), r2 * s] * q + + ! transform to sphere grid (inverse Lambert) + ! [note that there is no need to worry about dividing by zero, since XYZ(3) can not become zero] + c = sum(T**2) + s = Pi * c/(24.0*XYZ(3)**2) + c = sPi * c / r24 / XYZ(3) + q = sqrt( 1.0 - s ) + LamXYZ = [ T(order(2)) * q, T(order(1)) * q, pref * XYZ(3) - c ] + endif special + + ! reverse the coordinates back to the regular order according to the original pyramid number + ball = LamXYZ(p) + + endif center + +end function LambertCubeToBall + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief map from 3D ball to 3D cubic grid +!-------------------------------------------------------------------------- +pure function LambertBallToCube(xyz) result(cube) + use, intrinsic :: IEEE_ARITHMETIC + + implicit none + real(pReal), intent(in), dimension(3) :: xyz + real(pReal), dimension(3) :: cube, xyz1, xyz3 + real(pReal), dimension(2) :: Tinv, xyz2 + real(pReal) :: rs, qxy, q2, sq2, q, tt + integer(pInt) , dimension(3) :: p + + rs = norm2(xyz) + if (rs > R1) then + cube = IEEE_value(cube,IEEE_positive_inf) + return + endif + + center: if (all(dEq0(xyz))) then + cube = 0.0_pReal + else center + p = GetPyramidOrder(xyz) + xyz3 = xyz(p) + + ! inverse M_3 + xyz2 = xyz3(1:2) * sqrt( 2.0*rs/(rs+abs(xyz3(3))) ) + + ! inverse M_2 + qxy = sum(xyz2**2) + + special: if (dEq0(qxy)) then + Tinv = 0.0 + else special + q2 = qxy + maxval(abs(xyz2))**2 + sq2 = sqrt(q2) + q = (beta/r2/R1) * sqrt(q2*qxy/(q2-maxval(abs(xyz2))*sq2)) + tt = (minval(abs(xyz2))**2+maxval(abs(xyz2))*sq2)/r2/qxy + Tinv = q * sign(1.0,xyz2) * merge([ 1.0_pReal, acos(math_clip(tt,-1.0_pReal,1.0_pReal))/pi12], & + [ acos(math_clip(tt,-1.0_pReal,1.0_pReal))/pi12, 1.0_pReal], & + abs(xyz2(2)) <= abs(xyz2(1))) + endif special + + ! inverse M_1 + xyz1 = [ Tinv(1), Tinv(2), sign(1.0,xyz3(3)) * rs / pref ] /sc + + ! reverst the coordinates back to the regular order according to the original pyramid number + cube = xyz1(p) + + endif center + +end function LambertBallToCube + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief determine to which pyramid a point in a cubic grid belongs +!-------------------------------------------------------------------------- +pure function GetPyramidOrder(xyz) + + implicit none + real(pReal),intent(in),dimension(3) :: xyz + integer(pInt), dimension(3) :: GetPyramidOrder + + if (((abs(xyz(1)) <= xyz(3)).and.(abs(xyz(2)) <= xyz(3))) .or. & + ((abs(xyz(1)) <= -xyz(3)).and.(abs(xyz(2)) <= -xyz(3)))) then + GetPyramidOrder = [1,2,3] + else if (((abs(xyz(3)) <= xyz(1)).and.(abs(xyz(2)) <= xyz(1))) .or. & + ((abs(xyz(3)) <= -xyz(1)).and.(abs(xyz(2)) <= -xyz(1)))) then + GetPyramidOrder = [2,3,1] + else if (((abs(xyz(1)) <= xyz(2)).and.(abs(xyz(3)) <= xyz(2))) .or. & + ((abs(xyz(1)) <= -xyz(2)).and.(abs(xyz(3)) <= -xyz(2)))) then + GetPyramidOrder = [3,1,2] + else + GetPyramidOrder = -1 ! should be impossible, but might simplify debugging + end if + +end function GetPyramidOrder + +end module Lambert diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index 36f0244ef..75f540524 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -11,6 +11,9 @@ #include "debug.f90" #include "config.f90" #include "math.f90" +#include "quaternions.f90" +#include "Lambert.f90" +#include "rotations.f90" #include "FEsolving.f90" #include "mesh.f90" #include "material.f90" diff --git a/src/prec.f90 b/src/prec.f90 index 0f942b3c1..bc7f523d0 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -30,7 +30,9 @@ module prec integer(pInt), allocatable, dimension(:) :: realloc_lhs_test - type, public :: group_float !< variable length datatype used for storage of state + real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. ToDo: Better place? + + type, public :: group_float !< variable length datatype used for storage of state real(pReal), dimension(:), pointer :: p end type group_float diff --git a/src/quaternions.f90 b/src/quaternions.f90 new file mode 100644 index 000000000..60b8d387d --- /dev/null +++ b/src/quaternions.f90 @@ -0,0 +1,433 @@ +! ################################################################### +! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without modification, are +! permitted provided that the following conditions are met: +! +! - Redistributions of source code must retain the above copyright notice, this list +! of conditions and the following disclaimer. +! - Redistributions in binary form must reproduce the above copyright notice, this +! list of conditions and the following disclaimer in the documentation and/or +! other materials provided with the distribution. +! - Neither the names of Marc De Graef, Carnegie Mellon University nor the names +! of its contributors may be used to endorse or promote products derived from +! this software without specific prior written permission. +! +! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! ################################################################### + +module quaternions + + use prec + implicit none + + public + type, public :: quaternion + real(pReal) :: w = 0.0_pReal + real(pReal) :: x = 0.0_pReal + real(pReal) :: y = 0.0_pReal + real(pReal) :: z = 0.0_pReal + + + contains + procedure, private :: add__ + procedure, private :: pos__ + generic, public :: operator(+) => add__,pos__ + + procedure, private :: sub__ + procedure, private :: neg__ + generic, public :: operator(-) => sub__,neg__ + + procedure, private :: mul_quat__ + procedure, private :: mul_scal__ + generic, public :: operator(*) => mul_quat__, mul_scal__ + + procedure, private :: div_quat__ + procedure, private :: div_scal__ + generic, public :: operator(/) => div_quat__, div_scal__ + + procedure, private :: eq__ + generic, public :: operator(==) => eq__ + + procedure, private :: neq__ + generic, public :: operator(/=) => neq__ + + procedure, private :: pow_quat__ + procedure, private :: pow_scal__ + generic, public :: operator(**) => pow_quat__, pow_scal__ + + procedure, private :: abs__ + procedure, private :: dot_product__ + procedure, private :: conjg__ + procedure, private :: exp__ + procedure, private :: log__ + + procedure, public :: homomorphed => quat_homomorphed + + !procedure,private :: quat_write + !generic :: write(formatted) => quat_write + + end type + +interface assignment (=) + module procedure assign_quat__ + module procedure assign_vec__ +end interface assignment (=) + +interface quaternion + module procedure init__ +end interface quaternion + +interface abs + procedure abs__ +end interface abs + +interface dot_product + procedure dot_product__ +end interface dot_product + +interface conjg + module procedure conjg__ +end interface conjg + +interface exp + module procedure exp__ +end interface exp + +interface log + module procedure log__ +end interface log + +contains + + +!-------------------------------------------------------------------------- +!> constructor for a quaternion from a 4-vector +!-------------------------------------------------------------------------- +type(quaternion) pure function init__(array) + + implicit none + real(pReal), intent(in), dimension(4) :: array + + init__%w=array(1) + init__%x=array(2) + init__%y=array(3) + init__%z=array(4) + +end function init__ + + +!-------------------------------------------------------------------------- +!> assing a quaternion +!-------------------------------------------------------------------------- +elemental subroutine assign_quat__(self,other) + + implicit none + type(quaternion), intent(out) :: self + type(quaternion), intent(in) :: other + + self%w = other%w + self%x = other%x + self%y = other%y + self%z = other%z + +end subroutine assign_quat__ + + +!-------------------------------------------------------------------------- +!> assing a 4-vector +!-------------------------------------------------------------------------- +pure subroutine assign_vec__(self,other) + + implicit none + type(quaternion), intent(out) :: self + real(pReal), intent(in), dimension(4) :: other + + self%w = other(1) + self%x = other(2) + self%y = other(3) + self%z = other(4) + +end subroutine assign_vec__ + + +!-------------------------------------------------------------------------- +!> addition of two quaternions +!-------------------------------------------------------------------------- +type(quaternion) elemental function add__(self,other) + + implicit none + class(quaternion), intent(in) :: self,other + + add__%w = self%w + other%w + add__%x = self%x + other%x + add__%y = self%y + other%y + add__%z = self%z + other%z + +end function add__ + + +!-------------------------------------------------------------------------- +!> unary positive operator +!-------------------------------------------------------------------------- +type(quaternion) elemental function pos__(self) + + implicit none + class(quaternion), intent(in) :: self + + pos__%w = self%w + pos__%x = self%x + pos__%y = self%y + pos__%z = self%z + +end function pos__ + + +!-------------------------------------------------------------------------- +!> subtraction of two quaternions +!-------------------------------------------------------------------------- +type(quaternion) elemental function sub__(self,other) + + implicit none + class(quaternion), intent(in) :: self,other + + sub__%w = self%w - other%w + sub__%x = self%x - other%x + sub__%y = self%y - other%y + sub__%z = self%z - other%z + +end function sub__ + + +!-------------------------------------------------------------------------- +!> unary positive operator +!-------------------------------------------------------------------------- +type(quaternion) elemental function neg__(self) + + implicit none + class(quaternion), intent(in) :: self + + neg__%w = -self%w + neg__%x = -self%x + neg__%y = -self%y + neg__%z = -self%z + +end function neg__ + + +!-------------------------------------------------------------------------- +!> multiplication of two quaternions +!-------------------------------------------------------------------------- +type(quaternion) elemental function mul_quat__(self,other) + + implicit none + class(quaternion), intent(in) :: self, other + + mul_quat__%w = self%w*other%w - self%x*other%x - self%y*other%y - self%z*other%z + mul_quat__%x = self%w*other%x + self%x*other%w + epsijk * (self%y*other%z - self%z*other%y) + mul_quat__%y = self%w*other%y + self%y*other%w + epsijk * (self%z*other%x - self%x*other%z) + mul_quat__%z = self%w*other%z + self%z*other%w + epsijk * (self%x*other%y - self%y*other%x) + +end function mul_quat__ + + +!-------------------------------------------------------------------------- +!> multiplication of quaternions with scalar +!-------------------------------------------------------------------------- +type(quaternion) elemental function mul_scal__(self,scal) + + implicit none + class(quaternion), intent(in) :: self + real(pReal), intent(in) :: scal + + mul_scal__%w = self%w*scal + mul_scal__%x = self%x*scal + mul_scal__%y = self%y*scal + mul_scal__%z = self%z*scal + +end function mul_scal__ + + +!-------------------------------------------------------------------------- +!> division of two quaternions +!-------------------------------------------------------------------------- +type(quaternion) elemental function div_quat__(self,other) + + implicit none + class(quaternion), intent(in) :: self, other + + div_quat__ = self * (conjg(other)/(abs(other)**2.0_pReal)) + +end function div_quat__ + + +!-------------------------------------------------------------------------- +!> divisiont of quaternions by scalar +!-------------------------------------------------------------------------- +type(quaternion) elemental function div_scal__(self,scal) + + implicit none + class(quaternion), intent(in) :: self + real(pReal), intent(in) :: scal + + div_scal__ = [self%w,self%x,self%y,self%z]/scal + +end function div_scal__ + + +!-------------------------------------------------------------------------- +!> equality of two quaternions +!-------------------------------------------------------------------------- +logical elemental function eq__(self,other) + implicit none + class(quaternion), intent(in) :: self,other + + eq__ = all(dEq([ self%w, self%x, self%y, self%z], & + [other%w,other%x,other%y,other%z])) + +end function eq__ + + +!-------------------------------------------------------------------------- +!> inequality of two quaternions +!-------------------------------------------------------------------------- +logical elemental function neq__(self,other) + + implicit none + class(quaternion), intent(in) :: self,other + + neq__ = .not. self%eq__(other) + +end function neq__ + + +!-------------------------------------------------------------------------- +!> quaternion to the power of a scalar +!-------------------------------------------------------------------------- +type(quaternion) elemental function pow_scal__(self,expon) + + implicit none + class(quaternion), intent(in) :: self + real(pReal), intent(in) :: expon + + pow_scal__ = exp(log(self)*expon) + +end function pow_scal__ + + +!-------------------------------------------------------------------------- +!> quaternion to the power of a quaternion +!-------------------------------------------------------------------------- +type(quaternion) elemental function pow_quat__(self,expon) + + implicit none + class(quaternion), intent(in) :: self + type(quaternion), intent(in) :: expon + + pow_quat__ = exp(log(self)*expon) + +end function pow_quat__ + + +!-------------------------------------------------------------------------- +!> exponential of a quaternion +!> ToDo: Lacks any check for invalid operations +!-------------------------------------------------------------------------- +type(quaternion) elemental function exp__(self) + + implicit none + class(quaternion), intent(in) :: self + real(pReal) :: absImag + + absImag = norm2([self%x, self%y, self%z]) + + exp__ = exp(self%w) * [ cos(absImag), & + self%x/absImag * sin(absImag), & + self%y/absImag * sin(absImag), & + self%z/absImag * sin(absImag)] + +end function exp__ + + +!-------------------------------------------------------------------------- +!> logarithm of a quaternion +!> ToDo: Lacks any check for invalid operations +!-------------------------------------------------------------------------- +type(quaternion) elemental function log__(self) + + implicit none + class(quaternion), intent(in) :: self + real(pReal) :: absImag + + absImag = norm2([self%x, self%y, self%z]) + + log__ = [log(abs(self)), & + self%x/absImag * acos(self%w/abs(self)), & + self%y/absImag * acos(self%w/abs(self)), & + self%z/absImag * acos(self%w/abs(self))] + +end function log__ + + +!-------------------------------------------------------------------------- +!> norm of a quaternion +!-------------------------------------------------------------------------- +real(pReal) elemental function abs__(a) + + implicit none + class(quaternion), intent(in) :: a + + abs__ = norm2([a%w,a%x,a%y,a%z]) + +end function abs__ + + +!-------------------------------------------------------------------------- +!> dot product of two quaternions +!-------------------------------------------------------------------------- +real(pReal) elemental function dot_product__(a,b) + + implicit none + class(quaternion), intent(in) :: a,b + + dot_product__ = a%w*b%w + a%x*b%x + a%y*b%y + a%z*b%z + +end function dot_product__ + + +!-------------------------------------------------------------------------- +!> conjugate complex of a quaternion +!-------------------------------------------------------------------------- +type(quaternion) elemental function conjg__(a) + + implicit none + class(quaternion), intent(in) :: a + + conjg__ = quaternion([a%w, -a%x, -a%y, -a%z]) + +end function conjg__ + + +!-------------------------------------------------------------------------- +!> homomorphed quaternion of a quaternion +!-------------------------------------------------------------------------- +type(quaternion) elemental function quat_homomorphed(a) + + implicit none + class(quaternion), intent(in) :: a + + quat_homomorphed = quaternion(-[a%w,a%x,a%y,a%z]) + +end function quat_homomorphed + +end module quaternions diff --git a/src/rotations.f90 b/src/rotations.f90 new file mode 100644 index 000000000..830f49553 --- /dev/null +++ b/src/rotations.f90 @@ -0,0 +1,1088 @@ +! ################################################################### +! Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without modification, are +! permitted provided that the following conditions are met: +! +! - Redistributions of source code must retain the above copyright notice, this list +! of conditions and the following disclaimer. +! - Redistributions in binary form must reproduce the above copyright notice, this +! list of conditions and the following disclaimer in the documentation and/or +! other materials provided with the distribution. +! - Neither the names of Marc De Graef, Carnegie Mellon University nor the names +! of its contributors may be used to endorse or promote products derived from +! this software without specific prior written permission. +! +! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! ################################################################### + +module rotations + use prec + use quaternions + + implicit none + type, public :: rotation + type(quaternion), private :: q + contains + procedure, public :: asEulerAngles => asEulerAngles + procedure, public :: asAxisAnglePair => asAxisAnglePair + procedure, public :: asRodriguesFrankVector => asRodriguesFrankVector + procedure, public :: asRotationMatrix => asRotationMatrix + procedure, public :: rotVector + procedure, public :: rotTensor + end type + + interface rotation + module procedure init + end interface + +contains + +type(rotation) function init(eu,ax,om,qu,cu,ho,ro) + real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho + real(pReal), intent(in), optional, dimension(4) :: qu, ax, ro + real(pReal), intent(in), optional, dimension(3,3) :: om + + if (count([present(eu),present(ax),present(om),present(qu),& + present(cu),present(ho),present(ro)]) > 1_pInt) write(6,*) 'invalid' + + if (present(eu)) then + init%q = eu2qu(eu) + elseif (present(ax)) then + init%q = ax2qu(ax) + elseif (present(om)) then + init%q = om2qu(om) + elseif (present(qu)) then + init%q = quaternion(qu) + elseif (present(cu)) then + init%q = cu2qu(cu) + elseif (present(ho)) then + init%q = ho2qu(ho) + elseif (present(ro)) then + init%q = ro2qu(ro) + else + init%q = quaternion([1.0_pReal,0.0_pReal,0.0_pReal,0.0_pReal]) + endif + +end function + +function asEulerAngles(this) + class(rotation), intent(in) :: this + real(pReal), dimension(3) :: asEulerAngles + + asEulerAngles = qu2eu(this%q) + +end function asEulerAngles + + +function asAxisAnglePair(this) + class(rotation), intent(in) :: this + real(pReal), dimension(4) :: asAxisAnglePair + + asAxisAnglePair = qu2ax(this%q) + +end function asAxisAnglePair + + +function asRotationMatrix(this) + class(rotation), intent(in) :: this + real(pReal), dimension(3,3) :: asRotationMatrix + + asRotationMatrix = qu2om(this%q) + +end function asRotationMatrix + + +function asRodriguesFrankVector(this) + class(rotation), intent(in) :: this + real(pReal), dimension(4) :: asRodriguesFrankVector + + asRodriguesFrankVector = qu2ro(this%q) +end function asRodriguesFrankVector + + +function asHomochoric(this) + class(rotation), intent(in) :: this + real(pReal), dimension(3) :: asHomochoric + + asHomochoric = qu2ho(this%q) + +end function asHomochoric + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief rotates a vector passively (default) or actively +!-------------------------------------------------------------------------- +function rotVector(this,v,active) + class(rotation), intent(in) :: this + logical, intent(in), optional :: active + real(pReal),intent(in),dimension(3) :: v + real(pReal),dimension(3) :: rotVector + type(quaternion) :: q + + if (dEq(norm2(v),1.0_pReal,tol=1.0e-15_pReal)) then + passive: if (merge(.not. active, .true., present(active))) then + q = this%q * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * conjg(this%q) ) + else passive + q = conjg(this%q) * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * this%q ) + endif passive + rotVector = [q%x,q%y,q%z] + else + passive2: if (merge(.not. active, .true., present(active))) then + rotVector = matmul(this%asRotationMatrix(),v) + else passive2 + rotVector = matmul(transpose(this%asRotationMatrix()),v) + endif passive2 + endif + +end function rotVector + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief rotate a second rank tensor using a rotation matrix, active or passive (single precision) +!-------------------------------------------------------------------------- +function rotTensor(this,m,active) + class(rotation), intent(in) :: this + real(pReal),intent(in),dimension(3,3) :: m + logical, intent(in), optional :: active + real(pReal),dimension(3,3) :: rotTensor + + passive: if (merge(.not. active, .true., present(active))) then + rotTensor = matmul(matmul(this%asRotationMatrix(),m),transpose(this%asRotationMatrix())) + else passive + rotTensor = matmul(matmul(transpose(this%asRotationMatrix()),m),this%asRotationMatrix()) + endif passive + +end function rotTensor + + +!-------------------------------------------------------------------------- +!-------------------------------------------------------------------------- +! here we start with a series of conversion routines between representations +!-------------------------------------------------------------------------- +!-------------------------------------------------------------------------- + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Euler angles to orientation matrix [Morawiec, page 28] +!-------------------------------------------------------------------------- +pure function eu2om(eu) result(om) + + implicit none + real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians + real(pReal), dimension(3,3) :: om !< output orientation matrix + real(pReal), dimension(3) :: c, s + + c = cos(eu) + s = sin(eu) + + om(1,1) = c(1)*c(3)-s(1)*s(3)*c(2) + om(1,2) = s(1)*c(3)+c(1)*s(3)*c(2) + om(1,3) = s(3)*s(2) + om(2,1) = -c(1)*s(3)-s(1)*c(3)*c(2) + om(2,2) = -s(1)*s(3)+c(1)*c(3)*c(2) + om(2,3) = c(3)*s(2) + om(3,1) = s(1)*s(2) + om(3,2) = -c(1)*s(2) + om(3,3) = c(2) + + where(dEq0(om)) om = 0.0_pReal + +end function eu2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert euler to axis angle +!-------------------------------------------------------------------------- +pure function eu2ax(eu) result(ax) + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians + real(pReal), dimension(4) :: ax + real(pReal) :: t, delta, tau, alpha, sigma + + t = tan(eu(2)*0.5) + sigma = 0.5*(eu(1)+eu(3)) + delta = 0.5*(eu(1)-eu(3)) + tau = sqrt(t**2+sin(sigma)**2) + + alpha = merge(PI, 2.0*atan(tau/cos(sigma)), dEq(sigma,PI*0.5_pReal,tol=1.0e-15_pReal)) + + if (dEq0(alpha)) then ! return a default identity axis-angle pair + ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] + else + ax(1:3) = -epsijk/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front + ax(4) = alpha + if (alpha < 0.0) ax = -ax ! ensure alpha is positive + end if + +end function eu2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Euler angles to Rodrigues vector +!-------------------------------------------------------------------------- +pure function eu2ro(eu) result(ro) + use, intrinsic :: IEEE_ARITHMETIC + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians + real(pReal), dimension(4) :: ro + + ro = eu2ax(eu) ! convert to axis angle representation + if (ro(4) >= PI) then + ro(4) = IEEE_value(ro(4),IEEE_positive_inf) + elseif(dEq0(ro(4))) then + ro = [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal ] + else + ro(4) = tan(ro(4)*0.5) + end if + +end function eu2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Euler angles to quaternion +!-------------------------------------------------------------------------- +pure function eu2qu(eu) result(qu) + + implicit none + real(pReal), intent(in), dimension(3) :: eu + type(quaternion) :: qu + real(pReal), dimension(3) :: ee + real(pReal) :: cPhi, sPhi + + ee = 0.5_pReal*eu + + cPhi = cos(ee(2)) + sPhi = sin(ee(2)) + + ! passive quaternion + qu = quaternion([ cPhi*cos(ee(1)+ee(3)), & + -epsijk*sPhi*cos(ee(1)-ee(3)), & + -epsijk*sPhi*sin(ee(1)-ee(3)), & + -epsijk*cPhi*sin(ee(1)+ee(3))]) + if(qu%w < 0.0_pReal) qu = qu%homomorphed() + +end function eu2qu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief orientation matrix to euler angles +!-------------------------------------------------------------------------- +pure function om2eu(om) result(eu) + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(3,3) :: om !< orientation matrix + real(pReal), dimension(3) :: eu + real(pReal) :: zeta + + if (dEq(abs(om(3,3)),1.0_pReal,1.0e-15_pReal)) then + eu = [ atan2( om(1,2),om(1,1)), 0.5*PI*(1-om(3,3)),0.0_pReal ] + else + zeta = 1.0_pReal/sqrt(1.0_pReal-om(3,3)**2.0_pReal) + eu = [atan2(om(3,1)*zeta,-om(3,2)*zeta), & + acos(om(3,3)), & + atan2(om(1,3)*zeta, om(2,3)*zeta)] + end if + where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) + +end function om2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Axis angle pair to orientation matrix +!-------------------------------------------------------------------------- +pure function ax2om(ax) result(om) + + implicit none + real(pReal), intent(in), dimension(4) :: ax + real(pReal), dimension(3,3) :: om !< orientation matrix + real(pReal) :: q, c, s, omc + integer(pInt) :: i + + c = cos(ax(4)) + s = sin(ax(4)) + omc = 1.0-c + + forall(i=1:3) om(i,i) = ax(i)**2*omc + c + + q = omc*ax(1)*ax(2) + om(1,2) = q + s*ax(3) + om(2,1) = q - s*ax(3) + + q = omc*ax(2)*ax(3) + om(2,3) = q + s*ax(1) + om(3,2) = q - s*ax(1) + + q = omc*ax(3)*ax(1) + om(3,1) = q + s*ax(2) + om(1,3) = q - s*ax(2) + + if (epsijk > 0.0) om = transpose(om) + +end function ax2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Quaternion to Euler angles [Morawiec page 40, with errata !!!! ] +!-------------------------------------------------------------------------- +pure function qu2eu(qu) result(eu) + use math, only: & + PI + + implicit none + type(quaternion), intent(in) :: qu !< quaternion + real(pReal), dimension(3) :: eu + real(pReal) :: q12, q03, chi, chiInv + + q03 = qu%w**2+qu%z**2 + q12 = qu%x**2+qu%y**2 + chi = sqrt(q03*q12) + + degenerated: if (dEq0(chi)) then + eu = merge([atan2(-epsijk*2.0*qu%w*qu%z,qu%w**2-qu%z**2), 0.0_pReal, 0.0_pReal], & + [atan2(2.0*qu%x*qu%y,qu%x**2-qu%y**2), PI, 0.0_pReal], & + dEq0(q12)) + else degenerated + chiInv = 1.0/chi + eu = [atan2((-epsijk*qu%w*qu%y+qu%x*qu%z)*chi, (-epsijk*qu%w*qu%x-qu%y*qu%z)*chi ), & + atan2( 2.0*chi, q03-q12 ), & + atan2(( epsijk*qu%w*qu%y+qu%x*qu%z)*chi, (-epsijk*qu%w*qu%x+qu%y*qu%z)*chi )] + endif degenerated + where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) + +end function qu2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Axis angle pair to homochoric +!-------------------------------------------------------------------------- +pure function ax2ho(ax) result(ho) + + + real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + real(pReal), dimension(3) :: ho + real(pReal) :: f + + f = 0.75 * ( ax(4) - sin(ax(4)) ) + f = f**(1.0/3.0) + ho = ax(1:3) * f + +end function ax2ho + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Homochoric to axis angle pair +!-------------------------------------------------------------------------- +pure function ho2ax(ho) result(ax) + + implicit none + real(pReal), intent(in), dimension(3) :: ho !< homochoric coordinates + real(pReal), dimension(4) :: ax + integer(pInt) :: i + real(pReal) :: hmag_squared, s, hm + real(pReal), parameter, dimension(16) :: & + tfit = [ 1.0000000000018852_pReal, -0.5000000002194847_pReal, & + -0.024999992127593126_pReal, -0.003928701544781374_pReal, & + -0.0008152701535450438_pReal, -0.0002009500426119712_pReal, & + -0.00002397986776071756_pReal, -0.00008202868926605841_pReal, & + +0.00012448715042090092_pReal, -0.0001749114214822577_pReal, & + +0.0001703481934140054_pReal, -0.00012062065004116828_pReal, & + +0.000059719705868660826_pReal, -0.00001980756723965647_pReal, & + +0.000003953714684212874_pReal, -0.00000036555001439719544_pReal ] + + ! normalize h and store the magnitude + hmag_squared = sum(ho**2.0_pReal) + if (dEq0(hmag_squared)) then + ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] + else + hm = hmag_squared + + ! convert the magnitude to the rotation angle + s = tfit(1) + tfit(2) * hmag_squared + do i=3,16 + hm = hm*hmag_squared + s = s + tfit(i) * hm + end do + ax = [ho/sqrt(hmag_squared), 2.0_pReal*acos(s)] + end if + +end function ho2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert orientation matrix to axis angle +!-------------------------------------------------------------------------- +function om2ax(om) result(ax) + use IO, only: & + IO_error + use math, only: & + math_clip, & + math_trace33 + + implicit none + real(pReal), intent(in) :: om(3,3) + real(pReal) :: ax(4) + + real(pReal) :: t + real(pReal), dimension(3) :: Wr, Wi + real(pReal), dimension(10) :: WORK + real(pReal), dimension(3,3) :: VR, devNull, o + integer(pInt) :: INFO, LWORK, i + + external :: dgeev,sgeev + + o = om + + ! first get the rotation angle + t = 0.5_pReal * (math_trace33(om) - 1.0) + ax(4) = acos(math_clip(t,-1.0_pReal,1.0_pReal)) + + if (dEq0(ax(4))) then + ax(1:3) = [ 0.0, 0.0, 1.0 ] + else + ! set some initial LAPACK variables + INFO = 0 + ! first initialize the parameters for the LAPACK DGEEV routines + LWORK = 20 + + ! call the eigenvalue solver +#if (FLOAT==8) + call dgeev('N','V',3,o,3,Wr,Wi,devNull,3,VR,3,WORK,LWORK,INFO) +#elif (FLOAT==4) + call sgeev('N','V',3,o,3,Wr,Wi,devNull,3,VR,3,WORK,LWORK,INFO) +#else + NO SUITABLE PRECISION FOR REAL SELECTED, STOPPING COMPILATION +#endif + if (INFO /= 0) call IO_error(0_pInt,ext_msg='Error in om2ax/(s/d)geev: (S/D)GEEV return not zero') + i = maxloc(merge(1.0_pReal,0.0_pReal,cEq(cmplx(Wr,Wi,pReal),cmplx(1.0_pReal,0.0_pReal,pReal),tol=1.0e-14_pReal)),dim=1) ! poor substitute for findloc + ax(1:3) = VR(1:3,i) + where ( dNeq0([om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)])) & + ax(1:3) = sign(ax(1:3),-epsijk *[om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)]) + endif + +end function om2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Rodrigues vector to axis angle pair +!-------------------------------------------------------------------------- +pure function ro2ax(ro) result(ax) + use, intrinsic :: IEEE_ARITHMETIC + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(4) :: ro !< homochoric coordinates + real(pReal), dimension(4) :: ax + real(pReal) :: ta, angle + + ta = ro(4) + + if (dEq0(ta)) then + ax = [ 0.0, 0.0, 1.0, 0.0 ] + elseif (.not. IEEE_is_finite(ta)) then + ax = [ ro(1), ro(2), ro(3), PI ] + else + angle = 2.0*atan(ta) + ta = 1.0/norm2(ro(1:3)) + ax = [ ro(1)/ta, ro(2)/ta, ro(3)/ta, angle ] + end if + +end function ro2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert axis angle to Rodrigues +!-------------------------------------------------------------------------- +pure function ax2ro(ax) result(ro) + use, intrinsic :: IEEE_ARITHMETIC + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + real(pReal), dimension(4) :: ro + real(pReal), parameter :: thr = 1.0E-7 + + if (dEq0(ax(4))) then + ro = [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal ] + else + ro(1:3) = ax(1:3) + ! we need to deal with the 180 degree case + ro(4) = merge(IEEE_value(ro(4),IEEE_positive_inf),tan(ax(4)*0.5 ),abs(ax(4)-PI) < thr) + end if + +end function ax2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert axis angle to quaternion +!-------------------------------------------------------------------------- +pure function ax2qu(ax) result(qu) + + implicit none + real(pReal), intent(in), dimension(4) :: ax + type(quaternion) :: qu + real(pReal) :: c, s + + + if (dEq0(ax(4))) then + qu = quaternion([ 1.0_pReal, 0.0_pReal, 0.0_pReal, 0.0_pReal ]) + else + c = cos(ax(4)*0.5) + s = sin(ax(4)*0.5) + qu = quaternion([ c, ax(1)*s, ax(2)*s, ax(3)*s ]) + end if + +end function ax2qu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert rodrigues to homochoric +!-------------------------------------------------------------------------- +pure function ro2ho(ro) result(ho) + use, intrinsic :: IEEE_ARITHMETIC + use math, only: & + PI + + implicit none + real(pReal), intent(in), dimension(4) :: ro + real(pReal), dimension(3) :: ho + real(pReal) :: f + + if (dEq0(norm2(ro(1:3)))) then + ho = [ 0.0, 0.0, 0.0 ] + else + f = merge(2.0*atan(ro(4)) - sin(2.0*atan(ro(4))),PI, IEEE_is_finite(ro(4))) + ho = ro(1:3) * (0.75_pReal*f)**(1.0/3.0) + end if + +end function ro2ho + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert a quaternion to a 3x3 matrix +!-------------------------------------------------------------------------- +pure function qu2om(qu) result(om) + + implicit none + type(quaternion), intent(in) :: qu + real(pReal), dimension(3,3) :: om + real(pReal) :: qq + + qq = qu%w**2-(qu%x**2 + qu%y**2 + qu%z**2) + + + om(1,1) = qq+2.0*qu%x*qu%x + om(2,2) = qq+2.0*qu%y*qu%y + om(3,3) = qq+2.0*qu%z*qu%z + + om(1,2) = 2.0*(qu%x*qu%y-qu%w*qu%z) + om(2,3) = 2.0*(qu%y*qu%z-qu%w*qu%x) + om(3,1) = 2.0*(qu%z*qu%x-qu%w*qu%y) + om(2,1) = 2.0*(qu%y*qu%x+qu%w*qu%z) + om(3,2) = 2.0*(qu%z*qu%y+qu%w*qu%x) + om(1,3) = 2.0*(qu%x*qu%z+qu%w*qu%y) + + if (epsijk < 0.0) om = transpose(om) + +end function qu2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert a 3x3 rotation matrix to a unit quaternion (see Morawiec, page 37) +!-------------------------------------------------------------------------- +function om2qu(om) result(qu) + + implicit none + real(pReal), intent(in), dimension(3,3) :: om + type(quaternion) :: qu + real(pReal), dimension(4) :: qu_A + real(pReal), dimension(4) :: s + + s = [+om(1,1) +om(2,2) +om(3,3) +1.0_pReal, & + +om(1,1) -om(2,2) -om(3,3) +1.0_pReal, & + -om(1,1) +om(2,2) -om(3,3) +1.0_pReal, & + -om(1,1) -om(2,2) +om(3,3) +1.0_pReal] + + qu_A = sqrt(max(s,0.0_pReal))*0.5_pReal*[1.0_pReal,epsijk,epsijk,epsijk] + qu_A = qu_A/norm2(qu_A) + + if(any(dEq(abs(qu_A),1.0_pReal,1.0e-15_pReal))) & + where (.not.(dEq(abs(qu_A),1.0_pReal,1.0e-15_pReal))) qu_A = 0.0_pReal + + if (om(3,2) < om(2,3)) qu_A(2) = -qu_A(2) + if (om(1,3) < om(3,1)) qu_A(3) = -qu_A(3) + if (om(2,1) < om(1,2)) qu_A(4) = -qu_A(4) + + qu = quaternion(qu_A) + !qu_A = om2ax(om) + !if(any(qu_A(1:3) * [qu%x,qu%y,qu%z] < 0.0)) print*, 'sign error' + +end function om2qu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert quaternion to axis angle +!-------------------------------------------------------------------------- +pure function qu2ax(qu) result(ax) + use math, only: & + PI + + implicit none + type(quaternion), intent(in) :: qu + real(pReal), dimension(4) :: ax + real(pReal) :: omega, s + + omega = 2.0 * acos(qu%w) + ! if the angle equals zero, then we return the rotation axis as [001] + if (dEq0(omega)) then + ax = [ 0.0, 0.0, 1.0, 0.0 ] + elseif (dNeq0(qu%w)) then + s = sign(1.0_pReal,qu%w)/sqrt(qu%x**2+qu%y**2+qu%z**2) + ax = [ qu%x*s, qu%y*s, qu%z*s, omega ] + else + ax = [ qu%x, qu%y, qu%z, PI ] + end if + +end function qu2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert quaternion to Rodrigues +!-------------------------------------------------------------------------- +pure function qu2ro(qu) result(ro) + use, intrinsic :: IEEE_ARITHMETIC + + type(quaternion), intent(in) :: qu + real(pReal), dimension(4) :: ro + real(pReal) :: s + real(pReal), parameter :: thr = 1.0e-8_pReal + + if (qu%w < thr) then + ro = [qu%x, qu%y, qu%z, IEEE_value(ro(4),IEEE_positive_inf)] + else + s = norm2([qu%x,qu%y,qu%z]) + ro = merge ( [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal] , & + [ qu%x/s, qu%y/s, qu%z/s, tan(acos(qu%w))], & + s < thr) + end if + +end function qu2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert quaternion to homochoric +!-------------------------------------------------------------------------- +pure function qu2ho(qu) result(ho) + + implicit none + type(quaternion), intent(in) :: qu + real(pReal), dimension(3) :: ho + real(pReal) :: omega, f + + omega = 2.0 * acos(qu%w) + + if (dEq0(omega)) then + ho = [ 0.0, 0.0, 0.0 ] + else + ho = [qu%x, qu%y, qu%z] + f = 0.75 * ( omega - sin(omega) ) + ho = ho/norm2(ho)* f**(1.0/3.0) + end if + +end function qu2ho + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert homochoric to cubochoric +!-------------------------------------------------------------------------- +function ho2cu(ho) result(cu) + use Lambert, only: LambertBallToCube + + implicit none + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(3) :: cu + + cu = LambertBallToCube(ho) + +end function ho2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to homochoric +!-------------------------------------------------------------------------- +function cu2ho(cu) result(ho) + use Lambert, only: LambertCubeToBall + + implicit none + real(pReal), intent(in), dimension(3) :: cu + real(pReal), dimension(3) :: ho + + ho = LambertCubeToBall(cu) + +end function cu2ho + +!-------------------------------------------------------------------------- +!-------------------------------------------------------------------------- +! and here are a bunch of transformation routines that are derived from the others +!-------------------------------------------------------------------------- +!-------------------------------------------------------------------------- +!-------------------------------------------------------------------------- + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief Rodrigues vector to Euler angles +!-------------------------------------------------------------------------- +pure function ro2eu(ro) result(eu) + + implicit none + real(pReal), intent(in), dimension(4) :: ro !< Rodrigues vector + real(pReal), dimension(3) :: eu + + eu = om2eu(ro2om(ro)) + +end function ro2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert euler to homochoric +!-------------------------------------------------------------------------- +pure function eu2ho(eu) result(ho) + + implicit none + real(pReal), intent(in), dimension(3) :: eu + real(pReal), dimension(3) :: ho + + ho = ax2ho(eu2ax(eu)) + +end function eu2ho + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert orientation matrix to Rodrigues +!-------------------------------------------------------------------------- +pure function om2ro(om) result(ro) + + implicit none + real(pReal), intent(in), dimension(3,3) :: om + real(pReal), dimension(4) :: ro + + ro = eu2ro(om2eu(om)) + +end function om2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert orientation matrix to homochoric +!-------------------------------------------------------------------------- +function om2ho(om) result(ho) + + implicit none + real(pReal), intent(in), dimension(3,3) :: om + real(pReal), dimension(3) :: ho + + ho = ax2ho(om2ax(om)) + +end function om2ho + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert axis angle to euler +!-------------------------------------------------------------------------- +pure function ax2eu(ax) result(eu) + + implicit none + real(pReal), intent(in), dimension(4) :: ax + real(pReal), dimension(3) :: eu + + eu = om2eu(ax2om(ax)) + +end function ax2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert rodrigues to orientation matrix +!-------------------------------------------------------------------------- +pure function ro2om(ro) result(om) + + implicit none + real(pReal), intent(in), dimension(4) :: ro + real(pReal), dimension(3,3) :: om + + om = ax2om(ro2ax(ro)) + +end function ro2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert rodrigues to quaternion +!-------------------------------------------------------------------------- +pure function ro2qu(ro) result(qu) + + implicit none + real(pReal), intent(in), dimension(4) :: ro + type(quaternion) :: qu + + qu = ax2qu(ro2ax(ro)) + +end function ro2qu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert homochoric to euler +!-------------------------------------------------------------------------- +pure function ho2eu(ho) result(eu) + + implicit none + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(3) :: eu + + eu = ax2eu(ho2ax(ho)) + +end function ho2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert homochoric to orientation matrix +!-------------------------------------------------------------------------- +pure function ho2om(ho) result(om) + + implicit none + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(3,3) :: om + + om = ax2om(ho2ax(ho)) + +end function ho2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert homochoric to Rodrigues +!-------------------------------------------------------------------------- +pure function ho2ro(ho) result(ro) + + implicit none + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(4) :: ro + + + ro = ax2ro(ho2ax(ho)) + +end function ho2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert homochoric to quaternion +!-------------------------------------------------------------------------- +pure function ho2qu(ho) result(qu) + + implicit none + real(pReal), intent(in), dimension(3) :: ho + type(quaternion) :: qu + + qu = ax2qu(ho2ax(ho)) + +end function ho2qu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert euler angles to cubochoric +!-------------------------------------------------------------------------- +function eu2cu(eu) result(cu) + + implicit none + real(pReal), intent(in), dimension(3) :: eu !< Bunge-Euler angles in radians + real(pReal), dimension(3) :: cu + + cu = ho2cu(eu2ho(eu)) + +end function eu2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert orientation matrix to cubochoric +!-------------------------------------------------------------------------- +function om2cu(om) result(cu) + + implicit none + real(pReal), intent(in), dimension(3,3) :: om !< rotation matrix + real(pReal), dimension(3) :: cu + + cu = ho2cu(om2ho(om)) + +end function om2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert axis angle to cubochoric +!-------------------------------------------------------------------------- +function ax2cu(ax) result(cu) + + implicit none + real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + real(pReal), dimension(3) :: cu + + cu = ho2cu(ax2ho(ax)) + +end function ax2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert Rodrigues to cubochoric +!-------------------------------------------------------------------------- +function ro2cu(ro) result(cu) + + implicit none + real(pReal), intent(in), dimension(4) :: ro !< Rodrigues vector + real(pReal), dimension(3) :: cu + + cu = ho2cu(ro2ho(ro)) + +end function ro2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert quaternion to cubochoric +!-------------------------------------------------------------------------- +function qu2cu(qu) result(cu) + + implicit none + type(quaternion), intent(in) :: qu ! unit quaternion + real(pReal), dimension(3) :: cu + + cu = ho2cu(qu2ho(qu)) + +end function qu2cu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to euler angles +!-------------------------------------------------------------------------- +function cu2eu(cu) result(eu) + + implicit none + real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), dimension(3) :: eu + + eu = ho2eu(cu2ho(cu)) + +end function cu2eu + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to orientation matrix +!-------------------------------------------------------------------------- +function cu2om(cu) result(om) + + implicit none + real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), dimension(3,3) :: om + + om = ho2om(cu2ho(cu)) + +end function cu2om + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to axis angle +!-------------------------------------------------------------------------- +function cu2ax(cu) result(ax) + + implicit none + real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), dimension(4) :: ax + + ax = ho2ax(cu2ho(cu)) + +end function cu2ax + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to Rodrigues +!-------------------------------------------------------------------------- +function cu2ro(cu) result(ro) + + implicit none + real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), dimension(4) :: ro + + ro = ho2ro(cu2ho(cu)) + +end function cu2ro + + +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @brief convert cubochoric to quaternion +!-------------------------------------------------------------------------- +function cu2qu(cu) result(qu) + + implicit none + real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + type(quaternion) :: qu ! cubochoric? + + qu = ho2qu(cu2ho(cu)) + +end function cu2qu + +end module rotations From 5cdd603671696424bcdf36356e42edd8fe3a33cb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 11:40:27 +0100 Subject: [PATCH 02/97] dummy orientations module needs to be extendend to include symmetry --- src/CMakeLists.txt | 8 ++++++-- src/orientations.f90 | 8 ++++++++ src/quaternions.f90 | 3 +-- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/orientations.f90 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4210a79b3..e86fbe422 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,14 +65,18 @@ add_library(ROTATIONS OBJECT "rotations.f90") add_dependencies(ROTATIONS LAMBERT QUATERNIONS) list(APPEND OBJECTFILES $) +add_library(ORIENTATIONS OBJECT "orientations.f90") +add_dependencies(ORIENTATIONS ROTATIONS) +list(APPEND OBJECTFILES $) + # SPECTRAL solver and FEM solver use different mesh files if (PROJECT_NAME STREQUAL "DAMASK_spectral") add_library(MESH OBJECT "mesh.f90") - add_dependencies(MESH ROTATIONS FEsolving) + add_dependencies(MESH ORIENTATIONS FEsolving) list(APPEND OBJECTFILES $) elseif (PROJECT_NAME STREQUAL "DAMASK_FEM") add_library(FEZoo OBJECT "FEM_zoo.f90") - add_dependencies(FEZoo ROTATIONS FEsolving) + add_dependencies(FEZoo ORIENTATIONS FEsolving) list(APPEND OBJECTFILES $) add_library(MESH OBJECT "meshFEM.f90") add_dependencies(MESH FEZoo) diff --git a/src/orientations.f90 b/src/orientations.f90 new file mode 100644 index 000000000..1a5363ee6 --- /dev/null +++ b/src/orientations.f90 @@ -0,0 +1,8 @@ +module orientations + use rotations + + implicit none + type, extends(rotation), public :: orientation + end type + +end module orientations diff --git a/src/quaternions.f90 b/src/quaternions.f90 index 60b8d387d..78379c49b 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -27,10 +27,9 @@ ! ################################################################### module quaternions - use prec - implicit none + implicit none public type, public :: quaternion real(pReal) :: w = 0.0_pReal From 9686014ce0b17feb0ed74c79ece29038cd9a03bb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 12:52:52 +0100 Subject: [PATCH 03/97] polishing --- src/rotations.f90 | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index 830f49553..f9ec9cf74 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -33,24 +33,24 @@ module rotations implicit none type, public :: rotation type(quaternion), private :: q - contains - procedure, public :: asEulerAngles => asEulerAngles - procedure, public :: asAxisAnglePair => asAxisAnglePair - procedure, public :: asRodriguesFrankVector => asRodriguesFrankVector - procedure, public :: asRotationMatrix => asRotationMatrix - procedure, public :: rotVector - procedure, public :: rotTensor - end type + contains + procedure, public :: asEulerAngles + procedure, public :: asAxisAnglePair + procedure, public :: asRodriguesFrankVector + procedure, public :: asRotationMatrix + procedure, public :: rotVector + procedure, public :: rotTensor + end type interface rotation - module procedure init + module procedure :: init end interface contains type(rotation) function init(eu,ax,om,qu,cu,ho,ro) real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho - real(pReal), intent(in), optional, dimension(4) :: qu, ax, ro + real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro real(pReal), intent(in), optional, dimension(3,3) :: om if (count([present(eu),present(ax),present(om),present(qu),& @@ -119,7 +119,6 @@ function asHomochoric(this) end function asHomochoric - !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief rotates a vector passively (default) or actively @@ -239,7 +238,9 @@ end function eu2ax !> @brief Euler angles to Rodrigues vector !-------------------------------------------------------------------------- pure function eu2ro(eu) result(ro) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only: & + IEEE_value, & + IEEE_positive_inf use math, only: & PI From c1e5f66d777ac5dadb8bdf2025c92177d0812147 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 13:03:27 +0100 Subject: [PATCH 04/97] make quaternion accesible output as usual array to completly hide the internal representation --- src/rotations.f90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/rotations.f90 b/src/rotations.f90 index f9ec9cf74..539cc23c2 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -34,6 +34,7 @@ module rotations type, public :: rotation type(quaternion), private :: q contains + procedure, public :: asQuaternion procedure, public :: asEulerAngles procedure, public :: asAxisAnglePair procedure, public :: asRodriguesFrankVector @@ -76,6 +77,15 @@ type(rotation) function init(eu,ax,om,qu,cu,ho,ro) end function +function asQuaternion(this) + class(rotation), intent(in) :: this + real(pReal), dimension(4) :: asQuaternion + + asQuaternion = [this%q%w, this%q%x, this%q%y, this%q%z] + +end function asQuaternion + + function asEulerAngles(this) class(rotation), intent(in) :: this real(pReal), dimension(3) :: asEulerAngles From ccdf1e5e8e1e35a03ccb412e80266c1ec461a94c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 13:49:42 +0100 Subject: [PATCH 05/97] polishing --- src/math.f90 | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/math.f90 b/src/math.f90 index 725c0446e..55c082e3a 100644 --- a/src/math.f90 +++ b/src/math.f90 @@ -1797,7 +1797,6 @@ function math_sampleGaussOri(center,FWHM) math_sampleGaussOri = math_RtoEuler(math_mul33x33(R,math_EulerToR(center))) endif - end function math_sampleGaussOri @@ -1870,11 +1869,11 @@ real(pReal) function math_sampleGaussVar(meanvalue, stddev, width) tol_math_check implicit none - real(pReal), intent(in) :: meanvalue, & ! meanvalue of gauss distribution - stddev ! standard deviation of gauss distribution - real(pReal), intent(in), optional :: width ! width of considered values as multiples of standard deviation - real(pReal), dimension(2) :: rnd ! random numbers - real(pReal) :: scatter, & ! normalized scatter around meanvalue + real(pReal), intent(in) :: meanvalue, & ! meanvalue of gauss distribution + stddev ! standard deviation of gauss distribution + real(pReal), intent(in), optional :: width ! width of considered values as multiples of standard deviation + real(pReal), dimension(2) :: rnd ! random numbers + real(pReal) :: scatter, & ! normalized scatter around meanvalue myWidth if (abs(stddev) < tol_math_check) then From 5d6faff4d6c7c57fd719ec7b316cf56ed395ad23 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 15:44:00 +0100 Subject: [PATCH 06/97] moving nice initializers to orientation --- src/orientations.f90 | 23 ++++++++++++++++++++-- src/rotations.f90 | 45 ++++++++++++-------------------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/orientations.f90 b/src/orientations.f90 index 1a5363ee6..29760e05c 100644 --- a/src/orientations.f90 +++ b/src/orientations.f90 @@ -3,6 +3,25 @@ module orientations implicit none type, extends(rotation), public :: orientation - end type + end type orientation -end module orientations + interface orientation + module procedure :: orientation_init + end interface orientation + +contains + +type(orientation) function orientation_init(eu,ax,om,qu,cu,ho,ro) + use prec + implicit none + real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho + real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro + real(pReal), intent(in), optional, dimension(3,3) :: om + + if (present(om)) then + call orientation_init%fromRotationMatrix(om) + endif + +end function orientation_init + +end module diff --git a/src/rotations.f90 b/src/rotations.f90 index 539cc23c2..28c9b208f 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -39,44 +39,13 @@ module rotations procedure, public :: asAxisAnglePair procedure, public :: asRodriguesFrankVector procedure, public :: asRotationMatrix + procedure, public :: fromRotationMatrix procedure, public :: rotVector procedure, public :: rotTensor - end type - - interface rotation - module procedure :: init - end interface + end type rotation contains -type(rotation) function init(eu,ax,om,qu,cu,ho,ro) - real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho - real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro - real(pReal), intent(in), optional, dimension(3,3) :: om - - if (count([present(eu),present(ax),present(om),present(qu),& - present(cu),present(ho),present(ro)]) > 1_pInt) write(6,*) 'invalid' - - if (present(eu)) then - init%q = eu2qu(eu) - elseif (present(ax)) then - init%q = ax2qu(ax) - elseif (present(om)) then - init%q = om2qu(om) - elseif (present(qu)) then - init%q = quaternion(qu) - elseif (present(cu)) then - init%q = cu2qu(cu) - elseif (present(ho)) then - init%q = ho2qu(ho) - elseif (present(ro)) then - init%q = ro2qu(ro) - else - init%q = quaternion([1.0_pReal,0.0_pReal,0.0_pReal,0.0_pReal]) - endif - -end function - function asQuaternion(this) class(rotation), intent(in) :: this real(pReal), dimension(4) :: asQuaternion @@ -129,6 +98,16 @@ function asHomochoric(this) end function asHomochoric + +subroutine fromRotationMatrix(this,om) + class(rotation), intent(out) :: this + real(pReal), dimension(3,3), intent(in) :: om + + this%q = om2qu(om) + +end subroutine + + !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief rotates a vector passively (default) or actively From 58862a939dfbbeaf4cdd4a72a8670732c8d4c722 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 8 Dec 2018 15:54:59 +0100 Subject: [PATCH 07/97] initial handling of symmetry introduced --- src/orientations.f90 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/orientations.f90 b/src/orientations.f90 index 29760e05c..67c46c2bb 100644 --- a/src/orientations.f90 +++ b/src/orientations.f90 @@ -1,8 +1,11 @@ module orientations use rotations + use prec, only: & + pStringLen implicit none type, extends(rotation), public :: orientation + character(len=pStringLen) :: sym = 'none' end type orientation interface orientation @@ -11,13 +14,16 @@ module orientations contains -type(orientation) function orientation_init(eu,ax,om,qu,cu,ho,ro) +type(orientation) function orientation_init(sym,eu,ax,om,qu,cu,ho,ro) use prec implicit none - real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho - real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro - real(pReal), intent(in), optional, dimension(3,3) :: om - + character(len=pStringLen), intent(in), optional :: sym + real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho + real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro + real(pReal), intent(in), optional, dimension(3,3) :: om + + if (present(sym)) orientation_init%sym = sym + if (present(om)) then call orientation_init%fromRotationMatrix(om) endif From 8a2689da0ab0d7be1b45ee9cf56cdb872b6ad097 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 08:52:38 +0100 Subject: [PATCH 08/97] documentation was for a lot of things that are not in here setting constants without truncation --- src/Lambert.f90 | 88 ++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/src/Lambert.f90 b/src/Lambert.f90 index ab939bcc6..68ae2ab41 100644 --- a/src/Lambert.f90 +++ b/src/Lambert.f90 @@ -1,5 +1,6 @@ ! ################################################################### ! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University +! Modified 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH ! All rights reserved. ! ! Redistribution and use in source and binary forms, with or without modification, are @@ -29,19 +30,8 @@ !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University ! -!> @brief everything that has to do with the modified Lambert projections +!> @brief Mapping homochoric <-> cubochoric ! -!> @details This module contains a number of projection functions for the modified -!> Lambert projection between square lattice and 2D hemisphere, hexagonal lattice -!> and 2D hemisphere, as well as the more complex mapping between a 3D cubic grid -!> and the unit quaternion hemisphere with positive scalar component. In addition, there -!> are some other projections, such as the stereographic one. Each function is named -!> by the projection, the dimensionality of the starting grid, and the forward or inverse -!> character. For each function, there is also a single precision and a double precision -!> version, but we use the interface formalism to have only a single call. The Forward -!> mapping is taken to be the one from the simple grid to the curved grid. Since the module -!> deals with various grids, we also add a few functions/subroutines that apply symmetry -!> operations on those grids. !> References: !> D. Rosca, A. Morawiec, and M. De Graef. “A new method of constructing a grid !> in the space of 3D rotations and its applications to texture analysis”. @@ -49,24 +39,23 @@ !-------------------------------------------------------------------------- module Lambert use math - use prec + use prec, only: & + pReal implicit none - - real(pReal), private :: & - sPi = sqrt(PI), & - pref = sqrt(6.0_pReal/PI), & - ! the following constants are used for the cube to quaternion hemisphere mapping - ap = PI**(2.0_pReal/3.0_pReal), & - sc = 0.897772786961286_pReal, & ! a/ap - beta = 0.962874509979126_pReal, & ! pi^(5/6)/6^(1/6)/2 - R1 = 1.330670039491469_pReal, & ! (3pi/4)^(1/3) - r2 = sqrt(2.0_pReal), & - pi12 = PI/12.0_pReal, & - prek = 1.643456402972504_pReal, & ! R1 2^(1/4)/beta - r24 = sqrt(24.0_pReal) - private + real(pReal), parameter, private :: & + SPI = sqrt(PI), & + PREF = sqrt(6.0_pReal/PI), & + A = PI**(5.0_pReal/6.0_pReal)/6.0_pReal**(1.0_pReal/6.0_pReal), & + AP = PI**(2.0_pReal/3.0_pReal), & + SC = A/AP, & + BETA = A/2.0_pReal, & + R1 = (3.0_pReal*PI/4.0_pReal)**(1.0_pReal/3.0_pReal), & + R2 = sqrt(2.0_pReal), & + PI12 = PI/12.0_pReal, & + PREK = R1 * 2.0_pReal**(1.0_pReal/4.0_pReal)/BETA + public :: & LambertCubeToBall, & LambertBallToCube @@ -78,20 +67,24 @@ contains !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief map from 3D cubic grid to 3D ball !-------------------------------------------------------------------------- function LambertCubeToBall(cube) result(ball) use, intrinsic :: IEEE_ARITHMETIC + use prec, only: & + pInt, & + dEq0 implicit none real(pReal), intent(in), dimension(3) :: cube real(pReal), dimension(3) :: ball, LamXYZ, XYZ - real(pReal) :: T(2), c, s, q - real(pReal), parameter :: eps = 1.0e-8_pReal + real(pReal) :: T(2), c, s, q + real(pReal), parameter :: eps = 1.0e-8_pReal integer(pInt), dimension(3) :: p integer(pInt), dimension(2) :: order - if (maxval(abs(cube)) > ap/2.0+eps) then + if (maxval(abs(cube)) > AP/2.0+eps) then ball = IEEE_value(cube,IEEE_positive_inf) return end if @@ -109,17 +102,17 @@ function LambertCubeToBall(cube) result(ball) LamXYZ = [ 0.0_pReal, 0.0_pReal, pref * XYZ(3) ] else special order = merge( [2,1], [1,2], abs(XYZ(2)) <= abs(XYZ(1))) ! order of absolute values of XYZ - q = pi12 * XYZ(order(1))/XYZ(order(2)) ! smaller by larger + q = PI12 * XYZ(order(1))/XYZ(order(2)) ! smaller by larger c = cos(q) s = sin(q) - q = prek * XYZ(order(2))/ sqrt(r2-c) - T = [ (r2*c - 1.0), r2 * s] * q + q = prek * XYZ(order(2))/ sqrt(R2-c) + T = [ (R2*c - 1.0), R2 * s] * q ! transform to sphere grid (inverse Lambert) ! [note that there is no need to worry about dividing by zero, since XYZ(3) can not become zero] c = sum(T**2) s = Pi * c/(24.0*XYZ(3)**2) - c = sPi * c / r24 / XYZ(3) + c = sPi * c / sqrt(24.0_pReal) / XYZ(3) q = sqrt( 1.0 - s ) LamXYZ = [ T(order(2)) * q, T(order(1)) * q, pref * XYZ(3) - c ] endif special @@ -131,19 +124,26 @@ function LambertCubeToBall(cube) result(ball) end function LambertCubeToBall + !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief map from 3D ball to 3D cubic grid !-------------------------------------------------------------------------- pure function LambertBallToCube(xyz) result(cube) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only:& + IEEE_positive_inf, & + IEEE_value + use prec, only: & + pInt, & + dEq0 implicit none real(pReal), intent(in), dimension(3) :: xyz real(pReal), dimension(3) :: cube, xyz1, xyz3 real(pReal), dimension(2) :: Tinv, xyz2 real(pReal) :: rs, qxy, q2, sq2, q, tt - integer(pInt) , dimension(3) :: p + integer(pInt), dimension(3) :: p rs = norm2(xyz) if (rs > R1) then @@ -168,10 +168,10 @@ pure function LambertBallToCube(xyz) result(cube) else special q2 = qxy + maxval(abs(xyz2))**2 sq2 = sqrt(q2) - q = (beta/r2/R1) * sqrt(q2*qxy/(q2-maxval(abs(xyz2))*sq2)) - tt = (minval(abs(xyz2))**2+maxval(abs(xyz2))*sq2)/r2/qxy - Tinv = q * sign(1.0,xyz2) * merge([ 1.0_pReal, acos(math_clip(tt,-1.0_pReal,1.0_pReal))/pi12], & - [ acos(math_clip(tt,-1.0_pReal,1.0_pReal))/pi12, 1.0_pReal], & + q = (beta/R2/R1) * sqrt(q2*qxy/(q2-maxval(abs(xyz2))*sq2)) + tt = (minval(abs(xyz2))**2+maxval(abs(xyz2))*sq2)/R2/qxy + Tinv = q * sign(1.0,xyz2) * merge([ 1.0_pReal, acos(math_clip(tt,-1.0_pReal,1.0_pReal))/PI12], & + [ acos(math_clip(tt,-1.0_pReal,1.0_pReal))/PI12, 1.0_pReal], & abs(xyz2(2)) <= abs(xyz2(1))) endif special @@ -185,15 +185,19 @@ pure function LambertBallToCube(xyz) result(cube) end function LambertBallToCube + !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief determine to which pyramid a point in a cubic grid belongs !-------------------------------------------------------------------------- pure function GetPyramidOrder(xyz) + use prec, only: & + pInt implicit none real(pReal),intent(in),dimension(3) :: xyz - integer(pInt), dimension(3) :: GetPyramidOrder + integer(pInt), dimension(3) :: GetPyramidOrder if (((abs(xyz(1)) <= xyz(3)).and.(abs(xyz(2)) <= xyz(3))) .or. & ((abs(xyz(1)) <= -xyz(3)).and.(abs(xyz(2)) <= -xyz(3)))) then @@ -205,7 +209,7 @@ pure function GetPyramidOrder(xyz) ((abs(xyz(1)) <= -xyz(2)).and.(abs(xyz(3)) <= -xyz(2)))) then GetPyramidOrder = [3,1,2] else - GetPyramidOrder = -1 ! should be impossible, but might simplify debugging + GetPyramidOrder = -1 ! should be impossible, but might simplify debugging end if end function GetPyramidOrder From 17a682e883d363a5b5b0051649dc9695c9ef5995 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 08:53:57 +0100 Subject: [PATCH 09/97] P/epsijk parameter has nothing to do with precision --- src/prec.f90 | 2 -- src/quaternions.f90 | 17 +++++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/prec.f90 b/src/prec.f90 index bc7f523d0..ea539011f 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -29,8 +29,6 @@ module prec real(pReal), parameter, public :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation) integer(pInt), allocatable, dimension(:) :: realloc_lhs_test - - real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. ToDo: Better place? type, public :: group_float !< variable length datatype used for storage of state real(pReal), dimension(:), pointer :: p diff --git a/src/quaternions.f90 b/src/quaternions.f90 index 78379c49b..d4574e734 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -1,5 +1,6 @@ ! ################################################################### ! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University +! Modified 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH ! All rights reserved. ! ! Redistribution and use in source and binary forms, with or without modification, are @@ -27,10 +28,14 @@ ! ################################################################### module quaternions - use prec + use prec, only: & + pReal implicit none public + + real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. ToDo: Better place? + type, public :: quaternion real(pReal) :: w = 0.0_pReal real(pReal) :: x = 0.0_pReal @@ -73,9 +78,6 @@ module quaternions procedure, public :: homomorphed => quat_homomorphed - !procedure,private :: quat_write - !generic :: write(formatted) => quat_write - end type interface assignment (=) @@ -150,7 +152,7 @@ pure subroutine assign_vec__(self,other) implicit none type(quaternion), intent(out) :: self - real(pReal), intent(in), dimension(4) :: other + real(pReal), intent(in), dimension(4) :: other self%w = other(1) self%x = other(2) @@ -288,6 +290,9 @@ end function div_scal__ !> equality of two quaternions !-------------------------------------------------------------------------- logical elemental function eq__(self,other) + use prec, only: & + dEq + implicit none class(quaternion), intent(in) :: self,other @@ -346,7 +351,7 @@ type(quaternion) elemental function exp__(self) implicit none class(quaternion), intent(in) :: self - real(pReal) :: absImag + real(pReal) :: absImag absImag = norm2([self%x, self%y, self%z]) From 53a95ea84f9b1464af1385f781ea68e8360343bc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 10:01:54 +0100 Subject: [PATCH 10/97] cleaned and documented --- src/Lambert.f90 | 4 +- src/orientations.f90 | 6 + src/quaternions.f90 | 89 ++++--- src/rotations.f90 | 614 +++++++++++++++++++++++++------------------ 4 files changed, 413 insertions(+), 300 deletions(-) diff --git a/src/Lambert.f90 b/src/Lambert.f90 index 68ae2ab41..86c019688 100644 --- a/src/Lambert.f90 +++ b/src/Lambert.f90 @@ -29,10 +29,10 @@ !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -! +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Mapping homochoric <-> cubochoric ! -!> References: +!> @details !> D. Rosca, A. Morawiec, and M. De Graef. “A new method of constructing a grid !> in the space of 3D rotations and its applications to texture analysis”. !> Modeling and Simulations in Materials Science and Engineering 22, 075013 (2014). diff --git a/src/orientations.f90 b/src/orientations.f90 index 67c46c2bb..285492729 100644 --- a/src/orientations.f90 +++ b/src/orientations.f90 @@ -1,3 +1,9 @@ +!--------------------------------------------------------------------------------------------------- +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief orientation storage +!> @details: orientation = rotation + symmetry +!--------------------------------------------------------------------------------------------------- + module orientations use rotations use prec, only: & diff --git a/src/quaternions.f90 b/src/quaternions.f90 index d4574e734..b0dd37291 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -27,6 +27,11 @@ ! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ################################################################### +!--------------------------------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief general quaternion math, not limited to unit quaternions +!--------------------------------------------------------------------------------------------------- module quaternions use prec, only: & pReal @@ -112,9 +117,9 @@ end interface log contains -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> constructor for a quaternion from a 4-vector -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) pure function init__(array) implicit none @@ -128,9 +133,9 @@ type(quaternion) pure function init__(array) end function init__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> assing a quaternion -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- elemental subroutine assign_quat__(self,other) implicit none @@ -145,9 +150,9 @@ elemental subroutine assign_quat__(self,other) end subroutine assign_quat__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> assing a 4-vector -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- pure subroutine assign_vec__(self,other) implicit none @@ -162,9 +167,9 @@ pure subroutine assign_vec__(self,other) end subroutine assign_vec__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> addition of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function add__(self,other) implicit none @@ -178,9 +183,9 @@ type(quaternion) elemental function add__(self,other) end function add__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> unary positive operator -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function pos__(self) implicit none @@ -194,9 +199,9 @@ type(quaternion) elemental function pos__(self) end function pos__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> subtraction of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function sub__(self,other) implicit none @@ -210,9 +215,9 @@ type(quaternion) elemental function sub__(self,other) end function sub__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> unary positive operator -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function neg__(self) implicit none @@ -226,9 +231,9 @@ type(quaternion) elemental function neg__(self) end function neg__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> multiplication of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function mul_quat__(self,other) implicit none @@ -242,9 +247,9 @@ type(quaternion) elemental function mul_quat__(self,other) end function mul_quat__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> multiplication of quaternions with scalar -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function mul_scal__(self,scal) implicit none @@ -259,9 +264,9 @@ type(quaternion) elemental function mul_scal__(self,scal) end function mul_scal__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> division of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function div_quat__(self,other) implicit none @@ -272,9 +277,9 @@ type(quaternion) elemental function div_quat__(self,other) end function div_quat__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> divisiont of quaternions by scalar -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function div_scal__(self,scal) implicit none @@ -286,9 +291,9 @@ type(quaternion) elemental function div_scal__(self,scal) end function div_scal__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> equality of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- logical elemental function eq__(self,other) use prec, only: & dEq @@ -302,9 +307,9 @@ logical elemental function eq__(self,other) end function eq__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> inequality of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- logical elemental function neq__(self,other) implicit none @@ -315,9 +320,9 @@ logical elemental function neq__(self,other) end function neq__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> quaternion to the power of a scalar -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function pow_scal__(self,expon) implicit none @@ -329,9 +334,9 @@ type(quaternion) elemental function pow_scal__(self,expon) end function pow_scal__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> quaternion to the power of a quaternion -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function pow_quat__(self,expon) implicit none @@ -343,10 +348,10 @@ type(quaternion) elemental function pow_quat__(self,expon) end function pow_quat__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> exponential of a quaternion !> ToDo: Lacks any check for invalid operations -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function exp__(self) implicit none @@ -363,10 +368,10 @@ type(quaternion) elemental function exp__(self) end function exp__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> logarithm of a quaternion !> ToDo: Lacks any check for invalid operations -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function log__(self) implicit none @@ -383,9 +388,9 @@ type(quaternion) elemental function log__(self) end function log__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> norm of a quaternion -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- real(pReal) elemental function abs__(a) implicit none @@ -396,9 +401,9 @@ real(pReal) elemental function abs__(a) end function abs__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> dot product of two quaternions -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- real(pReal) elemental function dot_product__(a,b) implicit none @@ -409,9 +414,9 @@ real(pReal) elemental function dot_product__(a,b) end function dot_product__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> conjugate complex of a quaternion -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function conjg__(a) implicit none @@ -422,9 +427,9 @@ type(quaternion) elemental function conjg__(a) end function conjg__ -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> homomorphed quaternion of a quaternion -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- type(quaternion) elemental function quat_homomorphed(a) implicit none diff --git a/src/rotations.f90 b/src/rotations.f90 index 28c9b208f..e58963dea 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -1,5 +1,6 @@ ! ################################################################### ! Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University +! Modified 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH ! All rights reserved. ! ! Redistribution and use in source and binary forms, with or without modification, are @@ -26,11 +27,21 @@ ! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ################################################################### +!--------------------------------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief rotation storage and conversion +!> @details: rotation is internally stored as quaternion. It cabe inialized from different +!> represantations and also returns itself in different representations. +!--------------------------------------------------------------------------------------------------- + module rotations - use prec + use prec, only: & + pReal use quaternions implicit none + private type, public :: rotation type(quaternion), private :: q contains @@ -39,138 +50,179 @@ module rotations procedure, public :: asAxisAnglePair procedure, public :: asRodriguesFrankVector procedure, public :: asRotationMatrix + !------------------------------------------ procedure, public :: fromRotationMatrix + !------------------------------------------ procedure, public :: rotVector procedure, public :: rotTensor end type rotation + public :: & + asQuaternion, & + asEulerAngles, & + asAxisAnglePair, & + asRotationMatrix, & + asRodriguesFrankVector, & + asHomochoric, & + fromRotationMatrix, & + rotVector, & + rotTensor contains + +!--------------------------------------------------------------------------------------------------- +! Return rotation in different represenations +!--------------------------------------------------------------------------------------------------- function asQuaternion(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(4) :: asQuaternion + real(pReal), dimension(4) :: asQuaternion asQuaternion = [this%q%w, this%q%x, this%q%y, this%q%z] end function asQuaternion - - +!--------------------------------------------------------------------------------------------------- function asEulerAngles(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(3) :: asEulerAngles - + real(pReal), dimension(3) :: asEulerAngles + asEulerAngles = qu2eu(this%q) end function asEulerAngles - - +!--------------------------------------------------------------------------------------------------- function asAxisAnglePair(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(4) :: asAxisAnglePair + real(pReal), dimension(4) :: asAxisAnglePair asAxisAnglePair = qu2ax(this%q) end function asAxisAnglePair - - +!--------------------------------------------------------------------------------------------------- function asRotationMatrix(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(3,3) :: asRotationMatrix + real(pReal), dimension(3,3) :: asRotationMatrix asRotationMatrix = qu2om(this%q) end function asRotationMatrix - - +!--------------------------------------------------------------------------------------------------- function asRodriguesFrankVector(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(4) :: asRodriguesFrankVector + real(pReal), dimension(4) :: asRodriguesFrankVector asRodriguesFrankVector = qu2ro(this%q) + end function asRodriguesFrankVector - - +!--------------------------------------------------------------------------------------------------- function asHomochoric(this) + + implicit none class(rotation), intent(in) :: this - real(pReal), dimension(3) :: asHomochoric + real(pReal), dimension(3) :: asHomochoric asHomochoric = qu2ho(this%q) end function asHomochoric - - + +!--------------------------------------------------------------------------------------------------- +! Initialize rotation from different representations +!--------------------------------------------------------------------------------------------------- subroutine fromRotationMatrix(this,om) - class(rotation), intent(out) :: this - real(pReal), dimension(3,3), intent(in) :: om + + implicit none + class(rotation), intent(out) :: this + real(pReal), dimension(3,3), intent(in) :: om this%q = om2qu(om) end subroutine -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief rotates a vector passively (default) or actively -!-------------------------------------------------------------------------- +!> @brief rotate a vector passively (default) or actively +!> @details: rotation is based on unit quaternion or rotation matrix (fallback) +!--------------------------------------------------------------------------------------------------- function rotVector(this,v,active) - class(rotation), intent(in) :: this - logical, intent(in), optional :: active - real(pReal),intent(in),dimension(3) :: v - real(pReal),dimension(3) :: rotVector - type(quaternion) :: q + use prec, only: & + dEq + + implicit none + real(pReal), dimension(3) :: rotVector + class(rotation), intent(in) :: this + real(pReal), intent(in), dimension(3) :: v + logical, intent(in), optional :: active + + type(quaternion) :: q - if (dEq(norm2(v),1.0_pReal,tol=1.0e-15_pReal)) then - passive: if (merge(.not. active, .true., present(active))) then - q = this%q * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * conjg(this%q) ) - else passive - q = conjg(this%q) * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * this%q ) - endif passive - rotVector = [q%x,q%y,q%z] - else - passive2: if (merge(.not. active, .true., present(active))) then - rotVector = matmul(this%asRotationMatrix(),v) - else passive2 - rotVector = matmul(transpose(this%asRotationMatrix()),v) - endif passive2 - endif + if (dEq(norm2(v),1.0_pReal,tol=1.0e-15_pReal)) then + passive: if (merge(.not. active, .true., present(active))) then ! ToDo: not save (PGI) + q = this%q * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * conjg(this%q) ) + else passive + q = conjg(this%q) * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * this%q ) + endif passive + rotVector = [q%x,q%y,q%z] + else + passive2: if (merge(.not. active, .true., present(active))) then ! ToDo: not save (PGI) + rotVector = matmul(this%asRotationMatrix(),v) + else passive2 + rotVector = matmul(transpose(this%asRotationMatrix()),v) + endif passive2 + endif end function rotVector -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief rotate a second rank tensor using a rotation matrix, active or passive (single precision) -!-------------------------------------------------------------------------- +!> @brief rotate a second rank tensor passively (default) or actively +!> @details: rotation is based on rotation matrix +!--------------------------------------------------------------------------------------------------- function rotTensor(this,m,active) - class(rotation), intent(in) :: this - real(pReal),intent(in),dimension(3,3) :: m - logical, intent(in), optional :: active - real(pReal),dimension(3,3) :: rotTensor + + implicit none + real(pReal), dimension(3,3) :: rotTensor + class(rotation), intent(in) :: this + real(pReal), intent(in), dimension(3,3) :: m + logical, intent(in), optional :: active + - passive: if (merge(.not. active, .true., present(active))) then - rotTensor = matmul(matmul(this%asRotationMatrix(),m),transpose(this%asRotationMatrix())) - else passive - rotTensor = matmul(matmul(transpose(this%asRotationMatrix()),m),this%asRotationMatrix()) - endif passive + passive: if (merge(.not. active, .true., present(active))) then + rotTensor = matmul(matmul(this%asRotationMatrix(),m),transpose(this%asRotationMatrix())) + else passive + rotTensor = matmul(matmul(transpose(this%asRotationMatrix()),m),this%asRotationMatrix()) + endif passive end function rotTensor -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- -! here we start with a series of conversion routines between representations -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- +! The following routines convert between different representations +!--------------------------------------------------------------------------------------------------- + + +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Euler angles to orientation matrix [Morawiec, page 28] -!-------------------------------------------------------------------------- +!> @brief Euler angles to orientation matrix +!--------------------------------------------------------------------------------------------------- pure function eu2om(eu) result(om) + use prec, only: & + dEq0 implicit none - real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians - real(pReal), dimension(3,3) :: om !< output orientation matrix + real(pReal), intent(in), dimension(3) :: eu + real(pReal), dimension(3,3) :: om + real(pReal), dimension(3) :: c, s c = cos(eu) @@ -191,17 +243,21 @@ pure function eu2om(eu) result(om) end function eu2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief convert euler to axis angle -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- pure function eu2ax(eu) result(ax) + use prec, only: & + dEq0, & + dEq use math, only: & PI implicit none - real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians - real(pReal), dimension(4) :: ax + real(pReal), intent(in), dimension(3) :: eu + real(pReal), dimension(4) :: ax + real(pReal) :: t, delta, tau, alpha, sigma t = tan(eu(2)*0.5) @@ -211,22 +267,24 @@ pure function eu2ax(eu) result(ax) alpha = merge(PI, 2.0*atan(tau/cos(sigma)), dEq(sigma,PI*0.5_pReal,tol=1.0e-15_pReal)) - if (dEq0(alpha)) then ! return a default identity axis-angle pair + if (dEq0(alpha)) then ! return a default identity axis-angle pair ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] else - ax(1:3) = -epsijk/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front + ax(1:3) = -epsijk/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front ax(4) = alpha - if (alpha < 0.0) ax = -ax ! ensure alpha is positive + if (alpha < 0.0) ax = -ax ! ensure alpha is positive end if end function eu2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief Euler angles to Rodrigues vector -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- pure function eu2ro(eu) result(ro) + use prec, only: & + dEq0 use, intrinsic :: IEEE_ARITHMETIC, only: & IEEE_value, & IEEE_positive_inf @@ -234,10 +292,10 @@ pure function eu2ro(eu) result(ro) PI implicit none - real(pReal), intent(in), dimension(3) :: eu !< Euler angles in radians + real(pReal), intent(in), dimension(3) :: eu real(pReal), dimension(4) :: ro - ro = eu2ax(eu) ! convert to axis angle representation + ro = eu2ax(eu) if (ro(4) >= PI) then ro(4) = IEEE_value(ro(4),IEEE_positive_inf) elseif(dEq0(ro(4))) then @@ -249,24 +307,23 @@ pure function eu2ro(eu) result(ro) end function eu2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Euler angles to quaternion -!-------------------------------------------------------------------------- +!> @brief Euler angles to unit quaternion +!--------------------------------------------------------------------------------------------------- pure function eu2qu(eu) result(qu) implicit none - real(pReal), intent(in), dimension(3) :: eu + real(pReal), intent(in), dimension(3) :: eu type(quaternion) :: qu - real(pReal), dimension(3) :: ee - real(pReal) :: cPhi, sPhi + real(pReal), dimension(3) :: ee + real(pReal) :: cPhi, sPhi ee = 0.5_pReal*eu cPhi = cos(ee(2)) sPhi = sin(ee(2)) - ! passive quaternion qu = quaternion([ cPhi*cos(ee(1)+ee(3)), & -epsijk*sPhi*cos(ee(1)-ee(3)), & -epsijk*sPhi*sin(ee(1)-ee(3)), & @@ -276,16 +333,18 @@ pure function eu2qu(eu) result(qu) end function eu2qu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief orientation matrix to euler angles -!-------------------------------------------------------------------------- +!> @brief orientation matrix to Euler angles +!--------------------------------------------------------------------------------------------------- pure function om2eu(om) result(eu) + use prec, only: & + dEq use math, only: & PI implicit none - real(pReal), intent(in), dimension(3,3) :: om !< orientation matrix + real(pReal), intent(in), dimension(3,3) :: om real(pReal), dimension(3) :: eu real(pReal) :: zeta @@ -302,17 +361,20 @@ pure function om2eu(om) result(eu) end function om2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Axis angle pair to orientation matrix -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to orientation matrix +!--------------------------------------------------------------------------------------------------- pure function ax2om(ax) result(om) + use prec, only: & + pInt implicit none real(pReal), intent(in), dimension(4) :: ax - real(pReal), dimension(3,3) :: om !< orientation matrix + real(pReal), dimension(3,3) :: om + real(pReal) :: q, c, s, omc - integer(pInt) :: i + integer(pInt) :: i c = cos(ax(4)) s = sin(ax(4)) @@ -337,18 +399,21 @@ pure function ax2om(ax) result(om) end function ax2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Quaternion to Euler angles [Morawiec page 40, with errata !!!! ] -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to Euler angles +!--------------------------------------------------------------------------------------------------- pure function qu2eu(qu) result(eu) + use prec, only: & + dEq0 use math, only: & PI implicit none - type(quaternion), intent(in) :: qu !< quaternion - real(pReal), dimension(3) :: eu - real(pReal) :: q12, q03, chi, chiInv + type(quaternion), intent(in) :: qu + real(pReal), dimension(3) :: eu + + real(pReal) :: q12, q03, chi, chiInv q03 = qu%w**2+qu%z**2 q12 = qu%x**2+qu%y**2 @@ -369,15 +434,16 @@ pure function qu2eu(qu) result(eu) end function qu2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Axis angle pair to homochoric -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to homochoric +!--------------------------------------------------------------------------------------------------- pure function ax2ho(ax) result(ho) - - real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + implicit none + real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(3) :: ho + real(pReal) :: f f = 0.75 * ( ax(4) - sin(ax(4)) ) @@ -387,16 +453,19 @@ pure function ax2ho(ax) result(ho) end function ax2ho -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Homochoric to axis angle pair -!-------------------------------------------------------------------------- +!> @brief convert homochoric to axis angle pair +!--------------------------------------------------------------------------------------------------- pure function ho2ax(ho) result(ax) - + use prec, only: & + pInt, & + dEq0 implicit none - real(pReal), intent(in), dimension(3) :: ho !< homochoric coordinates + real(pReal), intent(in), dimension(3) :: ho real(pReal), dimension(4) :: ax - integer(pInt) :: i + + integer(pInt) :: i real(pReal) :: hmag_squared, s, hm real(pReal), parameter, dimension(16) :: & tfit = [ 1.0000000000018852_pReal, -0.5000000002194847_pReal, & @@ -427,11 +496,16 @@ pure function ho2ax(ho) result(ax) end function ho2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert orientation matrix to axis angle -!-------------------------------------------------------------------------- +!> @brief convert orientation matrix to axis angle pair +!--------------------------------------------------------------------------------------------------- function om2ax(om) result(ax) + use prec, only: & + pInt, & + dEq0, & + cEq, & + dNeq0 use IO, only: & IO_error use math, only: & @@ -439,13 +513,13 @@ function om2ax(om) result(ax) math_trace33 implicit none - real(pReal), intent(in) :: om(3,3) - real(pReal) :: ax(4) + real(pReal), intent(in) :: om(3,3) + real(pReal) :: ax(4) - real(pReal) :: t - real(pReal), dimension(3) :: Wr, Wi - real(pReal), dimension(10) :: WORK - real(pReal), dimension(3,3) :: VR, devNull, o + real(pReal) :: t + real(pReal), dimension(3) :: Wr, Wi + real(pReal), dimension(10) :: WORK + real(pReal), dimension(3,3) :: VR, devNull, o integer(pInt) :: INFO, LWORK, i external :: dgeev,sgeev @@ -482,18 +556,22 @@ function om2ax(om) result(ax) end function om2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Rodrigues vector to axis angle pair -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to axis angle pair +!--------------------------------------------------------------------------------------------------- pure function ro2ax(ro) result(ax) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only: & + IEEE_is_finite + use prec, only: & + dEq0 use math, only: & PI implicit none - real(pReal), intent(in), dimension(4) :: ro !< homochoric coordinates + real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(4) :: ax + real(pReal) :: ta, angle ta = ro(4) @@ -511,18 +589,23 @@ pure function ro2ax(ro) result(ax) end function ro2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert axis angle to Rodrigues -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to Rodrigues vector +!--------------------------------------------------------------------------------------------------- pure function ax2ro(ax) result(ro) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only: & + IEEE_value, & + IEEE_positive_inf + use prec, only: & + dEq0 use math, only: & PI implicit none - real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(4) :: ro + real(pReal), parameter :: thr = 1.0E-7 if (dEq0(ax(4))) then @@ -536,16 +619,19 @@ pure function ax2ro(ax) result(ro) end function ax2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert axis angle to quaternion -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to quaternion +!--------------------------------------------------------------------------------------------------- pure function ax2qu(ax) result(qu) - + use prec, only: & + dEq0 + implicit none - real(pReal), intent(in), dimension(4) :: ax + real(pReal), intent(in), dimension(4) :: ax type(quaternion) :: qu - real(pReal) :: c, s + + real(pReal) :: c, s if (dEq0(ax(4))) then @@ -559,18 +645,22 @@ pure function ax2qu(ax) result(qu) end function ax2qu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert rodrigues to homochoric -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to homochoric +!--------------------------------------------------------------------------------------------------- pure function ro2ho(ro) result(ho) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only: & + IEEE_is_finite + use prec, only: & + dEq0 use math, only: & PI implicit none real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(3) :: ho + real(pReal) :: f if (dEq0(norm2(ro(1:3)))) then @@ -583,16 +673,17 @@ pure function ro2ho(ro) result(ho) end function ro2ho -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert a quaternion to a 3x3 matrix -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to rotation matrix +!--------------------------------------------------------------------------------------------------- pure function qu2om(qu) result(om) implicit none type(quaternion), intent(in) :: qu - real(pReal), dimension(3,3) :: om - real(pReal) :: qq + real(pReal), dimension(3,3) :: om + + real(pReal) :: qq qq = qu%w**2-(qu%x**2 + qu%y**2 + qu%z**2) @@ -613,17 +704,20 @@ pure function qu2om(qu) result(om) end function qu2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert a 3x3 rotation matrix to a unit quaternion (see Morawiec, page 37) -!-------------------------------------------------------------------------- +!> @brief convert rotation matrix to a unit quaternion +!--------------------------------------------------------------------------------------------------- function om2qu(om) result(qu) + use prec, only: & + dEq implicit none - real(pReal), intent(in), dimension(3,3) :: om + real(pReal), intent(in), dimension(3,3) :: om type(quaternion) :: qu - real(pReal), dimension(4) :: qu_A - real(pReal), dimension(4) :: s + + real(pReal), dimension(4) :: qu_A + real(pReal), dimension(4) :: s s = [+om(1,1) +om(2,2) +om(3,3) +1.0_pReal, & +om(1,1) -om(2,2) -om(3,3) +1.0_pReal, & @@ -647,18 +741,22 @@ function om2qu(om) result(qu) end function om2qu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert quaternion to axis angle -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to axis angle pair +!--------------------------------------------------------------------------------------------------- pure function qu2ax(qu) result(ax) + use prec, only: & + dEq0, & + dNeq0 use math, only: & PI implicit none type(quaternion), intent(in) :: qu - real(pReal), dimension(4) :: ax - real(pReal) :: omega, s + real(pReal), dimension(4) :: ax + + real(pReal) :: omega, s omega = 2.0 * acos(qu%w) ! if the angle equals zero, then we return the rotation axis as [001] @@ -674,15 +772,20 @@ pure function qu2ax(qu) result(ax) end function qu2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert quaternion to Rodrigues -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to Rodrigues vector +!--------------------------------------------------------------------------------------------------- pure function qu2ro(qu) result(ro) - use, intrinsic :: IEEE_ARITHMETIC + use, intrinsic :: IEEE_ARITHMETIC, only: & + IEEE_value, & + IEEE_positive_inf + use prec, only: & + dEq0 type(quaternion), intent(in) :: qu real(pReal), dimension(4) :: ro + real(pReal) :: s real(pReal), parameter :: thr = 1.0e-8_pReal @@ -690,24 +793,27 @@ pure function qu2ro(qu) result(ro) ro = [qu%x, qu%y, qu%z, IEEE_value(ro(4),IEEE_positive_inf)] else s = norm2([qu%x,qu%y,qu%z]) - ro = merge ( [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal] , & + ro = merge ( [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal], & [ qu%x/s, qu%y/s, qu%z/s, tan(acos(qu%w))], & - s < thr) + s < thr) !ToDo: not save (PGI compiler) end if end function qu2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert quaternion to homochoric -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to homochoric +!--------------------------------------------------------------------------------------------------- pure function qu2ho(qu) result(ho) + use prec, only: & + dEq0 implicit none type(quaternion), intent(in) :: qu - real(pReal), dimension(3) :: ho - real(pReal) :: omega, f + real(pReal), dimension(3) :: ho + + real(pReal) :: omega, f omega = 2.0 * acos(qu%w) @@ -722,12 +828,13 @@ pure function qu2ho(qu) result(ho) end function qu2ho -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief convert homochoric to cubochoric -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- function ho2cu(ho) result(cu) - use Lambert, only: LambertBallToCube + use Lambert, only: & + LambertBallToCube implicit none real(pReal), intent(in), dimension(3) :: ho @@ -738,12 +845,13 @@ function ho2cu(ho) result(cu) end function ho2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief convert cubochoric to homochoric -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- function cu2ho(cu) result(ho) - use Lambert, only: LambertCubeToBall + use Lambert, only: & + LambertCubeToBall implicit none real(pReal), intent(in), dimension(3) :: cu @@ -753,21 +861,15 @@ function cu2ho(cu) result(ho) end function cu2ho -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- -! and here are a bunch of transformation routines that are derived from the others -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief Rodrigues vector to Euler angles -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to Euler angles +!--------------------------------------------------------------------------------------------------- pure function ro2eu(ro) result(eu) implicit none - real(pReal), intent(in), dimension(4) :: ro !< Rodrigues vector + real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(3) :: eu eu = om2eu(ro2om(ro)) @@ -775,10 +877,10 @@ pure function ro2eu(ro) result(eu) end function ro2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert euler to homochoric -!-------------------------------------------------------------------------- +!> @brief convert Euler angles to homochoric +!--------------------------------------------------------------------------------------------------- pure function eu2ho(eu) result(ho) implicit none @@ -790,10 +892,10 @@ pure function eu2ho(eu) result(ho) end function eu2ho -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert orientation matrix to Rodrigues -!-------------------------------------------------------------------------- +!> @brief convert rotation matrix to Rodrigues vector +!--------------------------------------------------------------------------------------------------- pure function om2ro(om) result(ro) implicit none @@ -805,10 +907,10 @@ pure function om2ro(om) result(ro) end function om2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert orientation matrix to homochoric -!-------------------------------------------------------------------------- +!> @brief convert rotation matrix to homochoric +!--------------------------------------------------------------------------------------------------- function om2ho(om) result(ho) implicit none @@ -820,10 +922,10 @@ function om2ho(om) result(ho) end function om2ho -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert axis angle to euler -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to Euler angles +!--------------------------------------------------------------------------------------------------- pure function ax2eu(ax) result(eu) implicit none @@ -835,10 +937,10 @@ pure function ax2eu(ax) result(eu) end function ax2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert rodrigues to orientation matrix -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to rotation matrix +!--------------------------------------------------------------------------------------------------- pure function ro2om(ro) result(om) implicit none @@ -850,14 +952,14 @@ pure function ro2om(ro) result(om) end function ro2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert rodrigues to quaternion -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to unit quaternion +!--------------------------------------------------------------------------------------------------- pure function ro2qu(ro) result(qu) implicit none - real(pReal), intent(in), dimension(4) :: ro + real(pReal), intent(in), dimension(4) :: ro type(quaternion) :: qu qu = ax2qu(ro2ax(ro)) @@ -865,10 +967,10 @@ pure function ro2qu(ro) result(qu) end function ro2qu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert homochoric to euler -!-------------------------------------------------------------------------- +!> @brief convert homochoric to Euler angles +!--------------------------------------------------------------------------------------------------- pure function ho2eu(ho) result(eu) implicit none @@ -880,10 +982,10 @@ pure function ho2eu(ho) result(eu) end function ho2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert homochoric to orientation matrix -!-------------------------------------------------------------------------- +!> @brief convert homochoric to rotation matrix +!--------------------------------------------------------------------------------------------------- pure function ho2om(ho) result(om) implicit none @@ -895,10 +997,10 @@ pure function ho2om(ho) result(om) end function ho2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert homochoric to Rodrigues -!-------------------------------------------------------------------------- +!> @brief convert homochoric to Rodrigues vector +!--------------------------------------------------------------------------------------------------- pure function ho2ro(ho) result(ro) implicit none @@ -911,14 +1013,14 @@ pure function ho2ro(ho) result(ro) end function ho2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert homochoric to quaternion -!-------------------------------------------------------------------------- +!> @brief convert homochoric to unit quaternion +!--------------------------------------------------------------------------------------------------- pure function ho2qu(ho) result(qu) implicit none - real(pReal), intent(in), dimension(3) :: ho + real(pReal), intent(in), dimension(3) :: ho type(quaternion) :: qu qu = ax2qu(ho2ax(ho)) @@ -926,14 +1028,14 @@ pure function ho2qu(ho) result(qu) end function ho2qu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert euler angles to cubochoric -!-------------------------------------------------------------------------- +!> @brief convert Euler angles to cubochoric +!--------------------------------------------------------------------------------------------------- function eu2cu(eu) result(cu) implicit none - real(pReal), intent(in), dimension(3) :: eu !< Bunge-Euler angles in radians + real(pReal), intent(in), dimension(3) :: eu real(pReal), dimension(3) :: cu cu = ho2cu(eu2ho(eu)) @@ -941,14 +1043,14 @@ function eu2cu(eu) result(cu) end function eu2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert orientation matrix to cubochoric -!-------------------------------------------------------------------------- +!> @brief convert rotation matrix to cubochoric +!--------------------------------------------------------------------------------------------------- function om2cu(om) result(cu) implicit none - real(pReal), intent(in), dimension(3,3) :: om !< rotation matrix + real(pReal), intent(in), dimension(3,3) :: om real(pReal), dimension(3) :: cu cu = ho2cu(om2ho(om)) @@ -956,14 +1058,14 @@ function om2cu(om) result(cu) end function om2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert axis angle to cubochoric -!-------------------------------------------------------------------------- +!> @brief convert axis angle pair to cubochoric +!--------------------------------------------------------------------------------------------------- function ax2cu(ax) result(cu) implicit none - real(pReal), intent(in), dimension(4) :: ax !< axis angle in degree/radians? + real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(3) :: cu cu = ho2cu(ax2ho(ax)) @@ -971,14 +1073,14 @@ function ax2cu(ax) result(cu) end function ax2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert Rodrigues to cubochoric -!-------------------------------------------------------------------------- +!> @brief convert Rodrigues vector to cubochoric +!--------------------------------------------------------------------------------------------------- function ro2cu(ro) result(cu) implicit none - real(pReal), intent(in), dimension(4) :: ro !< Rodrigues vector + real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(3) :: cu cu = ho2cu(ro2ho(ro)) @@ -986,29 +1088,29 @@ function ro2cu(ro) result(cu) end function ro2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert quaternion to cubochoric -!-------------------------------------------------------------------------- +!> @brief convert unit quaternion to cubochoric +!--------------------------------------------------------------------------------------------------- function qu2cu(qu) result(cu) implicit none - type(quaternion), intent(in) :: qu ! unit quaternion - real(pReal), dimension(3) :: cu + type(quaternion), intent(in) :: qu + real(pReal), dimension(3) :: cu cu = ho2cu(qu2ho(qu)) end function qu2cu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to euler angles -!-------------------------------------------------------------------------- +!> @brief convert cubochoric to Euler angles +!--------------------------------------------------------------------------------------------------- function cu2eu(cu) result(eu) implicit none - real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), intent(in), dimension(3) :: cu real(pReal), dimension(3) :: eu eu = ho2eu(cu2ho(cu)) @@ -1016,14 +1118,14 @@ function cu2eu(cu) result(eu) end function cu2eu -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to orientation matrix -!-------------------------------------------------------------------------- +!> @brief convert cubochoric to rotation matrix +!--------------------------------------------------------------------------------------------------- function cu2om(cu) result(om) implicit none - real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), intent(in), dimension(3) :: cu real(pReal), dimension(3,3) :: om om = ho2om(cu2ho(cu)) @@ -1031,14 +1133,14 @@ function cu2om(cu) result(om) end function cu2om -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to axis angle -!-------------------------------------------------------------------------- +!> @brief convert cubochoric to axis angle pair +!--------------------------------------------------------------------------------------------------- function cu2ax(cu) result(ax) implicit none - real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), intent(in), dimension(3) :: cu real(pReal), dimension(4) :: ax ax = ho2ax(cu2ho(cu)) @@ -1046,14 +1148,14 @@ function cu2ax(cu) result(ax) end function cu2ax -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to Rodrigues -!-------------------------------------------------------------------------- +!> @brief convert cubochoric to Rodrigues vector +!--------------------------------------------------------------------------------------------------- function cu2ro(cu) result(ro) implicit none - real(pReal), intent(in), dimension(3) :: cu ! cubochoric? + real(pReal), intent(in), dimension(3) :: cu real(pReal), dimension(4) :: ro ro = ho2ro(cu2ho(cu)) @@ -1061,15 +1163,15 @@ function cu2ro(cu) result(ro) end function cu2ro -!-------------------------------------------------------------------------- +!--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to quaternion -!-------------------------------------------------------------------------- +!> @brief convert cubochoric to unit quaternion +!--------------------------------------------------------------------------------------------------- function cu2qu(cu) result(qu) implicit none - real(pReal), intent(in), dimension(3) :: cu ! cubochoric? - type(quaternion) :: qu ! cubochoric? + real(pReal), intent(in), dimension(3) :: cu + type(quaternion) :: qu qu = ho2qu(cu2ho(cu)) From 9d25d677e6695e6f532cef4835dadceb0b533cf0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 10:11:46 +0100 Subject: [PATCH 11/97] using new orientation class not sure if transpose is needed for initialization --- src/crystallite.f90 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/crystallite.f90 b/src/crystallite.f90 index 45aca46d1..a9126015d 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -9,6 +9,11 @@ !-------------------------------------------------------------------------------------------------- module crystallite + use prec, only: & + pReal, & + pInt + use orientations, only: & + orientation use FEsolving, only: & FEsolving_execElem, & FEsolving_execIP @@ -16,9 +21,7 @@ module crystallite mesh_element use material, only: & homogenization_Ngrains - use prec, only: & - pReal, & - pInt + implicit none @@ -42,6 +45,9 @@ module crystallite crystallite_Tstar_v, & !< current 2nd Piola-Kirchhoff stress vector (end of converged time step) ToDo: Should be called S, 3x3 crystallite_Tstar0_v, & !< 2nd Piola-Kirchhoff stress vector at start of FE inc ToDo: Should be called S, 3x3 crystallite_partionedTstar0_v !< 2nd Piola-Kirchhoff stress vector at start of homog inc ToDo: Should be called S, 3x3 + type(orientation), dimension(:,:,:), allocatable, private :: & + crystallite_ori, & !< orientation as quaternion + crystallite_ori0 !< initial orientation as quaternion real(pReal), dimension(:,:,:,:), allocatable, private :: & crystallite_orientation, & !< orientation as quaternion crystallite_orientation0, & !< initial orientation as quaternion @@ -239,6 +245,8 @@ subroutine crystallite_init allocate(crystallite_subStep(cMax,iMax,eMax), source=0.0_pReal) allocate(crystallite_orientation(4,cMax,iMax,eMax), source=0.0_pReal) allocate(crystallite_orientation0(4,cMax,iMax,eMax), source=0.0_pReal) + allocate(crystallite_ori(cMax,iMax,eMax)) + !allocate(crystallite_ori0(cMax,iMax,eMax)) allocate(crystallite_rotation(4,cMax,iMax,eMax), source=0.0_pReal) allocate(crystallite_localPlasticity(cMax,iMax,eMax), source=.true.) allocate(crystallite_requested(cMax,iMax,eMax), source=.false.) @@ -900,6 +908,7 @@ subroutine crystallite_orientations do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) do c = 1_pInt,homogenization_Ngrains(mesh_element(3,e)) + call crystallite_ori(c,i,e)%fromRotationMatrix(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) crystallite_orientation(1:4,c,i,e) = math_RtoQ(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) crystallite_rotation(1:4,c,i,e) = lattice_qDisorientation(crystallite_orientation0(1:4,c,i,e), &! active rotation from initial crystallite_orientation(1:4,c,i,e)) ! to current orientation (with no symmetry) @@ -1020,7 +1029,7 @@ function crystallite_postResults(ipc, ip, el) / real(homogenization_Ngrains(mesh_element(3,el)),pReal) ! grain volume (not fraction but absolute) case (orientation_ID) mySize = 4_pInt - crystallite_postResults(c+1:c+mySize) = crystallite_orientation(1:4,ipc,ip,el) ! grain orientation as quaternion + crystallite_postResults(c+1:c+mySize) = crystallite_ori(ipc,ip,el)%asQuaternion() case (eulerangles_ID) mySize = 3_pInt crystallite_postResults(c+1:c+mySize) = inDeg & From 11a509970b8870736f816b90a721ed399323972d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 10:17:20 +0100 Subject: [PATCH 12/97] some comments --- python/damask/orientation.py | 3 ++- src/quaternions.f90 | 3 ++- src/rotations.f90 | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 63880a3e6..6a2685a2b 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -20,7 +20,8 @@ class Quaternion: Convention 4: Euler angle triplets are implemented using the Bunge convention, with the angular ranges as [0, 2π],[0, π],[0, 2π] Convention 5: the rotation angle ω is limited to the interval [0, π] - + Convention 6: P = 1 (as default) + w is the real part, (x, y, z) are the imaginary parts. Vector "a" (defined in coordinate system "A") is passively rotated diff --git a/src/quaternions.f90 b/src/quaternions.f90 index b0dd37291..b3a92ffdf 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -31,6 +31,7 @@ !> @author Marc De Graef, Carnegie Mellon University !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief general quaternion math, not limited to unit quaternions +!> @details w is the real part, (x, y, z) are the imaginary parts. !--------------------------------------------------------------------------------------------------- module quaternions use prec, only: & @@ -39,7 +40,7 @@ module quaternions implicit none public - real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. ToDo: Better place? + real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. type, public :: quaternion real(pReal) :: w = 0.0_pReal diff --git a/src/rotations.f90 b/src/rotations.f90 index e58963dea..a0e6e9250 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -33,6 +33,16 @@ !> @brief rotation storage and conversion !> @details: rotation is internally stored as quaternion. It cabe inialized from different !> represantations and also returns itself in different representations. +! +! All methods and naming conventions based on Rowenhorst_etal2015 +! Convention 1: coordinate frames are right-handed +! Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation +! when viewing from the end point of the rotation axis towards the origin +! Convention 3: rotations will be interpreted in the passive sense +! Convention 4: Euler angle triplets are implemented using the Bunge convention, +! with the angular ranges as [0, 2π],[0, π],[0, 2π] +! Convention 5: the rotation angle ω is limited to the interval [0, π] +! Convention 6: epsijk/P = -1 !--------------------------------------------------------------------------------------------------- module rotations From 06f67ce500aa77c9f965ac2558b853a4b409c12a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 10:24:10 +0100 Subject: [PATCH 13/97] orientations module was not compiled but is needed now --- src/commercialFEM_fileList.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index 353ca1497..a5d633e83 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -14,6 +14,7 @@ #include "quaternions.f90" #include "Lambert.f90" #include "rotations.f90" +#include "orientations.f90" #include "FEsolving.f90" #include "mesh.f90" #include "material.f90" From e6fe312f853451995e778b4c32304fe15b245541 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 1 Feb 2019 14:04:55 +0100 Subject: [PATCH 14/97] Corrected documented value for P (= -1!). Instead of repeating the assignment P=-1 in multiple internal functions, it might be advisable to define a class-wide parameter? --- python/damask/orientation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 6a2685a2b..29ecaf626 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -20,7 +20,7 @@ class Quaternion: Convention 4: Euler angle triplets are implemented using the Bunge convention, with the angular ranges as [0, 2π],[0, π],[0, 2π] Convention 5: the rotation angle ω is limited to the interval [0, π] - Convention 6: P = 1 (as default) + Convention 6: P = -1 (as default) w is the real part, (x, y, z) are the imaginary parts. From 0c1c40f1de8d3e862591f588787d0c775ab024a8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 16:43:34 +0100 Subject: [PATCH 15/97] don't use euler angles any more updated test --- PRIVATE | 2 +- examples/ConfigFiles/Crystallite_All.config | 1 - examples/SpectralMethod/Polycrystal/material.config | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/PRIVATE b/PRIVATE index beb9682ff..25006bc97 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit beb9682fff7d4d6c65aba12ffd04c7441dc6ba6b +Subproject commit 25006bc974b752faf3464b082511590d50093c37 diff --git a/examples/ConfigFiles/Crystallite_All.config b/examples/ConfigFiles/Crystallite_All.config index d46c3e0e6..ab4b63de4 100644 --- a/examples/ConfigFiles/Crystallite_All.config +++ b/examples/ConfigFiles/Crystallite_All.config @@ -3,7 +3,6 @@ (output) texture (output) volume (output) orientation # quaternion -(output) eulerangles # orientation as Bunge triple in degree (output) grainrotation # deviation from initial orientation as axis (1-3) and angle in degree (4) in crystal reference coordinates (output) f # deformation gradient tensor (output) fe # elastic deformation gradient tensor diff --git a/examples/SpectralMethod/Polycrystal/material.config b/examples/SpectralMethod/Polycrystal/material.config index 93a5a6710..39e7f1952 100644 --- a/examples/SpectralMethod/Polycrystal/material.config +++ b/examples/SpectralMethod/Polycrystal/material.config @@ -13,7 +13,6 @@ mech none (output) texture (output) volume (output) orientation # quaternion -(output) eulerangles # orientation as Bunge triple (output) grainrotation # deviation from initial orientation as axis (1-3) and angle in degree (4) (output) f # deformation gradient tensor; synonyms: "defgrad" (output) fe # elastic deformation gradient tensor From 407f94082fb845682d7d18c5ff7d9dae27f2d513 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 16:52:42 +0100 Subject: [PATCH 16/97] no need for orientation class at the moment implement only if we need symmetry aware operations --- src/CMakeLists.txt | 8 ++----- src/commercialFEM_fileList.f90 | 1 - src/crystallite.f90 | 6 +++--- src/orientations.f90 | 39 ---------------------------------- 4 files changed, 5 insertions(+), 49 deletions(-) delete mode 100644 src/orientations.f90 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1af42911..37913b6df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,18 +69,14 @@ add_library(ROTATIONS OBJECT "rotations.f90") add_dependencies(ROTATIONS LAMBERT QUATERNIONS) list(APPEND OBJECTFILES $) -add_library(ORIENTATIONS OBJECT "orientations.f90") -add_dependencies(ORIENTATIONS ROTATIONS) -list(APPEND OBJECTFILES $) - # SPECTRAL solver and FEM solver use different mesh files if (PROJECT_NAME STREQUAL "DAMASK_spectral") add_library(MESH OBJECT "mesh.f90") - add_dependencies(MESH ORIENTATIONS FEsolving) + add_dependencies(MESH ROTATIONS FEsolving) list(APPEND OBJECTFILES $) elseif (PROJECT_NAME STREQUAL "DAMASK_FEM") add_library(FEZoo OBJECT "FEM_zoo.f90") - add_dependencies(FEZoo ORIENTATIONS FEsolving) + add_dependencies(FEZoo ROTATIONS FEsolving) list(APPEND OBJECTFILES $) add_library(MESH OBJECT "meshFEM.f90") add_dependencies(MESH FEZoo) diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index a5d633e83..353ca1497 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -14,7 +14,6 @@ #include "quaternions.f90" #include "Lambert.f90" #include "rotations.f90" -#include "orientations.f90" #include "FEsolving.f90" #include "mesh.f90" #include "material.f90" diff --git a/src/crystallite.f90 b/src/crystallite.f90 index a9126015d..e2f05284e 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -12,8 +12,8 @@ module crystallite use prec, only: & pReal, & pInt - use orientations, only: & - orientation + use rotations, only: & + rotation use FEsolving, only: & FEsolving_execElem, & FEsolving_execIP @@ -45,7 +45,7 @@ module crystallite crystallite_Tstar_v, & !< current 2nd Piola-Kirchhoff stress vector (end of converged time step) ToDo: Should be called S, 3x3 crystallite_Tstar0_v, & !< 2nd Piola-Kirchhoff stress vector at start of FE inc ToDo: Should be called S, 3x3 crystallite_partionedTstar0_v !< 2nd Piola-Kirchhoff stress vector at start of homog inc ToDo: Should be called S, 3x3 - type(orientation), dimension(:,:,:), allocatable, private :: & + type(rotation), dimension(:,:,:), allocatable, private :: & crystallite_ori, & !< orientation as quaternion crystallite_ori0 !< initial orientation as quaternion real(pReal), dimension(:,:,:,:), allocatable, private :: & diff --git a/src/orientations.f90 b/src/orientations.f90 deleted file mode 100644 index 285492729..000000000 --- a/src/orientations.f90 +++ /dev/null @@ -1,39 +0,0 @@ -!--------------------------------------------------------------------------------------------------- -!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief orientation storage -!> @details: orientation = rotation + symmetry -!--------------------------------------------------------------------------------------------------- - -module orientations - use rotations - use prec, only: & - pStringLen - - implicit none - type, extends(rotation), public :: orientation - character(len=pStringLen) :: sym = 'none' - end type orientation - - interface orientation - module procedure :: orientation_init - end interface orientation - -contains - -type(orientation) function orientation_init(sym,eu,ax,om,qu,cu,ho,ro) - use prec - implicit none - character(len=pStringLen), intent(in), optional :: sym - real(pReal), intent(in), optional, dimension(3) :: eu, cu, ho - real(pReal), intent(in), optional, dimension(4) :: ax, qu, ro - real(pReal), intent(in), optional, dimension(3,3) :: om - - if (present(sym)) orientation_init%sym = sym - - if (present(om)) then - call orientation_init%fromRotationMatrix(om) - endif - -end function orientation_init - -end module From feb87c7db846ae29cb55e5617589207b4f229207 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 19:09:17 +0100 Subject: [PATCH 17/97] same name as in the python module --- src/quaternions.f90 | 8 ++++---- src/rotations.f90 | 36 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/quaternions.f90 b/src/quaternions.f90 index b3a92ffdf..17f943aa6 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -40,7 +40,7 @@ module quaternions implicit none public - real(pReal), parameter, public :: epsijk = -1.0_pReal !< parameter for orientation conversion. + real(pReal), parameter, public :: P = -1.0_pReal !< parameter for orientation conversion. type, public :: quaternion real(pReal) :: w = 0.0_pReal @@ -241,9 +241,9 @@ type(quaternion) elemental function mul_quat__(self,other) class(quaternion), intent(in) :: self, other mul_quat__%w = self%w*other%w - self%x*other%x - self%y*other%y - self%z*other%z - mul_quat__%x = self%w*other%x + self%x*other%w + epsijk * (self%y*other%z - self%z*other%y) - mul_quat__%y = self%w*other%y + self%y*other%w + epsijk * (self%z*other%x - self%x*other%z) - mul_quat__%z = self%w*other%z + self%z*other%w + epsijk * (self%x*other%y - self%y*other%x) + mul_quat__%x = self%w*other%x + self%x*other%w + P * (self%y*other%z - self%z*other%y) + mul_quat__%y = self%w*other%y + self%y*other%w + P * (self%z*other%x - self%x*other%z) + mul_quat__%z = self%w*other%z + self%z*other%w + P * (self%x*other%y - self%y*other%x) end function mul_quat__ diff --git a/src/rotations.f90 b/src/rotations.f90 index a0e6e9250..4ccea592b 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -42,7 +42,7 @@ ! Convention 4: Euler angle triplets are implemented using the Bunge convention, ! with the angular ranges as [0, 2π],[0, π],[0, 2π] ! Convention 5: the rotation angle ω is limited to the interval [0, π] -! Convention 6: epsijk/P = -1 +! Convention 6: P = -1 !--------------------------------------------------------------------------------------------------- module rotations @@ -280,7 +280,7 @@ pure function eu2ax(eu) result(ax) if (dEq0(alpha)) then ! return a default identity axis-angle pair ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] else - ax(1:3) = -epsijk/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front + ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front ax(4) = alpha if (alpha < 0.0) ax = -ax ! ensure alpha is positive end if @@ -309,7 +309,7 @@ pure function eu2ro(eu) result(ro) if (ro(4) >= PI) then ro(4) = IEEE_value(ro(4),IEEE_positive_inf) elseif(dEq0(ro(4))) then - ro = [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal ] + ro = [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal ] else ro(4) = tan(ro(4)*0.5) end if @@ -334,10 +334,10 @@ pure function eu2qu(eu) result(qu) cPhi = cos(ee(2)) sPhi = sin(ee(2)) - qu = quaternion([ cPhi*cos(ee(1)+ee(3)), & - -epsijk*sPhi*cos(ee(1)-ee(3)), & - -epsijk*sPhi*sin(ee(1)-ee(3)), & - -epsijk*cPhi*sin(ee(1)+ee(3))]) + qu = quaternion([ cPhi*cos(ee(1)+ee(3)), & + -P*sPhi*cos(ee(1)-ee(3)), & + -P*sPhi*sin(ee(1)-ee(3)), & + -P*cPhi*sin(ee(1)+ee(3))]) if(qu%w < 0.0_pReal) qu = qu%homomorphed() end function eu2qu @@ -404,7 +404,7 @@ pure function ax2om(ax) result(om) om(3,1) = q + s*ax(2) om(1,3) = q - s*ax(2) - if (epsijk > 0.0) om = transpose(om) + if (P > 0.0) om = transpose(om) end function ax2om @@ -430,14 +430,14 @@ pure function qu2eu(qu) result(eu) chi = sqrt(q03*q12) degenerated: if (dEq0(chi)) then - eu = merge([atan2(-epsijk*2.0*qu%w*qu%z,qu%w**2-qu%z**2), 0.0_pReal, 0.0_pReal], & - [atan2(2.0*qu%x*qu%y,qu%x**2-qu%y**2), PI, 0.0_pReal], & + eu = merge([atan2(-P*2.0*qu%w*qu%z,qu%w**2-qu%z**2), 0.0_pReal, 0.0_pReal], & + [atan2(2.0*qu%x*qu%y,qu%x**2-qu%y**2), PI, 0.0_pReal], & dEq0(q12)) else degenerated chiInv = 1.0/chi - eu = [atan2((-epsijk*qu%w*qu%y+qu%x*qu%z)*chi, (-epsijk*qu%w*qu%x-qu%y*qu%z)*chi ), & + eu = [atan2((-P*qu%w*qu%y+qu%x*qu%z)*chi, (-P*qu%w*qu%x-qu%y*qu%z)*chi ), & atan2( 2.0*chi, q03-q12 ), & - atan2(( epsijk*qu%w*qu%y+qu%x*qu%z)*chi, (-epsijk*qu%w*qu%x+qu%y*qu%z)*chi )] + atan2(( P*qu%w*qu%y+qu%x*qu%z)*chi, (-P*qu%w*qu%x+qu%y*qu%z)*chi )] endif degenerated where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) @@ -559,8 +559,8 @@ function om2ax(om) result(ax) if (INFO /= 0) call IO_error(0_pInt,ext_msg='Error in om2ax/(s/d)geev: (S/D)GEEV return not zero') i = maxloc(merge(1.0_pReal,0.0_pReal,cEq(cmplx(Wr,Wi,pReal),cmplx(1.0_pReal,0.0_pReal,pReal),tol=1.0e-14_pReal)),dim=1) ! poor substitute for findloc ax(1:3) = VR(1:3,i) - where ( dNeq0([om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)])) & - ax(1:3) = sign(ax(1:3),-epsijk *[om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)]) + where ( dNeq0([om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)])) & + ax(1:3) = sign(ax(1:3),-P *[om(2,3)-om(3,2), om(3,1)-om(1,3), om(1,2)-om(2,1)]) endif end function om2ax @@ -619,7 +619,7 @@ pure function ax2ro(ax) result(ro) real(pReal), parameter :: thr = 1.0E-7 if (dEq0(ax(4))) then - ro = [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal ] + ro = [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal ] else ro(1:3) = ax(1:3) ! we need to deal with the 180 degree case @@ -709,7 +709,7 @@ pure function qu2om(qu) result(om) om(3,2) = 2.0*(qu%z*qu%y+qu%w*qu%x) om(1,3) = 2.0*(qu%x*qu%z+qu%w*qu%y) - if (epsijk < 0.0) om = transpose(om) + if (P < 0.0) om = transpose(om) end function qu2om @@ -734,7 +734,7 @@ function om2qu(om) result(qu) -om(1,1) +om(2,2) -om(3,3) +1.0_pReal, & -om(1,1) -om(2,2) +om(3,3) +1.0_pReal] - qu_A = sqrt(max(s,0.0_pReal))*0.5_pReal*[1.0_pReal,epsijk,epsijk,epsijk] + qu_A = sqrt(max(s,0.0_pReal))*0.5_pReal*[1.0_pReal,P,P,P] qu_A = qu_A/norm2(qu_A) if(any(dEq(abs(qu_A),1.0_pReal,1.0e-15_pReal))) & @@ -803,7 +803,7 @@ pure function qu2ro(qu) result(ro) ro = [qu%x, qu%y, qu%z, IEEE_value(ro(4),IEEE_positive_inf)] else s = norm2([qu%x,qu%y,qu%z]) - ro = merge ( [ 0.0_pReal, 0.0_pReal, epsijk, 0.0_pReal], & + ro = merge ( [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal], & [ qu%x/s, qu%y/s, qu%z/s, tan(acos(qu%w))], & s < thr) !ToDo: not save (PGI compiler) end if From 878331e5e9cfe59f6bcbff0a26f6040eb3fcb835 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 19:29:19 +0100 Subject: [PATCH 18/97] this code was never used and is quite old --- python/damask/orientation.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 29ecaf626..0386bc714 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -575,19 +575,6 @@ class 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 -# 'hexagonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red -# [1.,0.,0.], # direction of green -# [np.sqrt(3.),1.,0.]/np.sqrt(4.)]).transpose()), # direction of blue -# 'tetragonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red -# [1.,0.,0.], # direction of green -# [1.,1.,0.]/np.sqrt(2.)]).transpose()), # direction of blue -# 'orthorhombic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red -# [1.,0.,0.], # direction of green -# [0.,1.,0.]]).transpose()), # direction of blue -# } if self.lattice == 'cubic': basis = {'improper':np.array([ [-1. , 0. , 1. ], @@ -854,7 +841,7 @@ class Orientation: if int(direction) == 0: return None # KS from S. Morito et al./Journal of Alloys and Compounds 5775 (2013) S587-S592 - # for KS rotation matrices also check K. Kitahara et al./Acta Materialia 54 (2006) 1279-1288 + # for KS rotation matrices also check K. Kitahara et al./Acta Materialia 54 (2006) 1279-1288 # GT from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 # GT' from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 # NW from H. Kitahara et al./Materials Characterization 54 (2005) 378-386 From 08009079ff2d49295011897d18ff1074c21accd4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 20:17:12 +0100 Subject: [PATCH 19/97] avoiding numerical errors (if quaternion norm is > 1.) use consistently "self" instead of "this" function for misorientation --- src/quaternions.f90 | 2 +- src/rotations.f90 | 96 ++++++++++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/quaternions.f90 b/src/quaternions.f90 index 17f943aa6..39dc1d3cd 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -240,7 +240,7 @@ type(quaternion) elemental function mul_quat__(self,other) implicit none class(quaternion), intent(in) :: self, other - mul_quat__%w = self%w*other%w - self%x*other%x - self%y*other%y - self%z*other%z + mul_quat__%w = self%w*other%w - self%x*other%x - self%y*other%y - self%z*other%z mul_quat__%x = self%w*other%x + self%x*other%w + P * (self%y*other%z - self%z*other%y) mul_quat__%y = self%w*other%y + self%y*other%w + P * (self%z*other%x - self%x*other%z) mul_quat__%z = self%w*other%z + self%z*other%w + P * (self%x*other%y - self%y*other%x) diff --git a/src/rotations.f90 b/src/rotations.f90 index 4ccea592b..59ee3512d 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -65,17 +65,9 @@ module rotations !------------------------------------------ procedure, public :: rotVector procedure, public :: rotTensor + procedure, public :: misorientation end type rotation - public :: & - asQuaternion, & - asEulerAngles, & - asAxisAnglePair, & - asRotationMatrix, & - asRodriguesFrankVector, & - asHomochoric, & - fromRotationMatrix, & - rotVector, & - rotTensor + contains @@ -83,76 +75,76 @@ contains !--------------------------------------------------------------------------------------------------- ! Return rotation in different represenations !--------------------------------------------------------------------------------------------------- -function asQuaternion(this) +function asQuaternion(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(4) :: asQuaternion - asQuaternion = [this%q%w, this%q%x, this%q%y, this%q%z] + asQuaternion = [self%q%w, self%q%x, self%q%y, self%q%z] end function asQuaternion !--------------------------------------------------------------------------------------------------- -function asEulerAngles(this) +function asEulerAngles(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(3) :: asEulerAngles - asEulerAngles = qu2eu(this%q) + asEulerAngles = qu2eu(self%q) end function asEulerAngles !--------------------------------------------------------------------------------------------------- -function asAxisAnglePair(this) +function asAxisAnglePair(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(4) :: asAxisAnglePair - asAxisAnglePair = qu2ax(this%q) + asAxisAnglePair = qu2ax(self%q) end function asAxisAnglePair !--------------------------------------------------------------------------------------------------- -function asRotationMatrix(this) +function asRotationMatrix(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(3,3) :: asRotationMatrix - asRotationMatrix = qu2om(this%q) + asRotationMatrix = qu2om(self%q) end function asRotationMatrix !--------------------------------------------------------------------------------------------------- -function asRodriguesFrankVector(this) +function asRodriguesFrankVector(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(4) :: asRodriguesFrankVector - asRodriguesFrankVector = qu2ro(this%q) + asRodriguesFrankVector = qu2ro(self%q) end function asRodriguesFrankVector !--------------------------------------------------------------------------------------------------- -function asHomochoric(this) +function asHomochoric(self) implicit none - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), dimension(3) :: asHomochoric - asHomochoric = qu2ho(this%q) + asHomochoric = qu2ho(self%q) end function asHomochoric !--------------------------------------------------------------------------------------------------- ! Initialize rotation from different representations !--------------------------------------------------------------------------------------------------- -subroutine fromRotationMatrix(this,om) +subroutine fromRotationMatrix(self,om) implicit none - class(rotation), intent(out) :: this + class(rotation), intent(out) :: self real(pReal), dimension(3,3), intent(in) :: om - this%q = om2qu(om) + self%q = om2qu(om) end subroutine @@ -162,13 +154,13 @@ end subroutine !> @brief rotate a vector passively (default) or actively !> @details: rotation is based on unit quaternion or rotation matrix (fallback) !--------------------------------------------------------------------------------------------------- -function rotVector(this,v,active) +function rotVector(self,v,active) use prec, only: & dEq implicit none real(pReal), dimension(3) :: rotVector - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), intent(in), dimension(3) :: v logical, intent(in), optional :: active @@ -176,16 +168,16 @@ function rotVector(this,v,active) if (dEq(norm2(v),1.0_pReal,tol=1.0e-15_pReal)) then passive: if (merge(.not. active, .true., present(active))) then ! ToDo: not save (PGI) - q = this%q * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * conjg(this%q) ) + q = self%q * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * conjg(self%q) ) else passive - q = conjg(this%q) * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * this%q ) + q = conjg(self%q) * (quaternion([0.0_pReal, v(1), v(2), v(3)]) * self%q ) endif passive rotVector = [q%x,q%y,q%z] else passive2: if (merge(.not. active, .true., present(active))) then ! ToDo: not save (PGI) - rotVector = matmul(this%asRotationMatrix(),v) + rotVector = matmul(self%asRotationMatrix(),v) else passive2 - rotVector = matmul(transpose(this%asRotationMatrix()),v) + rotVector = matmul(transpose(self%asRotationMatrix()),v) endif passive2 endif @@ -197,24 +189,37 @@ end function rotVector !> @brief rotate a second rank tensor passively (default) or actively !> @details: rotation is based on rotation matrix !--------------------------------------------------------------------------------------------------- -function rotTensor(this,m,active) +function rotTensor(self,m,active) implicit none real(pReal), dimension(3,3) :: rotTensor - class(rotation), intent(in) :: this + class(rotation), intent(in) :: self real(pReal), intent(in), dimension(3,3) :: m logical, intent(in), optional :: active passive: if (merge(.not. active, .true., present(active))) then - rotTensor = matmul(matmul(this%asRotationMatrix(),m),transpose(this%asRotationMatrix())) + rotTensor = matmul(matmul(self%asRotationMatrix(),m),transpose(self%asRotationMatrix())) else passive - rotTensor = matmul(matmul(transpose(this%asRotationMatrix()),m),this%asRotationMatrix()) + rotTensor = matmul(matmul(transpose(self%asRotationMatrix()),m),self%asRotationMatrix()) endif passive end function rotTensor +!--------------------------------------------------------------------------------------------------- +!> @brief misorientation +!--------------------------------------------------------------------------------------------------- +function misorientation(self,other) + + implicit none + type(rotation) :: misorientation + class(rotation), intent(in) :: self, other + + misorientation%q = conjg(self%q) * other%q !ToDo: this is the convention used in math + +end function misorientation + !--------------------------------------------------------------------------------------------------- ! The following routines convert between different representations @@ -760,7 +765,8 @@ pure function qu2ax(qu) result(ax) dEq0, & dNeq0 use math, only: & - PI + PI, & + math_clip implicit none type(quaternion), intent(in) :: qu @@ -768,7 +774,7 @@ pure function qu2ax(qu) result(ax) real(pReal) :: omega, s - omega = 2.0 * acos(qu%w) + omega = 2.0 * acos(math_clip(qu%w,0.0_pReal,1.0_pReal)) ! if the angle equals zero, then we return the rotation axis as [001] if (dEq0(omega)) then ax = [ 0.0, 0.0, 1.0, 0.0 ] @@ -818,6 +824,8 @@ end function qu2ro pure function qu2ho(qu) result(ho) use prec, only: & dEq0 + use math, only: & + math_clip implicit none type(quaternion), intent(in) :: qu @@ -825,7 +833,7 @@ pure function qu2ho(qu) result(ho) real(pReal) :: omega, f - omega = 2.0 * acos(qu%w) + omega = 2.0 * acos(math_clip(qu%w,0.0_pReal,1.0_pReal)) if (dEq0(omega)) then ho = [ 0.0, 0.0, 0.0 ] From 9a4e9e62b66a84abe610ee17f9aaa07f081e5ee7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 1 Feb 2019 20:28:07 +0100 Subject: [PATCH 20/97] using new rotation class --- python/damask/orientation.py | 1 - src/constitutive.f90 | 4 +-- src/crystallite.f90 | 48 ++++++++++++------------------------ src/plastic_nonlocal.f90 | 15 ++++++----- 4 files changed, 24 insertions(+), 44 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 0386bc714..a1fe1f845 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -575,7 +575,6 @@ class Symmetry: proper considers only vectors with z >= 0, hence uses two neighboring SSTs. Return inverse pole figure color if requested. """ - if self.lattice == 'cubic': basis = {'improper':np.array([ [-1. , 0. , 1. ], [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], diff --git a/src/constitutive.f90 b/src/constitutive.f90 index a0d7147a6..9483f2610 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -348,7 +348,7 @@ end function constitutive_homogenizedC !-------------------------------------------------------------------------------------------------- !> @brief calls microstructure function of the different constitutive models !-------------------------------------------------------------------------------------------------- -subroutine constitutive_microstructure(orientations, Fe, Fp, ipc, ip, el) +subroutine constitutive_microstructure(Fe, Fp, ipc, ip, el) use prec, only: & pReal use material, only: & @@ -381,8 +381,6 @@ subroutine constitutive_microstructure(orientations, Fe, Fp, ipc, ip, el) ho, & !< homogenization tme, & !< thermal member position instance, of - real(pReal), intent(in), dimension(:,:,:,:) :: & - orientations !< crystal orientations as quaternions ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) diff --git a/src/crystallite.f90 b/src/crystallite.f90 index e2f05284e..013c28a38 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -46,12 +46,8 @@ module crystallite crystallite_Tstar0_v, & !< 2nd Piola-Kirchhoff stress vector at start of FE inc ToDo: Should be called S, 3x3 crystallite_partionedTstar0_v !< 2nd Piola-Kirchhoff stress vector at start of homog inc ToDo: Should be called S, 3x3 type(rotation), dimension(:,:,:), allocatable, private :: & - crystallite_ori, & !< orientation as quaternion - crystallite_ori0 !< initial orientation as quaternion - real(pReal), dimension(:,:,:,:), allocatable, private :: & - crystallite_orientation, & !< orientation as quaternion - crystallite_orientation0, & !< initial orientation as quaternion - crystallite_rotation !< grain rotation away from initial orientation as axis-angle (in degrees) in crystal reference frame + crystallite_orientation, & !< orientation + crystallite_orientation0 !< initial orientation real(pReal), dimension(:,:,:,:,:), allocatable, public, protected :: & crystallite_Fe, & !< current "elastic" def grad (end of converged time step) crystallite_P !< 1st Piola-Kirchhoff stress per grain @@ -243,11 +239,8 @@ subroutine crystallite_init allocate(crystallite_subdt(cMax,iMax,eMax), source=0.0_pReal) allocate(crystallite_subFrac(cMax,iMax,eMax), source=0.0_pReal) allocate(crystallite_subStep(cMax,iMax,eMax), source=0.0_pReal) - allocate(crystallite_orientation(4,cMax,iMax,eMax), source=0.0_pReal) - allocate(crystallite_orientation0(4,cMax,iMax,eMax), source=0.0_pReal) - allocate(crystallite_ori(cMax,iMax,eMax)) - !allocate(crystallite_ori0(cMax,iMax,eMax)) - allocate(crystallite_rotation(4,cMax,iMax,eMax), source=0.0_pReal) + allocate(crystallite_orientation(cMax,iMax,eMax)) + allocate(crystallite_orientation0(cMax,iMax,eMax)) allocate(crystallite_localPlasticity(cMax,iMax,eMax), source=.true.) allocate(crystallite_requested(cMax,iMax,eMax), source=.false.) allocate(crystallite_todo(cMax,iMax,eMax), source=.false.) @@ -296,8 +289,6 @@ subroutine crystallite_init crystallite_outputID(o,c) = orientation_ID case ('grainrotation') outputName crystallite_outputID(o,c) = grainrotation_ID - case ('eulerangles') outputName - crystallite_outputID(o,c) = eulerangles_ID case ('defgrad','f') outputName crystallite_outputID(o,c) = defgrad_ID case ('fe') outputName @@ -334,8 +325,6 @@ subroutine crystallite_init mySize = 1_pInt case(orientation_ID,grainrotation_ID) mySize = 4_pInt - case(eulerangles_ID) - mySize = 3_pInt case(defgrad_ID,fe_ID,fp_ID,fi_ID,lp_ID,li_ID,p_ID,s_ID) mySize = 9_pInt case(elasmatrix_ID) @@ -401,13 +390,12 @@ subroutine crystallite_init call crystallite_orientations() crystallite_orientation0 = crystallite_orientation ! store initial orientations for calculation of grain rotations - + !$OMP PARALLEL DO do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) do c = 1_pInt,homogenization_Ngrains(mesh_element(3,e)) - call constitutive_microstructure(crystallite_orientation, & - crystallite_Fe(1:3,1:3,c,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,c,i,e), & crystallite_Fp(1:3,1:3,c,i,e), & c,i,e) ! update dependent state variables to be consistent with basic states enddo @@ -908,10 +896,7 @@ subroutine crystallite_orientations do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) do c = 1_pInt,homogenization_Ngrains(mesh_element(3,e)) - call crystallite_ori(c,i,e)%fromRotationMatrix(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) - crystallite_orientation(1:4,c,i,e) = math_RtoQ(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) - crystallite_rotation(1:4,c,i,e) = lattice_qDisorientation(crystallite_orientation0(1:4,c,i,e), &! active rotation from initial - crystallite_orientation(1:4,c,i,e)) ! to current orientation (with no symmetry) + call crystallite_orientation(c,i,e)%fromRotationMatrix(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) enddo; enddo; enddo !$OMP END PARALLEL DO @@ -920,7 +905,7 @@ subroutine crystallite_orientations !$OMP PARALLEL DO do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) - if (plasticState(material_phase(1,i,e))%nonLocal) & ! if nonlocal model + if (plasticState(material_phase(1,i,e))%nonLocal) & ! if nonlocal model call plastic_nonlocal_updateCompatibility(crystallite_orientation,i,e) enddo; enddo !$OMP END PARALLEL DO @@ -987,6 +972,8 @@ function crystallite_postResults(ipc, ip, el) use constitutive, only: & constitutive_homogenizedC, & constitutive_postResults + use rotations, only: & + rotation implicit none integer(pInt), intent(in):: & @@ -1006,6 +993,7 @@ function crystallite_postResults(ipc, ip, el) crystID, & mySize, & n + type(rotation) :: rot crystID = microstructure_crystallite(mesh_element(4,el)) @@ -1029,15 +1017,12 @@ function crystallite_postResults(ipc, ip, el) / real(homogenization_Ngrains(mesh_element(3,el)),pReal) ! grain volume (not fraction but absolute) case (orientation_ID) mySize = 4_pInt - crystallite_postResults(c+1:c+mySize) = crystallite_ori(ipc,ip,el)%asQuaternion() - case (eulerangles_ID) - mySize = 3_pInt - crystallite_postResults(c+1:c+mySize) = inDeg & - * math_qToEuler(crystallite_orientation(1:4,ipc,ip,el)) ! grain orientation as Euler angles in degree + crystallite_postResults(c+1:c+mySize) = crystallite_orientation(ipc,ip,el)%asQuaternion() + case (grainrotation_ID) + rot = crystallite_orientation0(ipc,ip,el)%misorientation(crystallite_orientation(ipc,ip,el)) mySize = 4_pInt - crystallite_postResults(c+1:c+mySize) = & - math_qToEulerAxisAngle(crystallite_rotation(1:4,ipc,ip,el)) ! grain rotation away from initial orientation as axis-angle in sample reference coordinates + crystallite_postResults(c+1:c+mySize) = rot%asAxisAnglePair() crystallite_postResults(c+4) = inDeg * crystallite_postResults(c+4) ! angle in degree ! remark: tensor output is of the form 11,12,13, 21,22,23, 31,32,33 @@ -2222,8 +2207,7 @@ subroutine update_dependentState() do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) do g = 1,homogenization_Ngrains(mesh_element(3,e)) if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) & - call constitutive_dependentState(crystallite_orientation, & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_dependentState(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & g, i, e) enddo; enddo; enddo diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index e1355da8f..112592a8c 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -3005,10 +3005,9 @@ end subroutine plastic_nonlocal_dotState !* that sum up to a total of 1 are considered, all others are set to * !* zero. * !********************************************************************* -subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) - -use math, only: math_mul3x3, & - math_qRot +subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) +use math, only: math_mul3x3, math_qRot +use rotations, only: rotation use material, only: material_phase, & material_texture, & phase_localPlasticity, & @@ -3030,7 +3029,7 @@ implicit none !* input variables integer(pInt), intent(in) :: i, & ! ip index e ! element index -real(pReal), dimension(4,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems), intent(in) :: & +type(rotation), dimension(1,mesh_maxNips,mesh_NcpElems), intent(in) :: & orientation ! crystal orientation in quaternions !* local variables @@ -3059,7 +3058,7 @@ real(pReal) my_compatibilitySum, & nThresholdValues logical, dimension(totalNslip(phase_plasticityInstance(material_phase(1,i,e)))) :: & belowThreshold - +type(rotation) :: rot Nneighbors = FE_NipNeighbors(FE_celltype(FE_geomtype(mesh_element(2,e)))) ph = material_phase(1,i,e) @@ -3129,8 +3128,8 @@ neighbors: do n = 1_pInt,Nneighbors !* Finally the smallest my_compatibility value is decreased until the sum is exactly equal to one. !* All values below the threshold are set to zero. else - absoluteMisorientation = lattice_qDisorientation(orientation(1:4,1,i,e), & - orientation(1:4,1,neighbor_i,neighbor_e)) ! no symmetry + rot = orientation(1,i,e)%misorientation(orientation(1,neighbor_i,neighbor_e)) + absoluteMisorientation = rot%asQuaternion() mySlipSystems: do s1 = 1_pInt,ns neighborSlipSystems: do s2 = 1_pInt,ns my_compatibility(1,s2,s1,n) = math_mul3x3(slipNormal(1:3,s1), math_qRot(absoluteMisorientation, slipNormal(1:3,s2))) & From 5320803842a1f5d4abd99052e872d1c68c8f72e9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 4 Feb 2019 00:06:38 +0100 Subject: [PATCH 21/97] bugfix: valid range for unit quaternion range is [-1,+1] --- src/rotations.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index 59ee3512d..3f06d9a38 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -353,8 +353,6 @@ end function eu2qu !> @brief orientation matrix to Euler angles !--------------------------------------------------------------------------------------------------- pure function om2eu(om) result(eu) - use prec, only: & - dEq use math, only: & PI @@ -363,7 +361,7 @@ pure function om2eu(om) result(eu) real(pReal), dimension(3) :: eu real(pReal) :: zeta - if (dEq(abs(om(3,3)),1.0_pReal,1.0e-15_pReal)) then + if (abs(om(3,3))>1.0_pReal) then eu = [ atan2( om(1,2),om(1,1)), 0.5*PI*(1-om(3,3)),0.0_pReal ] else zeta = 1.0_pReal/sqrt(1.0_pReal-om(3,3)**2.0_pReal) @@ -774,7 +772,7 @@ pure function qu2ax(qu) result(ax) real(pReal) :: omega, s - omega = 2.0 * acos(math_clip(qu%w,0.0_pReal,1.0_pReal)) + omega = 2.0 * acos(math_clip(qu%w,-1.0_pReal,1.0_pReal)) ! if the angle equals zero, then we return the rotation axis as [001] if (dEq0(omega)) then ax = [ 0.0, 0.0, 1.0, 0.0 ] @@ -798,6 +796,8 @@ pure function qu2ro(qu) result(ro) IEEE_positive_inf use prec, only: & dEq0 + use math, only: & + math_clip type(quaternion), intent(in) :: qu real(pReal), dimension(4) :: ro @@ -810,7 +810,7 @@ pure function qu2ro(qu) result(ro) else s = norm2([qu%x,qu%y,qu%z]) ro = merge ( [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal], & - [ qu%x/s, qu%y/s, qu%z/s, tan(acos(qu%w))], & + [ qu%x/s, qu%y/s, qu%z/s, tan(acos(math_clip(qu%w,-1.0_pReal,1.0_pReal))], & s < thr) !ToDo: not save (PGI compiler) end if @@ -833,7 +833,7 @@ pure function qu2ho(qu) result(ho) real(pReal) :: omega, f - omega = 2.0 * acos(math_clip(qu%w,0.0_pReal,1.0_pReal)) + omega = 2.0 * acos(math_clip(qu%w,-1.0_pReal,1.0_pReal)) if (dEq0(omega)) then ho = [ 0.0, 0.0, 0.0 ] From 40740b831e8819dc7c4845f1aeb446a669685e31 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 4 Feb 2019 00:10:49 +0100 Subject: [PATCH 22/97] reverted code removal was not "just commented out" but served as documentation. now easier to see --- python/damask/orientation.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index a1fe1f845..1bc850734 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -574,6 +574,21 @@ class Symmetry: proper considers only vectors with z >= 0, hence uses two neighboring SSTs. Return inverse pole figure color if requested. + Bases are computed from + + 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.)]).T), # direction of blue + 'hexagonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + [1.,0.,0.], # direction of green + [np.sqrt(3.),1.,0.]/np.sqrt(4.)]).T), # direction of blue + 'tetragonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + [1.,0.,0.], # direction of green + [1.,1.,0.]/np.sqrt(2.)]).T), # direction of blue + 'orthorhombic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + [1.,0.,0.], # direction of green + [0.,1.,0.]]).T), # direction of blue + } """ if self.lattice == 'cubic': basis = {'improper':np.array([ [-1. , 0. , 1. ], From 453f4556e5368df0bef909b8c0f6a55e2b212af6 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 4 Feb 2019 00:12:27 +0100 Subject: [PATCH 23/97] bracket was missing --- src/rotations.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index 3f06d9a38..cf6f66af8 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -810,7 +810,7 @@ pure function qu2ro(qu) result(ro) else s = norm2([qu%x,qu%y,qu%z]) ro = merge ( [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal], & - [ qu%x/s, qu%y/s, qu%z/s, tan(acos(math_clip(qu%w,-1.0_pReal,1.0_pReal))], & + [ qu%x/s, qu%y/s, qu%z/s, tan(acos(math_clip(qu%w,-1.0_pReal,1.0_pReal)))], & s < thr) !ToDo: not save (PGI compiler) end if From e931b716fd6347f64161d50704c0c4a8184b8720 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 11 Feb 2019 23:11:11 +0100 Subject: [PATCH 24/97] conversion routines from Marc de Graefs 3D rotation repository Python version available on https://github.com/MarDiehl/3Drotations --- python/damask/Lambert.py | 122 ++++++++++ python/damask/orientation.py | 443 +++++++++++++++++++++++++++++++++++ 2 files changed, 565 insertions(+) create mode 100644 python/damask/Lambert.py diff --git a/python/damask/Lambert.py b/python/damask/Lambert.py new file mode 100644 index 000000000..9972b7965 --- /dev/null +++ b/python/damask/Lambert.py @@ -0,0 +1,122 @@ +#################################################################################################### +# Code below available according to below conditions on https://github.com/MarDiehl/3Drotations +#################################################################################################### +# Copyright (c) 2017-2019, Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +# Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# - Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# - Neither the names of Marc De Graef, Carnegie Mellon University nor the names +# of its contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#################################################################################################### +import numpy as np + +sc = np.pi**(1./6.)/6.**(1./6.) +beta = np.pi**(5./6.)/6.**(1./6.)/2. +R1 = (3.*np.pi/4.)**(1./3.) + +def CubeToBall(cube): + + if np.abs(np.max(cube))>np.pi**(2./3.) * 0.5: + raise ValueError + + # transform to the sphere grid via the curved square, and intercept the zero point + if np.allclose(cube,0.0,rtol=0.0,atol=1.0e-300): + ball = np.zeros(3) + else: + # get pyramide and scale by grid parameter ratio + p = GetPyramidOrder(cube) + XYZ = cube[p] * sc + + # intercept all the points along the z-axis + if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-300): + ball = np.array([0.0, 0.0, np.sqrt(6.0/np.pi) * XYZ[2]]) + else: + order = [1,0] if np.abs(XYZ[1]) <= np.abs(XYZ[0]) else [0,1] + q = np.pi/12.0 * XYZ[order[0]]/XYZ[order[1]] + c = np.cos(q) + s = np.sin(q) + q = R1*2.0**0.25/beta * XYZ[order[1]] / np.sqrt(np.sqrt(2.0)-c) + T = np.array([ (np.sqrt(2.0)*c - 1.0), np.sqrt(2.0) * s]) * q + + # transform to sphere grid (inverse Lambert) + # note that there is no need to worry about dividing by zero, since XYZ[2] can not become zero + c = np.sum(T**2) + s = c * np.pi/24.0 /XYZ[2]**2 + c = c * np.sqrt(np.pi/24.0)/XYZ[2] + q = np.sqrt( 1.0 - s ) + ball = np.array([ T[order[1]] * q, T[order[0]] * q, np.sqrt(6.0/np.pi) * XYZ[2] - c ]) + + # reverse the coordinates back to the regular order according to the original pyramid number + ball = ball[p] + + return ball + + +def BallToCube(ball): + + rs = np.linalg.norm(ball) + if rs > R1: + raise ValueError + + if np.allclose(ball,0.0,rtol=0.0,atol=1.0e-300): + cube = np.zeros(3) + else: + p = GetPyramidOrder(ball) + xyz3 = ball[p] + + # inverse M_3 + xyz2 = xyz3[0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[2])) ) + + # inverse M_2 + qxy = np.sum(xyz2**2) + + if np.isclose(qxy,0.0,rtol=0.0,atol=1.0e-300): + Tinv = np.zeros(2) + else: + q2 = qxy + np.max(np.abs(xyz2))**2 + sq2 = np.sqrt(q2) + q = (beta/np.sqrt(2.0)/R1) * np.sqrt(q2*qxy/(q2-np.max(np.abs(xyz2))*sq2)) + tt = np.clip((np.min(np.abs(xyz2))**2+np.max(np.abs(xyz2))*sq2)/np.sqrt(2.0)/qxy,-1.0,1.0) + Tinv = np.array([1.0,np.arccos(tt)/np.pi*12.0]) if np.abs(xyz2[1]) <= np.abs(xyz2[0]) else \ + np.array([np.arccos(tt)/np.pi*12.0,1.0]) + Tinv = q * np.where(xyz2<0.0,-Tinv,Tinv) + + # inverse M_1 + cube = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /sc + + # reverst the coordinates back to the regular order according to the original pyramid number + cube = cube[p] + + return cube + +def GetPyramidOrder(xyz): + + if (abs(xyz[0])<= xyz[2]) and (abs(xyz[1])<= xyz[2]) or \ + (abs(xyz[0])<=-xyz[2]) and (abs(xyz[1])<=-xyz[2]): + return [0,1,2] + elif (abs(xyz[2])<= xyz[0]) and (abs(xyz[1])<= xyz[0]) or \ + (abs(xyz[2])<=-xyz[0]) and (abs(xyz[1])<=-xyz[0]): + return [1,2,0] + elif (abs(xyz[0])<= xyz[1]) and (abs(xyz[2])<= xyz[1]) or \ + (abs(xyz[0])<=-xyz[1]) and (abs(xyz[2])<=-xyz[1]): + return [2,0,1] diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 1bc850734..73b7620ca 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -6,6 +6,9 @@ import math,os import numpy as np +from . import Lambert + +P = -1 # ****************************************************************************************** class Quaternion: @@ -1093,3 +1096,443 @@ class Orientation: rot=np.dot(otherMatrix,myMatrix.T) return Orientation(matrix=np.dot(rot,self.asMatrix()),symmetry=targetSymmetry) + +#################################################################################################### +# Code below available according to below conditions on https://github.com/MarDiehl/3Drotations +#################################################################################################### +# Copyright (c) 2017-2019, Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +# Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# - Redistributions of source code must retain the above copyright notice, this list +# of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# - Neither the names of Marc De Graef, Carnegie Mellon University nor the names +# of its contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#################################################################################################### + +def isone(a): + return np.isclose(a,1.0,atol=1.0e-15,rtol=0.0) + +def iszero(a): + return np.isclose(a,0.0,atol=1.0e-300,rtol=0.0) + + +def eu2om(eu): + """Euler angles to orientation matrix""" + c = np.cos(eu) + s = np.sin(eu) + + om = np.array([[+c[0]*c[2]-s[0]*s[2]*c[1], +s[0]*c[2]+c[0]*s[2]*c[1], +s[2]*s[1]], + [-c[0]*s[2]-s[0]*c[2]*c[1], -s[0]*s[2]+c[0]*c[2]*c[1], +c[2]*s[1]], + [+s[0]*s[1], -c[0]*s[1], +c[1] ]]) + + om[np.where(iszero(om))] = 0.0 + return om + + +def eu2ax(eu): + """Euler angles to axis angle""" + t = np.tan(eu[1]*0.5) + sigma = 0.5*(eu[0]+eu[2]) + delta = 0.5*(eu[0]-eu[2]) + tau = np.linalg.norm([t,np.sin(sigma)]) + alpha = np.pi if iszero(np.cos(sigma)) else \ + 2.0*np.arctan(tau/np.cos(sigma)) + + if iszero(alpha): + ax = np.array([ 0.0, 0.0, 1.0, 0.0 ]) + else: + ax = -P/tau * np.array([ t*np.cos(delta), t*np.sin(delta), np.sin(sigma) ]) # passive axis-angle pair so a minus sign in front + ax = np.append(ax,alpha) + if alpha < 0.0: ax *= -1.0 # ensure alpha is positive + + return ax + + +def eu2ro(eu): + """Euler angles to Rodrigues vector""" + ro = eu2ax(eu) # convert to axis angle representation + if ro[3] >= np.pi: # Differs from original implementation. check convention 5 + ro[3] = np.inf + elif iszero(ro[3]): + ro = np.array([ 0.0, 0.0, P, 0.0 ]) + else: + ro[3] = np.tan(ro[3]*0.5) + + return ro + + +def eu2qu(eu): + """Euler angles to quaternion""" + ee = 0.5*eu + cPhi = np.cos(ee[1]) + sPhi = np.sin(ee[1]) + qu = np.array([ cPhi*np.cos(ee[0]+ee[2]), + -P*sPhi*np.cos(ee[0]-ee[2]), + -P*sPhi*np.sin(ee[0]-ee[2]), + -P*cPhi*np.sin(ee[0]+ee[2]) ]) + #if qu[0] < 0.0: qu.homomorph() !ToDo: Check with original + return qu + + +def om2eu(om): + """Euler angles to orientation matrix""" + if isone(om[2,2]**2): + eu = np.array([np.arctan2( om[0,1],om[0,0]), np.pi*0.5*(1-om[2,2]),0.0]) # following the paper, not the reference implementation + else: + zeta = 1.0/np.sqrt(1.0-om[2,2]**2) + eu = np.array([np.arctan2(om[2,0]*zeta,-om[2,1]*zeta), + np.arccos(om[2,2]), + np.arctan2(om[0,2]*zeta, om[1,2]*zeta)]) + + # reduce Euler angles to definition range, i.e a lower limit of 0.0 + eu = np.where(eu<0, (eu+2.0*np.pi)%np.array([2.0*np.pi,np.pi,2.0*np.pi]),eu) + return eu + + +def ax2om(ax): + """Axis angle to orientation matrix""" + c = np.cos(ax[3]) + s = np.sin(ax[3]) + omc = 1.0-c + om=np.diag(ax[0:3]**2*omc + c) + + for idx in [[0,1,2],[1,2,0],[2,0,1]]: + q = omc*ax[idx[0]] * ax[idx[1]] + om[idx[0],idx[1]] = q + s*ax[idx[2]] + om[idx[1],idx[0]] = q - s*ax[idx[2]] + + return om if P < 0.0 else om.T + + +def qu2eu(qu): + """Quaternion to Euler angles""" + q03 = qu[0]**2+qu[3]**2 + q12 = qu[1]**2+qu[2]**2 + chi = np.sqrt(q03*q12) + + if iszero(chi): + eu = np.array([np.arctan2(-P*2.0*qu[0]*qu[3],qu[0]**2-qu[3]**2), 0.0, 0.0]) if iszero(q12) else \ + np.array([np.arctan2(2.0*qu[1]*qu[2],qu[1]**2-qu[2]**2), np.pi, 0.0]) + else: + #chiInv = 1.0/chi ToDo: needed for what? + eu = np.array([np.arctan2((-P*qu[0]*qu[2]+qu[1]*qu[3])*chi, (-P*qu[0]*qu[1]-qu[2]*qu[3])*chi ), + np.arctan2( 2.0*chi, q03-q12 ), + np.arctan2(( P*qu[0]*qu[2]+qu[1]*qu[3])*chi, (-P*qu[0]*qu[1]+qu[2]*qu[3])*chi )]) + + # reduce Euler angles to definition range, i.e a lower limit of 0.0 + eu = np.where(eu<0, (eu+2.0*np.pi)%np.array([2.0*np.pi,np.pi,2.0*np.pi]),eu) + return eu + + +def ax2ho(ax): + """Axis angle to homochoric""" + f = (0.75 * ( ax[3] - np.sin(ax[3]) ))**(1.0/3.0) + ho = ax[0:3] * f + return ho + + +def ho2ax(ho): + """Homochoric to axis angle""" + tfit = np.array([+1.0000000000018852, -0.5000000002194847, + -0.024999992127593126, -0.003928701544781374, + -0.0008152701535450438, -0.0002009500426119712, + -0.00002397986776071756, -0.00008202868926605841, + +0.00012448715042090092, -0.0001749114214822577, + +0.0001703481934140054, -0.00012062065004116828, + +0.000059719705868660826, -0.00001980756723965647, + +0.000003953714684212874, -0.00000036555001439719544]) + # normalize h and store the magnitude + hmag_squared = np.sum(ho**2.) + if iszero(hmag_squared): + ax = np.array([ 0.0, 0.0, 1.0, 0.0 ]) + else: + hm = hmag_squared + + # convert the magnitude to the rotation angle + s = tfit[0] + tfit[1] * hmag_squared + for i in range(2,16): + hm *= hmag_squared + s += tfit[i] * hm + ax = np.append(ho/np.sqrt(hmag_squared),2.0*np.arccos(s)) # ToDo: Check sanity check in reference implementation + + return ax + + +def om2ax(om): + """Orientation matrix to axis angle""" + ax=np.empty(4) + + # first get the rotation angle + t = 0.5*(om.trace() -1.0) + ax[3] = np.arccos(np.clip(t,-1.0,1.0)) + + if iszero(ax[3]): + ax = [ 0.0, 0.0, 1.0, 0.0] + else: + w,vr = np.linalg.eig(om) + # next, find the eigenvalue (1,0j) + i = np.where(np.isclose(w,1.0+0.0j))[0][0] + ax[0:3] = np.real(vr[0:3,i]) + diagDelta = np.array([om[1,2]-om[2,1],om[2,0]-om[0,2],om[0,1]-om[1,0]]) + ax[0:3] = np.where(iszero(diagDelta), ax[0:3],np.abs(ax[0:3])*np.sign(-P*diagDelta)) + + return np.array(ax) + + +def ro2ax(ro): + """Rodrigues vector to axis angle""" + ta = ro[3] + + if iszero(ta): + ax = [ 0.0, 0.0, 1.0, 0.0 ] + elif not np.isfinite(ta): + ax = [ ro[0], ro[1], ro[2], np.pi ] + else: + angle = 2.0*np.arctan(ta) + ta = 1.0/np.linalg.norm(ro[0:3]) + ax = [ ro[0]/ta, ro[1]/ta, ro[2]/ta, angle ] + + return np.array(ax) + + +def ax2ro(ax): + """Axis angle to Rodrigues vector""" + if iszero(ax[3]): + ro = [ 0.0, 0.0, P, 0.0 ] + else: + ro = [ax[0], ax[1], ax[2]] + # 180 degree case + ro += [np.inf] if np.isclose(ax[3],np.pi,atol=1.0e-15,rtol=0.0) else \ + [np.tan(ax[3]*0.5)] + + return np.array(ro) + + +def ax2qu(ax): + """Axis angle to quaternion""" + if iszero(ax[3]): + qu = np.array([ 1.0, 0.0, 0.0, 0.0 ]) + else: + c = np.cos(ax[3]*0.5) + s = np.sin(ax[3]*0.5) + qu = np.array([ c, ax[0]*s, ax[1]*s, ax[2]*s ]) + + return qu + + +def ro2ho(ro): + """Rodrigues vector to homochoric""" + if iszero(np.sum(ro[0:3]**2.0)): + ho = [ 0.0, 0.0, 0.0 ] + else: + f = 2.0*np.arctan(ro[3]) -np.sin(2.0*np.arctan(ro[3])) if np.isfinite(ro[3]) else np.pi + ho = ro[0:3] * (0.75*f)**(1.0/3.0) + + return np.array(ho) + + +def qu2om(qu): + """Quaternion to orientation matrix""" + qq = qu[0]**2-(qu[1]**2 + qu[2]**2 + qu[3]**2) + om = np.diag(qq + 2.0*np.array([qu[1],qu[2],qu[3]])**2) + + om[1,0] = 2.0*(qu[2]*qu[1]+qu[0]*qu[3]) + om[0,1] = 2.0*(qu[1]*qu[2]-qu[0]*qu[3]) + om[2,1] = 2.0*(qu[3]*qu[2]+qu[0]*qu[1]) + om[1,2] = 2.0*(qu[2]*qu[3]-qu[0]*qu[1]) + om[0,2] = 2.0*(qu[1]*qu[3]+qu[0]*qu[2]) + om[2,0] = 2.0*(qu[3]*qu[1]-qu[0]*qu[2]) + return om if P > 0.0 else om.T + + +def om2qu(om): + """Orientation matrix to quaternion""" + s = [+om[0,0] +om[1,1] +om[2,2] +1.0, + +om[0,0] -om[1,1] -om[2,2] +1.0, + -om[0,0] +om[1,1] -om[2,2] +1.0, + -om[0,0] -om[1,1] +om[2,2] +1.0] + s = np.maximum(np.zeros(4),s) + qu = np.sqrt(s)*0.5*np.array([1.0,P,P,P]) + # verify the signs (q0 always positive) + #ToDo: Here I donot understand the original shortcut from paper to implementation + + qu /= np.linalg.norm(qu) + if any(isone(abs(qu))): qu[np.where(np.logical_not(isone(qu)))] = 0.0 + if om[2,1] < om[1,2]: qu[1] *= -1.0 + if om[0,2] < om[2,0]: qu[2] *= -1.0 + if om[1,0] < om[0,1]: qu[3] *= -1.0 + if any(om2ax(om)[0:3]*qu[1:4] < 0.0): print(om2ax(om),qu) # something is wrong here + return qu + +def qu2ax(qu): + """Quaternion to axis angle""" + omega = 2.0 * np.arccos(qu[0]) + if iszero(omega): # return axis as [001] if the angle is zero + ax = [ 0.0, 0.0, 1.0, 0.0 ] + elif not iszero(qu[0]): + s = np.sign(qu[0])/np.sqrt(qu[1]**2+qu[2]**2+qu[3]**2) + ax = [ qu[1]*s, qu[2]*s, qu[3]*s, omega ] + else: + ax = [ qu[1], qu[2], qu[3], np.pi] + + return np.array(ax) + + +def qu2ro(qu): + """Quaternion to Rodrigues vector""" + if iszero(qu[0]): + ro = [qu[1], qu[2], qu[3], np.inf] + else: + s = np.linalg.norm([qu[1],qu[2],qu[3]]) + ro = [0.0,0.0,P,0.0] if iszero(s) else \ + [ qu[1]/s, qu[2]/s, qu[3]/s, np.tan(np.arccos(qu[0]))] + + return np.array(ro) + + +def qu2ho(qu): + """Quaternion to homochoric""" + omega = 2.0 * np.arccos(qu[0]) + + if iszero(omega): + ho = np.array([ 0.0, 0.0, 0.0 ]) + else: + ho = np.array([qu[1], qu[2], qu[3]]) + f = 0.75 * ( omega - np.sin(omega) ) + ho = ho/np.linalg.norm(ho) * f**(1./3.) + + return ho + + +def ho2cu(ho): + """Homochoric to cubochoric""" + return Lambert.BallToCube(ho) + + +def cu2ho(cu): + """Cubochoric to homochoric""" + return Lambert.CubeToBall(cu) + + +def ro2eu(ro): + """Rodrigues vector to orientation matrix""" + return om2eu(ro2om(ro)) + + +def eu2ho(eu): + """Euler angles to homochoric""" + return ax2ho(eu2ax(eu)) + + +def om2ro(om): + """Orientation matrix to Rodriques vector""" + return eu2ro(om2eu(om)) + + +def om2ho(om): + """Orientation matrix to homochoric""" + return ax2ho(om2ax(om)) + + +def ax2eu(ax): + """Orientation matrix to Euler angles""" + return om2eu(ax2om(ax)) + + +def ro2om(ro): + """Rodgrigues vector to orientation matrix""" + return ax2om(ro2ax(ro)) + + +def ro2qu(ro): + """Rodrigues vector to quaternion""" + return ax2qu(ro2ax(ro)) + + +def ho2eu(ho): + """Homochoric to Euler angles""" + return ax2eu(ho2ax(ho)) + + +def ho2om(ho): + """Homochoric to orientation matrix""" + return ax2om(ho2ax(ho)) + + +def ho2ro(ho): + """Axis angle to Rodriques vector""" + return ax2ro(ho2ax(ho)) + + +def ho2qu(ho): + """Homochoric to quaternion""" + return ax2qu(ho2ax(ho)) + + +def eu2cu(eu): + """Euler angles to cubochoric""" + return ho2cu(eu2ho(eu)) + + +def om2cu(om): + """Orientation matrix to cubochoric""" + return ho2cu(om2ho(om)) + + +def ax2cu(ax): + """Axis angle to cubochoric""" + return ho2cu(ax2ho(ax)) + + +def ro2cu(ro): + """Rodrigues vector to cubochoric""" + return ho2cu(ro2ho(ro)) + + +def qu2cu(qu): + """Quaternion to cubochoric""" + return ho2cu(qu2ho(qu)) + + +def cu2eu(cu): + """Cubochoric to Euler angles""" + return ho2eu(cu2ho(cu)) + + +def cu2om(cu): + """Cubochoric to orientation matrix""" + return ho2om(cu2ho(cu)) + + +def cu2ax(cu): + """Cubochoric to axis angle""" + return ho2ax(cu2ho(cu)) + + +def cu2ro(cu): + """Cubochoric to Rodrigues vector""" + return ho2ro(cu2ho(cu)) + + +def cu2qu(cu): + """Cubochoric to quaternion""" + return ho2qu(cu2ho(cu)) From 7ee933b79d7749a393083455ee72ea841fbd3895 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 11 Feb 2019 23:50:02 +0100 Subject: [PATCH 25/97] Rotation class uses (and hides) Quaternion2. Should replace Quaternion class. Orientation class should inherit from Rotation and adds symmetry. --- python/damask/__init__.py | 2 +- python/damask/orientation.py | 345 +++++++++++++++++++++++++++++++++++ 2 files changed, 346 insertions(+), 1 deletion(-) diff --git a/python/damask/__init__.py b/python/damask/__init__.py index c8981069d..a9209a1c6 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -13,7 +13,7 @@ from .asciitable import ASCIItable # noqa from .config import Material # noqa from .colormaps import Colormap, Color # noqa -from .orientation import Quaternion, Symmetry, Orientation # noqa +from .orientation import Quaternion, Symmetry, Rotation, Orientation # noqa #from .block import Block # only one class from .result import Result # noqa diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 73b7620ca..9a92c77d4 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -10,6 +10,350 @@ from . import Lambert P = -1 +#################################################################################################### +class Quaternion2: + u""" + Quaternion with basic operations + + q is the real part, p = (x, y, z) are the imaginary parts. + Defintion of multiplication depends on variable P, P ∉ {-1,1}. + """ + + def __init__(self, + q = 0.0, + p = np.zeros(3,dtype=float)): + """Initializes to identity unless specified""" + self.q = q + self.p = np.array(p) + + + def __copy__(self): + """Copy""" + return self.__class__(q=self.q, + p=self.p.copy()) + + copy = __copy__ + + + def __iter__(self): + """Components""" + return iter(self.asList()) + + def asArray(self): + """As numpy array""" + return np.array((self.q,self.p[0],self.p[1],self.p[2])) + + def asList(self): + return [self.q]+list(self.p) + + + def __repr__(self): + """Readable string""" + return 'Quaternion(real={q:+.6f}, imag=<{p[0]:+.6f}, {p[1]:+.6f}, {p[2]:+.6f}>)'.format(q=self.q,p=self.p) + + + def __add__(self, other): + """Addition""" + if isinstance(other, Quaternion2): + return self.__class__(q=self.q + other.q, + p=self.p + other.p) + else: + return NotImplemented + + def __iadd__(self, other): + """In-place addition""" + if isinstance(other, Quaternion2): + self.q += other.q + self.p += other.p + return self + else: + return NotImplemented + + def __pos__(self): + """Unary positive operator""" + return self + + + def __sub__(self, other): + """Subtraction""" + if isinstance(other, Quaternion2): + return self.__class__(q=self.q - other.q, + p=self.p - other.p) + else: + return NotImplemented + + def __isub__(self, other): + """In-place subtraction""" + if isinstance(other, Quaternion2): + self.q -= other.q + self.p -= other.p + return self + else: + return NotImplemented + + def __neg__(self): + """Unary positive operator""" + self.q *= -1.0 + self.p *= -1.0 + return self + + + def __mul__(self, other): + """Multiplication with quaternion or scalar""" + if isinstance(other, Quaternion2): + return self.__class__(q=self.q*other.q - np.dot(self.p,other.p), + p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)) + elif isinstance(other, (int, float)): + return self.__class__(q=self.q*other, + p=self.p*other) + else: + return NotImplemented + + def __imul__(self, other): + """In-place multiplication with quaternion or scalar""" + if isinstance(other, Quaternion2): + self.q = self.q*other.q - np.dot(self.p,other.p) + self.p = self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p) + return self + elif isinstance(other, (int, float)): + self *= other + return self + else: + return NotImplemented + + + def __truediv__(self, other): + """Divsion with quaternion or scalar""" + if isinstance(other, Quaternion2): + s = other.conjugate()/abs(other)**2. + return self.__class__(q=self.q * s, + p=self.p * s) + elif isinstance(other, (int, float)): + self.q /= other + self.p /= other + return self + else: + return NotImplemented + + def __itruediv__(self, other): + """In-place divsion with quaternion or scalar""" + if isinstance(other, Quaternion2): + s = other.conjugate()/abs(other)**2. + self *= s + return self + elif isinstance(other, (int, float)): + self.q /= other + return self + else: + return NotImplemented + + + def __pow__(self, exponent): + """Power""" + if isinstance(exponent, (int, float)): + omega = np.acos(self.q) + return self.__class__(q= np.cos(exponent*omega), + p=self.p * np.sin(exponent*omega)/np.sin(omega)) + else: + return NotImplemented + + def __ipow__(self, exponent): + """In-place power""" + if isinstance(exponent, (int, float)): + omega = np.acos(self.q) + self.q = np.cos(exponent*omega) + self.p *= np.sin(exponent*omega)/np.sin(omega) + else: + return NotImplemented + + + def __abs__(self): + """Norm""" + return math.sqrt(self.q ** 2 + np.dot(self.p,self.p)) + + magnitude = __abs__ + + + def __eq__(self,other): + """Equal (sufficiently close) to each other""" + return np.isclose(( self-other).magnitude(),0.0) \ + or np.isclose((-self-other).magnitude(),0.0) + + def __ne__(self,other): + """Not equal (sufficiently close) to each other""" + return not self.__eq__(other) + + + def normalize(self): + d = self.magnitude() + if d > 0.0: + self.q /= d + self.p /= d + return self + + def normalized(self): + return self.copy().normalize() + + + def conjugate(self): + self.p = -self.p + return self + + def conjugated(self): + return self.copy().conjugate() + + + def homomorph(self): + if self.q < 0.0: + self.q = -self.q + self.p = -self.p + return self + + def homomorphed(self): + return self.copy().homomorph() + + + +#################################################################################################### +class Rotation: + u""" + Orientation stored as unit quaternion. + + All methods and naming conventions based on Rowenhorst_etal2015 + Convention 1: coordinate frames are right-handed + Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation + when viewing from the end point of the rotation axis towards the origin + Convention 3: rotations will be interpreted in the passive sense + Convention 4: Euler angle triplets are implemented using the Bunge convention, + with the angular ranges as [0, 2π],[0, π],[0, 2π] + Convention 5: the rotation angle ω is limited to the interval [0, π] + Convention 6: P = -1 (as default) + + q is the real part, p = (x, y, z) are the imaginary parts. + + Vector "a" (defined in coordinate system "A") is passively rotated + resulting in new coordinates "b" when expressed in system "B". + b = Q * a + b = np.dot(Q.asMatrix(),a) + ToDo: Denfine how to 3x3 and 3x3x3x3 matrices + """ + + __slots__ = ['quaternion'] + + def __init__(self,quaternion = np.array([1.0,0.0,0.0,0.0])): + """Initializes to identity unless specified""" + self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4]) + self.quaternion.homomorph() # ToDo: Needed? + + def __repr__(self): + """Value in selected representation""" + return '\n'.join([ + 'Quaternion: {}'.format(self.quaternion), + 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ), + 'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ), + ]) + + + def asQuaternion(self): + return self.quaternion.asArray() + + def asEulers(self, + degrees = False): + return np.degrees(qu2eu(self.quaternion.asArray())) if degrees else qu2eu(self.quaternion.asArray()) + + def asAngleAxis(self, + degrees = False): + + ax = qu2ax(self.quaternion.asArray()) + if degrees: ax[0] = np.degrees(ax[0]) + + return ax + + def asMatrix(self): + return qu2om(self.quaternion.asArray()) + + def asRodrigues(self): + return qu2ro(self.quaternion.asArray()) + + def asHomochoric(self): + return qu2ho(self.quaternion.asArray()) + + def asCubochoric(self): + return qu2cu(self.quaternion.asArray()) + + + + @classmethod + def fromQuaternion(cls, + quaternion, + P = -1): + + qu = quaternion + if P > 0: qu[1:3] *= -1 # convert from P=1 to P=-1 + if qu[0] < 0.0: + raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0])) + if not np.isclose(np.linalg.norm(qu), 1.0): + raise ValueError('Quaternion is not of unit length.\n{} {} {} {}'.format(*qu)) + + return cls(qu) + + @classmethod + def fromEulers(cls, + eulers, + degrees = False): + + eu = np.radians(eulers) if degrees else eulers + if np.any(eu < 0.0) or np.any(eu > 2.0*np.pi) or eu[1] > np.pi: + raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eu)) + + return cls(eu2qu(eu)) + + @classmethod + def fromAngleAxis(cls, + angleAxis, + degrees = False, + P = -1): + + ax = angleAxis + if P > 0: ax[1:3] *= -1 # convert from P=1 to P=-1 + if degrees: ax[0] = np.degrees(ax[0]) + if ax[0] < 0.0 or ax[0] > np.pi: + raise ValueError('Axis angle rotation angle outside of [0..π].\n'.format(ax[0])) + if not np.isclose(np.linalg.norm(ax[1:3]), 1.0): + raise ValueError('Axis angle rotation axis is not of unit length.\n{} {} {}'.format(*ax[1:3])) + + return cls(ax2qu(ax)) + + @classmethod + def fromMatrix(cls, + matrix): + + om = matrix + if not np.isclose(np.linalg.det(om),1.0): + raise ValueError('matrix is not a proper rotation.\n{}'.format(om)) + if not np.isclose(np.dot(om[0],om[1]), 0.0) \ + or not np.isclose(np.dot(om[1],om[2]), 0.0) \ + or not np.isclose(np.dot(om[2],om[0]), 0.0): + raise ValueError('matrix is not orthogonal.\n{}'.format(om)) + + return cls(om2qu(om)) + + @classmethod + def fromRodrigues(cls, + rodrigues, + P = -1): + + ro = rodrigues + if P > 0: ro[1:3] *= -1 # convert from P=1 to P=-1 + if not np.isclose(np.linalg.norm(ro[1:3]), 1.0): + raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[1:3])) + if ro[0] < 0.0: + raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[0])) + + return cls(ro2qu(ro)) + + + # ****************************************************************************************** class Quaternion: u""" @@ -1383,6 +1727,7 @@ def om2qu(om): if any(om2ax(om)[0:3]*qu[1:4] < 0.0): print(om2ax(om),qu) # something is wrong here return qu + def qu2ax(qu): """Quaternion to axis angle""" omega = 2.0 * np.arccos(qu[0]) From 48b0307fab9c932b7925bd3fa852dca67bdf1092 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 00:11:22 +0100 Subject: [PATCH 26/97] using new rotation class cannot rotate matrices (3,3) and (3,3,3,3) at the moment --- processing/post/addOrientations.py | 47 +++++++---------------------- processing/pre/geom_addPrimitive.py | 11 +++---- python/damask/orientation.py | 32 ++++++++++++++++++-- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index a33f96b91..ec824c88c 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -9,31 +9,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -# -------------------------------------------------------------------- -# convention conformity checks -# -------------------------------------------------------------------- - -def check_Eulers(eulers): - if np.any(eulers < 0.0) or np.any(eulers > 2.0*np.pi) or eulers[1] > np.pi: # Euler angles within valid range? - raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eulers)) - return eulers - -def check_quaternion(q): - if q[0] < 0.0: # positive first quaternion component? - raise ValueError('quaternion has negative first component.\n{}'.format(q[0])) - if not np.isclose(np.linalg.norm(q), 1.0): # unit quaternion? - raise ValueError('quaternion is not of unit length.\n{} {} {} {}'.format(*q)) - return q - -def check_matrix(M): - if not np.isclose(np.linalg.det(M),1.0): # proper rotation? - raise ValueError('matrix is not a proper rotation.\n{}'.format(M)) - if not np.isclose(np.dot(M[0],M[1]), 0.0) \ - or not np.isclose(np.dot(M[1],M[2]), 0.0) \ - or not np.isclose(np.dot(M[2],M[0]), 0.0): # all orthogonal? - raise ValueError('matrix is not orthogonal.\n{}'.format(M)) - return M - # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- @@ -133,9 +108,8 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') (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 -r = damask.Quaternion.fromAngleAxis(toRadians*options.crystalrotation[0],options.crystalrotation[1:]) # crystal frame rotation -R = damask.Quaternion.fromAngleAxis(toRadians*options. labrotation[0],options. labrotation[1:]) # lab frame rotation +r = damask.Rotation.fromAngleAxis(np.array(options.crystalrotation),options.degrees) # crystal frame rotation +R = damask.Rotation.fromAngleAxis(np.array(options.labrotation),options.degrees) # lab frame rotation # --- loop over input files ------------------------------------------------------------------------ @@ -179,23 +153,24 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table if inputtype == 'eulers': + o = damask.Rotation.fromEulers(np.array(list(map(float,table.data[column:column+3]))),options.degrees) - o = damask.Orientation(Eulers = check_Eulers(np.array(list(map(float,table.data[column:column+3])))*toRadians)) elif inputtype == 'rodrigues': - o = damask.Orientation(Rodrigues = np.array(list(map(float,table.data[column:column+3])))) - elif inputtype == 'matrix': + o = damask.Rotation.fromRodrigues(np.array(list(map(float,table.data[column:column+3])))) - o = damask.Orientation(matrix = check_matrix(np.array(list(map(float,table.data[column:column+9]))).reshape(3,3))) + elif inputtype == 'matrix': + o = damask.Rotation.fromMatrix(np.array(list(map(float,table.data[column:column+9]))).reshape(3,3)) + elif inputtype == 'frame': M = np.array(list(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).T - o = damask.Orientation(matrix = check_matrix(M/np.linalg.norm(M,axis=0))) - elif inputtype == 'quaternion': + o = damask.Rotation.fromMatrix(M/np.linalg.norm(M,axis=0)) - o = damask.Orientation(quaternion = check_quaternion(np.array(list(map(float,table.data[column:column+4]))))) + elif inputtype == 'quaternion': + o = damask.Rotation.fromQuaternion(np.array(list(map(float,table.data[column:column+4])))) - o.quaternion = r*o.quaternion*R # apply additional lab and crystal frame rotations + o= r*o*R # apply additional lab and crystal frame rotations for output in options.output: if output == 'quaternion': table.data_append(o.asQuaternion()) diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 54de558f7..08281bd5c 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -43,7 +43,7 @@ parser.add_option('-f', '--fill', dest='fill', type='int', metavar = 'int' help='grain index to fill primitive. "0" selects maximum microstructure index + 1 [%default]') parser.add_option('-q', '--quaternion', dest='quaternion', type='float', nargs = 4, metavar=' '.join(['float']*4), help = 'rotation of primitive as quaternion') -parser.add_option('-a', '--angleaxis', dest='angleaxis', nargs = 4, metavar=' '.join(['float']*4), +parser.add_option('-a', '--angleaxis', dest='angleaxis', nargs = 4, metavar=' '.join(['float']*4), type=float, help = 'angle,x,y,z clockwise rotation of primitive about axis by angle') parser.add_option( '--degrees', dest='degrees', action='store_true', help = 'angle is given in degrees [%default]') @@ -63,14 +63,11 @@ parser.set_defaults(center = (.0,.0,.0), if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: - options.angleaxis = list(map(float,options.angleaxis)) - rotation = damask.Quaternion.fromAngleAxis(np.radians(options.angleaxis[0]) if options.degrees else options.angleaxis[0], - options.angleaxis[1:4]) + rotation = damask.Rotation.fromAngleAxis(np.array(options.angleaxis),options.degrees) elif options.quaternion is not None: - options.quaternion = list(map(float,options.quaternion)) - rotation = damask.Quaternion(quat=options.quaternion) + rotation = damask.Rotation.fromQuaternion(np.array(options.quaternion)) else: - rotation = damask.Quaternion() + rotation = damask.Rotation() options.center = np.array(options.center) options.dimension = np.array(options.dimension) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 9a92c77d4..bba13eb8a 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -235,7 +235,6 @@ class Rotation: resulting in new coordinates "b" when expressed in system "B". b = Q * a b = np.dot(Q.asMatrix(),a) - ToDo: Denfine how to 3x3 and 3x3x3x3 matrices """ __slots__ = ['quaternion'] @@ -351,9 +350,38 @@ class Rotation: raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[0])) return cls(ro2qu(ro)) - + def __mul__(self, other): + """ + Multiplication + + Rotation: Details needed (active/passive), more cases (3,3), (3,3,3,3) need to be considered + """ + if isinstance(other, Rotation): + return self.__class__((self.quaternion * other.quaternion).asArray()) + elif isinstance(other, np.ndarray): + if other.shape == (3,): + ( x, y, z) = self.quaternion.p + (Vx,Vy,Vz) = other[0:3] + A = self.quaternion.q*self.quaternion.q - np.dot(self.quaternion.p,self.quaternion.p) + B = 2.0 * (x*Vx + y*Vy + z*Vz) + C = 2.0 * P*self.quaternion.q + + return np.array([ + A*Vx + B*x + C*(y*Vz - z*Vy), + A*Vy + B*y + C*(z*Vx - x*Vz), + A*Vz + B*z + C*(x*Vy - y*Vx), + ]) + elif other.shape == (3,3,): + raise NotImplementedError + elif other.shape == (3,3,3,3): + raise NotImplementedError + else: + return NotImplemented + else: + return NotImplemented + # ****************************************************************************************** class Quaternion: u""" From e47c275e0c8af0ff5e0307430d558e740adb7c24 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 06:18:21 +0100 Subject: [PATCH 27/97] unknown encoding caused problem (on python2?) --- python/damask/Lambert.py | 9 ++++++--- python/damask/orientation.py | 8 ++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/python/damask/Lambert.py b/python/damask/Lambert.py index 9972b7965..5d07f73f4 100644 --- a/python/damask/Lambert.py +++ b/python/damask/Lambert.py @@ -1,7 +1,9 @@ +# -*- coding: UTF-8 no BOM -*- + #################################################################################################### -# Code below available according to below conditions on https://github.com/MarDiehl/3Drotations +# Code below available according to the followin conditions on https://github.com/MarDiehl/3Drotations #################################################################################################### -# Copyright (c) 2017-2019, Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +# Copyright (c) 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH # Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University # All rights reserved. # @@ -28,6 +30,7 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #################################################################################################### + import numpy as np sc = np.pi**(1./6.)/6.**(1./6.) @@ -104,7 +107,7 @@ def BallToCube(ball): # inverse M_1 cube = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /sc - # reverst the coordinates back to the regular order according to the original pyramid number + # reverse the coordinates back to the regular order according to the original pyramid number cube = cube[p] return cube diff --git a/python/damask/orientation.py b/python/damask/orientation.py index bba13eb8a..5316b2026 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -1,9 +1,5 @@ # -*- coding: UTF-8 no BOM -*- -################################################### -# NOTE: everything here needs to be a np array # -################################################### - import math,os import numpy as np from . import Lambert @@ -1470,9 +1466,9 @@ class Orientation: return Orientation(matrix=np.dot(rot,self.asMatrix()),symmetry=targetSymmetry) #################################################################################################### -# Code below available according to below conditions on https://github.com/MarDiehl/3Drotations +# Code below available according to the followin conditions on https://github.com/MarDiehl/3Drotations #################################################################################################### -# Copyright (c) 2017-2019, Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +# Copyright (c) 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH # Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University # All rights reserved. # From 4215ae3888582d70eedc5707375158b202d08ecb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 06:32:26 +0100 Subject: [PATCH 28/97] rotation of matrix is defined in class --- python/damask/orientation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 5316b2026..cb3b61ee2 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -45,7 +45,7 @@ class Quaternion2: def __repr__(self): """Readable string""" - return 'Quaternion(real={q:+.6f}, imag=<{p[0]:+.6f}, {p[1]:+.6f}, {p[2]:+.6f}>)'.format(q=self.q,p=self.p) + return 'Quaternion: (real={q:+.6f}, imag=<{p[0]:+.6f}, {p[1]:+.6f}, {p[2]:+.6f}>)'.format(q=self.q,p=self.p) def __add__(self, other): @@ -243,7 +243,7 @@ class Rotation: def __repr__(self): """Value in selected representation""" return '\n'.join([ - 'Quaternion: {}'.format(self.quaternion), + '{}'.format(self.quaternion), 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ), 'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ), ]) @@ -370,7 +370,7 @@ class Rotation: A*Vz + B*z + C*(x*Vy - y*Vx), ]) elif other.shape == (3,3,): - raise NotImplementedError + return np.dot(self.asMatrix(),np.dot(other,self.asMatrix().T)) elif other.shape == (3,3,3,3): raise NotImplementedError else: From ef3fc0b58ad32eea2fc0c8dbffaf99070f129c1d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 07:42:46 +0100 Subject: [PATCH 29/97] bugfix: wrong array indexing rotation of meshgrid tuple implemented --- processing/post/rotateData.py | 11 +++---- processing/pre/geom_addPrimitive.py | 5 ++- python/damask/orientation.py | 49 ++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 95102345b..3712b8c73 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -40,9 +40,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.), if options.data is None: parser.error('no data column specified.') -toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale degrees to radians -q = damask.Quaternion().fromAngleAxis(toRadians*options.rotation[0],options.rotation[1:]) -R = q.asMatrix() +r = damask.Rotation.fromAngleAxis(options.rotation,degrees) # --- loop over input files ------------------------------------------------------------------------- @@ -90,12 +88,11 @@ for name in filenames: while outputAlive and table.data_read(): # read next data line of ASCII table for v in active['vector']: column = table.label_index(v) - table.data[column:column+3] = q * np.array(list(map(float,table.data[column:column+3]))) + table.data[column:column+3] = r * np.array(list(map(float,table.data[column:column+3]))) for t in active['tensor']: column = table.label_index(t) - table.data[column:column+9] = \ - np.dot(R,np.dot(np.array(list(map(float,table.data[column:column+9]))).reshape((3,3)), - R.transpose())).reshape((9)) + table.data[column:column+9] = (r * (np.array(list(map(float,table.data[column:column+9]))))).reshape((3,3)) + outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 08281bd5c..f93cdd54f 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -63,7 +63,7 @@ parser.set_defaults(center = (.0,.0,.0), if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: - rotation = damask.Rotation.fromAngleAxis(np.array(options.angleaxis),options.degrees) + rotation = damask.Rotation.fromAngleAxis(np.array(options.angleaxis),options.degrees,normalise=True) elif options.quaternion is not None: rotation = damask.Rotation.fromQuaternion(np.array(options.quaternion)) else: @@ -156,8 +156,7 @@ for name in filenames: X -= options.center[0] - 0.5 Y -= options.center[1] - 0.5 Z -= options.center[2] - 0.5 - # and then by applying the quaternion - # this should be rotation.conjugate() * (X,Y,Z), but it is this way for backwards compatibility with the older version of this script + # and then by applying the rotation (X, Y, Z) = rotation * (X, Y, Z) # and finally by scaling (we don't worry about options.dimension being negative, np.abs occurs on the microstructure = np.where... line) X /= options.dimension[0] * 0.5 diff --git a/python/damask/orientation.py b/python/damask/orientation.py index cb3b61ee2..54482332b 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -284,7 +284,7 @@ class Rotation: P = -1): qu = quaternion - if P > 0: qu[1:3] *= -1 # convert from P=1 to P=-1 + if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1 if qu[0] < 0.0: raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0])) if not np.isclose(np.linalg.norm(qu), 1.0): @@ -307,15 +307,17 @@ class Rotation: def fromAngleAxis(cls, angleAxis, degrees = False, + normalise = False, P = -1): ax = angleAxis - if P > 0: ax[1:3] *= -1 # convert from P=1 to P=-1 - if degrees: ax[0] = np.degrees(ax[0]) + if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1 + if degrees: ax[0] = np.degrees(ax[0]) + if normalise: ax[1:4] /=np.linalg.norm(ax[1:4]) if ax[0] < 0.0 or ax[0] > np.pi: raise ValueError('Axis angle rotation angle outside of [0..π].\n'.format(ax[0])) - if not np.isclose(np.linalg.norm(ax[1:3]), 1.0): - raise ValueError('Axis angle rotation axis is not of unit length.\n{} {} {}'.format(*ax[1:3])) + if not np.isclose(np.linalg.norm(ax[1:4]), 1.0): + raise ValueError('Axis angle rotation axis is not of unit length.\n{} {} {}'.format(*ax[1:4])) return cls(ax2qu(ax)) @@ -336,12 +338,14 @@ class Rotation: @classmethod def fromRodrigues(cls, rodrigues, + normalise = False, P = -1): ro = rodrigues - if P > 0: ro[1:3] *= -1 # convert from P=1 to P=-1 - if not np.isclose(np.linalg.norm(ro[1:3]), 1.0): - raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[1:3])) + if P > 0: ro[1:4] *= -1 # convert from P=1 to P=-1 + if normalise: ro[1:4] /=np.linalg.norm(ro[1:4]) + if not np.isclose(np.linalg.norm(ro[1:4]), 1.0): + raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[1:4])) if ro[0] < 0.0: raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[0])) @@ -354,10 +358,10 @@ class Rotation: Rotation: Details needed (active/passive), more cases (3,3), (3,3,3,3) need to be considered """ - if isinstance(other, Rotation): + if isinstance(other, Rotation): # rotate a rotation return self.__class__((self.quaternion * other.quaternion).asArray()) elif isinstance(other, np.ndarray): - if other.shape == (3,): + if other.shape == (3,): # rotate a single (3)-vector ( x, y, z) = self.quaternion.p (Vx,Vy,Vz) = other[0:3] A = self.quaternion.q*self.quaternion.q - np.dot(self.quaternion.p,self.quaternion.p) @@ -369,14 +373,37 @@ class Rotation: A*Vy + B*y + C*(z*Vx - x*Vz), A*Vz + B*z + C*(x*Vy - y*Vx), ]) - elif other.shape == (3,3,): + elif other.shape == (3,3,): # rotate a single (3x3)-matrix return np.dot(self.asMatrix(),np.dot(other,self.asMatrix().T)) elif other.shape == (3,3,3,3): raise NotImplementedError else: return NotImplemented + elif isinstance(other, tuple): # used to rotate a meshgrid-tuple + ( x, y, z) = self.quaternion.p + (Vx,Vy,Vz) = other[0:3] + A = self.quaternion.q*self.quaternion.q - np.dot(self.quaternion.p,self.quaternion.p) + B = 2.0 * (x*Vx + y*Vy + z*Vz) + C = 2.0 * P*self.quaternion.q + + return np.array([ + A*Vx + B*x + C*(y*Vz - z*Vy), + A*Vy + B*y + C*(z*Vx - x*Vz), + A*Vz + B*z + C*(x*Vy - y*Vx), + ]) else: return NotImplemented + + + def inverse(self): + """Inverse rotation/backward rotation""" + self.quaternion.conjugate() + return self + + def inversed(self): + """In-place inverse rotation/backward rotation""" + return self.__class__(self.quaternion.conjugated().asArray()) + # ****************************************************************************************** class Quaternion: From 97ac4376865b9f8061b1a5345b5955c646e44a35 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 07:55:54 +0100 Subject: [PATCH 30/97] more user friendly constructors --- PRIVATE | 2 +- processing/post/addOrientations.py | 16 +++++------ processing/post/rotateData.py | 8 +++--- processing/pre/geom_addPrimitive.py | 4 +-- python/damask/orientation.py | 44 +++++++++++++++++++---------- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/PRIVATE b/PRIVATE index 25006bc97..406d482f8 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 25006bc974b752faf3464b082511590d50093c37 +Subproject commit 406d482f8059b4459634af729ce85491a9a3245c diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index ec824c88c..65444bcb9 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -79,8 +79,8 @@ parser.add_option('-z', help = 'label of lab z vector (expressed in crystal coords)') parser.set_defaults(output = [], - labrotation = (0.,1.,1.,1.), # no rotation about 1,1,1 - crystalrotation = (0.,1.,1.,1.), # no rotation about 1,1,1 + labrotation = (0.,1.,0.,0.), # no rotation about 1,0,0 + crystalrotation = (0.,1.,0.,0.), # no rotation about 1,0,0 degrees = False, ) @@ -108,8 +108,8 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') (options.quaternion,4,'quaternion'), ][np.where(input)[0][0]] # select input label that was requested -r = damask.Rotation.fromAngleAxis(np.array(options.crystalrotation),options.degrees) # crystal frame rotation -R = damask.Rotation.fromAngleAxis(np.array(options.labrotation),options.degrees) # lab frame rotation +r = damask.Rotation.fromAngleAxis(options.crystalrotation,options.degrees) # crystal frame rotation +R = damask.Rotation.fromAngleAxis(options.labrotation,options.degrees) # lab frame rotation # --- loop over input files ------------------------------------------------------------------------ @@ -153,13 +153,13 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table if inputtype == 'eulers': - o = damask.Rotation.fromEulers(np.array(list(map(float,table.data[column:column+3]))),options.degrees) + o = damask.Rotation.fromEulers(list(map(float,table.data[column:column+3])),options.degrees) elif inputtype == 'rodrigues': - o = damask.Rotation.fromRodrigues(np.array(list(map(float,table.data[column:column+3])))) + o = damask.Rotation.fromRodrigues(list(map(float,table.data[column:column+3]))) elif inputtype == 'matrix': - o = damask.Rotation.fromMatrix(np.array(list(map(float,table.data[column:column+9]))).reshape(3,3)) + o = damask.Rotation.fromMatrix(list(map(float,table.data[column:column+9])).reshape(3,3)) elif inputtype == 'frame': M = np.array(list(map(float,table.data[column[0]:column[0]+3] + \ @@ -168,7 +168,7 @@ for name in filenames: o = damask.Rotation.fromMatrix(M/np.linalg.norm(M,axis=0)) elif inputtype == 'quaternion': - o = damask.Rotation.fromQuaternion(np.array(list(map(float,table.data[column:column+4])))) + o = damask.Rotation.fromQuaternion(list(map(float,table.data[column:column+4]))) o= r*o*R # apply additional lab and crystal frame rotations diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 3712b8c73..293f0f0b8 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: UTF-8 no BOM -*- -import os,sys,math +import os,sys import numpy as np from optparse import OptionParser import damask @@ -29,9 +29,9 @@ parser.add_option('-r', '--rotation', parser.add_option('--degrees', dest = 'degrees', action = 'store_true', - help = 'angles are given in degrees [%default]') + help = 'angle is given in degrees [%default]') -parser.set_defaults(rotation = (0.,1.,1.,1.), # no rotation about 1,1,1 +parser.set_defaults(rotation = (0.,1.,0.,0.), # no rotation about 1,0,0 degrees = False, ) @@ -40,7 +40,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.), if options.data is None: parser.error('no data column specified.') -r = damask.Rotation.fromAngleAxis(options.rotation,degrees) +r = damask.Rotation.fromAngleAxis(options.rotation,options.degrees,normalise=True) # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index f93cdd54f..e0d1094cf 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -63,9 +63,9 @@ parser.set_defaults(center = (.0,.0,.0), if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: - rotation = damask.Rotation.fromAngleAxis(np.array(options.angleaxis),options.degrees,normalise=True) + rotation = damask.Rotation.fromAngleAxis(options.angleaxis,options.degrees,normalise=True) elif options.quaternion is not None: - rotation = damask.Rotation.fromQuaternion(np.array(options.quaternion)) + rotation = damask.Rotation.fromQuaternion(options.quaternion) else: rotation = damask.Rotation() diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 54482332b..e53915b13 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -236,7 +236,12 @@ class Rotation: __slots__ = ['quaternion'] def __init__(self,quaternion = np.array([1.0,0.0,0.0,0.0])): - """Initializes to identity unless specified""" + """ + Initializes to identity unless specified + + If a quaternion is given, it needs to comply with the convection. Use .fromQuaternion + to check the input. + """ self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4]) self.quaternion.homomorph() # ToDo: Needed? @@ -247,7 +252,9 @@ class Rotation: 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ), 'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ), ]) - + + ################################################################################################ + # convert to different orientation representations (numpy arrays) def asQuaternion(self): return self.quaternion.asArray() @@ -276,14 +283,16 @@ class Rotation: def asCubochoric(self): return qu2cu(self.quaternion.asArray()) - - + + ################################################################################################ + # static constructors. The input data needs to follow the convention, options allow to + # relax these convections @classmethod def fromQuaternion(cls, - quaternion, - P = -1): + quaternion, + P = -1): - qu = quaternion + qu = quaternion if isinstance(quaternion, np.ndarray) else np.array(quaternion) if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1 if qu[0] < 0.0: raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0])) @@ -296,8 +305,9 @@ class Rotation: def fromEulers(cls, eulers, degrees = False): - - eu = np.radians(eulers) if degrees else eulers + + eu = eulers if isinstance(eulers, np.ndarray) else np.array(eulers) + eu = np.radians(eu) if degrees else eu if np.any(eu < 0.0) or np.any(eu > 2.0*np.pi) or eu[1] > np.pi: raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eu)) @@ -309,8 +319,8 @@ class Rotation: degrees = False, normalise = False, P = -1): - - ax = angleAxis + + ax = angleAxis if isinstance(angleAxis, np.ndarray) else np.array(angleAxis) if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1 if degrees: ax[0] = np.degrees(ax[0]) if normalise: ax[1:4] /=np.linalg.norm(ax[1:4]) @@ -323,9 +333,13 @@ class Rotation: @classmethod def fromMatrix(cls, - matrix): + matrix, + containsStretch = False): #ToDo: better name? - om = matrix + om = matrix if isinstance(matrix, np.ndarray) else np.array(matrix) + if containsStretch: + (U,S,Vh) = np.linalg.svd(om) # singular value decomposition + om = np.dot(U,Vh) if not np.isclose(np.linalg.det(om),1.0): raise ValueError('matrix is not a proper rotation.\n{}'.format(om)) if not np.isclose(np.dot(om[0],om[1]), 0.0) \ @@ -341,7 +355,7 @@ class Rotation: normalise = False, P = -1): - ro = rodrigues + ro = rodrigues if isinstance(rodrigues, np.ndarray) else np.array(rodrigues) if P > 0: ro[1:4] *= -1 # convert from P=1 to P=-1 if normalise: ro[1:4] /=np.linalg.norm(ro[1:4]) if not np.isclose(np.linalg.norm(ro[1:4]), 1.0): @@ -356,7 +370,7 @@ class Rotation: """ Multiplication - Rotation: Details needed (active/passive), more cases (3,3), (3,3,3,3) need to be considered + Rotation: Details needed (active/passive), more rotation of (3,3,3,3) should be considered """ if isinstance(other, Rotation): # rotate a rotation return self.__class__((self.quaternion * other.quaternion).asArray()) From 336a80091fc4fd6fc6fa5857541429a49a4aa79d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 08:58:23 +0100 Subject: [PATCH 31/97] rodrigues is 4-vector with rotation being the last component established a single source of truth for length --- processing/post/addOrientations.py | 42 ++++++++++++++++-------------- python/damask/orientation.py | 14 +++++----- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 65444bcb9..8353e0403 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -21,19 +21,19 @@ Additional (globally fixed) rotations of the lab frame and/or crystal frame can """, version = scriptID) -outputChoices = { - 'quaternion': ['quat',4], - 'rodrigues': ['rodr',3], +representations = { + 'quaternion': ['quat',4], #ToDo: Use here Rowenhorst names (qu/ro/om/ax?) + 'rodrigues': ['rodr',4], 'eulers': ['eulr',3], 'matrix': ['mtrx',9], 'angleaxis': ['aaxs',4], - } + } parser.add_option('-o', '--output', dest = 'output', action = 'extend', metavar = '', - help = 'output orientation formats {{{}}}'.format(', '.join(outputChoices))) + help = 'output orientation formats {{{}}}'.format(', '.join(representations))) parser.add_option('-d', '--degrees', dest = 'degrees', @@ -87,8 +87,8 @@ parser.set_defaults(output = [], (options, filenames) = parser.parse_args() options.output = list(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))) +if options.output == [] or (not set(options.output).issubset(set(representations))): + parser.error('output must be chosen from {}.'.format(', '.join(representations))) input = [options.eulers is not None, options.rodrigues is not None, @@ -101,11 +101,11 @@ input = [options.eulers is not None, if np.sum(input) != 1: parser.error('needs exactly one input format.') -(label,dim,inputtype) = [(options.eulers,3,'eulers'), - (options.rodrigues,3,'rodrigues'), +(label,dim,inputtype) = [(options.eulers,representations['eulers'][1],'eulers'), + (options.rodrigues,representations['rodrigues'][1],'rodrigues'), ([options.x,options.y,options.z],[3,3,3],'frame'), - (options.matrix,9,'matrix'), - (options.quaternion,4,'quaternion'), + (options.matrix,representations['matrix'][1],'matrix'), + (options.quaternion,representations['quaternion'][1],'quaternion'), ][np.where(input)[0][0]] # select input label that was requested r = damask.Rotation.fromAngleAxis(options.crystalrotation,options.degrees) # crystal frame rotation @@ -143,9 +143,9 @@ for name in filenames: table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) for output in options.output: - if output in outputChoices: - table.labels_append(['{}_{}({})'.format(i+1,outputChoices[output][0],label) \ - for i in range(outputChoices[output][1])]) + if output in representations: + table.labels_append(['{}_{}({})'.format(i+1,representations[output][0],label) \ + for i in range(representations[output][1])]) table.head_write() # ------------------------------------------ process data ------------------------------------------ @@ -153,13 +153,16 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table if inputtype == 'eulers': - o = damask.Rotation.fromEulers(list(map(float,table.data[column:column+3])),options.degrees) + l = representations['eulers'][1] + o = damask.Rotation.fromEulers(list(map(float,table.data[column:column+l])),options.degrees) elif inputtype == 'rodrigues': - o = damask.Rotation.fromRodrigues(list(map(float,table.data[column:column+3]))) + l = representations['rodrigues'][1] + o = damask.Rotation.fromRodrigues(list(map(float,table.data[column:column+l]))) elif inputtype == 'matrix': - o = damask.Rotation.fromMatrix(list(map(float,table.data[column:column+9])).reshape(3,3)) + l = representations['matrix'][1] + o = damask.Rotation.fromMatrix(list(map(float,table.data[column:column+l]))) elif inputtype == 'frame': M = np.array(list(map(float,table.data[column[0]:column[0]+3] + \ @@ -168,7 +171,8 @@ for name in filenames: o = damask.Rotation.fromMatrix(M/np.linalg.norm(M,axis=0)) elif inputtype == 'quaternion': - o = damask.Rotation.fromQuaternion(list(map(float,table.data[column:column+4]))) + l = representations['quaternion'][1] + o = damask.Rotation.fromQuaternion(list(map(float,table.data[column:column+l]))) o= r*o*R # apply additional lab and crystal frame rotations @@ -177,7 +181,7 @@ for name in filenames: elif output == 'rodrigues': table.data_append(o.asRodrigues()) elif output == 'eulers': table.data_append(o.asEulers(degrees=options.degrees)) elif output == 'matrix': table.data_append(o.asMatrix()) - elif output == 'angleaxis': table.data_append(o.asAngleAxis(degrees=options.degrees,flat=True)) + elif output == 'angleaxis': table.data_append(o.asAngleAxis(degrees=options.degrees)) outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- diff --git a/python/damask/orientation.py b/python/damask/orientation.py index e53915b13..6f1b12671 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -336,7 +336,7 @@ class Rotation: matrix, containsStretch = False): #ToDo: better name? - om = matrix if isinstance(matrix, np.ndarray) else np.array(matrix) + om = matrix if isinstance(matrix, np.ndarray) else np.array(matrix).reshape((3,3)) # ToDo: Reshape here or require explicit? if containsStretch: (U,S,Vh) = np.linalg.svd(om) # singular value decomposition om = np.dot(U,Vh) @@ -356,12 +356,12 @@ class Rotation: P = -1): ro = rodrigues if isinstance(rodrigues, np.ndarray) else np.array(rodrigues) - if P > 0: ro[1:4] *= -1 # convert from P=1 to P=-1 - if normalise: ro[1:4] /=np.linalg.norm(ro[1:4]) - if not np.isclose(np.linalg.norm(ro[1:4]), 1.0): - raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[1:4])) - if ro[0] < 0.0: - raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[0])) + if P > 0: ro[0:3] *= -1 # convert from P=1 to P=-1 + if normalise: ro[0:3] /=np.linalg.norm(ro[0:3]) + if not np.isclose(np.linalg.norm(ro[0:3]), 1.0): + raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[0:3])) + if ro[3] < 0.0: + raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[3])) return cls(ro2qu(ro)) From 7da8980cc04ed0e5e641cd1feebff4c5c8188b1f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 09:04:35 +0100 Subject: [PATCH 32/97] bugfixes: wrong shape, wrong conversion --- processing/post/addSchmidfactors.py | 6 +++--- processing/post/rotateData.py | 2 +- python/damask/orientation.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 6335b419e..37dd56512 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -212,10 +212,10 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table - o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4])))) + o = damask.Rotation(list(map(float,table.data[column:column+4]))) - table.data_append( np.abs( np.sum(slip_direction * (o.quaternion * force) ,axis=1) \ - * np.sum(slip_normal * (o.quaternion * normal),axis=1))) + table.data_append( np.abs( np.sum(slip_direction * (o * force) ,axis=1) \ + * np.sum(slip_normal * (o * normal),axis=1))) outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 293f0f0b8..1aafe7eb9 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -91,7 +91,7 @@ for name in filenames: table.data[column:column+3] = r * np.array(list(map(float,table.data[column:column+3]))) for t in active['tensor']: column = table.label_index(t) - table.data[column:column+9] = (r * (np.array(list(map(float,table.data[column:column+9]))))).reshape((3,3)) + table.data[column:column+9] = (r * np.array(list(map(float,table.data[column:column+9]))).reshape((3,3))).reshape(9) outputAlive = table.data_write() # output processed line diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 6f1b12671..85f3fb173 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -322,7 +322,7 @@ class Rotation: ax = angleAxis if isinstance(angleAxis, np.ndarray) else np.array(angleAxis) if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1 - if degrees: ax[0] = np.degrees(ax[0]) + if degrees: ax[0] = np.radians(ax[0]) if normalise: ax[1:4] /=np.linalg.norm(ax[1:4]) if ax[0] < 0.0 or ax[0] > np.pi: raise ValueError('Axis angle rotation angle outside of [0..π].\n'.format(ax[0])) From 608852df839498244e3591ef9170d260f2948b95 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 10:53:28 +0100 Subject: [PATCH 33/97] rotation paper has angle as last component --- processing/post/addOrientations.py | 7 +++++-- processing/post/rotateData.py | 3 ++- processing/pre/geom_addPrimitive.py | 3 ++- python/damask/orientation.py | 16 ++++++++-------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 8353e0403..c25bfed39 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -108,8 +108,11 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') (options.quaternion,representations['quaternion'][1],'quaternion'), ][np.where(input)[0][0]] # select input label that was requested -r = damask.Rotation.fromAngleAxis(options.crystalrotation,options.degrees) # crystal frame rotation -R = damask.Rotation.fromAngleAxis(options.labrotation,options.degrees) # lab frame rotation +crystalrotation = np.array(options.crystalrotation[1:4] + (options.crystalrotation[0],)) # Compatibility hack +labrotation = np.array(options.labrotation[1:4], + (options.labrotation[0],)) # Compatibility hack +r = damask.Rotation.fromAngleAxis(crystalrotation,options.degrees) # crystal frame rotation +R = damask.Rotation.fromAngleAxis(labrotation,options.degrees) # lab frame rotation + # --- loop over input files ------------------------------------------------------------------------ diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 1aafe7eb9..5be38f1e8 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -40,7 +40,8 @@ parser.set_defaults(rotation = (0.,1.,0.,0.), if options.data is None: parser.error('no data column specified.') -r = damask.Rotation.fromAngleAxis(options.rotation,options.degrees,normalise=True) +rotation = np.array(options.rotation[1:4]+(options.rotation[0],)) # Compatibility hack +r = damask.Rotation.fromAngleAxis(rotation,options.degrees,normalise=True) # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index e0d1094cf..8e512c44d 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -63,7 +63,8 @@ parser.set_defaults(center = (.0,.0,.0), if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: - rotation = damask.Rotation.fromAngleAxis(options.angleaxis,options.degrees,normalise=True) + ax = np.array(options.angleaxis[1:4] + (options.angleaxis[0],)) # Compatibility hack + rotation = damask.Rotation.fromAngleAxis(ax,options.degrees,normalise=True) elif options.quaternion is not None: rotation = damask.Rotation.fromQuaternion(options.quaternion) else: diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 85f3fb173..442a98f6e 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -267,7 +267,7 @@ class Rotation: degrees = False): ax = qu2ax(self.quaternion.asArray()) - if degrees: ax[0] = np.degrees(ax[0]) + if degrees: ax[3] = np.degrees(ax[3]) return ax @@ -321,13 +321,13 @@ class Rotation: P = -1): ax = angleAxis if isinstance(angleAxis, np.ndarray) else np.array(angleAxis) - if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1 - if degrees: ax[0] = np.radians(ax[0]) - if normalise: ax[1:4] /=np.linalg.norm(ax[1:4]) - if ax[0] < 0.0 or ax[0] > np.pi: - raise ValueError('Axis angle rotation angle outside of [0..π].\n'.format(ax[0])) - if not np.isclose(np.linalg.norm(ax[1:4]), 1.0): - raise ValueError('Axis angle rotation axis is not of unit length.\n{} {} {}'.format(*ax[1:4])) + if P > 0: ax[0:3] *= -1 # convert from P=1 to P=-1 + if degrees: ax[3] = np.radians(ax[3]) + if normalise: ax[0:3] /=np.linalg.norm(ax[0:3]) + if ax[3] < 0.0 or ax[3] > np.pi: + raise ValueError('Axis angle rotation angle outside of [0..π].\n'.format(ax[3])) + if not np.isclose(np.linalg.norm(ax[0:3]), 1.0): + raise ValueError('Axis angle rotation axis is not of unit length.\n{} {} {}'.format(*ax[0:3])) return cls(ax2qu(ax)) From 217024667b65c86d1063537350f1b7e41398b879 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 12 Feb 2019 11:30:43 +0100 Subject: [PATCH 34/97] forgotten comma --- processing/post/addOrientations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index c25bfed39..c9db1cbd7 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -109,7 +109,7 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') ][np.where(input)[0][0]] # select input label that was requested crystalrotation = np.array(options.crystalrotation[1:4] + (options.crystalrotation[0],)) # Compatibility hack -labrotation = np.array(options.labrotation[1:4], + (options.labrotation[0],)) # Compatibility hack +labrotation = np.array(options.labrotation[1:4] + (options.labrotation[0],)) # Compatibility hack r = damask.Rotation.fromAngleAxis(crystalrotation,options.degrees) # crystal frame rotation R = damask.Rotation.fromAngleAxis(labrotation,options.degrees) # lab frame rotation From 1567b0ee94ea840987e856e69347618cab0437c3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 15 Feb 2019 07:03:52 +0100 Subject: [PATCH 35/97] was not used --- src/plastic_nonlocal.f90 | 361 +-------------------------------------- 1 file changed, 5 insertions(+), 356 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index cba989cb5..ccb38d0c9 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -43,8 +43,8 @@ module plastic_nonlocal integer(pInt), dimension(:), allocatable, public, protected :: & plastic_nonlocal_sizeDotState, & !< number of dotStates = number of basic state variables plastic_nonlocal_sizeDependentState, & !< number of dependent state variables - plastic_nonlocal_sizeState, & !< total number of state variables - plastic_nonlocal_sizePostResults !< cumulative size of post results + plastic_nonlocal_sizeState !< total number of state variables + integer(pInt), dimension(:,:), allocatable, target, public :: & plastic_nonlocal_sizePostResult !< size of each post result output @@ -204,8 +204,7 @@ module plastic_nonlocal plastic_nonlocal_postResults private :: & - plastic_nonlocal_kinetics, & - plastic_nonlocal_dislocationstress + plastic_nonlocal_kinetics contains @@ -298,7 +297,6 @@ integer(pInt) :: phase, & allocate(plastic_nonlocal_sizeDotState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizeDependentState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizeState(maxNinstances), source=0_pInt) -allocate(plastic_nonlocal_sizePostResults(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) allocate(plastic_nonlocal_Noutput(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) @@ -924,12 +922,11 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), if (mySize > 0_pInt) then ! any meaningful output found plastic_nonlocal_sizePostResult(o,instance) = mySize - plastic_nonlocal_sizePostResults(instance) = plastic_nonlocal_sizePostResults(instance) + mySize endif enddo outputsLoop - plasticState(phase)%sizePostResults = plastic_nonlocal_sizePostResults(instance) + plasticState(phase)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) plasticState(phase)%nonlocal = .true. call material_allocatePlasticState(phase,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & totalNslip(instance),0_pInt,0_pInt) @@ -2785,353 +2782,6 @@ compatibility(1:2,1:ns,1:ns,1:Nneighbors,i,e) = my_compatibility end subroutine plastic_nonlocal_updateCompatibility -!********************************************************************* -!* calculates quantities characterizing the microstructure * -!********************************************************************* -function plastic_nonlocal_dislocationstress(Fe, ip, el) -use prec, only: & - dEq0 -use math, only: math_mul33x33, & - math_mul33x3, & - math_inv33, & - math_transpose33, & - pi -use mesh, only: mesh_NcpElems, & - mesh_maxNips, & - mesh_element, & - mesh_node0, & - mesh_cellCenterCoordinates, & - mesh_ipVolume, & - mesh_periodicSurface, & - FE_Nips, & - FE_geomtype -use material, only: homogenization_maxNgrains, & - material_phase, & - plasticState, & - phaseAt, phasememberAt,& - phase_localPlasticity, & - phase_plasticityInstance -use lattice, only: lattice_mu, & - lattice_nu - -implicit none - -!*** input variables -integer(pInt), intent(in) :: ip, & !< current integration point - el !< current element -real(pReal), dimension(3,3,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems), intent(in) :: & - Fe !< elastic deformation gradient - -!*** output variables -real(pReal), dimension(3,3) :: plastic_nonlocal_dislocationstress - -!*** local variables -integer(pInt) neighbor_el, & !< element number of neighbor material point - neighbor_ip, & !< integration point of neighbor material point - instance, & !< my instance of this plasticity - neighbor_instance, & !< instance of this plasticity of neighbor material point - ph, & - neighbor_phase, & - ns, & !< total number of active slip systems at my material point - neighbor_ns, & !< total number of active slip systems at neighbor material point - c, & !< index of dilsocation character (edge, screw) - s, & !< slip system index - o,& !< offset shortcut - no,& !< neighbour offset shortcut - p,& !< phase shortcut - np,& !< neighbour phase shortcut - t, & !< index of dilsocation type (e+, e-, s+, s-, used e+, used e-, used s+, used s-) - dir, & - deltaX, deltaY, deltaZ, & - side, & - j -integer(pInt), dimension(2,3) :: periodicImages -real(pReal) x, y, z, & !< coordinates of connection vector in neighbor lattice frame - xsquare, ysquare, zsquare, & !< squares of respective coordinates - distance, & !< length of connection vector - segmentLength, & !< segment length of dislocations - lambda, & - R, Rsquare, Rcube, & - denominator, & - flipSign, & - neighbor_ipVolumeSideLength -real(pReal), dimension(3) :: connection, & !< connection vector between me and my neighbor in the deformed configuration - connection_neighborLattice, & !< connection vector between me and my neighbor in the lattice configuration of my neighbor - connection_neighborSlip, & !< connection vector between me and my neighbor in the slip system frame of my neighbor - maxCoord, minCoord, & - meshSize, & - coords, & !< x,y,z coordinates of cell center of ip volume - neighbor_coords !< x,y,z coordinates of cell center of neighbor ip volume -real(pReal), dimension(3,3) :: sigma, & !< dislocation stress for one slip system in neighbor material point's slip system frame - Tdislo_neighborLattice, & !< dislocation stress as 2nd Piola-Kirchhoff stress at neighbor material point - invFe, & !< inverse of my elastic deformation gradient - neighbor_invFe, & - neighborLattice2myLattice !< mapping from neighbor MPs lattice configuration to my lattice configuration -real(pReal), dimension(2,2,maxval(totalNslip)) :: & - neighbor_rhoExcess !< excess density at neighbor material point (edge/screw,mobile/dead,slipsystem) -real(pReal), dimension(2,maxval(totalNslip)) :: & - rhoExcessDead -real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),8) :: & - rhoSgl ! single dislocation density (edge+, edge-, screw+, screw-, used edge+, used edge-, used screw+, used screw-) - -ph = material_phase(1_pInt,ip,el) -instance = phase_plasticityInstance(ph) -ns = totalNslip(instance) -p = phaseAt(1,ip,el) -o = phasememberAt(1,ip,el) - -!*** get basic states - -forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) - rhoSgl(s,t) = max(plasticState(p)%state(iRhoU(s,t,instance),o), 0.0_pReal) ! ensure positive single mobile densities - rhoSgl(s,t+4_pInt) = plasticState(p)%state(iRhoB(s,t,instance),o) -endforall - - - -!*** calculate the dislocation stress of the neighboring excess dislocation densities -!*** zero for material points of local plasticity - -plastic_nonlocal_dislocationstress = 0.0_pReal - -if (.not. phase_localPlasticity(ph)) then - invFe = math_inv33(Fe(1:3,1:3,1_pInt,ip,el)) - - !* in case of periodic surfaces we have to find out how many periodic images in each direction we need - - do dir = 1_pInt,3_pInt - maxCoord(dir) = maxval(mesh_node0(dir,:)) - minCoord(dir) = minval(mesh_node0(dir,:)) - enddo - meshSize = maxCoord - minCoord - coords = mesh_cellCenterCoordinates(ip,el) - periodicImages = 0_pInt - do dir = 1_pInt,3_pInt - if (mesh_periodicSurface(dir)) then - periodicImages(1,dir) = floor((coords(dir) - cutoffRadius(instance) - minCoord(dir)) / meshSize(dir), pInt) - periodicImages(2,dir) = ceiling((coords(dir) + cutoffRadius(instance) - maxCoord(dir)) / meshSize(dir), pInt) - endif - enddo - - - !* loop through all material points (also through their periodic images if present), - !* but only consider nonlocal neighbors within a certain cutoff radius R - - do neighbor_el = 1_pInt,mesh_NcpElems - ipLoop: do neighbor_ip = 1_pInt,FE_Nips(FE_geomtype(mesh_element(2,neighbor_el))) - neighbor_phase = material_phase(1_pInt,neighbor_ip,neighbor_el) - np = phaseAt(1,neighbor_ip,neighbor_el) - no = phasememberAt(1,neighbor_ip,neighbor_el) - - if (phase_localPlasticity(neighbor_phase)) cycle - neighbor_instance = phase_plasticityInstance(neighbor_phase) - neighbor_ns = totalNslip(neighbor_instance) - neighbor_invFe = math_inv33(Fe(1:3,1:3,1,neighbor_ip,neighbor_el)) - neighbor_ipVolumeSideLength = mesh_ipVolume(neighbor_ip,neighbor_el) ** (1.0_pReal/3.0_pReal) ! reference volume used here - - forall (s = 1_pInt:neighbor_ns, c = 1_pInt:2_pInt) - neighbor_rhoExcess(c,1,s) = plasticState(np)%state(iRhoU(s,2*c-1,neighbor_instance),no) & ! positive mobiles - - plasticState(np)%state(iRhoU(s,2*c,neighbor_instance),no) ! negative mobiles - neighbor_rhoExcess(c,2,s) = abs(plasticState(np)%state(iRhoB(s,2*c-1,neighbor_instance),no)) & ! positive deads - - abs(plasticState(np)%state(iRhoB(s,2*c,neighbor_instance),no)) ! negative deads - - endforall - Tdislo_neighborLattice = 0.0_pReal - do deltaX = periodicImages(1,1),periodicImages(2,1) - do deltaY = periodicImages(1,2),periodicImages(2,2) - do deltaZ = periodicImages(1,3),periodicImages(2,3) - - - !* regular case - - if (neighbor_el /= el .or. neighbor_ip /= ip & - .or. deltaX /= 0_pInt .or. deltaY /= 0_pInt .or. deltaZ /= 0_pInt) then - - neighbor_coords = mesh_cellCenterCoordinates(neighbor_ip,neighbor_el) & - + [real(deltaX,pReal), real(deltaY,pReal), real(deltaZ,pReal)] * meshSize - connection = neighbor_coords - coords - distance = sqrt(sum(connection * connection)) - if (distance > cutoffRadius(instance)) cycle - - - !* the segment length is the minimum of the third root of the control volume and the ip distance - !* this ensures, that the central MP never sits on a neighbor dislocation segment - - connection_neighborLattice = math_mul33x3(neighbor_invFe, connection) - segmentLength = min(neighbor_ipVolumeSideLength, distance) - - - !* loop through all slip systems of the neighbor material point - !* and add up the stress contributions from egde and screw excess on these slip systems (if significant) - - do s = 1_pInt,neighbor_ns - if (all(abs(neighbor_rhoExcess(:,:,s)) < significantRho(instance))) cycle ! not significant - - - !* map the connection vector from the lattice into the slip system frame - - connection_neighborSlip = math_mul33x3(lattice2slip(1:3,1:3,s,neighbor_instance), & - connection_neighborLattice) - - - !* edge contribution to stress - sigma = 0.0_pReal - - x = connection_neighborSlip(1) - y = connection_neighborSlip(2) - z = connection_neighborSlip(3) - xsquare = x * x - ysquare = y * y - zsquare = z * z - - do j = 1_pInt,2_pInt - if (abs(neighbor_rhoExcess(1,j,s)) < significantRho(instance)) then - cycle - elseif (j > 1_pInt) then - x = connection_neighborSlip(1) & - + sign(0.5_pReal * segmentLength, & - plasticState(np)%state(iRhoB(s,1,neighbor_instance),no) & - - plasticState(np)%state(iRhoB(s,2,neighbor_instance),no)) - - xsquare = x * x - endif - - flipSign = sign(1.0_pReal, -y) - do side = 1_pInt,-1_pInt,-2_pInt - lambda = real(side,pReal) * 0.5_pReal * segmentLength - y - R = sqrt(xsquare + zsquare + lambda * lambda) - Rsquare = R * R - Rcube = Rsquare * R - denominator = R * (R + flipSign * lambda) - if (dEq0(denominator)) exit ipLoop - - sigma(1,1) = sigma(1,1) - real(side,pReal) & - * flipSign * z / denominator & - * (1.0_pReal + xsquare / Rsquare + xsquare / denominator) & - * neighbor_rhoExcess(1,j,s) - sigma(2,2) = sigma(2,2) - real(side,pReal) & - * (flipSign * 2.0_pReal * lattice_nu(ph) * z / denominator + z * lambda / Rcube) & - * neighbor_rhoExcess(1,j,s) - sigma(3,3) = sigma(3,3) + real(side,pReal) & - * flipSign * z / denominator & - * (1.0_pReal - zsquare / Rsquare - zsquare / denominator) & - * neighbor_rhoExcess(1,j,s) - sigma(1,2) = sigma(1,2) + real(side,pReal) & - * x * z / Rcube * neighbor_rhoExcess(1,j,s) - sigma(1,3) = sigma(1,3) + real(side,pReal) & - * flipSign * x / denominator & - * (1.0_pReal - zsquare / Rsquare - zsquare / denominator) & - * neighbor_rhoExcess(1,j,s) - sigma(2,3) = sigma(2,3) - real(side,pReal) & - * (lattice_nu(ph) / R - zsquare / Rcube) * neighbor_rhoExcess(1,j,s) - enddo - enddo - - !* screw contribution to stress - - x = connection_neighborSlip(1) ! have to restore this value, because position might have been adapted for edge deads before - do j = 1_pInt,2_pInt - if (abs(neighbor_rhoExcess(2,j,s)) < significantRho(instance)) then - cycle - elseif (j > 1_pInt) then - y = connection_neighborSlip(2) & - + sign(0.5_pReal * segmentLength, & - plasticState(np)%state(iRhoB(s,3,neighbor_instance),no) & - - plasticState(np)%state(iRhoB(s,4,neighbor_instance),no)) - ysquare = y * y - endif - - flipSign = sign(1.0_pReal, x) - do side = 1_pInt,-1_pInt,-2_pInt - lambda = x + real(side,pReal) * 0.5_pReal * segmentLength - R = sqrt(ysquare + zsquare + lambda * lambda) - Rsquare = R * R - Rcube = Rsquare * R - denominator = R * (R + flipSign * lambda) - if (dEq0(denominator)) exit ipLoop - - sigma(1,2) = sigma(1,2) - real(side,pReal) * flipSign * z & - * (1.0_pReal - lattice_nu(ph)) / denominator & - * neighbor_rhoExcess(2,j,s) - sigma(1,3) = sigma(1,3) + real(side,pReal) * flipSign * y & - * (1.0_pReal - lattice_nu(ph)) / denominator & - * neighbor_rhoExcess(2,j,s) - enddo - enddo - - if (all(abs(sigma) < 1.0e-10_pReal)) cycle ! SIGMA IS NOT A REAL STRESS, THATS WHY WE NEED A REALLY SMALL VALUE HERE - - !* copy symmetric parts - - sigma(2,1) = sigma(1,2) - sigma(3,1) = sigma(1,3) - sigma(3,2) = sigma(2,3) - - - !* scale stresses and map them into the neighbor material point's lattice configuration - - sigma = sigma * lattice_mu(neighbor_phase) * burgers(s,neighbor_instance) & - / (4.0_pReal * pi * (1.0_pReal - lattice_nu(neighbor_phase))) & - * mesh_ipVolume(neighbor_ip,neighbor_el) / segmentLength ! reference volume is used here (according to the segment length calculation) - Tdislo_neighborLattice = Tdislo_neighborLattice & - + math_mul33x33(math_transpose33(lattice2slip(1:3,1:3,s,neighbor_instance)), & - math_mul33x33(sigma, lattice2slip(1:3,1:3,s,neighbor_instance))) - - enddo ! slip system loop - - - !* special case of central ip volume - !* only consider dead dislocations - !* we assume that they all sit at a distance equal to half the third root of V - !* in direction of the according slip direction - - else - - forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) & - - rhoExcessDead(c,s) = plasticState(p)%state(iRhoB(s,2*c-1,instance),o) & ! positive deads (here we use symmetry: if this has negative sign it is - !treated as negative density at positive position instead of positive - !density at negative position) - + plasticState(p)%state(iRhoB(s,2*c,instance),o) ! negative deads (here we use symmetry: if this has negative sign it is - !treated as positive density at positive position instead of negative - !density at negative position) - do s = 1_pInt,ns - if (all(abs(rhoExcessDead(:,s)) < significantRho(instance))) cycle ! not significant - sigma = 0.0_pReal ! all components except for sigma13 are zero - sigma(1,3) = - (rhoExcessDead(1,s) + rhoExcessDead(2,s) * (1.0_pReal - lattice_nu(ph))) & - * neighbor_ipVolumeSideLength * lattice_mu(ph) * burgers(s,instance) & - / (sqrt(2.0_pReal) * pi * (1.0_pReal - lattice_nu(ph))) - sigma(3,1) = sigma(1,3) - - Tdislo_neighborLattice = Tdislo_neighborLattice & - + math_mul33x33(math_transpose33(lattice2slip(1:3,1:3,s,instance)), & - math_mul33x33(sigma, lattice2slip(1:3,1:3,s,instance))) - - enddo ! slip system loop - - endif - - enddo ! deltaZ loop - enddo ! deltaY loop - enddo ! deltaX loop - - - !* map the stress from the neighbor MP's lattice configuration into the deformed configuration - !* and back into my lattice configuration - - neighborLattice2myLattice = math_mul33x33(invFe, Fe(1:3,1:3,1,neighbor_ip,neighbor_el)) - plastic_nonlocal_dislocationstress = plastic_nonlocal_dislocationstress & - + math_mul33x33(neighborLattice2myLattice, & - math_mul33x33(Tdislo_neighborLattice, & - math_transpose33(neighborLattice2myLattice))) - - enddo ipLoop - enddo ! element loop - -endif - -end function plastic_nonlocal_dislocationstress - !-------------------------------------------------------------------------------------------------- !> @brief return array of constitutive results @@ -3170,8 +2820,7 @@ function plastic_nonlocal_postResults(Tstar_v,Fe,ip,el) ip, & !< integration point el !< element - real(pReal), dimension(plastic_nonlocal_sizePostResults(& - phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & + real(pReal), dimension(sum(plastic_nonlocal_sizePostResult(:,phase_plasticityInstance(material_phase(1_pInt,ip,el))))) :: & plastic_nonlocal_postResults integer(pInt) :: & From d78bf18483e3ba2b91fa6d0ebd83e46f1c0a58c2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 15 Feb 2019 07:25:25 +0100 Subject: [PATCH 36/97] simplified output --- src/plastic_nonlocal.f90 | 408 ++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 216 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index ccb38d0c9..f095caeeb 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -189,6 +189,82 @@ module plastic_nonlocal maximumdipoleheight_screw_ID, & accumulatedshear_ID end enum + + type, private :: tParameters !< container type for internal constitutive parameters + + real(pReal) :: & + atomicVolume, & !< atomic volume + Dsd0, & !< prefactor for self-diffusion coefficient + selfDiffusionEnergy, & !< activation enthalpy for diffusion + aTolRho, & !< absolute tolerance for dislocation density in state integration + aTolShear, & !< absolute tolerance for accumulated shear in state integration + significantRho, & !< density considered significant + significantN, & !< number of dislocations considered significant + cutoffRadius, & !< cutoff radius for dislocation stress + doublekinkwidth, & !< width of a doubkle kink in multiples of the burgers vector length b + solidSolutionEnergy, & !< activation energy for solid solution in J + solidSolutionSize, & !< solid solution obstacle size in multiples of the burgers vector length + solidSolutionConcentration, & !< concentration of solid solution in atomic parts + p, & !< parameter for kinetic law (Kocks,Argon,Ashby) + q, & !< parameter for kinetic law (Kocks,Argon,Ashby) + viscosity, & !< viscosity for dislocation glide in Pa s + fattack, & !< attack frequency in Hz + rhoSglScatter, & !< standard deviation of scatter in initial dislocation density + surfaceTransmissivity, & !< transmissivity at free surface + grainboundaryTransmissivity, & !< transmissivity at grain boundary (identified by different texture) + CFLfactor, & !< safety factor for CFL flux condition + fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) + rhoSglRandom, & + rhoSglRandomBinning, & + linetensionEffect, & + edgeJogFactor, & + mu, & + nu + + real(pReal), dimension(:), allocatable :: & + + rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance + rhoSglEdgeNeg0, & !< initial edge_neg dislocation density per slip system for each family and instance + rhoSglScrewPos0, & !< initial screw_pos dislocation density per slip system for each family and instance + rhoSglScrewNeg0, & !< initial screw_neg dislocation density per slip system for each family and instance + rhoDipEdge0, & !< initial edge dipole dislocation density per slip system for each family and instance + rhoDipScrew0,& !< initial screw dipole dislocation density per slip system for each family and instance + lambda0, & !< mean free path prefactor for each slip system and instance + burgers !< absolute length of burgers vector [m] for each slip system and instance + + real(pReal), dimension(:,:), allocatable :: & + interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance + forestProjectionEdge, & !< matrix of forest projections of edge dislocations for each instance + forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance + integer(pInt), dimension(:), allocatable, private :: & + iGamma, & !< state indices for accumulated shear + iRhoF !< state indices for forest density + real(pReal), dimension(:), allocatable, private :: & + nonSchmidCoeff + integer(pInt) :: totalNslip + + real(pReal), dimension(:,:,:), allocatable, private :: & + Schmid, & !< Schmid contribution + nonSchmid_pos, & + nonSchmid_neg !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) + + integer(pInt) , dimension(:) ,allocatable , public:: & + Nslip,& + slipFamily, & !< lookup table relating active slip system to slip family for each instance + slipSystemLattice, & !< lookup table relating active slip system index to lattice slip system index for each instance + colinearSystem !< colinear system to the active slip system (only valid for fcc!) + + logical, private :: & + shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term + probabilisticMultiplication + + integer(kind(undefined_ID)), dimension(:), allocatable :: & + outputID !< ID of each post result output + end type tParameters + + type(tParameters), dimension(:), allocatable, target, private :: param !< containers of constitutive parameters (len Ninstance) + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & plastic_nonlocal_outputID !< ID of each post result output @@ -245,7 +321,7 @@ use material, only: phase_plasticity, & plasticState, & material_phase, & material_allocatePlasticState -use config, only: MATERIAL_partPhase +use config use lattice @@ -253,11 +329,14 @@ use lattice implicit none integer(pInt), intent(in) :: fileUnit + character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] + integer(pInt), dimension(0), parameter :: emptyInt = [integer(pInt)::] + real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] !*** local variables integer(pInt), allocatable, dimension(:) :: chunkPos integer(pInt) :: phase, & maxNinstances, & - maxTotalNslip, & + maxTotalNslip, p, i, & f, & ! index of my slip family instance, & ! index of my instance of this plasticity l, & @@ -278,7 +357,10 @@ integer(pInt) :: phase, & line = '' integer(pInt) :: sizeState, sizeDotState,sizeDependentState, sizeDeltaState + integer(kind(undefined_ID)) :: & + outputID !< ID of each post result output + character(len=65536), dimension(:), allocatable :: outputs integer(pInt) :: NofMyPhase @@ -293,6 +375,7 @@ integer(pInt) :: phase, & write(6,'(a16,1x,i5,/)') '# instances:',maxNinstances !*** memory allocation for global variables +allocate(param(maxNinstances)) allocate(plastic_nonlocal_sizeDotState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizeDependentState(maxNinstances), source=0_pInt) @@ -347,7 +430,6 @@ allocate(minDipoleHeightPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=0.0_pReal) allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), source=0.0_pReal) - rewind(fileUnit) phase = 0_pInt do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to @@ -375,199 +457,6 @@ allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), s chunkPos = IO_stringPos(line) tag = IO_lc(IO_stringValue(line,chunkPos,1_pInt)) ! extract key select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,chunkPos,2_pInt))) - case ('rho_sgl_edge_pos_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_edge_pos_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_edge_neg_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_edge_neg_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_screw_pos_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_screw_pos_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_screw_neg_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_screw_neg_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_edge_pos_immobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_edge_pos_immobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_edge_neg_immobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_edge_neg_immobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_screw_pos_immobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_screw_pos_immobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_sgl_screw_neg_immobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_sgl_screw_neg_immobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dip_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dip_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dip_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dip_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_forest') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_forest_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('shearrate') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = shearrate_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('resolvedstress') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = resolvedstress_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('resolvedstress_external') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = resolvedstress_external_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('resolvedstress_back') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = resolvedstress_back_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('resistance') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = resistance_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_sgl') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_sgl_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_sgl_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_sgl_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_dip') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_dip_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_gen') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_gen_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_gen_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_gen_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_gen_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_gen_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_sgl2dip_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_sgl2dip_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_sgl2dip_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_sgl2dip_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_ann_ath') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_ann_ath_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_ann_the_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_ann_the_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_ann_the_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_ann_the_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_edgejogs') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_edgejogs_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_flux_mobile') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_flux_mobile_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_flux_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_flux_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('rho_dot_flux_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = rho_dot_flux_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('velocity_edge_pos') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = velocity_edge_pos_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('velocity_edge_neg') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = velocity_edge_neg_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('velocity_screw_pos') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = velocity_screw_pos_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('velocity_screw_neg') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = velocity_screw_neg_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('maximumdipoleheight_edge') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = maximumdipoleheight_edge_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('maximumdipoleheight_screw') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = maximumdipoleheight_screw_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - case ('accumulatedshear','accumulated_shear') - plastic_nonlocal_Noutput(instance) = plastic_nonlocal_Noutput(instance) + 1_pInt - plastic_nonlocal_outputID(plastic_nonlocal_Noutput(instance),instance) = accumulatedshear_ID - plastic_nonlocal_output(plastic_nonlocal_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,chunkPos,2_pInt)) - end select case ('nslip') if (chunkPos(1) < 1_pInt + Nchunks_SlipFamilies) & call IO_warning(50_pInt,ext_msg=trim(tag)//' ('//PLASTICITY_NONLOCAL_LABEL//')') @@ -698,10 +587,6 @@ allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), s instance = phase_plasticityInstance(phase) if (sum(Nslip(:,instance)) <= 0_pInt) & call IO_error(211_pInt,ext_msg='Nslip ('//PLASTICITY_NONLOCAL_label//')') - do o = 1_pInt,maxval(phase_Noutput) - if(len(plastic_nonlocal_output(o,instance)) > 64_pInt) & - call IO_error(666_pInt) - enddo do f = 1_pInt,lattice_maxNslipFamily if (Nslip(f,instance) > 0_pInt) then if (rhoSglEdgePos0(f,instance) < 0.0_pReal) & @@ -911,22 +796,9 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), if (iD(ns,2,instance) /= sizeState) & ! check if last index is equal to size of state call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') - - !*** determine size of postResults array - - outputsLoop: do o = 1_pInt,plastic_nonlocal_Noutput(instance) - select case(plastic_nonlocal_outputID(o,instance)) - case default - mySize = totalNslip(instance) - end select - - if (mySize > 0_pInt) then ! any meaningful output found - plastic_nonlocal_sizePostResult(o,instance) = mySize - endif - enddo outputsLoop - plasticState(phase)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) + plasticState(phase)%nonlocal = .true. call material_allocatePlasticState(phase,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & totalNslip(instance),0_pInt,0_pInt) @@ -1011,6 +883,110 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), endif myPhase2 enddo initializeInstances + + + do p=1_pInt, size(config_phase) + if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle + instance = phase_plasticityInstance(p) + associate(prm => param(instance), & + config => config_phase(p)) + + + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) + allocate(prm%outputID(0)) + do i=1_pInt, size(outputs) + outputID = undefined_ID + select case(trim(outputs(i))) + case ('rho_sgl_edge_pos_mobile') + outputID = rho_sgl_edge_pos_mobile_ID + case ('rho_sgl_edge_neg_mobile') + outputID = rho_sgl_edge_neg_mobile_ID + case ('rho_sgl_screw_pos_mobile') + outputID = rho_sgl_screw_pos_mobile_ID + case ('rho_sgl_screw_neg_mobile') + outputID = rho_sgl_screw_neg_mobile_ID + case ('rho_sgl_edge_pos_immobile') + outputID = rho_sgl_edge_pos_immobile_ID + case ('rho_sgl_edge_neg_immobile') + outputID = rho_sgl_edge_neg_immobile_ID + case ('rho_sgl_screw_pos_immobile') + outputID = rho_sgl_screw_pos_immobile_ID + case ('rho_sgl_screw_neg_immobile') + outputID = rho_sgl_screw_neg_immobile_ID + case ('rho_dip_edge') + outputID = rho_dip_edge_ID + case ('rho_dip_screw') + outputID = rho_dip_screw_ID + case ('rho_forest') + outputID = rho_forest_ID + case ('shearrate') + outputID = shearrate_ID + case ('resolvedstress') + outputID = resolvedstress_ID + case ('resolvedstress_external') + outputID = resolvedstress_external_ID + case ('resolvedstress_back') + outputID = resolvedstress_back_ID + case ('resistance') + outputID = resistance_ID + case ('rho_dot_sgl') + outputID = rho_dot_sgl_ID + case ('rho_dot_sgl_mobile') + outputID = rho_dot_sgl_mobile_ID + case ('rho_dot_dip') + outputID = rho_dot_dip_ID + case ('rho_dot_gen') + outputID = rho_dot_gen_ID + case ('rho_dot_gen_edge') + outputID = rho_dot_gen_edge_ID + case ('rho_dot_gen_screw') + outputID = rho_dot_gen_screw_ID + case ('rho_dot_sgl2dip_edge') + outputID = rho_dot_sgl2dip_edge_ID + case ('rho_dot_sgl2dip_screw') + outputID = rho_dot_sgl2dip_screw_ID + case ('rho_dot_ann_ath') + outputID = rho_dot_ann_ath_ID + case ('rho_dot_ann_the_edge') + outputID = rho_dot_ann_the_edge_ID + case ('rho_dot_ann_the_screw') + outputID = rho_dot_ann_the_screw_ID + case ('rho_dot_edgejogs') + outputID = rho_dot_edgejogs_ID + case ('rho_dot_flux_mobile') + outputID = rho_dot_flux_mobile_ID + case ('rho_dot_flux_edge') + outputID = rho_dot_flux_edge_ID + case ('rho_dot_flux_screw') + outputID = rho_dot_flux_screw_ID + case ('velocity_edge_pos') + outputID = velocity_edge_pos_ID + case ('velocity_edge_neg') + outputID = velocity_edge_neg_ID + case ('velocity_screw_pos') + outputID = velocity_screw_pos_ID + case ('velocity_screw_neg') + outputID = velocity_screw_neg_ID + case ('maximumdipoleheight_edge') + outputID = maximumdipoleheight_edge_ID + case ('maximumdipoleheight_screw') + outputID = maximumdipoleheight_screw_ID + case ('accumulatedshear','accumulated_shear') + outputID = accumulatedshear_ID + end select + + if (outputID /= undefined_ID) then + plastic_nonlocal_output(i,instance) = outputs(i) + plastic_nonlocal_sizePostResult(i,instance) = totalNslip(instance) + prm%outputID = [prm%outputID , outputID] + endif + + enddo + end associate + + plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) + + enddo end subroutine plastic_nonlocal_init @@ -2924,8 +2900,8 @@ forall (s = 1_pInt:ns) & lattice_sn(1:3,slipSystemLattice(s,instance),ph)) -outputsLoop: do o = 1_pInt,plastic_nonlocal_Noutput(instance) - select case(plastic_nonlocal_outputID(o,instance)) + outputsLoop: do o = 1_pInt,size(param(instance)%outputID) + select case(param(instance)%outputID(o)) case (rho_sgl_edge_pos_mobile_ID) plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,1) From 2584f8576045ad4543b8dd80c9fe8bc9892fee7c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 16 Feb 2019 18:38:13 +0100 Subject: [PATCH 37/97] parameters are stored in parameter structure --- src/plastic_nonlocal.f90 | 163 ++++++++++++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 36 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 76b9339fa..287de8dd5 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -11,32 +11,6 @@ module plastic_nonlocal implicit none private - character(len=22), dimension(11), parameter, private :: & - BASICSTATES = ['rhoSglEdgePosMobile ', & - 'rhoSglEdgeNegMobile ', & - 'rhoSglScrewPosMobile ', & - 'rhoSglScrewNegMobile ', & - 'rhoSglEdgePosImmobile ', & - 'rhoSglEdgeNegImmobile ', & - 'rhoSglScrewPosImmobile', & - 'rhoSglScrewNegImmobile', & - 'rhoDipEdge ', & - 'rhoDipScrew ', & - 'accumulatedshear ' ] !< list of "basic" microstructural state variables that are independent from other state variables - - character(len=16), dimension(3), parameter, private :: & - DEPENDENTSTATES = ['rhoForest ', & - 'tauThreshold ', & - 'tauBack ' ] !< list of microstructural state variables that depend on other state variables - - character(len=20), dimension(6), parameter, private :: & - OTHERSTATES = ['velocityEdgePos ', & - 'velocityEdgeNeg ', & - 'velocityScrewPos ', & - 'velocityScrewNeg ', & - 'maxDipoleHeightEdge ', & - 'maxDipoleHeightScrew' ] !< list of other dependent state variables that are not updated by microstructure - real(pReal), parameter, private :: & KB = 1.38e-23_pReal !< Physical parameter, Boltzmann constant in J/Kelvin @@ -293,7 +267,8 @@ subroutine plastic_nonlocal_init(fileUnit) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use math, only: math_Voigt66to3333, & math_mul3x3, & - math_transpose33 + math_transpose33, & + math_expand use IO, only: IO_read, & IO_lc, & IO_getTag, & @@ -357,7 +332,9 @@ integer(pInt) :: phase, & integer(pInt) :: sizeState, sizeDotState,sizeDependentState, sizeDeltaState integer(kind(undefined_ID)) :: & outputID !< ID of each post result output - + character(len=512) :: & + extmsg = '', & + structure character(len=65536), dimension(:), allocatable :: outputs integer(pInt) :: NofMyPhase @@ -737,11 +714,32 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), ns = totalNslip(instance) - sizeDotState = int(size(BASICSTATES),pInt) * ns - sizeDependentState = int(size(DEPENDENTSTATES),pInt) * ns - sizeState = sizeDotState + sizeDependentState & - + int(size(OTHERSTATES),pInt) * ns - sizeDeltaState = sizeDotState + sizeDotState = int(size(& + ['rhoSglEdgePosMobile ', & + 'rhoSglEdgeNegMobile ', & + 'rhoSglScrewPosMobile ', & + 'rhoSglScrewNegMobile ', & + 'rhoSglEdgePosImmobile ', & + 'rhoSglEdgeNegImmobile ', & + 'rhoSglScrewPosImmobile', & + 'rhoSglScrewNegImmobile', & + 'rhoDipEdge ', & + 'rhoDipScrew ', & + 'accumulatedshear ' ] & !< list of "basic" microstructural state variables that are independent from other state variables + &),pInt) * ns + sizeDependentState = int(size(& + ['rhoForest '] & !< list of microstructural state variables that depend on other state variables + &),pInt) * ns + sizeState = sizeDotState + sizeDependentState & + + int(size(& + ['velocityEdgePos ', & + 'velocityEdgeNeg ', & + 'velocityScrewPos ', & + 'velocityScrewNeg ', & + 'maxDipoleHeightEdge ', & + 'maxDipoleHeightScrew' ] & !< list of other dependent state variables that are not updated by microstructure + &),pInt) * ns + sizeDeltaState = sizeDotState !*** determine indices to state array @@ -889,7 +887,100 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), associate(prm => param(instance), & config => config_phase(p)) + prm%mu = lattice_mu(p) + prm%nu = lattice_nu(p) + structure = config_phase(p)%getString('lattice_structure') +param(instance)%shortRangeStressCorrection = .false. +param(instance)%probabilisticMultiplication = .false. + + prm%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) + prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,structure(1:3),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + if(structure=='bcc') then + prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& + defaultVal = emptyRealArray) + prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1_pInt) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1_pInt) + else + prm%nonSchmid_pos = prm%Schmid + prm%nonSchmid_neg = prm%Schmid + endif + prm%interactionSlipSlip = lattice_interaction_SlipSlip(prm%Nslip, & + config%getFloats('interaction_slipslip'), & + structure(1:3)) + + + + prm%rhoSglEdgePos0 = config_phase(p)%getFloats('rhosgledgepos0') + prm%rhoSglEdgeNeg0 = config_phase(p)%getFloats('rhosgledgeneg0') + prm%rhoSglScrewPos0 = config_phase(p)%getFloats('rhosglscrewpos0') + prm%rhoSglScrewNeg0 = config_phase(p)%getFloats('rhosglscrewneg0') + + prm%rhoDipEdge0 = config_phase(p)%getFloats('rhodipedge0') + prm%rhoDipScrew0 = config_phase(p)%getFloats('rhodipscrew0') + prm%lambda0 = config_phase(p)%getFloats('lambda0') + + if(size(prm%lambda0)/= size(prm%Nslip)) call IO_error(211_pInt,ext_msg='lambda0') + prm%lambda0 = math_expand(prm%lambda0,prm%Nslip) + + + prm%burgers = config_phase(p)%getFloats('burgers') + + if (size(prm%burgers) /= size(prm%Nslip)) call IO_error(150_pInt,ext_msg='burgers') + prm%burgers = math_expand(prm%burgers,prm%Nslip) + + + minDipoleHeightPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightedge')!,'ddipminedge') + minDipoleHeightPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightscrew')!,'ddipminscrew') + peierlsStressPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloat('peierlsstressedge')!,'peierlsstress_edge') + peierlsStressPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloat('peierlsstressscrew')!,'peierlsstress_screw') + + prm%atomicVolume = config_phase(p)%getFloat('atomicvolume') + prm%cutoffRadius = config_phase(p)%getFloat('r')!,cutoffradius') + prm%Dsd0 = config_phase(p)%getFloat('selfdiffusionprefactor') !,'dsd0') + prm%selfDiffusionEnergy = config_phase(p)%getFloat('selfdiffusionenergy') !,'qsd') + + prm%aTolRho = config_phase(p)%getFloat('atol_rho') !,'atol_density','absolutetolerancedensity','absolutetolerance_density') + prm%aTolShear = config_phase(p)%getFloat('atol_shear') !,'atol_plasticshear','atol_accumulatedshear','absolutetoleranceshear','absolutetolerance_shear') + + + prm%significantRho = config_phase(p)%getFloat('significantrho')!,'significant_rho','significantdensity','significant_density') + prm%significantN = config_phase(p)%getFloat('significantn', 0.0_pReal)!,'significant_n','significantdislocations','significant_dislcations') + + + + prm%linetensionEffect = config_phase(p)%getFloat('linetension')!,'linetensioneffect','linetension_effect') + prm%edgeJogFactor = config_phase(p)%getFloat('edgejog')!,'edgejogs','edgejogeffect','edgejog_effect') + prm%doublekinkwidth = config_phase(p)%getFloat('doublekinkwidth') + + prm%solidSolutionEnergy = config_phase(p)%getFloat('solidsolutionenergy') + prm%solidSolutionSize = config_phase(p)%getFloat('solidsolutionsize') + prm%solidSolutionConcentration = config_phase(p)%getFloat('solidsolutionconcentration') + + + prm%p = config_phase(p)%getFloat('p') + prm%q = config_phase(p)%getFloat('q') + + + prm%viscosity = config_phase(p)%getFloat('viscosity')!,'glideviscosity') + prm%fattack = config_phase(p)%getFloat('attackfrequency')!,'fattack') + + prm%rhoSglScatter = config_phase(p)%getFloat('rhosglscatter') + prm%rhoSglRandom = config_phase(p)%getFloat('rhosglrandom',0.0_pReal) + + if (config_phase(p)%keyExists('rhosglrandom')) & + prm%rhoSglRandomBinning = config_phase(p)%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? + + + prm%surfaceTransmissivity = config_phase(p)%getFloat('surfacetransmissivity') + prm%grainboundaryTransmissivity = config_phase(p)%getFloat('grainboundarytransmissivity') + prm%CFLfactor = config_phase(p)%getFloat('cflfactor') + + prm%fEdgeMultiplication = config_phase(p)%getFloat('edgemultiplication')!,'edgemultiplicationfactor','fedgemultiplication') + prm%shortRangeStressCorrection = config_phase(p)%getInt('shortrangestresscorrection' ) > 0_pInt + prm%probabilisticMultiplication = config_phase(p)%keyExists('/probabilisticmultiplication/' )!,'randomsources','randommultiplication','discretesources') + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -2389,7 +2480,7 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then !* FLUX FROM ME TO MY NEIGHBOR - !* This is not considered, if my opposite neighbor has a different constitutive law than nonlocal (still considered for nonlocal law with lcal properties). + !* This is not considered, if my opposite neighbor has a different constitutive law than nonlocal (still considered for nonlocal law with local properties). !* Then, we assume, that the opposite(!) neighbor sends an equal amount of dislocations to me. !* So the net flux in the direction of my neighbor is equal to zero: !* leaving flux to neighbor == entering flux from opposite neighbor @@ -2423,9 +2514,9 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then endif normal_me2neighbor_defConf = math_det33(Favg) & - * math_mul33x3(math_inv33(math_transpose33(Favg)), & + * math_mul33x3(math_inv33(transpose(Favg)), & mesh_ipAreaNormal(1:3,n,ip,el)) ! calculate the normal of the interface in (average) deformed configuration (pointing from me to my neighbor!!!) - normal_me2neighbor = math_mul33x3(math_transpose33(my_Fe), normal_me2neighbor_defConf) & + normal_me2neighbor = math_mul33x3(transpose(my_Fe), normal_me2neighbor_defConf) & / math_det33(my_Fe) ! interface normal in my lattice configuration area = mesh_ipArea(n,ip,el) * norm2(normal_me2neighbor) normal_me2neighbor = normal_me2neighbor / norm2(normal_me2neighbor) ! normalize the surface normal to unit length From c7abe559447d79ef26bc68a68291396dd5bd7f2f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 16 Feb 2019 22:09:06 +0100 Subject: [PATCH 38/97] was not needed --- src/plastic_nonlocal.f90 | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 287de8dd5..341f7c9cc 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -264,10 +264,8 @@ contains !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_init(fileUnit) -use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use math, only: math_Voigt66to3333, & math_mul3x3, & - math_transpose33, & math_expand use IO, only: IO_read, & IO_lc, & @@ -340,8 +338,6 @@ integer(pInt) :: phase, & integer(pInt) :: NofMyPhase write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" maxNinstances = int(count(phase_plasticity == PLASTICITY_NONLOCAL_ID),pInt) if (maxNinstances == 0) return ! we don't have to do anything if there's no instance for this constitutive law @@ -848,7 +844,7 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), !*** rotation matrix from lattice configuration to slip system lattice2slip(1:3,1:3,s1,instance) & - = math_transpose33( reshape([ lattice_sd(1:3, slipSystemLattice(s1,instance), phase), & + = transpose( reshape([ lattice_sd(1:3, slipSystemLattice(s1,instance), phase), & -lattice_st(1:3, slipSystemLattice(s1,instance), phase), & lattice_sn(1:3, slipSystemLattice(s1,instance), phase)], [3,3])) enddo @@ -1231,8 +1227,7 @@ use math, only: & pi, & math_mul33x3, & math_mul3x3, & - math_inv33, & - math_transpose33 + math_inv33 use debug, only: & debug_level, & debug_constitutive, & @@ -1422,7 +1417,7 @@ if (.not. phase_localPlasticity(ph) .and. shortRangeStressCorrection(instance)) connection_latticeConf(1:3,n) = & math_mul33x3(invFe, mesh_ipCoordinates(1:3,neighbor_ip,neighbor_el) & - mesh_ipCoordinates(1:3,ip,el)) - normal_latticeConf = math_mul33x3(math_transpose33(invFp), mesh_ipAreaNormal(1:3,n,ip,el)) + normal_latticeConf = math_mul33x3(transpose(invFp), mesh_ipAreaNormal(1:3,n,ip,el)) if (math_mul3x3(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) then ! neighboring connection points in opposite direction to face normal: must be periodic image connection_latticeConf(1:3,n) = normal_latticeConf * mesh_ipVolume(ip,el) & / mesh_ipArea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell @@ -1745,7 +1740,8 @@ Lp = 0.0_pReal dLp_dTstar3333 = 0.0_pReal instance = phase_plasticityInstance(ph) -ns = totalNslip(instance) +associate(prm => param(instance)) +ns = prm%totalNslip !*** shortcut to state variables @@ -1864,7 +1860,7 @@ dLp_dTstar99 = math_3333to99(dLp_dTstar3333) write(6,'(a,/,3(12x,3(f12.7,1x),/))') '<< CONST >> Lp',transpose(Lp) endif #endif - +end associate end subroutine plastic_nonlocal_LpAndItsTangent @@ -2077,7 +2073,6 @@ use math, only: math_mul6x6, & math_mul33x33, & math_inv33, & math_det33, & - math_transpose33, & pi use mesh, only: theMesh, & mesh_element, & From 0f319e2cf63a3864660bad78e41c08598c3f3569 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 16 Feb 2019 23:18:53 +0100 Subject: [PATCH 39/97] fixed state size and output size --- src/plastic_nonlocal.f90 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 341f7c9cc..28d79df68 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -26,8 +26,6 @@ module plastic_nonlocal character(len=64), dimension(:,:), allocatable, target, public :: & plastic_nonlocal_output !< name of each post result output - integer(pInt), dimension(:), allocatable, target, public :: & - plastic_nonlocal_Noutput !< number of outputs per instance of this plasticity integer(pInt), dimension(:,:), allocatable, private :: & iGamma, & !< state indices for accumulated shear @@ -352,7 +350,6 @@ allocate(plastic_nonlocal_sizeDotState(maxNinstances), allocate(plastic_nonlocal_sizeDependentState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizeState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) -allocate(plastic_nonlocal_Noutput(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) plastic_nonlocal_output = '' allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) @@ -724,7 +721,9 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), 'accumulatedshear ' ] & !< list of "basic" microstructural state variables that are independent from other state variables &),pInt) * ns sizeDependentState = int(size(& - ['rhoForest '] & !< list of microstructural state variables that depend on other state variables + ['rhoForest ', & + 'tauThreshold ', & + 'tauBack ' ]& !< list of microstructural state variables that depend on other state variables &),pInt) * ns sizeState = sizeDotState + sizeDependentState & + int(size(& @@ -891,6 +890,7 @@ param(instance)%shortRangeStressCorrection = .false. param(instance)%probabilisticMultiplication = .false. prm%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) + prm%totalNslip = sum(prm%Nslip) prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,structure(1:3),& config%getFloat('c/a',defaultVal=0.0_pReal)) if(structure=='bcc') then @@ -1743,12 +1743,10 @@ instance = phase_plasticityInstance(ph) associate(prm => param(instance)) ns = prm%totalNslip - !*** shortcut to state variables forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) - rhoSgl(s,t) = max(plasticState(ph)%state(iRhoU(s,t,instance),of), 0.0_pReal) ! ensure positive single mobile densities rhoSgl(s,t+4_pInt) = plasticState(ph)%state(iRhoB(s,t,instance),of) endforall @@ -2970,8 +2968,8 @@ forall (s = 1_pInt:ns) & lattice_sn(1:3,slipSystemLattice(s,instance),ph)) -outputsLoop: do o = 1_pInt,plastic_nonlocal_Noutput(instance) - select case(plastic_nonlocal_outputID(o,instance)) +outputsLoop: do o = 1_pInt,size(param(instance)%outputID) + select case(param(instance)%outputID(o)) case (rho_sgl_edge_pos_mobile_ID) plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,1) From cf32e7d1f5e214a7e224891316ff255245cc6e55 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 12:15:46 +0100 Subject: [PATCH 40/97] use parameter structure and avoid conversion 33<->6 --- src/constitutive.f90 | 42 +++++----- src/crystallite.f90 | 25 +++--- src/plastic_nonlocal.f90 | 169 ++++++++++++++------------------------- 3 files changed, 90 insertions(+), 146 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index ac8ee0484..88d521af9 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -402,15 +402,15 @@ end subroutine constitutive_microstructure !-------------------------------------------------------------------------------------------------- !> @brief contains the constitutive equation for calculating the velocity gradient +! ToDo: Discuss wheter it makes sense if crystallite handles the configuration conversion, i.e. +! Mp in, dLp_dMp out !-------------------------------------------------------------------------------------------------- -subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, S6, Fi, ipc, ip, el) +subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, & + S, Fi, ipc, ip, el) use prec, only: & pReal use math, only: & - math_mul33x33, & - math_6toSym33, & - math_sym33to6, & - math_99to3333 + math_mul33x33 use material, only: & phasememberAt, & phase_plasticity, & @@ -444,9 +444,8 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, S6, Fi, ipc, ip, e ipc, & !< component-ID of integration point ip, & !< integration point el !< element - real(pReal), intent(in), dimension(6) :: & - S6 !< 2nd Piola-Kirchhoff stress (vector notation) real(pReal), intent(in), dimension(3,3) :: & + S, & !< 2nd Piola-Kirchhoff stress Fi !< intermediate deformation gradient real(pReal), intent(out), dimension(3,3) :: & Lp !< plastic velocity gradient @@ -455,11 +454,8 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, S6, Fi, ipc, ip, e dLp_dFi !< derivative of Lp with respect to Fi real(pReal), dimension(3,3,3,3) :: & dLp_dMp !< derivative of Lp with respect to Mandel stress - real(pReal), dimension(9,9) :: & - dLp_dMp99 !< derivative of Lp with respect to Mstar (matrix notation) real(pReal), dimension(3,3) :: & - Mp, & !< Mandel stress work conjugate with Lp - S !< 2nd Piola-Kirchhoff stress + Mp !< Mandel stress work conjugate with Lp integer(pInt) :: & ho, & !< homogenization tme !< thermal member position @@ -469,7 +465,6 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, S6, Fi, ipc, ip, e ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) - S = math_6toSym33(S6) Mp = math_mul33x33(math_mul33x33(transpose(Fi),Fi),S) plasticityType: select case (phase_plasticity(material_phase(ipc,ip,el))) @@ -491,12 +486,11 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, S6, Fi, ipc, ip, e case (PLASTICITY_KINEHARDENING_ID) plasticityType of = phasememberAt(ipc,ip,el) instance = phase_plasticityInstance(material_phase(ipc,ip,el)) - call plastic_kinehardening_LpAndItsTangent (Lp,dLp_dMp, Mp,instance,of) + call plastic_kinehardening_LpAndItsTangent (Lp,dLp_dMp,Mp,instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp99, math_sym33to6(Mp), & + call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, & temperature(ho)%p(tme),ip,el) - dLp_dMp = math_99to3333(dLp_dMp99) ! ToDo: We revert here the last statement in plastic_xx_LpAndItsTanget case (PLASTICITY_DISLOTWIN_ID) plasticityType of = phasememberAt(ipc,ip,el) @@ -993,7 +987,7 @@ end subroutine constitutive_collectDeltaState !-------------------------------------------------------------------------------------------------- !> @brief returns array of constitutive results !-------------------------------------------------------------------------------------------------- -function constitutive_postResults(S6, Fi, FeArray, ipc, ip, el) +function constitutive_postResults(S, Fi, FeArray, ipc, ip, el) use prec, only: & pReal use math, only: & @@ -1058,8 +1052,8 @@ function constitutive_postResults(S6, Fi, FeArray, ipc, ip, el) Fi !< intermediate deformation gradient real(pReal), intent(in), dimension(3,3,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%Nelems) :: & FeArray !< elastic deformation gradient - real(pReal), intent(in), dimension(6) :: & - S6 !< 2nd Piola Kirchhoff stress (vector notation) + real(pReal), intent(in), dimension(3,3) :: & + S !< 2nd Piola Kirchhoff stress real(pReal), dimension(3,3) :: & Mp !< Mandel stress integer(pInt) :: & @@ -1067,11 +1061,11 @@ function constitutive_postResults(S6, Fi, FeArray, ipc, ip, el) integer(pInt) :: & ho, & !< homogenization tme, & !< thermal member position - s, of, instance !< counter in source loop + i, of, instance !< counter in source loop constitutive_postResults = 0.0_pReal - Mp = math_mul33x33(math_mul33x33(transpose(Fi),Fi),math_6toSym33(S6)) + Mp = math_mul33x33(math_mul33x33(transpose(Fi),Fi),S) ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) @@ -1112,13 +1106,13 @@ function constitutive_postResults(S6, Fi, FeArray, ipc, ip, el) case (PLASTICITY_NONLOCAL_ID) plasticityType constitutive_postResults(startPos:endPos) = & - plastic_nonlocal_postResults (S6,FeArray,ip,el) + plastic_nonlocal_postResults (Mp,FeArray,ip,el) end select plasticityType - SourceLoop: do s = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) + SourceLoop: do i = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) startPos = endPos + 1_pInt - endPos = endPos + sourceState(material_phase(ipc,ip,el))%p(s)%sizePostResults - sourceType: select case (phase_source(s,material_phase(ipc,ip,el))) + endPos = endPos + sourceState(material_phase(ipc,ip,el))%p(i)%sizePostResults + sourceType: select case (phase_source(i,material_phase(ipc,ip,el))) case (SOURCE_damage_isoBrittle_ID) sourceType constitutive_postResults(startPos:endPos) = source_damage_isoBrittle_postResults(ipc, ip, el) case (SOURCE_damage_isoDuctile_ID) sourceType diff --git a/src/crystallite.f90 b/src/crystallite.f90 index c272abd07..f049cd400 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -286,7 +286,7 @@ subroutine crystallite_init crystallite_outputID(o,c) = grainrotation_ID case ('eulerangles') outputName crystallite_outputID(o,c) = eulerangles_ID - case ('defgrad','f') outputName + case ('defgrad','f') outputName ! ToDo: no alias (f only) crystallite_outputID(o,c) = defgrad_ID case ('fe') outputName crystallite_outputID(o,c) = fe_ID @@ -298,15 +298,15 @@ subroutine crystallite_init crystallite_outputID(o,c) = lp_ID case ('li') outputName crystallite_outputID(o,c) = li_ID - case ('p','firstpiola','1stpiola') outputName + case ('p','firstpiola','1stpiola') outputName ! ToDo: no alias (p only) crystallite_outputID(o,c) = p_ID - case ('s','tstar','secondpiola','2ndpiola') outputName + case ('s','tstar','secondpiola','2ndpiola') outputName ! ToDo: no alias (s only) crystallite_outputID(o,c) = s_ID case ('elasmatrix') outputName crystallite_outputID(o,c) = elasmatrix_ID - case ('neighboringip') outputName + case ('neighboringip') outputName ! ToDo: this is not a result, it is static. Should be written out by mesh crystallite_outputID(o,c) = neighboringip_ID - case ('neighboringelement') outputName + case ('neighboringelement') outputName ! ToDo: this is not a result, it is static. Should be written out by mesh crystallite_outputID(o,c) = neighboringelement_ID case default outputName call IO_error(105_pInt,ext_msg=trim(str(o))//' (Crystallite)') @@ -426,7 +426,7 @@ end subroutine crystallite_init !-------------------------------------------------------------------------------------------------- !> @brief calculate stress (P) !-------------------------------------------------------------------------------------------------- -function crystallite_stress(a) +function crystallite_stress(dummyArgumentToPreventInternalCompilerErrorWithGCC) use prec, only: & tol_math_check, & dNeq0 @@ -462,14 +462,11 @@ function crystallite_stress(a) sourceState, & phase_Nsources, & phaseAt, phasememberAt - use constitutive, only: & - constitutive_SandItsTangents, & - constitutive_LpAndItsTangents, & - constitutive_LiAndItsTangents implicit none logical, dimension(theMesh%elem%nIPs,theMesh%Nelems) :: crystallite_stress - real(pReal), intent(in), optional :: a !ToDo: for some reason this prevents an internal compiler error in GNU. Very strange + real(pReal), intent(in), optional :: & + dummyArgumentToPreventInternalCompilerErrorWithGCC real(pReal) :: & formerSubStep integer(pInt) :: & @@ -793,7 +790,7 @@ subroutine crystallite_stressTangent() endif call constitutive_LpAndItsTangents(devNull,dLpdS,dLpdFi, & - crystallite_Tstar_v(1:6,c,i,e), & + math_6toSym33(crystallite_Tstar_v(1:6,c,i,e)), & crystallite_Fi(1:3,1:3,c,i,e),c,i,e) ! call constitutive law to calculate Lp tangent in lattice configuration dLpdS = math_mul3333xx3333(dLpdFi,dFidS) + dLpdS @@ -1078,7 +1075,7 @@ function crystallite_postResults(ipc, ip, el) c = c + 1_pInt if (size(crystallite_postResults)-c > 0_pInt) & crystallite_postResults(c+1:size(crystallite_postResults)) = & - constitutive_postResults(crystallite_Tstar_v(1:6,ipc,ip,el), crystallite_Fi(1:3,1:3,ipc,ip,el), & + constitutive_postResults(math_6toSym33(crystallite_Tstar_v(1:6,ipc,ip,el)), crystallite_Fi(1:3,1:3,ipc,ip,el), & crystallite_Fe, ipc, ip, el) end function crystallite_postResults @@ -1289,7 +1286,7 @@ logical function integrateStress(& !* calculate plastic velocity gradient and its tangent from constitutive law call constitutive_LpAndItsTangents(Lp_constitutive, dLp_dS, dLp_dFi, & - math_sym33to6(S), Fi_new, ipc, ip, el) + S, Fi_new, ipc, ip, el) #ifdef DEBUG if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 28d79df68..4a2d6b42f 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -107,14 +107,11 @@ module plastic_nonlocal rhoDotMultiplicationOutput, & rhoDotSingle2DipoleGlideOutput, & rhoDotAthermalAnnihilationOutput, & - rhoDotThermalAnnihilationOutput, & - nonSchmidProjection !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) + rhoDotThermalAnnihilationOutput !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & compatibility !< slip system compatibility between me and my neighbors - real(pReal), dimension(:,:), allocatable, private :: & - nonSchmidCoeff logical, dimension(:), allocatable, private :: & shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term @@ -275,7 +272,6 @@ use IO, only: IO_read, & IO_intValue, & IO_warning, & IO_error, & - IO_timeStamp, & IO_EOF use debug, only: debug_level, & debug_constitutive, & @@ -319,7 +315,6 @@ integer(pInt) :: phase, & c, & ! index of dislocation character Nchunks_SlipSlip = 0_pInt, & Nchunks_SlipFamilies = 0_pInt, & - Nchunks_nonSchmid = 0_pInt, & mySize = 0_pInt ! to suppress warnings, safe as init is called only once character(len=65536) :: & tag = '', & @@ -396,7 +391,6 @@ allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), s allocate(interactionSlipSlip(lattice_maxNinteraction,maxNinstances), source=0.0_pReal) allocate(minDipoleHeightPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=-1.0_pReal) allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=0.0_pReal) -allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), source=0.0_pReal) rewind(fileUnit) @@ -417,7 +411,6 @@ allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), s if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then Nchunks_SlipFamilies = count(lattice_NslipSystem(:,phase) > 0_pInt) Nchunks_SlipSlip = maxval(lattice_InteractionSlipSlip(:,:,phase)) - Nchunks_nonSchmid = lattice_NnonSchmid(phase) endif cycle endif @@ -539,12 +532,6 @@ allocate(nonSchmidCoeff(lattice_maxNnonSchmid,maxNinstances), s fEdgeMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) case('shortrangestresscorrection') shortRangeStressCorrection(instance) = IO_floatValue(line,chunkPos,2_pInt) > 0.0_pReal - case ('nonschmid_coefficients') - if (chunkPos(1) < 1_pInt + Nchunks_nonSchmid) & - call IO_warning(52_pInt,ext_msg=trim(tag)//' ('//PLASTICITY_NONLOCAL_label//')') - do f = 1_pInt,Nchunks_nonSchmid - nonSchmidCoeff(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo case('probabilisticmultiplication','randomsources','randommultiplication','discretesources') probabilisticMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) > 0.0_pReal end select @@ -686,7 +673,6 @@ allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,t source=0.0_pReal) allocate(peierlsStress(maxTotalNslip,2,maxNinstances), source=0.0_pReal) allocate(colinearSystem(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), source=0.0_pReal) initializeInstances: do phase = 1_pInt, size(phase_plasticity) NofMyPhase=count(material_phase==phase) @@ -856,19 +842,6 @@ allocate(nonSchmidProjection(3,3,4,maxTotalNslip,maxNinstances), !* 3) negative screw at positive resolved stress !* 4) negative screw at negative resolved stress - do s = 1_pInt,ns - do l = 1_pInt,lattice_NnonSchmid(phase) - nonSchmidProjection(1:3,1:3,1,s,instance) = nonSchmidProjection(1:3,1:3,1,s,instance) & - + nonSchmidCoeff(l,instance) * lattice_Sslip(1:3,1:3,2*l,slipSystemLattice(s,instance),phase) - nonSchmidProjection(1:3,1:3,2,s,instance) = nonSchmidProjection(1:3,1:3,2,s,instance) & - + nonSchmidCoeff(l,instance) * lattice_Sslip(1:3,1:3,2*l+1,slipSystemLattice(s,instance),phase) - enddo - nonSchmidProjection(1:3,1:3,3,s,instance) = -nonSchmidProjection(1:3,1:3,2,s,instance) - nonSchmidProjection(1:3,1:3,4,s,instance) = -nonSchmidProjection(1:3,1:3,1,s,instance) - forall (t = 1:4) & - nonSchmidProjection(1:3,1:3,t,s,instance) = nonSchmidProjection(1:3,1:3,t,s,instance) & - + lattice_Sslip(1:3,1:3,1,slipSystemLattice(s,instance),phase) - enddo call plastic_nonlocal_aTolState(phase,instance) endif myPhase2 @@ -1322,7 +1295,9 @@ real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1_pI ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) -ns = totalNslip(instance) +associate(prm => param(instance)) + +ns = prm%totalNslip !*** get basic states @@ -1334,11 +1309,11 @@ endforall forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) & rhoDip(s,c) = max(plasticState(ph)%state(iRhoD(s,c,instance),of), 0.0_pReal) ! ensure positive dipole densities -where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoSgl) < significantRho(instance)) & +where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal -where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoDip) < significantRho(instance)) & +where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoDip) < prm%significantRho) & rhoDip = 0.0_pReal !*** calculate the forest dislocation density @@ -1377,7 +1352,7 @@ forall (s = 1_pInt:ns) & tauBack = 0.0_pReal -if (.not. phase_localPlasticity(ph) .and. shortRangeStressCorrection(instance)) then +if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then invFe = math_inv33(Fe) invFp = math_inv33(Fp) rhoExcess(1,1:ns) = rhoSgl(1:ns,1) - rhoSgl(1:ns,2) @@ -1418,10 +1393,9 @@ if (.not. phase_localPlasticity(ph) .and. shortRangeStressCorrection(instance)) math_mul33x3(invFe, mesh_ipCoordinates(1:3,neighbor_ip,neighbor_el) & - mesh_ipCoordinates(1:3,ip,el)) normal_latticeConf = math_mul33x3(transpose(invFp), mesh_ipAreaNormal(1:3,n,ip,el)) - if (math_mul3x3(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) then ! neighboring connection points in opposite direction to face normal: must be periodic image + if (math_mul3x3(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) & ! neighboring connection points in opposite direction to face normal: must be periodic image connection_latticeConf(1:3,n) = normal_latticeConf * mesh_ipVolume(ip,el) & / mesh_ipArea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell - endif else ! different number of active slip systems call IO_error(-1_pInt,ext_msg='different number of active slip systems in neighboring IPs of same crystal structure') @@ -1507,7 +1481,7 @@ plasticState(ph)%state(iTauB(1:ns,instance),of) = tauBack write(6,'(a,/,12x,12(f10.5,1x),/)') '<< CONST >> tauBack / MPa', tauBack*1e-6 endif #endif - + end associate end subroutine plastic_nonlocal_microstructure @@ -1671,7 +1645,7 @@ end subroutine plastic_nonlocal_kinetics !-------------------------------------------------------------------------------------------------- !> @brief calculates plastic velocity gradient and its tangent !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dTstar99, Tstar_v, Temperature, ip, el) +subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, Mp, Temperature, ip, el) use math, only: math_3333to99, & math_mul6x6, & @@ -1687,9 +1661,6 @@ use material, only: material_phase, & plasticState, & phaseAt, phasememberAt,& phase_plasticityInstance -use lattice, only: lattice_Sslip, & - lattice_Sslip_v, & - lattice_NnonSchmid use mesh, only: mesh_ipVolume implicit none @@ -1698,12 +1669,12 @@ implicit none integer(pInt), intent(in) :: ip, & !< current integration point el !< current element number real(pReal), intent(in) :: Temperature !< temperature -real(pReal), dimension(6), intent(in) :: Tstar_v !< 2nd Piola-Kirchhoff stress in Mandel notation +real(pReal), dimension(3,3), intent(in) :: Mp !*** output variables real(pReal), dimension(3,3), intent(out) :: Lp !< plastic velocity gradient -real(pReal), dimension(9,9), intent(out) :: dLp_dTstar99 !< derivative of Lp with respect to Tstar (9x9 matrix) +real(pReal), dimension(3,3,3,3), intent(out) :: dLp_dMp !< derivative of Lp with respect to Tstar (9x9 matrix) !*** local variables integer(pInt) instance, & !< current instance of this plasticity @@ -1717,7 +1688,6 @@ integer(pInt) instance, & t, & !< dislocation type s, & !< index of my current slip system sLattice !< index of my current slip system according to lattice order -real(pReal), dimension(3,3,3,3) :: dLp_dTstar3333 !< derivative of Lp with respect to Tstar (3x3x3x3 matrix) real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),8) :: & rhoSgl !< single dislocation densities (including blocked) real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),4) :: & @@ -1737,7 +1707,7 @@ of = phasememberAt(1_pInt,ip,el) !*** initialize local variables Lp = 0.0_pReal -dLp_dTstar3333 = 0.0_pReal +dLp_dMp = 0.0_pReal instance = phase_plasticityInstance(ph) associate(prm => param(instance)) @@ -1762,16 +1732,15 @@ tauThreshold = plasticState(ph)%state(iTauF(1:ns,instance),of) !*** for screws possible non-schmid contributions are also taken into account do s = 1_pInt,ns - sLattice = slipSystemLattice(s,instance) - tau(s) = math_mul6x6(Tstar_v, lattice_Sslip_v(1:6,1,sLattice,ph)) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) tauNS(s,1) = tau(s) tauNS(s,2) = tau(s) if (tau(s) > 0.0_pReal) then - tauNS(s,3) = math_mul33xx33(math_6toSym33(Tstar_v), nonSchmidProjection(1:3,1:3,1,s,instance)) - tauNS(s,4) = math_mul33xx33(math_6toSym33(Tstar_v), nonSchmidProjection(1:3,1:3,3,s,instance)) + tauNS(s,3) = math_mul33xx33(Mp, +prm%nonSchmid_pos(1:3,1:3,s)) + tauNS(s,4) = math_mul33xx33(Mp, -prm%nonSchmid_neg(1:3,1:3,s)) else - tauNS(s,3) = math_mul33xx33(math_6toSym33(Tstar_v), nonSchmidProjection(1:3,1:3,2,s,instance)) - tauNS(s,4) = math_mul33xx33(math_6toSym33(Tstar_v), nonSchmidProjection(1:3,1:3,4,s,instance)) + tauNS(s,3) = math_mul33xx33(Mp, +prm%nonSchmid_neg(1:3,1:3,s)) + tauNS(s,4) = math_mul33xx33(Mp, -prm%nonSchmid_pos(1:3,1:3,s)) endif enddo forall (t = 1_pInt:4_pInt) & @@ -1790,7 +1759,7 @@ dv_dtau(1:ns,2) = dv_dtau(1:ns,1) dv_dtauNS(1:ns,2) = dv_dtauNS(1:ns,1) !screws -if (lattice_NnonSchmid(ph) == 0_pInt) then ! no non-Schmid contributions +if (size(prm%nonSchmidCoeff) == 0_pInt) then ! no non-Schmid contributions forall(t = 3_pInt:4_pInt) v(1:ns,t) = v(1:ns,1) dv_dtau(1:ns,t) = dv_dtau(1:ns,1) @@ -1817,47 +1786,37 @@ forall (s = 1_pInt:ns, t = 5_pInt:8_pInt, rhoSgl(s,t) * v(s,t-4_pInt) < 0.0_pRea !*** Calculation of Lp and its tangent -gdotTotal = sum(rhoSgl(1:ns,1:4) * v, 2) * burgers(1:ns,instance) +gdotTotal = sum(rhoSgl(1:ns,1:4) * v, 2) * prm%burgers(1:ns) do s = 1_pInt,ns - sLattice = slipSystemLattice(s,instance) - Lp = Lp + gdotTotal(s) * lattice_Sslip(1:3,1:3,1,sLattice,ph) + Lp = Lp + gdotTotal(s) * prm%Schmid(1:3,1:3,s) ! Schmid contributions to tangent forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLp_dTstar3333(i,j,k,l) = dLp_dTstar3333(i,j,k,l) & - + lattice_Sslip(i,j,1,sLattice,ph) * lattice_Sslip(k,l,1,sLattice,ph) & - * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * burgers(s,instance) + dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & + + prm%Schmid(i,j,s) * prm%Schmid(k,l,s) & + * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * prm%burgers(s) + ! non Schmid contributions to tangent if (tau(s) > 0.0_pReal) then forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLp_dTstar3333(i,j,k,l) = dLp_dTstar3333(i,j,k,l) & - + lattice_Sslip(i,j,1,sLattice,ph) & - * ( nonSchmidProjection(k,l,1,s,instance) * rhoSgl(s,3) * dv_dtauNS(s,3) & - + nonSchmidProjection(k,l,3,s,instance) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & - * burgers(s,instance) + dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & + + prm%Schmid(i,j,s) & + * ( prm%nonSchmid_pos(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & + - prm%nonSchmid_neg(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & + * prm%burgers(s) else forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLp_dTstar3333(i,j,k,l) = dLp_dTstar3333(i,j,k,l) & - + lattice_Sslip(i,j,1,sLattice,ph) & - * ( nonSchmidProjection(k,l,2,s,instance) * rhoSgl(s,3) * dv_dtauNS(s,3) & - + nonSchmidProjection(k,l,4,s,instance) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & - * burgers(s,instance) + dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & + + prm%Schmid(i,j,s) & + * ( prm%nonSchmid_neg(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & + - prm%nonSchmid_pos(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & + * prm%burgers(s) endif enddo -dLp_dTstar99 = math_3333to99(dLp_dTstar3333) -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0_pInt )) then - write(6,'(/,a,i8,1x,i2,1x,i1,/)') '<< CONST >> nonlocal_LpandItsTangent at el ip',el,ip - write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> gdot total',gdotTotal - write(6,'(a,/,3(12x,3(f12.7,1x),/))') '<< CONST >> Lp',transpose(Lp) - endif -#endif end associate end subroutine plastic_nonlocal_LpAndItsTangent @@ -1866,7 +1825,7 @@ end subroutine plastic_nonlocal_LpAndItsTangent !-------------------------------------------------------------------------------------------------- !> @brief (instantaneous) incremental change of microstructure !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_deltaState(Tstar_v,ip,el) +subroutine plastic_nonlocal_deltaState(Mp,ip,el) use prec, only: & dNeq0 use debug, only: debug_level, & @@ -1877,9 +1836,8 @@ use debug, only: debug_level, & debug_i, & debug_e use math, only: pi, & - math_mul6x6 -use lattice, only: lattice_Sslip_v ,& - lattice_mu, & + math_mul33xx33 +use lattice, only: lattice_mu, & lattice_nu use mesh, only: mesh_ipVolume use material, only: material_phase, & @@ -1890,7 +1848,7 @@ use material, only: material_phase, & implicit none integer(pInt), intent(in) :: ip, & ! current grain number el ! current element number -real(pReal), dimension(6), intent(in) :: Tstar_v ! current 2nd Piola-Kirchhoff stress in Mandel notation +real(pReal), dimension(3,3), intent(in) :: Mp !< MandelStress integer(pInt) :: & @@ -1931,6 +1889,7 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,e ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) + associate(prm => param(instance)) ns = totalNslip(instance) @@ -1980,8 +1939,7 @@ enddo !*** calculate limits for stable dipole height do s = 1_pInt,ns - sLattice = slipSystemLattice(s,instance) - tau(s) = math_mul6x6(Tstar_v, lattice_Sslip_v(1:6,1,sLattice,ph)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo dLower = minDipoleHeight(1:ns,1:2,instance) @@ -2042,13 +2000,14 @@ forall (s = 1:ns, c = 1_pInt:2_pInt) & write(6,'(a,/,10(12x,12(e12.5,1x),/),/)') '<< CONST >> dipole dissociation by stress increase', deltaRhoDipole2SingleStress endif #endif + end associate end subroutine plastic_nonlocal_deltaState !--------------------------------------------------------------------------------------------------- !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_dotState(Tstar_v, Fe, Fp, Temperature, & +subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & timestep,subfrac, ip,el) use, intrinsic :: & IEEE_arithmetic @@ -2065,9 +2024,9 @@ use debug, only: debug_level, & debug_g, & debug_i, & debug_e -use math, only: math_mul6x6, & - math_mul3x3, & +use math, only: math_mul3x3, & math_mul33x3, & + math_mul33xx33, & math_mul33x33, & math_inv33, & math_det33, & @@ -2086,8 +2045,7 @@ use material, only: homogenization_maxNgrains, & phaseAt, phasememberAt, & phase_plasticity ,& PLASTICITY_NONLOCAL_ID -use lattice, only: lattice_Sslip_v, & - lattice_sd, & +use lattice, only: lattice_sd, & lattice_st ,& lattice_mu, & lattice_nu, & @@ -2102,7 +2060,7 @@ integer(pInt), intent(in) :: ip, & el !< current element number real(pReal), intent(in) :: Temperature, & !< temperature timestep !< substepped crystallite time increment -real(pReal), dimension(6), intent(in) :: Tstar_v !< current 2nd Piola-Kirchhoff stress in Mandel notation +real(pReal), dimension(3,3), intent(in) :: Mp !< MandelStress real(pReal), dimension(homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & subfrac !< fraction of timestep at the beginning of the substepped crystallite time increment real(pReal), dimension(3,3,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & @@ -2198,6 +2156,7 @@ logical considerEnteringFlux, & ph = material_phase(1_pInt,ip,el) instance = phase_plasticityInstance(ph) +associate(prm => param(instance)) ns = totalNslip(instance) tau = 0.0_pReal @@ -2271,8 +2230,7 @@ forall (t = 1_pInt:4_pInt) & !*** calculate limits for stable dipole height do s = 1_pInt,ns ! loop over slip systems - sLattice = slipSystemLattice(s,instance) - tau(s) = math_mul6x6(Tstar_v, lattice_Sslip_v(1:6,1,sLattice,ph)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo @@ -2661,7 +2619,7 @@ else forall (s = 1:ns) & plasticState(p)%dotState(iGamma(s,instance),o) = sum(gdot(s,1:4)) endif - + end associate end subroutine plastic_nonlocal_dotState @@ -2831,13 +2789,12 @@ end subroutine plastic_nonlocal_updateCompatibility !-------------------------------------------------------------------------------------------------- !> @brief return array of constitutive results !-------------------------------------------------------------------------------------------------- -function plastic_nonlocal_postResults(Tstar_v,Fe,ip,el) +function plastic_nonlocal_postResults(Mp,Fe,ip,el) use prec, only: & dNeq0 use math, only: & - math_mul6x6, & math_mul33x3, & - math_mul33x33, & + math_mul33xx33, & pi use mesh, only: & theMesh @@ -2848,7 +2805,6 @@ function plastic_nonlocal_postResults(Tstar_v,Fe,ip,el) plasticState, & phase_plasticityInstance use lattice, only: & - lattice_Sslip_v, & lattice_sd, & lattice_st, & lattice_sn, & @@ -2856,8 +2812,7 @@ function plastic_nonlocal_postResults(Tstar_v,Fe,ip,el) lattice_nu implicit none - real(pReal), dimension(6), intent(in) :: & - Tstar_v !< 2nd Piola Kirchhoff stress tensor in Mandel notation + real(pReal), dimension(3,3), intent(in) :: Mp !< MandelStress real(pReal), dimension(3,3,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & Fe !< elastic deformation gradient integer(pInt), intent(in) :: & @@ -2910,7 +2865,7 @@ ns = totalNslip(instance) cs = 0_pInt plastic_nonlocal_postResults = 0.0_pReal - +associate(prm => param(instance)) !* short hand notations for state variables forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) @@ -2937,8 +2892,7 @@ forall (t = 1_pInt:4_pInt) & !* calculate limits for stable dipole height do s = 1_pInt,ns - sLattice = slipSystemLattice(s,instance) - tau(s) = math_mul6x6(Tstar_v, lattice_Sslip_v(1:6,1,sLattice,ph)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo @@ -3029,8 +2983,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) case (resolvedstress_external_ID) do s = 1_pInt,ns - sLattice = slipSystemLattice(s,instance) - plastic_nonlocal_postResults(cs+s) = math_mul6x6(Tstar_v, lattice_Sslip_v(1:6,1,sLattice,ph)) + plastic_nonlocal_postResults(cs+s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) enddo cs = cs + ns @@ -3053,7 +3006,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) case (rho_dot_gen_ID) ! Obsolete plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) + + rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_gen_edge_ID) @@ -3074,7 +3027,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) case (rho_dot_ann_ath_ID) plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotAthermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotAthermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) + + rhoDotAthermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_ann_the_edge_ID) @@ -3133,7 +3086,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) end select enddo outputsLoop - +end associate end function plastic_nonlocal_postResults end module plastic_nonlocal From 7ad866b90fe8f1d3c1157736a16c5e212e43bb71 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 12:16:12 +0100 Subject: [PATCH 41/97] not needed any more --- src/lattice.f90 | 79 +++++-------------------------------------------- src/math.f90 | 12 +------- 2 files changed, 9 insertions(+), 82 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 9be30a5d3..70f4443ce 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -27,11 +27,9 @@ module lattice lattice_interactionSlipSlip !< Slip--slip interaction type real(pReal), allocatable, dimension(:,:,:,:,:), protected, public :: & - lattice_Sslip, & !< Schmid and non-Schmid matrices lattice_Scleavage !< Schmid matrices for cleavage systems real(pReal), allocatable, dimension(:,:,:,:), protected, public :: & - lattice_Sslip_v, & !< Mandel notation of lattice_Sslip lattice_Scleavage_v !< Mandel notation of lattice_Scleavege real(pReal), allocatable, dimension(:,:,:), protected, public :: & @@ -39,8 +37,6 @@ module lattice lattice_st, & !< sd x sn lattice_sd !< slip direction of slip system - integer(pInt), allocatable, dimension(:), protected, public :: & - lattice_NnonSchmid !< total # of non-Schmid contributions for each structure ! END DEPRECATED @@ -726,14 +722,8 @@ contains !> @brief Module initialization !-------------------------------------------------------------------------------------------------- subroutine lattice_init -#if defined(__GFORTRAN__) || __INTEL_COMPILER >= 1800 - use, intrinsic :: iso_fortran_env, only: & - compiler_version, & - compiler_options -#endif use IO, only: & - IO_error, & - IO_timeStamp + IO_error use config, only: & config_phase @@ -748,8 +738,6 @@ subroutine lattice_init write(6,'(/,a)') ' <<<+- lattice init -+>>>' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" Nphases = size(config_phase) @@ -769,9 +757,6 @@ subroutine lattice_init allocate(lattice_mu(Nphases), source=0.0_pReal) allocate(lattice_nu(Nphases), source=0.0_pReal) - allocate(lattice_NnonSchmid(Nphases), source=0_pInt) - allocate(lattice_Sslip(3,3,1+2*lattice_maxNnonSchmid,lattice_maxNslip,Nphases),source=0.0_pReal) - allocate(lattice_Sslip_v(6,1+2*lattice_maxNnonSchmid,lattice_maxNslip,Nphases),source=0.0_pReal) allocate(lattice_NslipSystem(lattice_maxNslipFamily,Nphases),source=0_pInt) allocate(lattice_interactionSlipSlip(lattice_maxNslip,lattice_maxNslip,Nphases),source=0_pInt) ! other:me @@ -863,34 +848,22 @@ subroutine lattice_initializeStructure(myPhase,CoverA) use prec, only: & tol_math_check use math, only: & - math_crossproduct, & - math_tensorproduct33, & math_mul33x33, & - math_mul33x3, & - math_trace33, & math_symmetric33, & math_sym33to6, & math_sym3333to66, & math_Voigt66to3333, & - math_axisAngleToR, & - INRAD, & - MATH_I3 + math_crossproduct use IO, only: & - IO_error, & - IO_warning + IO_error implicit none integer(pInt), intent(in) :: myPhase real(pReal), intent(in) :: & CoverA - real(pReal), dimension(3) :: & - sdU, snU, & - np, nn real(pReal), dimension(3,lattice_maxNslip) :: & sd, sn - real(pReal), dimension(3,3,2,lattice_maxNnonSchmid,lattice_maxNslip) :: & - sns integer(pInt) :: & j, i, & myNslip, myNcleavage @@ -951,34 +924,11 @@ subroutine lattice_initializeStructure(myPhase,CoverA) myNcleavage = lattice_bcc_Ncleavage lattice_NslipSystem(1:lattice_maxNslipFamily,myPhase) = lattice_bcc_NslipSystem lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,myPhase) = lattice_bcc_NcleavageSystem - lattice_NnonSchmid(myPhase) = lattice_bcc_NnonSchmid lattice_interactionSlipSlip(1:myNslip,1:myNslip,myPhase) = lattice_bcc_interactionSlipSlip lattice_Scleavage(1:3,1:3,1:3,1:myNcleavage,myPhase) = & lattice_SchmidMatrix_cleavage(lattice_bcc_ncleavagesystem,'bcc',covera) - do i = 1_pInt,myNslip ! assign slip system vectors - sd(1:3,i) = lattice_bcc_systemSlip(1:3,i) - sn(1:3,i) = lattice_bcc_systemSlip(4:6,i) - sdU = sd(1:3,i) / norm2(sd(1:3,i)) - snU = sn(1:3,i) / norm2(sn(1:3,i)) - ! "np" and "nn" according to Gröger_etal2008, Acta Materialia 56 (2008) 5412–5425, table 1 (corresponds to their "n1" for positive and negative slip direction respectively) - np = math_mul33x3(math_axisAngleToR(sdU,60.0_pReal*INRAD), snU) - nn = math_mul33x3(math_axisAngleToR(-sdU,60.0_pReal*INRAD), snU) - ! Schmid matrices with non-Schmid contributions according to Koester_etal2012, Acta Materialia 60 (2012) 3894–3901, eq. (17) ("n1" is replaced by either "np" or "nn" according to either positive or negative slip direction) - sns(1:3,1:3,1,1,i) = math_tensorproduct33(sdU, np) - sns(1:3,1:3,2,1,i) = math_tensorproduct33(-sdU, nn) - sns(1:3,1:3,1,2,i) = math_tensorproduct33(math_crossproduct(snU, sdU), snU) - sns(1:3,1:3,2,2,i) = math_tensorproduct33(math_crossproduct(snU, -sdU), snU) - sns(1:3,1:3,1,3,i) = math_tensorproduct33(math_crossproduct(np, sdU), np) - sns(1:3,1:3,2,3,i) = math_tensorproduct33(math_crossproduct(nn, -sdU), nn) - sns(1:3,1:3,1,4,i) = math_tensorproduct33(snU, snU) - sns(1:3,1:3,2,4,i) = math_tensorproduct33(snU, snU) - sns(1:3,1:3,1,5,i) = math_tensorproduct33(math_crossproduct(snU, sdU), math_crossproduct(snU, sdU)) - sns(1:3,1:3,2,5,i) = math_tensorproduct33(math_crossproduct(snU, -sdU), math_crossproduct(snU, -sdU)) - sns(1:3,1:3,1,6,i) = math_tensorproduct33(sdU, sdU) - sns(1:3,1:3,2,6,i) = math_tensorproduct33(-sdU, -sdU) - enddo !-------------------------------------------------------------------------------------------------- ! hex (including conversion from miller-bravais (a1=a2=a3=c) to miller (a, b, c) indices) @@ -1014,8 +964,6 @@ subroutine lattice_initializeStructure(myPhase,CoverA) sd(3,i) = lattice_bct_systemSlip(3,i)*CoverA sn(1:2,i) = lattice_bct_systemSlip(4:5,i) sn(3,i) = lattice_bct_systemSlip(6,i)/CoverA - sdU = sd(1:3,i) / norm2(sd(1:3,i)) - snU = sn(1:3,i) / norm2(sn(1:3,i)) enddo !-------------------------------------------------------------------------------------------------- @@ -1046,18 +994,7 @@ subroutine lattice_initializeStructure(myPhase,CoverA) do i = 1_pInt,myNslip ! store slip system vectors and Schmid matrix for my structure lattice_sd(1:3,i,myPhase) = sd(1:3,i)/norm2(sd(1:3,i)) ! make unit vector lattice_sn(1:3,i,myPhase) = sn(1:3,i)/norm2(sn(1:3,i)) ! make unit vector - lattice_st(1:3,i,myPhase) = math_crossproduct(lattice_sd(1:3,i,myPhase), & - lattice_sn(1:3,i,myPhase)) - lattice_Sslip(1:3,1:3,1,i,myPhase) = math_tensorproduct33(lattice_sd(1:3,i,myPhase), & - lattice_sn(1:3,i,myPhase)) ! calculate Schmid matrix d \otimes n - do j = 1_pInt,lattice_NnonSchmid(myPhase) - lattice_Sslip(1:3,1:3,2*j ,i,myPhase) = sns(1:3,1:3,1,j,i) - lattice_Sslip(1:3,1:3,2*j+1,i,myPhase) = sns(1:3,1:3,2,j,i) - enddo - do j = 1_pInt,1_pInt+2_pInt*lattice_NnonSchmid(myPhase) - lattice_Sslip_v(1:6,j,i,myPhase) = & - math_sym33to6(math_symmetric33(lattice_Sslip(1:3,1:3,j,i,myPhase))) - enddo + lattice_st(1:3,i,myPhase) = math_crossproduct(lattice_sd(1:3,i,myPhase),lattice_sn(1:3,i,myPhase)) enddo do i = 1_pInt,myNcleavage ! store slip system vectors and Schmid matrix for my structure @@ -1462,8 +1399,8 @@ function lattice_C66_trans(Ntrans,C_parent66,structure_target, & INRAD, & MATH_I3, & math_axisAngleToR, & - math_Mandel3333to66, & - math_Mandel66to3333, & + math_sym3333to66, & + math_66toSym3333, & math_rotate_forward3333, & math_mul33x33, & math_tensorproduct33, & @@ -1514,11 +1451,11 @@ function lattice_C66_trans(Ntrans,C_parent66,structure_target, & if (abs(C_target_unrotated66(i,i)) Date: Sun, 17 Feb 2019 13:16:00 +0100 Subject: [PATCH 42/97] stress tensor was accidentally still converted --- src/constitutive.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 88d521af9..d73d694a7 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -882,7 +882,7 @@ subroutine constitutive_collectDotState(S6, FeArray, Fi, FpArray, subdt, subfrac call plastic_disloucla_dotState (Mp,temperature(ho)%p(tme),instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_dotState (math_sym33to6(Mp),FeArray,FpArray,temperature(ho)%p(tme), & + call plastic_nonlocal_dotState (Mp,FeArray,FpArray,temperature(ho)%p(tme), & subdt,subfracArray,ip,el) end select plasticityType @@ -965,7 +965,7 @@ subroutine constitutive_collectDeltaState(S, Fe, Fi, ipc, ip, el) call plastic_kinehardening_deltaState(Mp,instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_deltaState(math_sym33to6(Mp),ip,el) + call plastic_nonlocal_deltaState(Mp,ip,el) end select plasticityType From d3e6430b9480ac9d10fb325db2d2b6b2a78849f2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 14:30:58 +0100 Subject: [PATCH 43/97] only used internally --- src/lattice.f90 | 51 ++++++++++++++++++++-------------------- src/plastic_nonlocal.f90 | 13 +++++----- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 70f4443ce..7ee6ed54c 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -42,16 +42,16 @@ module lattice !-------------------------------------------------------------------------------------------------- ! face centered cubic - integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, private :: & LATTICE_FCC_NSLIPSYSTEM = int([12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],pInt) !< # of slip systems per family for fcc - integer(pInt), dimension(1), parameter, public :: & + integer(pInt), dimension(1), parameter, private :: & LATTICE_FCC_NTWINSYSTEM = int([12],pInt) !< # of twin systems per family for fcc - integer(pInt), dimension(1), parameter, public :: & + integer(pInt), dimension(1), parameter, private :: & LATTICE_FCC_NTRANSSYSTEM = int([12],pInt) !< # of transformation systems per family for fcc - integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, private :: & LATTICE_FCC_NCLEAVAGESYSTEM = int([3, 4, 0],pInt) !< # of cleavage systems per family for fcc integer(pInt), parameter, private :: & @@ -84,7 +84,7 @@ module lattice 0, 1,-1, 0, 1, 1 & ],pReal),shape(LATTICE_FCC_SYSTEMSLIP)) !< Slip system <110>{111} directions. Sorted according to Eisenlohr & Hantcherli - character(len=*), dimension(2), parameter, public :: LATTICE_FCC_SLIPFAMILY_NAME = & + character(len=*), dimension(2), parameter, private :: LATTICE_FCC_SLIPFAMILY_NAME = & ['<0 1 -1>{1 1 1}', & '<0 1 -1>{0 1 1}'] @@ -104,11 +104,11 @@ module lattice -1, 1, 2, -1, 1,-1 & ],pReal),shape(LATTICE_FCC_SYSTEMTWIN)) !< Twin system <112>{111} directions. Sorted according to Eisenlohr & Hantcherli - character(len=*), dimension(1), parameter, public :: LATTICE_FCC_TWINFAMILY_NAME = & + character(len=*), dimension(1), parameter, private :: LATTICE_FCC_TWINFAMILY_NAME = & ['<-2 1 1>{1 1 1}'] - integer(pInt), dimension(2_pInt,LATTICE_FCC_NTWIN), parameter, public :: & + integer(pInt), dimension(2_pInt,LATTICE_FCC_NTWIN), parameter, private :: & LATTICE_FCC_TWINNUCLEATIONSLIPPAIR = reshape(int( [& 2,3, & 1,3, & @@ -125,7 +125,7 @@ module lattice ],pInt),shape(LATTICE_FCC_TWINNUCLEATIONSLIPPAIR)) ! ToDo: should be in the interaction function - integer(pInt), dimension(LATTICE_FCC_NSLIP,LATTICE_FCC_NSLIP), parameter, public :: & + integer(pInt), dimension(LATTICE_FCC_NSLIP,LATTICE_FCC_NSLIP), parameter, private :: & LATTICE_FCC_INTERACTIONSLIPSLIP = reshape(int( [& 1, 2, 2, 4, 6, 5, 3, 5, 5, 4, 5, 6, 9,10, 9,10,11,12, & ! ---> slip 2, 1, 2, 6, 4, 5, 5, 4, 6, 5, 3, 5, 9,10,11,12, 9,10, & ! | @@ -174,13 +174,13 @@ module lattice !-------------------------------------------------------------------------------------------------- ! body centered cubic - integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, private :: & LATTICE_BCC_NSLIPSYSTEM = int([ 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], pInt) !< # of slip systems per family for bcc - integer(pInt), dimension(1), parameter, public :: & + integer(pInt), dimension(1), parameter, private :: & LATTICE_BCC_NTWINSYSTEM = int([12], pInt) !< # of twin systems per family for bcc - integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, private :: & LATTICE_bcc_NcleavageSystem = int([3, 6, 0],pInt) !< # of cleavage systems per family for bcc integer(pInt), parameter, private :: & @@ -220,7 +220,7 @@ module lattice 1, 1, 1, 1, 1,-2 & ],pReal),shape(LATTICE_BCC_SYSTEMSLIP)) - character(len=*), dimension(2), parameter, public :: LATTICE_BCC_SLIPFAMILY_NAME = & + character(len=*), dimension(2), parameter, private :: LATTICE_BCC_SLIPFAMILY_NAME = & ['<1 -1 1>{0 1 1}', & '<1 -1 1>{2 1 1}'] @@ -241,12 +241,12 @@ module lattice 1, 1, 1, 1, 1,-2 & ],pReal),shape(LATTICE_BCC_SYSTEMTWIN)) - character(len=*), dimension(1), parameter, public :: LATTICE_BCC_TWINFAMILY_NAME = & + character(len=*), dimension(1), parameter, private :: LATTICE_BCC_TWINFAMILY_NAME = & ['<1 1 1>{2 1 1}'] - integer(pInt), dimension(LATTICE_BCC_NSLIP,LATTICE_BCC_NSLIP), parameter, public :: & + integer(pInt), dimension(LATTICE_BCC_NSLIP,LATTICE_BCC_NSLIP), parameter, private :: & LATTICE_bcc_interactionSlipSlip = reshape(int( [& 1,2,6,6,5,4,4,3,4,3,5,4, 6,6,4,3,3,4,6,6,4,3,6,6, & ! ---> slip 2,1,6,6,4,3,5,4,5,4,4,3, 6,6,3,4,4,3,6,6,3,4,6,6, & ! | @@ -297,13 +297,13 @@ module lattice !-------------------------------------------------------------------------------------------------- ! hexagonal - integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, private :: & LATTICE_HEX_NSLIPSYSTEM = int([ 3, 3, 3, 6, 12, 6, 0, 0, 0, 0, 0, 0, 0],pInt) !< # of slip systems per family for hex - integer(pInt), dimension(4), parameter, public :: & + integer(pInt), dimension(4), parameter, private :: & LATTICE_HEX_NTWINSYSTEM = int([ 6, 6, 6, 6],pInt) !< # of slip systems per family for hex - integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, private :: & LATTICE_hex_NcleavageSystem = int([3, 0, 0],pInt) !< # of cleavage systems per family for hex integer(pInt), parameter, private :: & @@ -355,7 +355,7 @@ module lattice 1, 1, -2, 3, -1, -1, 2, 2 & ],pReal),shape(LATTICE_HEX_SYSTEMSLIP)) !< slip systems for hex sorted by A. Alankar & P. Eisenlohr - character(len=*), dimension(6), parameter, public :: LATTICE_HEX_SLIPFAMILY_NAME = & + character(len=*), dimension(6), parameter, private :: LATTICE_HEX_SLIPFAMILY_NAME = & ['<1 1 . 1>{0 0 . 1} ', & '<1 1 . 1>{1 0 . 0} ', & '<1 0 . 0>{1 1 . 0} ', & @@ -395,14 +395,14 @@ module lattice 1, 1, -2, -3, 1, 1, -2, 2 & ],pReal),shape(LATTICE_HEX_SYSTEMTWIN)) !< twin systems for hex, order follows Prof. Tom Bieler's scheme; but numbering in data was restarted from 1 - character(len=*), dimension(4), parameter, public :: LATTICE_HEX_TWINFAMILY_NAME = & + character(len=*), dimension(4), parameter, private :: LATTICE_HEX_TWINFAMILY_NAME = & ['<-1 0 . 1>{1 0 . 2} ', & '<1 1 . 6>{-1 -1 . 1}', & '<1 0 . -2>{1 0 . 1} ', & '<1 1 . -3>{1 1 . 2} '] - integer(pInt), dimension(LATTICE_HEX_NSLIP,LATTICE_HEX_NSLIP), parameter, public :: & + integer(pInt), dimension(LATTICE_HEX_NSLIP,LATTICE_HEX_NSLIP), parameter, private :: & LATTICE_hex_interactionSlipSlip = reshape(int( [& 1, 2, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! ---> slip 2, 1, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! | @@ -456,7 +456,7 @@ module lattice !-------------------------------------------------------------------------------------------------- ! body centered tetragonal - integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNslipFamily), parameter, private :: & LATTICE_bct_NslipSystem = int([2, 2, 2, 4, 2, 4, 2, 2, 4, 8, 4, 8, 8 ],pInt) !< # of slip systems per family for bct (Sn) Bieler J. Electr Mater 2009 integer(pInt), parameter, private :: & @@ -532,7 +532,7 @@ module lattice 1, 1, 1, 1,-2, 1 & ],pReal),[ 3_pInt + 3_pInt,LATTICE_bct_Nslip]) !< slip systems for bct sorted by Bieler - character(len=*), dimension(13), parameter, public :: LATTICE_BCT_SLIPFAMILY_NAME = & + character(len=*), dimension(13), parameter, private :: LATTICE_BCT_SLIPFAMILY_NAME = & ['{1 0 0)<0 0 1] ', & '{1 1 0)<0 0 1] ', & '{1 0 0)<0 1 0] ', & @@ -547,7 +547,7 @@ module lattice '{2 1 1)<0 1 -1]', & '{2 1 1)<-1 1 1]'] - integer(pInt), dimension(LATTICE_bct_Nslip,LATTICE_bct_Nslip), parameter, public :: & + integer(pInt), dimension(LATTICE_bct_Nslip,LATTICE_bct_Nslip), parameter, private :: & LATTICE_bct_interactionSlipSlip = reshape(int( [& 1, 2, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & 2, 1, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & @@ -618,7 +618,7 @@ module lattice !-------------------------------------------------------------------------------------------------- ! isotropic - integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, private :: & LATTICE_iso_NcleavageSystem = int([3, 0, 0],pInt) !< # of cleavage systems per family for iso integer(pInt), parameter, private :: & @@ -635,7 +635,7 @@ module lattice !-------------------------------------------------------------------------------------------------- ! orthorhombic - integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, public :: & + integer(pInt), dimension(LATTICE_maxNcleavageFamily), parameter, private :: & LATTICE_ort_NcleavageSystem = int([1, 1, 1],pInt) !< # of cleavage systems per family for ortho integer(pInt), parameter, private :: & @@ -653,7 +653,6 @@ module lattice integer(pInt), parameter, public :: & LATTICE_maxNslip = max(LATTICE_FCC_NSLIP,LATTICE_BCC_NSLIP,LATTICE_HEX_NSLIP, & LATTICE_bct_Nslip), & !< max # of slip systems over lattice structures - LATTICE_maxNnonSchmid = LATTICE_bcc_NnonSchmid, & !< max # of non-Schmid contributions over lattice structures LATTICE_maxNcleavage = max(LATTICE_fcc_Ncleavage,LATTICE_bcc_Ncleavage, & LATTICE_hex_Ncleavage, & LATTICE_iso_Ncleavage,LATTICE_ort_Ncleavage), & !< max # of cleavage systems over lattice structures diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 4a2d6b42f..733834beb 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -915,7 +915,7 @@ param(instance)%probabilisticMultiplication = .false. prm%significantRho = config_phase(p)%getFloat('significantrho')!,'significant_rho','significantdensity','significant_density') - prm%significantN = config_phase(p)%getFloat('significantn', 0.0_pReal)!,'significant_n','significantdislocations','significant_dislcations') + prm%significantN = config_phase(p)%getFloat('significantn', 0.0_pReal)!,'significant_n','significantdislocations','significant_dislcations') @@ -1035,7 +1035,7 @@ param(instance)%probabilisticMultiplication = .false. if (outputID /= undefined_ID) then plastic_nonlocal_output(i,instance) = outputs(i) - plastic_nonlocal_sizePostResult(i,instance) = totalNslip(instance) + plastic_nonlocal_sizePostResult(i,instance) = prm%totalNslip prm%outputID = [prm%outputID , outputID] endif @@ -1645,7 +1645,8 @@ end subroutine plastic_nonlocal_kinetics !-------------------------------------------------------------------------------------------------- !> @brief calculates plastic velocity gradient and its tangent !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, Mp, Temperature, ip, el) +subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & + Mp, Temperature, ip, el) use math, only: math_3333to99, & math_mul6x6, & @@ -1704,10 +1705,7 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt ph = phaseAt(1_pInt,ip,el) of = phasememberAt(1_pInt,ip,el) -!*** initialize local variables -Lp = 0.0_pReal -dLp_dMp = 0.0_pReal instance = phase_plasticityInstance(ph) associate(prm => param(instance)) @@ -1788,6 +1786,9 @@ forall (s = 1_pInt:ns, t = 5_pInt:8_pInt, rhoSgl(s,t) * v(s,t-4_pInt) < 0.0_pRea gdotTotal = sum(rhoSgl(1:ns,1:4) * v, 2) * prm%burgers(1:ns) +Lp = 0.0_pReal +dLp_dMp = 0.0_pReal + do s = 1_pInt,ns Lp = Lp + gdotTotal(s) * prm%Schmid(1:3,1:3,s) From c4b3ac3afb360748aaa16d12050952332469d943 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 17:04:26 +0100 Subject: [PATCH 44/97] slip system definition for bcc still needed --- src/lattice.f90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 7ee6ed54c..07f8aed82 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -108,7 +108,7 @@ module lattice ['<-2 1 1>{1 1 1}'] - integer(pInt), dimension(2_pInt,LATTICE_FCC_NTWIN), parameter, private :: & + integer(pInt), dimension(2_pInt,LATTICE_FCC_NTWIN), parameter, public :: & LATTICE_FCC_TWINNUCLEATIONSLIPPAIR = reshape(int( [& 2,3, & 1,3, & @@ -928,6 +928,10 @@ subroutine lattice_initializeStructure(myPhase,CoverA) lattice_Scleavage(1:3,1:3,1:3,1:myNcleavage,myPhase) = & lattice_SchmidMatrix_cleavage(lattice_bcc_ncleavagesystem,'bcc',covera) + do i = 1_pInt,myNslip + sd(1:3,i) = lattice_bcc_systemSlip(1:3,i) + sn(1:3,i) = lattice_bcc_systemSlip(4:6,i) + enddo !-------------------------------------------------------------------------------------------------- ! hex (including conversion from miller-bravais (a1=a2=a3=c) to miller (a, b, c) indices) From 44e41465d07d7a6b73cff6f58d3bfc32ff321e1d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 17:56:01 +0100 Subject: [PATCH 45/97] use functions from lattice to calculate slip systems don't rely on internal coding for collinear systems --- src/plastic_nonlocal.f90 | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 733834beb..8727e576c 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -85,8 +85,8 @@ module plastic_nonlocal lambda0PerSlipFamily, & !< mean free path prefactor for each family and instance lambda0, & !< mean free path prefactor for each slip system and instance burgersPerSlipFamily, & !< absolute length of burgers vector [m] for each family and instance - burgers, & !< absolute length of burgers vector [m] for each slip system and instance - interactionSlipSlip !< coefficients for slip-slip interaction for each interaction type and instance + burgers !< absolute length of burgers vector [m] for each slip system and instance + real(pReal), dimension(:,:,:), allocatable, private :: & minDipoleHeightPerSlipFamily, & !< minimum stable edge/screw dipole height for each family and instance @@ -94,8 +94,7 @@ module plastic_nonlocal peierlsStressPerSlipFamily, & !< Peierls stress (edge and screw) peierlsStress, & !< Peierls stress (edge and screw) forestProjectionEdge, & !< matrix of forest projections of edge dislocations for each instance - forestProjectionScrew, & !< matrix of forest projections of screw dislocations for each instance - interactionMatrixSlipSlip !< interaction matrix of the different slip systems for each instance + forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance real(pReal), dimension(:,:,:,:), allocatable, private :: & lattice2slip, & !< orthogonal transformation matrix from lattice coordinate system to slip coordinate system (passive rotation !!!) @@ -259,6 +258,7 @@ contains !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_init(fileUnit) +use prec, only: dEq use math, only: math_Voigt66to3333, & math_mul3x3, & math_expand @@ -388,7 +388,6 @@ allocate(rhoDipEdge0(lattice_maxNslipFamily,maxNinstances), s allocate(rhoDipScrew0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(burgersPerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) -allocate(interactionSlipSlip(lattice_maxNinteraction,maxNinstances), source=0.0_pReal) allocate(minDipoleHeightPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=-1.0_pReal) allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=0.0_pReal) @@ -408,10 +407,8 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s endif if (IO_getTag(line,'[',']') /= '') then ! next phase phase = phase + 1_pInt ! advance phase section counter - if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then + if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) & Nchunks_SlipFamilies = count(lattice_NslipSystem(:,phase) > 0_pInt) - Nchunks_SlipSlip = maxval(lattice_InteractionSlipSlip(:,:,phase)) - endif cycle endif if (phase > 0_pInt ) then; if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then ! one of my phases. do not short-circuit here (.and. with next if statement). It's not safe in Fortran @@ -482,12 +479,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s significantRho(instance) = IO_floatValue(line,chunkPos,2_pInt) case('significantn','significant_n','significantdislocations','significant_dislcations') significantN(instance) = IO_floatValue(line,chunkPos,2_pInt) - case ('interaction_slipslip') - if (chunkPos(1) < 1_pInt + Nchunks_SlipSlip) & - call IO_warning(52_pInt,ext_msg=trim(tag)//' ('//PLASTICITY_NONLOCAL_LABEL//')') - do it = 1_pInt,Nchunks_SlipSlip - interactionSlipSlip(it,instance) = IO_floatValue(line,chunkPos,1_pInt+it) - enddo case('linetension','linetensioneffect','linetension_effect') linetensionEffect(instance) = IO_floatValue(line,chunkPos,2_pInt) case('edgejog','edgejogs','edgejogeffect','edgejog_effect') @@ -571,8 +562,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') endif enddo - if (any(interactionSlipSlip(1:maxval(lattice_interactionSlipSlip(:,:,phase)),instance) < 0.0_pReal)) & - call IO_error(211_pInt,ext_msg='interaction_SlipSlip ('//PLASTICITY_NONLOCAL_label//')') if (linetensionEffect(instance) < 0.0_pReal .or. linetensionEffect(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='linetension ('//PLASTICITY_NONLOCAL_label//')') if (edgeJogFactor(instance) < 0.0_pReal .or. edgeJogFactor(instance) > 1.0_pReal) & @@ -651,7 +640,6 @@ allocate(lambda0(maxTotalNslip,maxNinstances), allocate(minDipoleHeight(maxTotalNslip,2,maxNinstances), source=-1.0_pReal) allocate(forestProjectionEdge(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(forestProjectionScrew(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) -allocate(interactionMatrixSlipSlip(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(lattice2slip(1:3, 1:3, maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & source=2.0_pReal) @@ -809,21 +797,13 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), = abs(math_mul3x3(lattice_sn(1:3,slipSystemLattice(s1,instance),phase), & lattice_sd(1:3,slipSystemLattice(s2,instance),phase))) ! forest projection of screw dislocations is the projection of b onto the slip normal of the respective splip plane - !*** calculation of interaction matrices - - interactionMatrixSlipSlip(s1,s2,instance) & - = interactionSlipSlip(lattice_interactionSlipSlip(slipSystemLattice(s1,instance), & - slipSystemLattice(s2,instance), & - phase), instance) !*** colinear slip system (only makes sense for fcc like it is defined here) - if (lattice_interactionSlipSlip(slipSystemLattice(s1,instance), & - slipSystemLattice(s2,instance), & - phase) == 3_pInt) then + if ((all(dEq(lattice_sd(1:3,slipSystemLattice(s1,instance),phase), & + lattice_sd(1:3,slipSystemLattice(s2,instance),phase))) .or. all(dEq(lattice_sd(1:3,slipSystemLattice(s1,instance),phase), & + -1.0_pReal* lattice_sd(1:3,slipSystemLattice(s2,instance),phase)))) .and. s1 /= s2) & colinearSystem(s1,instance) = s2 - endif - enddo !*** rotation matrix from lattice configuration to slip system @@ -1331,7 +1311,7 @@ forall (s = 1_pInt:ns) & !*** (see Kubin,Devincre,Hoc; 2008; Modeling dislocation storage rates and mean free paths in face-centered cubic crystals) myInteractionMatrix = 0.0_pReal -myInteractionMatrix(1:ns,1:ns) = interactionMatrixSlipSlip(1:ns,1:ns,instance) +myInteractionMatrix(1:ns,1:ns) = prm%interactionSlipSlip(1:ns,1:ns) if (lattice_structure(ph) == LATTICE_bcc_ID .or. lattice_structure(ph) == LATTICE_fcc_ID) then ! only fcc and bcc do s = 1_pInt,ns myRhoForest = max(rhoForest(s),significantRho(instance)) From 690fef6f06e4a72b1adf1b23f7bb1d5b06505566 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 17 Feb 2019 17:56:48 +0100 Subject: [PATCH 46/97] avoid publicly avaialbe data, rather provide setters and getters --- src/lattice.f90 | 388 +++++++++++++++++++++++------------------------- 1 file changed, 187 insertions(+), 201 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 07f8aed82..7566c7579 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -23,9 +23,6 @@ module lattice lattice_NslipSystem, & !< total # of slip systems in each family lattice_NcleavageSystem !< total # of transformation systems in each family - integer(pInt), allocatable, dimension(:,:,:), protected, public :: & - lattice_interactionSlipSlip !< Slip--slip interaction type - real(pReal), allocatable, dimension(:,:,:,:,:), protected, public :: & lattice_Scleavage !< Schmid matrices for cleavage systems @@ -89,7 +86,7 @@ module lattice '<0 1 -1>{0 1 1}'] real(pReal), dimension(3+3,LATTICE_FCC_NTWIN), parameter, private :: & - LATTICE_fcc_systemTwin = reshape(real( [& + LATTICE_FCC_SYSTEMTWIN = reshape(real( [& -2, 1, 1, 1, 1, 1, & 1,-2, 1, 1, 1, 1, & 1, 1,-2, 1, 1, 1, & @@ -124,42 +121,6 @@ module lattice 10,11 & ],pInt),shape(LATTICE_FCC_TWINNUCLEATIONSLIPPAIR)) -! ToDo: should be in the interaction function - integer(pInt), dimension(LATTICE_FCC_NSLIP,LATTICE_FCC_NSLIP), parameter, private :: & - LATTICE_FCC_INTERACTIONSLIPSLIP = reshape(int( [& - 1, 2, 2, 4, 6, 5, 3, 5, 5, 4, 5, 6, 9,10, 9,10,11,12, & ! ---> slip - 2, 1, 2, 6, 4, 5, 5, 4, 6, 5, 3, 5, 9,10,11,12, 9,10, & ! | - 2, 2, 1, 5, 5, 3, 5, 6, 4, 6, 5, 4, 11,12, 9,10, 9,10, & ! | - 4, 6, 5, 1, 2, 2, 4, 5, 6, 3, 5, 5, 9,10,10, 9,12,11, & ! v slip - 6, 4, 5, 2, 1, 2, 5, 3, 5, 5, 4, 6, 9,10,12,11,10, 9, & - 5, 5, 3, 2, 2, 1, 6, 5, 4, 5, 6, 4, 11,12,10, 9,10, 9, & - 3, 5, 5, 4, 5, 6, 1, 2, 2, 4, 6, 5, 10, 9,10, 9,11,12, & - 5, 4, 6, 5, 3, 5, 2, 1, 2, 6, 4, 5, 10, 9,12,11, 9,10, & - 5, 6, 4, 6, 5, 4, 2, 2, 1, 5, 5, 3, 12,11,10, 9, 9,10, & - 4, 5, 6, 3, 5, 5, 4, 6, 5, 1, 2, 2, 10, 9, 9,10,12,11, & - 5, 3, 5, 5, 4, 6, 6, 4, 5, 2, 1, 2, 10, 9,11,12,10, 9, & - 6, 5, 4, 5, 6, 4, 5, 5, 3, 2, 2, 1, 12,11, 9,10,10, 9, & - - 9, 9,11, 9, 9,11,10,10,12,10,10,12, 1, 7, 8, 8, 8, 8, & - 10,10,12,10,10,12, 9, 9,11, 9, 9,11, 7, 1, 8, 8, 8, 8, & - 9,11, 9,10,12,10,10,12,10, 9,11, 9, 8, 8, 1, 7, 8, 8, & - 10,12,10, 9,11, 9, 9,11, 9,10,12,10, 8, 8, 7, 1, 8, 8, & - 11, 9, 9,12,10,10,11, 9, 9,12,10,10, 8, 8, 8, 8, 1, 7, & - 12,10,10,11, 9, 9,12,10,10,11, 9, 9, 8, 8, 8, 8, 7, 1 & - ],pInt),shape(LATTICE_FCC_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for fcc - !< 1: self interaction - !< 2: coplanar interaction - !< 3: collinear interaction - !< 4: Hirth locks - !< 5: glissile junctions - !< 6: Lomer locks - !< 7: crossing (similar to Hirth locks in <110>{111} for two {110} planes) - !< 8: similar to Lomer locks in <110>{111} for two {110} planes - !< 9: similar to Lomer locks in <110>{111} btw one {110} and one {111} plane - !<10: similar to glissile junctions in <110>{111} btw one {110} and one {111} plane - !<11: crossing btw one {110} and one {111} plane - !<12: collinear btw one {110} and one {111} plane - real(pReal), dimension(3+3,LATTICE_fcc_Ncleavage), parameter, private :: & LATTICE_fcc_systemCleavage = reshape(real([& ! Cleavage direction Plane normal @@ -186,7 +147,6 @@ module lattice integer(pInt), parameter, private :: & LATTICE_BCC_NSLIP = sum(LATTICE_BCC_NSLIPSYSTEM), & !< total # of slip systems for bcc LATTICE_BCC_NTWIN = sum(LATTICE_BCC_NTWINSYSTEM), & !< total # of twin systems for bcc - LATTICE_bcc_NnonSchmid = 6_pInt, & !< total # of non-Schmid contributions for bcc (A. Koester, A. Ma, A. Hartmaier 2012) LATTICE_bcc_Ncleavage = sum(lattice_bcc_NcleavageSystem) !< total # of cleavage systems for bcc real(pReal), dimension(3+3,LATTICE_BCC_NSLIP), parameter, private :: & @@ -244,43 +204,6 @@ module lattice character(len=*), dimension(1), parameter, private :: LATTICE_BCC_TWINFAMILY_NAME = & ['<1 1 1>{2 1 1}'] - - - integer(pInt), dimension(LATTICE_BCC_NSLIP,LATTICE_BCC_NSLIP), parameter, private :: & - LATTICE_bcc_interactionSlipSlip = reshape(int( [& - 1,2,6,6,5,4,4,3,4,3,5,4, 6,6,4,3,3,4,6,6,4,3,6,6, & ! ---> slip - 2,1,6,6,4,3,5,4,5,4,4,3, 6,6,3,4,4,3,6,6,3,4,6,6, & ! | - 6,6,1,2,4,5,3,4,4,5,3,4, 4,3,6,6,6,6,3,4,6,6,4,3, & ! | - 6,6,2,1,3,4,4,5,3,4,4,5, 3,4,6,6,6,6,4,3,6,6,3,4, & ! v slip - 5,4,4,3,1,2,6,6,3,4,5,4, 3,6,4,6,6,4,6,3,4,6,3,6, & - 4,3,5,4,2,1,6,6,4,5,4,3, 4,6,3,6,6,3,6,4,3,6,4,6, & - 4,5,3,4,6,6,1,2,5,4,3,4, 6,3,6,4,4,6,3,6,6,4,6,3, & - 3,4,4,5,6,6,2,1,4,3,4,5, 6,4,6,3,3,6,4,6,6,3,6,4, & - 4,5,4,3,3,4,5,4,1,2,6,6, 3,6,6,4,4,6,6,3,6,4,3,6, & - 3,4,5,4,4,5,4,3,2,1,6,6, 4,6,6,3,3,6,6,4,6,3,4,6, & - 5,4,3,4,5,4,3,4,6,6,1,2, 6,3,4,6,6,4,3,6,4,6,6,3, & - 4,3,4,5,4,3,4,5,6,6,2,1, 6,4,3,6,6,3,4,6,3,6,6,4, & - ! - 6,6,4,3,3,4,6,6,3,4,6,6, 1,5,6,6,5,6,6,3,5,6,3,6, & - 6,6,3,4,6,6,3,4,6,6,3,4, 5,1,6,6,6,5,3,6,6,5,6,3, & - 4,3,6,6,4,3,6,6,6,6,4,3, 6,6,1,5,6,3,5,6,3,6,5,6, & - 3,4,6,6,6,6,4,3,4,3,6,6, 6,6,5,1,3,6,6,5,6,3,6,5, & - 3,4,6,6,6,6,4,3,4,3,6,6, 5,6,6,3,1,6,5,6,5,3,6,6, & - 4,3,6,6,4,3,6,6,6,6,4,3, 6,5,3,6,6,1,6,5,3,5,6,6, & - 6,6,3,4,6,6,3,4,6,6,3,4, 6,3,5,6,5,6,1,6,6,6,5,3, & - 6,6,4,3,3,4,6,6,3,4,6,6, 3,6,6,5,6,5,6,1,6,6,3,5, & - 4,3,6,6,4,3,6,6,6,6,4,3, 5,6,3,6,5,3,6,6,1,6,6,5, & - 3,4,6,6,6,6,4,3,4,3,6,6, 6,5,6,3,3,5,6,6,6,1,5,6, & - 6,6,4,3,3,4,6,6,3,4,6,6, 3,6,5,6,6,6,5,3,6,5,1,6, & - 6,6,3,4,6,6,3,4,6,6,3,4, 6,3,6,5,6,6,3,5,5,6,6,1 & - ],pInt),shape(LATTICE_BCC_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for bcc from Queyreau et al. Int J Plast 25 (2009) 361–377 - !< 1: self interaction - !< 2: coplanar interaction - !< 3: collinear interaction - !< 4: mixed-asymmetrical junction - !< 5: mixed-symmetrical junction - !< 6: edge junction - real(pReal), dimension(3+3,LATTICE_bcc_Ncleavage), parameter, private :: & LATTICE_bcc_systemCleavage = reshape(real([& ! Cleavage direction Plane normal @@ -401,50 +324,6 @@ module lattice '<1 0 . -2>{1 0 . 1} ', & '<1 1 . -3>{1 1 . 2} '] - - integer(pInt), dimension(LATTICE_HEX_NSLIP,LATTICE_HEX_NSLIP), parameter, private :: & - LATTICE_hex_interactionSlipSlip = reshape(int( [& - 1, 2, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! ---> slip - 2, 1, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! | - 2, 2, 1, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! | - ! v slip - 6, 6, 6, 4, 5, 5, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & - 6, 6, 6, 5, 4, 5, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & - 6, 6, 6, 5, 5, 4, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & - ! - 12,12,12, 11,11,11, 9,10,10, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & - 12,12,12, 11,11,11, 10, 9,10, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & - 12,12,12, 11,11,11, 10,10, 9, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & - ! - 20,20,20, 19,19,19, 18,18,18, 16,17,17,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - 20,20,20, 19,19,19, 18,18,18, 17,16,17,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - 20,20,20, 19,19,19, 18,18,18, 17,17,16,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - 20,20,20, 19,19,19, 18,18,18, 17,17,17,16,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - 20,20,20, 19,19,19, 18,18,18, 17,17,17,17,16,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - 20,20,20, 19,19,19, 18,18,18, 17,17,17,17,17,16, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & - ! - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 25,26,26,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,25,26,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,25,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,25,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,25,26,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,25,26,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,25,26,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,25,26,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,25,26,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,25,26,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,26,25,26, 35,35,35,35,35,35, & - 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,26,26,25, 35,35,35,35,35,35, & - ! - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 36,37,37,37,37,37, & - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,36,37,37,37,37, & - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,36,37,37,37, & - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,36,37,37, & - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,37,36,37, & - 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,37,37,36 & - ],pInt),shape(LATTICE_HEX_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for hex (onion peel naming scheme) - - real(pReal), dimension(4+4,LATTICE_hex_Ncleavage), parameter, private :: & LATTICE_hex_systemCleavage = reshape(real([& ! Cleavage direction Plane normal @@ -547,74 +426,6 @@ module lattice '{2 1 1)<0 1 -1]', & '{2 1 1)<-1 1 1]'] - integer(pInt), dimension(LATTICE_bct_Nslip,LATTICE_bct_Nslip), parameter, private :: & - LATTICE_bct_interactionSlipSlip = reshape(int( [& - 1, 2, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & - 2, 1, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & - ! - 6, 6, 4, 5, 8, 8, 14, 14, 14, 14, 22, 22, 32, 32, 32, 32, 44, 44, 58, 58, 74, 74, 74, 74, 92, 92, 92, 92, 92, 92, 92, 92, 112, 112, 112, 112, 134,134,134,134,134,134,134,134, 158,158,158,158,158,158,158,158, & - 6, 6, 5, 4, 8, 8, 14, 14, 14, 14, 22, 22, 32, 32, 32, 32, 44, 44, 58, 58, 74, 74, 74, 74, 92, 92, 92, 92, 92, 92, 92, 92, 112, 112, 112, 112, 134,134,134,134,134,134,134,134, 158,158,158,158,158,158,158,158, & - ! - 12, 12, 11, 11, 9, 10, 15, 15, 15, 15, 23, 23, 33, 33, 33, 33, 45, 45, 59, 59, 75, 75, 75, 75, 93, 93, 93, 93, 93, 93, 93, 93, 113, 113, 113, 113, 135,135,135,135,135,135,135,135, 159,159,159,159,159,159,159,159, & - 12, 12, 11, 11, 10, 9, 15, 15, 15, 15, 23, 23, 33, 33, 33, 33, 45, 45, 59, 59, 75, 75, 75, 75, 93, 93, 93, 93, 93, 93, 93, 93, 113, 113, 113, 113, 135,135,135,135,135,135,135,135, 159,159,159,159,159,159,159,159, & - ! - 20, 20, 19, 19, 18, 18, 16, 17, 17, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & - 20, 20, 19, 19, 18, 18, 17, 16, 17, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & - 20, 20, 19, 19, 18, 18, 17, 17, 16, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & - 20, 20, 19, 19, 18, 18, 17, 17, 17, 16, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & - ! - 30, 30, 29, 29, 28, 28, 27, 27, 27, 27, 25, 26, 35, 35, 35, 35, 47, 47, 61, 61, 77, 77, 77, 77, 95, 95, 95, 95, 95, 95, 95, 95, 115, 115, 115, 115, 137,137,137,137,137,137,137,137, 161,161,161,161,161,161,161,161, & - 30, 30, 29, 29, 28, 28, 27, 27, 27, 27, 26, 25, 35, 35, 35, 35, 47, 47, 61, 61, 77, 77, 77, 77, 95, 95, 95, 95, 95, 95, 95, 95, 115, 115, 115, 115, 137,137,137,137,137,137,137,137, 161,161,161,161,161,161,161,161, & - ! - 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 36, 37, 37, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & - 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 36, 37, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & - 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 37, 36, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & - 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 37, 37, 36, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & - ! - 56, 56, 55, 55, 54, 54, 53, 53, 53, 53, 52, 52, 51, 51, 51, 51, 49, 50, 63, 63, 79, 79, 79, 79, 97, 97, 97, 97, 97, 97, 97, 97, 117, 117, 117, 117, 139,139,139,139,139,139,139,139, 163,163,163,163,163,163,163,163, & - 56, 56, 55, 55, 54, 54, 53, 53, 53, 53, 52, 52, 51, 51, 51, 51, 50, 49, 63, 63, 79, 79, 79, 79, 97, 97, 97, 97, 97, 97, 97, 97, 117, 117, 117, 117, 139,139,139,139,139,139,139,139, 163,163,163,163,163,163,163,163, & - ! - 72, 72, 71, 71, 70, 70, 69, 69, 69, 69, 68, 68, 67, 67, 67, 67, 66, 66, 64, 65, 80, 80, 80, 80, 98, 98, 98, 98, 98, 98, 98, 98, 118, 118, 118, 118, 140,140,140,140,140,140,140,140, 164,164,164,164,164,164,164,164, & - 72, 72, 71, 71, 70, 70, 69, 69, 69, 69, 68, 68, 67, 67, 67, 67, 66, 66, 65, 64, 80, 80, 80, 80, 98, 98, 98, 98, 98, 98, 98, 98, 118, 118, 118, 118, 140,140,140,140,140,140,140,140, 164,164,164,164,164,164,164,164, & - ! - 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 81, 82, 82, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & - 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 81, 82, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & - 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 82, 81, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & - 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & - ! - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 100,101,101,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,100,101,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,100,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,100,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,100,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,100,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,101,100,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,101,101,100, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & - ! - 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 122, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & - 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 121, 122, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & - 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 121, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & - 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 122, 121, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & - ! - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 144,145,145,145,145,145,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,144,145,145,145,145,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,144,145,145,145,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,144,145,145,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,144,145,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,144,145,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,145,144,145, 168,168,168,168,168,168,168,168, & - 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,145,145,144, 168,168,168,168,168,168,168,168, & - ! - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,169,170,170,170,170,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,169,170,170,170,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,170,169,170,170,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,170,170,169,170,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,169,170,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,169,170, & - 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,170,169 & - ],pInt),[lattice_bct_Nslip,lattice_bct_Nslip],order=[2,1]) - !-------------------------------------------------------------------------------------------------- ! isotropic @@ -655,8 +466,7 @@ module lattice LATTICE_bct_Nslip), & !< max # of slip systems over lattice structures LATTICE_maxNcleavage = max(LATTICE_fcc_Ncleavage,LATTICE_bcc_Ncleavage, & LATTICE_hex_Ncleavage, & - LATTICE_iso_Ncleavage,LATTICE_ort_Ncleavage), & !< max # of cleavage systems over lattice structures - LATTICE_maxNinteraction = 182_pInt + LATTICE_iso_Ncleavage,LATTICE_ort_Ncleavage) !< max # of cleavage systems over lattice structures !END DEPRECATED real(pReal), dimension(:,:,:), allocatable, public, protected :: & @@ -757,7 +567,6 @@ subroutine lattice_init allocate(lattice_nu(Nphases), source=0.0_pReal) allocate(lattice_NslipSystem(lattice_maxNslipFamily,Nphases),source=0_pInt) - allocate(lattice_interactionSlipSlip(lattice_maxNslip,lattice_maxNslip,Nphases),source=0_pInt) ! other:me allocate(lattice_Scleavage(3,3,3,lattice_maxNslip,Nphases),source=0.0_pReal) allocate(lattice_Scleavage_v(6,3,lattice_maxNslip,Nphases),source=0.0_pReal) @@ -905,7 +714,6 @@ subroutine lattice_initializeStructure(myPhase,CoverA) myNcleavage = lattice_fcc_Ncleavage lattice_NslipSystem (1:lattice_maxNslipFamily,myPhase) = lattice_fcc_NslipSystem lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,myPhase) = lattice_fcc_NcleavageSystem - lattice_interactionSlipSlip(1:myNslip,1:myNslip,myPhase) = lattice_fcc_interactionSlipSlip lattice_Scleavage(1:3,1:3,1:3,1:myNcleavage,myPhase) = & lattice_SchmidMatrix_cleavage(lattice_fcc_ncleavageSystem,'fcc',covera) @@ -923,7 +731,6 @@ subroutine lattice_initializeStructure(myPhase,CoverA) myNcleavage = lattice_bcc_Ncleavage lattice_NslipSystem(1:lattice_maxNslipFamily,myPhase) = lattice_bcc_NslipSystem lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,myPhase) = lattice_bcc_NcleavageSystem - lattice_interactionSlipSlip(1:myNslip,1:myNslip,myPhase) = lattice_bcc_interactionSlipSlip lattice_Scleavage(1:3,1:3,1:3,1:myNcleavage,myPhase) = & lattice_SchmidMatrix_cleavage(lattice_bcc_ncleavagesystem,'bcc',covera) @@ -940,7 +747,6 @@ subroutine lattice_initializeStructure(myPhase,CoverA) myNcleavage = lattice_hex_Ncleavage lattice_NslipSystem(1:lattice_maxNslipFamily,myPhase) = LATTICE_HEX_NSLIPSystem lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,myPhase) = lattice_hex_NcleavageSystem - lattice_interactionSlipSlip(1:myNslip,1:myNslip,myPhase) = lattice_hex_interactionSlipSlip lattice_Scleavage(1:3,1:3,1:3,1:myNcleavage,myPhase) = & lattice_SchmidMatrix_cleavage(lattice_hex_ncleavagesystem,'hex',covera) @@ -960,7 +766,6 @@ subroutine lattice_initializeStructure(myPhase,CoverA) case (LATTICE_bct_ID) myNslip = lattice_bct_Nslip lattice_NslipSystem(1:lattice_maxNslipFamily,myPhase) = lattice_bct_NslipSystem - lattice_interactionSlipSlip(1:myNslip,1:myNslip,myPhase) = lattice_bct_interactionSlipSlip do i = 1_pInt,myNslip ! assign slip system vectors sd(1:2,i) = lattice_bct_systemSlip(1:2,i) @@ -1532,22 +1337,203 @@ function lattice_interaction_SlipSlip(Nslip,interactionValues,structure) result( integer(pInt), dimension(:), allocatable :: NslipMax integer(pInt), dimension(:,:), allocatable :: interactionTypes + + integer(pInt), dimension(LATTICE_FCC_NSLIP,LATTICE_FCC_NSLIP), parameter :: & + FCC_INTERACTIONSLIPSLIP = reshape(int( [& + 1, 2, 2, 4, 6, 5, 3, 5, 5, 4, 5, 6, 9,10, 9,10,11,12, & ! ---> slip + 2, 1, 2, 6, 4, 5, 5, 4, 6, 5, 3, 5, 9,10,11,12, 9,10, & ! | + 2, 2, 1, 5, 5, 3, 5, 6, 4, 6, 5, 4, 11,12, 9,10, 9,10, & ! | + 4, 6, 5, 1, 2, 2, 4, 5, 6, 3, 5, 5, 9,10,10, 9,12,11, & ! v slip + 6, 4, 5, 2, 1, 2, 5, 3, 5, 5, 4, 6, 9,10,12,11,10, 9, & + 5, 5, 3, 2, 2, 1, 6, 5, 4, 5, 6, 4, 11,12,10, 9,10, 9, & + 3, 5, 5, 4, 5, 6, 1, 2, 2, 4, 6, 5, 10, 9,10, 9,11,12, & + 5, 4, 6, 5, 3, 5, 2, 1, 2, 6, 4, 5, 10, 9,12,11, 9,10, & + 5, 6, 4, 6, 5, 4, 2, 2, 1, 5, 5, 3, 12,11,10, 9, 9,10, & + 4, 5, 6, 3, 5, 5, 4, 6, 5, 1, 2, 2, 10, 9, 9,10,12,11, & + 5, 3, 5, 5, 4, 6, 6, 4, 5, 2, 1, 2, 10, 9,11,12,10, 9, & + 6, 5, 4, 5, 6, 4, 5, 5, 3, 2, 2, 1, 12,11, 9,10,10, 9, & + + 9, 9,11, 9, 9,11,10,10,12,10,10,12, 1, 7, 8, 8, 8, 8, & + 10,10,12,10,10,12, 9, 9,11, 9, 9,11, 7, 1, 8, 8, 8, 8, & + 9,11, 9,10,12,10,10,12,10, 9,11, 9, 8, 8, 1, 7, 8, 8, & + 10,12,10, 9,11, 9, 9,11, 9,10,12,10, 8, 8, 7, 1, 8, 8, & + 11, 9, 9,12,10,10,11, 9, 9,12,10,10, 8, 8, 8, 8, 1, 7, & + 12,10,10,11, 9, 9,12,10,10,11, 9, 9, 8, 8, 8, 8, 7, 1 & + ],pInt),shape(FCC_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for fcc + !< 1: self interaction + !< 2: coplanar interaction + !< 3: collinear interaction + !< 4: Hirth locks + !< 5: glissile junctions + !< 6: Lomer locks + !< 7: crossing (similar to Hirth locks in <110>{111} for two {110} planes) + !< 8: similar to Lomer locks in <110>{111} for two {110} planes + !< 9: similar to Lomer locks in <110>{111} btw one {110} and one {111} plane + !<10: similar to glissile junctions in <110>{111} btw one {110} and one {111} plane + !<11: crossing btw one {110} and one {111} plane + !<12: collinear btw one {110} and one {111} plane + + integer(pInt), dimension(LATTICE_BCC_NSLIP,LATTICE_BCC_NSLIP), parameter :: & + BCC_INTERACTIONSLIPSLIP = reshape(int( [& + 1,2,6,6,5,4,4,3,4,3,5,4, 6,6,4,3,3,4,6,6,4,3,6,6, & ! ---> slip + 2,1,6,6,4,3,5,4,5,4,4,3, 6,6,3,4,4,3,6,6,3,4,6,6, & ! | + 6,6,1,2,4,5,3,4,4,5,3,4, 4,3,6,6,6,6,3,4,6,6,4,3, & ! | + 6,6,2,1,3,4,4,5,3,4,4,5, 3,4,6,6,6,6,4,3,6,6,3,4, & ! v slip + 5,4,4,3,1,2,6,6,3,4,5,4, 3,6,4,6,6,4,6,3,4,6,3,6, & + 4,3,5,4,2,1,6,6,4,5,4,3, 4,6,3,6,6,3,6,4,3,6,4,6, & + 4,5,3,4,6,6,1,2,5,4,3,4, 6,3,6,4,4,6,3,6,6,4,6,3, & + 3,4,4,5,6,6,2,1,4,3,4,5, 6,4,6,3,3,6,4,6,6,3,6,4, & + 4,5,4,3,3,4,5,4,1,2,6,6, 3,6,6,4,4,6,6,3,6,4,3,6, & + 3,4,5,4,4,5,4,3,2,1,6,6, 4,6,6,3,3,6,6,4,6,3,4,6, & + 5,4,3,4,5,4,3,4,6,6,1,2, 6,3,4,6,6,4,3,6,4,6,6,3, & + 4,3,4,5,4,3,4,5,6,6,2,1, 6,4,3,6,6,3,4,6,3,6,6,4, & + ! + 6,6,4,3,3,4,6,6,3,4,6,6, 1,5,6,6,5,6,6,3,5,6,3,6, & + 6,6,3,4,6,6,3,4,6,6,3,4, 5,1,6,6,6,5,3,6,6,5,6,3, & + 4,3,6,6,4,3,6,6,6,6,4,3, 6,6,1,5,6,3,5,6,3,6,5,6, & + 3,4,6,6,6,6,4,3,4,3,6,6, 6,6,5,1,3,6,6,5,6,3,6,5, & + 3,4,6,6,6,6,4,3,4,3,6,6, 5,6,6,3,1,6,5,6,5,3,6,6, & + 4,3,6,6,4,3,6,6,6,6,4,3, 6,5,3,6,6,1,6,5,3,5,6,6, & + 6,6,3,4,6,6,3,4,6,6,3,4, 6,3,5,6,5,6,1,6,6,6,5,3, & + 6,6,4,3,3,4,6,6,3,4,6,6, 3,6,6,5,6,5,6,1,6,6,3,5, & + 4,3,6,6,4,3,6,6,6,6,4,3, 5,6,3,6,5,3,6,6,1,6,6,5, & + 3,4,6,6,6,6,4,3,4,3,6,6, 6,5,6,3,3,5,6,6,6,1,5,6, & + 6,6,4,3,3,4,6,6,3,4,6,6, 3,6,5,6,6,6,5,3,6,5,1,6, & + 6,6,3,4,6,6,3,4,6,6,3,4, 6,3,6,5,6,6,3,5,5,6,6,1 & + ],pInt),shape(BCC_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for bcc from Queyreau et al. Int J Plast 25 (2009) 361–377 + !< 1: self interaction + !< 2: coplanar interaction + !< 3: collinear interaction + !< 4: mixed-asymmetrical junction + !< 5: mixed-symmetrical junction + !< 6: edge junction + + integer(pInt), dimension(LATTICE_HEX_NSLIP,LATTICE_HEX_NSLIP), parameter :: & + HEX_INTERACTIONSLIPSLIP = reshape(int( [& + 1, 2, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! ---> slip + 2, 1, 2, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! | + 2, 2, 1, 3, 3, 3, 7, 7, 7, 13,13,13,13,13,13, 21,21,21,21,21,21,21,21,21,21,21,21, 31,31,31,31,31,31, & ! | + ! v slip + 6, 6, 6, 4, 5, 5, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & + 6, 6, 6, 5, 4, 5, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & + 6, 6, 6, 5, 5, 4, 8, 8, 8, 14,14,14,14,14,14, 22,22,22,22,22,22,22,22,22,22,22,22, 32,32,32,32,32,32, & + ! + 12,12,12, 11,11,11, 9,10,10, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & + 12,12,12, 11,11,11, 10, 9,10, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & + 12,12,12, 11,11,11, 10,10, 9, 15,15,15,15,15,15, 23,23,23,23,23,23,23,23,23,23,23,23, 33,33,33,33,33,33, & + ! + 20,20,20, 19,19,19, 18,18,18, 16,17,17,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + 20,20,20, 19,19,19, 18,18,18, 17,16,17,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + 20,20,20, 19,19,19, 18,18,18, 17,17,16,17,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + 20,20,20, 19,19,19, 18,18,18, 17,17,17,16,17,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + 20,20,20, 19,19,19, 18,18,18, 17,17,17,17,16,17, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + 20,20,20, 19,19,19, 18,18,18, 17,17,17,17,17,16, 24,24,24,24,24,24,24,24,24,24,24,24, 34,34,34,34,34,34, & + ! + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 25,26,26,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,25,26,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,25,26,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,25,26,26,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,25,26,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,25,26,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,25,26,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,25,26,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,25,26,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,25,26,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,26,25,26, 35,35,35,35,35,35, & + 30,30,30, 29,29,29, 28,28,28, 27,27,27,27,27,27, 26,26,26,26,26,26,26,26,26,26,26,25, 35,35,35,35,35,35, & + ! + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 36,37,37,37,37,37, & + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,36,37,37,37,37, & + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,36,37,37,37, & + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,36,37,37, & + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,37,36,37, & + 42,42,42, 41,41,41, 40,40,40, 39,39,39,39,39,39, 38,38,38,38,38,38,38,38,38,38,38,38, 37,37,37,37,37,36 & + ],pInt),shape(HEX_INTERACTIONSLIPSLIP),order=[2,1]) !< Slip--slip interaction types for hex (onion peel naming scheme) + + integer(pInt), dimension(LATTICE_BCT_NSLIP,LATTICE_BCT_NSLIP), parameter :: & + BCT_INTERACTIONSLIPSLIP = reshape(int( [& + 1, 2, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & + 2, 1, 3, 3, 7, 7, 13, 13, 13, 13, 21, 21, 31, 31, 31, 31, 43, 43, 57, 57, 73, 73, 73, 73, 91, 91, 91, 91, 91, 91, 91, 91, 111, 111, 111, 111, 133,133,133,133,133,133,133,133, 157,157,157,157,157,157,157,157, & + ! + 6, 6, 4, 5, 8, 8, 14, 14, 14, 14, 22, 22, 32, 32, 32, 32, 44, 44, 58, 58, 74, 74, 74, 74, 92, 92, 92, 92, 92, 92, 92, 92, 112, 112, 112, 112, 134,134,134,134,134,134,134,134, 158,158,158,158,158,158,158,158, & + 6, 6, 5, 4, 8, 8, 14, 14, 14, 14, 22, 22, 32, 32, 32, 32, 44, 44, 58, 58, 74, 74, 74, 74, 92, 92, 92, 92, 92, 92, 92, 92, 112, 112, 112, 112, 134,134,134,134,134,134,134,134, 158,158,158,158,158,158,158,158, & + ! + 12, 12, 11, 11, 9, 10, 15, 15, 15, 15, 23, 23, 33, 33, 33, 33, 45, 45, 59, 59, 75, 75, 75, 75, 93, 93, 93, 93, 93, 93, 93, 93, 113, 113, 113, 113, 135,135,135,135,135,135,135,135, 159,159,159,159,159,159,159,159, & + 12, 12, 11, 11, 10, 9, 15, 15, 15, 15, 23, 23, 33, 33, 33, 33, 45, 45, 59, 59, 75, 75, 75, 75, 93, 93, 93, 93, 93, 93, 93, 93, 113, 113, 113, 113, 135,135,135,135,135,135,135,135, 159,159,159,159,159,159,159,159, & + ! + 20, 20, 19, 19, 18, 18, 16, 17, 17, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & + 20, 20, 19, 19, 18, 18, 17, 16, 17, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & + 20, 20, 19, 19, 18, 18, 17, 17, 16, 17, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & + 20, 20, 19, 19, 18, 18, 17, 17, 17, 16, 24, 24, 34, 34, 34, 34, 46, 46, 60, 60, 76, 76, 76, 76, 94, 94, 94, 94, 94, 94, 94, 94, 114, 114, 114, 114, 136,136,136,136,136,136,136,136, 160,160,160,160,160,160,160,160, & + ! + 30, 30, 29, 29, 28, 28, 27, 27, 27, 27, 25, 26, 35, 35, 35, 35, 47, 47, 61, 61, 77, 77, 77, 77, 95, 95, 95, 95, 95, 95, 95, 95, 115, 115, 115, 115, 137,137,137,137,137,137,137,137, 161,161,161,161,161,161,161,161, & + 30, 30, 29, 29, 28, 28, 27, 27, 27, 27, 26, 25, 35, 35, 35, 35, 47, 47, 61, 61, 77, 77, 77, 77, 95, 95, 95, 95, 95, 95, 95, 95, 115, 115, 115, 115, 137,137,137,137,137,137,137,137, 161,161,161,161,161,161,161,161, & + ! + 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 36, 37, 37, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & + 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 36, 37, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & + 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 37, 36, 37, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & + 42, 42, 41, 41, 40, 40, 39, 39, 39, 39, 38, 38, 37, 37, 37, 36, 48, 48, 62, 62, 78, 78, 78, 78, 96, 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, 116, 138,138,138,138,138,138,138,138, 162,162,162,162,162,162,162,162, & + ! + 56, 56, 55, 55, 54, 54, 53, 53, 53, 53, 52, 52, 51, 51, 51, 51, 49, 50, 63, 63, 79, 79, 79, 79, 97, 97, 97, 97, 97, 97, 97, 97, 117, 117, 117, 117, 139,139,139,139,139,139,139,139, 163,163,163,163,163,163,163,163, & + 56, 56, 55, 55, 54, 54, 53, 53, 53, 53, 52, 52, 51, 51, 51, 51, 50, 49, 63, 63, 79, 79, 79, 79, 97, 97, 97, 97, 97, 97, 97, 97, 117, 117, 117, 117, 139,139,139,139,139,139,139,139, 163,163,163,163,163,163,163,163, & + ! + 72, 72, 71, 71, 70, 70, 69, 69, 69, 69, 68, 68, 67, 67, 67, 67, 66, 66, 64, 65, 80, 80, 80, 80, 98, 98, 98, 98, 98, 98, 98, 98, 118, 118, 118, 118, 140,140,140,140,140,140,140,140, 164,164,164,164,164,164,164,164, & + 72, 72, 71, 71, 70, 70, 69, 69, 69, 69, 68, 68, 67, 67, 67, 67, 66, 66, 65, 64, 80, 80, 80, 80, 98, 98, 98, 98, 98, 98, 98, 98, 118, 118, 118, 118, 140,140,140,140,140,140,140,140, 164,164,164,164,164,164,164,164, & + ! + 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 81, 82, 82, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & + 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 81, 82, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & + 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 82, 81, 82, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & + 90, 90, 89, 89, 88, 88, 87, 87, 87, 87, 86, 86, 85, 85, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 99, 99, 99, 99, 99, 99, 99, 99, 119, 119, 119, 119, 141,141,141,141,141,141,141,141, 165,165,165,165,165,165,165,165, & + ! + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 100,101,101,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,100,101,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,100,101,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,100,101,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,100,101,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,100,101,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,101,100,101, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + 110,110, 109,109, 108,108, 107,107,107,107, 106,106, 105,105,105,105, 104,104, 103,103, 102,102,102,102, 101,101,101,101,101,101,101,100, 120, 120, 120, 120, 142,142,142,142,142,142,142,142, 166,166,166,166,166,166,166,166, & + ! + 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 122, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & + 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 121, 122, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & + 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 121, 122, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & + 132,132, 131,131, 130,130, 129,129,129,129, 128,128, 127,127,127,127, 126,126, 125,125, 124,124,124,124, 123,123,123,123,123,123,123,123, 121, 122, 122, 121, 143,143,143,143,143,143,143,143, 167,167,167,167,167,167,167,167, & + ! + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 144,145,145,145,145,145,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,144,145,145,145,145,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,144,145,145,145,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,144,145,145,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,144,145,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,144,145,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,145,144,145, 168,168,168,168,168,168,168,168, & + 156,156, 155,155, 154,154, 153,153,153,153, 152,152, 151,151,151,151, 150,150, 149,149, 148,148,148,148, 147,147,147,147,147,147,147,147, 146, 146, 146, 146, 145,145,145,145,145,145,145,144, 168,168,168,168,168,168,168,168, & + ! + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,169,170,170,170,170,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,169,170,170,170,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,170,169,170,170,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 170,170,170,170,169,170,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,169,170,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,169,170, & + 182,182, 181,181, 180,180, 179,179,179,179, 178,178, 177,177,177,177, 176,176, 175,175, 174,174,174,174, 173,173,173,173,173,173,173,173, 172, 172, 172, 172, 171,171,171,171,171,171,171,171, 169,170,170,170,170,170,170,169 & + ],pInt),shape(BCT_INTERACTIONSLIPSLIP),order=[2,1]) + if (len_trim(structure) /= 3_pInt) & call IO_error(137_pInt,ext_msg='lattice_interaction_SlipSlip: '//trim(structure)) select case(structure(1:3)) case('fcc') - interactionTypes = LATTICE_FCC_INTERACTIONSLIPSLIP + interactionTypes = FCC_INTERACTIONSLIPSLIP NslipMax = LATTICE_FCC_NSLIPSYSTEM case('bcc') - interactionTypes = LATTICE_BCC_INTERACTIONSLIPSLIP + interactionTypes = BCC_INTERACTIONSLIPSLIP NslipMax = LATTICE_BCC_NSLIPSYSTEM case('hex') - interactionTypes = LATTICE_HEX_INTERACTIONSLIPSLIP + interactionTypes = HEX_INTERACTIONSLIPSLIP NslipMax = LATTICE_HEX_NSLIPSYSTEM case('bct') - interactionTypes = LATTICE_BCT_INTERACTIONSLIPSLIP + interactionTypes = BCT_INTERACTIONSLIPSLIP NslipMax = LATTICE_BCT_NSLIPSYSTEM case default call IO_error(137_pInt,ext_msg='lattice_interaction_SlipSlip: '//trim(structure)) From 435dce220c615e2bf01c1044977163c6529be4b4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 18 Feb 2019 07:24:56 +0100 Subject: [PATCH 47/97] move stress conversion one level up should be totally avoided --- src/constitutive.f90 | 40 ++++++++++++++++++++-------------------- src/crystallite.f90 | 8 +++++--- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 64f7cb60e..e5adaf4cf 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -176,8 +176,6 @@ subroutine constitutive_init() call config_deallocate('material.config/phase') write(6,'(/,a)') ' <<<+- constitutive init -+>>>' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" mainProcess: if (worldrank == 0) then !-------------------------------------------------------------------------------------------------- @@ -525,7 +523,8 @@ end subroutine constitutive_LpAndItsTangents !> @brief contains the constitutive equation for calculating the velocity gradient ! ToDo: MD: S is Mi? !-------------------------------------------------------------------------------------------------- -subroutine constitutive_LiAndItsTangents(Li, dLi_dS, dLi_dFi, S6, Fi, ipc, ip, el) +subroutine constitutive_LiAndItsTangents(Li, dLi_dS, dLi_dFi, & + S, Fi, ipc, ip, el) use prec, only: & pReal use math, only: & @@ -560,8 +559,8 @@ subroutine constitutive_LiAndItsTangents(Li, dLi_dS, dLi_dFi, S6, Fi, ipc, ip, e ipc, & !< component-ID of integration point ip, & !< integration point el !< element - real(pReal), intent(in), dimension(6) :: & - S6 !< 2nd Piola-Kirchhoff stress (vector notation) + real(pReal), intent(in), dimension(3,3) :: & + S !< 2nd Piola-Kirchhoff stress real(pReal), intent(in), dimension(3,3) :: & Fi !< intermediate deformation gradient real(pReal), intent(out), dimension(3,3) :: & @@ -590,7 +589,7 @@ subroutine constitutive_LiAndItsTangents(Li, dLi_dS, dLi_dFi, S6, Fi, ipc, ip, e case (PLASTICITY_isotropic_ID) plasticityType of = phasememberAt(ipc,ip,el) instance = phase_plasticityInstance(material_phase(ipc,ip,el)) - call plastic_isotropic_LiAndItsTangent(my_Li, my_dLi_dS, math_6toSym33(S6),instance,of) + call plastic_isotropic_LiAndItsTangent(my_Li, my_dLi_dS, S ,instance,of) case default plasticityType my_Li = 0.0_pReal my_dLi_dS = 0.0_pReal @@ -602,9 +601,9 @@ subroutine constitutive_LiAndItsTangents(Li, dLi_dS, dLi_dFi, S6, Fi, ipc, ip, e KinematicsLoop: do k = 1_pInt, phase_Nkinematics(material_phase(ipc,ip,el)) kinematicsType: select case (phase_kinematics(k,material_phase(ipc,ip,el))) case (KINEMATICS_cleavage_opening_ID) kinematicsType - call kinematics_cleavage_opening_LiAndItsTangent(my_Li, my_dLi_dS, math_6toSym33(S6), ipc, ip, el) + call kinematics_cleavage_opening_LiAndItsTangent(my_Li, my_dLi_dS, S, ipc, ip, el) case (KINEMATICS_slipplane_opening_ID) kinematicsType - call kinematics_slipplane_opening_LiAndItsTangent(my_Li, my_dLi_dS, math_6toSym33(S6), ipc, ip, el) + call kinematics_slipplane_opening_LiAndItsTangent(my_Li, my_dLi_dS, S, ipc, ip, el) case (KINEMATICS_thermal_expansion_ID) kinematicsType call kinematics_thermal_expansion_LiAndItsTangent(my_Li, my_dLi_dS, ipc, ip, el) case default kinematicsType @@ -703,7 +702,8 @@ end subroutine constitutive_SandItsTangents !> @brief returns the 2nd Piola-Kirchhoff stress tensor and its tangent with respect to !> the elastic and intermeidate deformation gradients using Hookes law !-------------------------------------------------------------------------------------------------- -subroutine constitutive_hooke_SandItsTangents(S, dS_dFe, dS_dFi, Fe, Fi, ipc, ip, el) +subroutine constitutive_hooke_SandItsTangents(S, dS_dFe, dS_dFi, & + Fe, Fi, ipc, ip, el) use prec, only: & pReal use math, only : & @@ -767,7 +767,7 @@ end subroutine constitutive_hooke_SandItsTangents !-------------------------------------------------------------------------------------------------- !> @brief contains the constitutive equation for calculating the rate of change of microstructure !-------------------------------------------------------------------------------------------------- -subroutine constitutive_collectDotState(S6, FeArray, Fi, FpArray, subdt, subfracArray,ipc, ip, el) +subroutine constitutive_collectDotState(S, FeArray, Fi, FpArray, subdt, subfracArray,ipc, ip, el) use prec, only: & pReal, & pLongInt @@ -839,20 +839,20 @@ subroutine constitutive_collectDotState(S6, FeArray, Fi, FpArray, subdt, subfrac FpArray !< plastic deformation gradient real(pReal), intent(in), dimension(3,3) :: & Fi !< intermediate deformation gradient - real(pReal), intent(in), dimension(6) :: & - S6 !< 2nd Piola Kirchhoff stress (vector notation) + real(pReal), intent(in), dimension(3,3) :: & + S !< 2nd Piola Kirchhoff stress (vector notation) real(pReal), dimension(3,3) :: & Mp integer(pInt) :: & ho, & !< homogenization tme, & !< thermal member position - s, & !< counter in source loop + i, & !< counter in source loop instance, of ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) - Mp = math_mul33x33(math_mul33x33(transpose(Fi),Fi),math_6toSym33(S6)) + Mp = math_mul33x33(math_mul33x33(transpose(Fi),Fi),S) plasticityType: select case (phase_plasticity(material_phase(ipc,ip,el))) @@ -886,21 +886,21 @@ subroutine constitutive_collectDotState(S6, FeArray, Fi, FpArray, subdt, subfrac subdt,subfracArray,ip,el) end select plasticityType - SourceLoop: do s = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) + SourceLoop: do i = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) - sourceType: select case (phase_source(s,material_phase(ipc,ip,el))) + sourceType: select case (phase_source(i,material_phase(ipc,ip,el))) case (SOURCE_damage_anisoBrittle_ID) sourceType - call source_damage_anisoBrittle_dotState (math_6toSym33(S6), ipc, ip, el) !< correct stress? + call source_damage_anisoBrittle_dotState (S, ipc, ip, el) !< correct stress? case (SOURCE_damage_isoDuctile_ID) sourceType - call source_damage_isoDuctile_dotState ( ipc, ip, el) + call source_damage_isoDuctile_dotState ( ipc, ip, el) case (SOURCE_damage_anisoDuctile_ID) sourceType - call source_damage_anisoDuctile_dotState ( ipc, ip, el) + call source_damage_anisoDuctile_dotState ( ipc, ip, el) case (SOURCE_thermal_externalheat_ID) sourceType - call source_thermal_externalheat_dotState( ipc, ip, el) + call source_thermal_externalheat_dotState( ipc, ip, el) end select sourceType diff --git a/src/crystallite.f90 b/src/crystallite.f90 index f049cd400..b357b4a02 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -761,7 +761,7 @@ subroutine crystallite_stressTangent() crystallite_Fe(1:3,1:3,c,i,e), & crystallite_Fi(1:3,1:3,c,i,e),c,i,e) ! call constitutive law to calculate elastic stress tangent call constitutive_LiAndItsTangents(devNull,dLidS,dLidFi, & - crystallite_Tstar_v(1:6,c,i,e), & + math_6toSym33(crystallite_Tstar_v(1:6,c,i,e)), & crystallite_Fi(1:3,1:3,c,i,e), & c,i,e) ! call constitutive law to calculate Li tangent in lattice configuration @@ -1387,7 +1387,7 @@ logical function integrateStress(& !* calculate intermediate velocity gradient and its tangent from constitutive law call constitutive_LiAndItsTangents(Li_constitutive, dLi_dS, dLi_dFi, & - math_sym33to6(S), Fi_new, ipc, ip, el) + S, Fi_new, ipc, ip, el) #ifdef DEBUG if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & @@ -2268,6 +2268,8 @@ end subroutine update_state subroutine update_dotState(timeFraction) use, intrinsic :: & IEEE_arithmetic + use math, only: & + math_6toSym33 !ToDo: Temporarly needed until T_star_v is called S and stored as matrix use material, only: & plasticState, & sourceState, & @@ -2300,7 +2302,7 @@ subroutine update_dotState(timeFraction) do g = 1,homogenization_Ngrains(mesh_element(3,e)) !$OMP FLUSH(nonlocalStop) if ((crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) .and. .not. nonlocalStop) then - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & + call constitutive_collectDotState(math_6toSym33(crystallite_Tstar_v(1:6,g,i,e)), & crystallite_Fe, & crystallite_Fi(1:3,1:3,g,i,e), & crystallite_Fp, & From ae9d8e4e8d7f4dbc05d1c4457d1453d0b008c7c7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 18 Feb 2019 10:28:08 +0100 Subject: [PATCH 48/97] cleaning --- src/lattice.f90 | 8 +- src/plastic_nonlocal.f90 | 213 ++++++++++++--------------------------- 2 files changed, 68 insertions(+), 153 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 9ed8cced4..b9fb71065 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -30,7 +30,6 @@ module lattice lattice_sn, & !< normal direction of slip system lattice_st, & !< sd x sn lattice_sd !< slip direction of slip system - ! END DEPRECATED @@ -273,7 +272,7 @@ module lattice -2, 1, 1, 3, 2, -1, -1, 2, & 1, -2, 1, 3, -1, 2, -1, 2, & 1, 1, -2, 3, -1, -1, 2, 2 & - ],pReal),shape(LATTICE_HEX_SYSTEMSLIP)) !< slip systems for hex sorted by A. Alankar & P. Eisenlohr + ],pReal),shape(LATTICE_HEX_SYSTEMSLIP)) !< slip systems for hex sorted by A. Alankar & P. Eisenlohr character(len=*), dimension(6), parameter, private :: LATTICE_HEX_SLIPFAMILY_NAME = & ['<1 1 . 1>{0 0 . 1} ', & @@ -313,7 +312,7 @@ module lattice -2, 1, 1, -3, -2, 1, 1, 2, & 1, -2, 1, -3, 1, -2, 1, 2, & 1, 1, -2, -3, 1, 1, -2, 2 & - ],pReal),shape(LATTICE_HEX_SYSTEMTWIN)) !< twin systems for hex, order follows Prof. Tom Bieler's scheme; but numbering in data was restarted from 1 + ],pReal),shape(LATTICE_HEX_SYSTEMTWIN)) !< twin systems for hex, order follows Prof. Tom Bieler's scheme character(len=*), dimension(4), parameter, private :: LATTICE_HEX_TWINFAMILY_NAME = & ['<-1 0 . 1>{1 0 . 2} ', & @@ -406,7 +405,7 @@ module lattice 1,-1, 1, -2,-1, 1, & -1, 1, 1, -1,-2, 1, & 1, 1, 1, 1,-2, 1 & - ],pReal),[ 3_pInt + 3_pInt,LATTICE_bct_Nslip]) !< slip systems for bct sorted by Bieler + ],pReal),[ 3_pInt + 3_pInt,LATTICE_bct_Nslip]) !< slip systems for bct sorted by Bieler character(len=*), dimension(13), parameter, private :: LATTICE_BCT_SLIPFAMILY_NAME = & ['{1 0 0)<0 0 1] ', & @@ -495,6 +494,7 @@ module lattice LATTICE_bct_ID, & LATTICE_ort_ID end enum + integer(kind(LATTICE_undefined_ID)), dimension(:), allocatable, public, protected :: & lattice_structure, trans_lattice_structure diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 8727e576c..79b1df55a 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -51,11 +51,8 @@ module plastic_nonlocal real(pReal), dimension(:), allocatable, private :: & atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient - selfDiffusionEnergy, & !< activation enthalpy for diffusion aTolRho, & !< absolute tolerance for dislocation density in state integration aTolShear, & !< absolute tolerance for accumulated shear in state integration - significantRho, & !< density considered significant - significantN, & !< number of dislocations considered significant cutoffRadius, & !< cutoff radius for dislocation stress doublekinkwidth, & !< width of a doubkle kink in multiples of the burgers vector length b solidSolutionEnergy, & !< activation energy for solid solution in J @@ -63,8 +60,6 @@ module plastic_nonlocal solidSolutionConcentration, & !< concentration of solid solution in atomic parts pParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) qParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) - viscosity, & !< viscosity for dislocation glide in Pa s - fattack, & !< attack frequency in Hz rhoSglScatter, & !< standard deviation of scatter in initial dislocation density surfaceTransmissivity, & !< transmissivity at free surface grainboundaryTransmissivity, & !< transmissivity at grain boundary (identified by different texture) @@ -72,8 +67,7 @@ module plastic_nonlocal fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) rhoSglRandom, & rhoSglRandomBinning, & - linetensionEffect, & - edgeJogFactor + linetensionEffect real(pReal), dimension(:,:), allocatable, private :: & rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance @@ -204,9 +198,6 @@ module plastic_nonlocal interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance forestProjectionEdge, & !< matrix of forest projections of edge dislocations for each instance forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance - integer(pInt), dimension(:), allocatable, private :: & - iGamma, & !< state indices for accumulated shear - iRhoF !< state indices for forest density real(pReal), dimension(:), allocatable, private :: & nonSchmidCoeff integer(pInt) :: totalNslip @@ -249,7 +240,7 @@ module plastic_nonlocal private :: & plastic_nonlocal_kinetics - + contains @@ -310,12 +301,9 @@ integer(pInt) :: phase, & s, & ! index of my slip system s1, & ! index of my slip system s2, & ! index of my slip system - it, & ! index of my interaction type t, & ! index of dislocation type c, & ! index of dislocation character - Nchunks_SlipSlip = 0_pInt, & - Nchunks_SlipFamilies = 0_pInt, & - mySize = 0_pInt ! to suppress warnings, safe as init is called only once + Nchunks_SlipFamilies character(len=65536) :: & tag = '', & line = '' @@ -354,11 +342,8 @@ allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) allocate(atomicVolume(maxNinstances), source=0.0_pReal) allocate(Dsd0(maxNinstances), source=-1.0_pReal) -allocate(selfDiffusionEnergy(maxNinstances), source=0.0_pReal) allocate(aTolRho(maxNinstances), source=0.0_pReal) allocate(aTolShear(maxNinstances), source=0.0_pReal) -allocate(significantRho(maxNinstances), source=0.0_pReal) -allocate(significantN(maxNinstances), source=0.0_pReal) allocate(cutoffRadius(maxNinstances), source=-1.0_pReal) allocate(doublekinkwidth(maxNinstances), source=0.0_pReal) allocate(solidSolutionEnergy(maxNinstances), source=0.0_pReal) @@ -366,8 +351,6 @@ allocate(solidSolutionSize(maxNinstances), source=0.0_pReal) allocate(solidSolutionConcentration(maxNinstances), source=0.0_pReal) allocate(pParam(maxNinstances), source=1.0_pReal) allocate(qParam(maxNinstances), source=1.0_pReal) -allocate(viscosity(maxNinstances), source=0.0_pReal) -allocate(fattack(maxNinstances), source=0.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) @@ -376,7 +359,6 @@ allocate(grainboundaryTransmissivity(maxNinstances), source=-1.0_pReal) allocate(CFLfactor(maxNinstances), source=2.0_pReal) allocate(fEdgeMultiplication(maxNinstances), source=0.0_pReal) allocate(linetensionEffect(maxNinstances), source=0.0_pReal) -allocate(edgeJogFactor(maxNinstances), source=1.0_pReal) allocate(shortRangeStressCorrection(maxNinstances), source=.false.) allocate(probabilisticMultiplication(maxNinstances), source=.false.) @@ -469,20 +451,12 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s atomicVolume(instance) = IO_floatValue(line,chunkPos,2_pInt) case('selfdiffusionprefactor','dsd0') Dsd0(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('selfdiffusionenergy','qsd') - selfDiffusionEnergy(instance) = IO_floatValue(line,chunkPos,2_pInt) case('atol_rho','atol_density','absolutetolerancedensity','absolutetolerance_density') aTolRho(instance) = IO_floatValue(line,chunkPos,2_pInt) case('atol_shear','atol_plasticshear','atol_accumulatedshear','absolutetoleranceshear','absolutetolerance_shear') aTolShear(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('significantrho','significant_rho','significantdensity','significant_density') - significantRho(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('significantn','significant_n','significantdislocations','significant_dislcations') - significantN(instance) = IO_floatValue(line,chunkPos,2_pInt) case('linetension','linetensioneffect','linetension_effect') linetensionEffect(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('edgejog','edgejogs','edgejogeffect','edgejog_effect') - edgeJogFactor(instance) = IO_floatValue(line,chunkPos,2_pInt) case('peierlsstressedge','peierlsstress_edge') do f = 1_pInt, Nchunks_SlipFamilies peierlsStressPerSlipFamily(f,1_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) @@ -503,10 +477,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s pParam(instance) = IO_floatValue(line,chunkPos,2_pInt) case('q') qParam(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('viscosity','glideviscosity') - viscosity(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('attackfrequency','fattack') - fattack(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglscatter') rhoSglScatter(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandom') @@ -564,24 +534,16 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s enddo if (linetensionEffect(instance) < 0.0_pReal .or. linetensionEffect(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='linetension ('//PLASTICITY_NONLOCAL_label//')') - if (edgeJogFactor(instance) < 0.0_pReal .or. edgeJogFactor(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='edgejog ('//PLASTICITY_NONLOCAL_label//')') if (cutoffRadius(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='r ('//PLASTICITY_NONLOCAL_label//')') if (atomicVolume(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') if (Dsd0(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='selfDiffusionPrefactor ('//PLASTICITY_NONLOCAL_label//')') - if (selfDiffusionEnergy(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='selfDiffusionEnergy ('//PLASTICITY_NONLOCAL_label//')') if (aTolRho(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='aTol_rho ('//PLASTICITY_NONLOCAL_label//')') if (aTolShear(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='aTol_shear ('//PLASTICITY_NONLOCAL_label//')') - if (significantRho(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='significantRho ('//PLASTICITY_NONLOCAL_label//')') - if (significantN(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='significantN ('//PLASTICITY_NONLOCAL_label//')') if (doublekinkwidth(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='doublekinkwidth ('//PLASTICITY_NONLOCAL_label//')') if (solidSolutionEnergy(instance) <= 0.0_pReal) & @@ -594,10 +556,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='p ('//PLASTICITY_NONLOCAL_label//')') if (qParam(instance) < 1.0_pReal .or. qParam(instance) > 2.0_pReal) & call IO_error(211_pInt,ext_msg='q ('//PLASTICITY_NONLOCAL_label//')') - if (viscosity(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='viscosity ('//PLASTICITY_NONLOCAL_label//')') - if (fattack(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='attackFrequency ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglScatter(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandom(instance) < 0.0_pReal) & @@ -930,6 +888,15 @@ param(instance)%probabilisticMultiplication = .false. prm%shortRangeStressCorrection = config_phase(p)%getInt('shortrangestresscorrection' ) > 0_pInt prm%probabilisticMultiplication = config_phase(p)%keyExists('/probabilisticmultiplication/' )!,'randomsources','randommultiplication','discretesources') + + ! sanity checks + if ( prm%viscosity <= 0.0_pReal) extmsg = trim(extmsg)//' viscosity' + if ( prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' + if ( prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' + if ( prm%selfDiffusionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' selfDiffusionEnergy' + if ( prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' + if (prm%edgeJogFactor < 0.0_pReal .or. prm%edgeJogFactor > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -1037,8 +1004,7 @@ use IO, only: IO_error use lattice, only: lattice_maxNslipFamily use math, only: math_sampleGaussVar use mesh, only: mesh_ipVolume, & - theMesh, & - mesh_element + theMesh use material, only: material_phase, & phase_plasticityInstance, & plasticState, & @@ -1190,7 +1156,6 @@ use debug, only: & debug_e use mesh, only: & theMesh, & - mesh_element, & mesh_ipNeighborhood, & mesh_ipCoordinates, & mesh_ipVolume, & @@ -1205,8 +1170,6 @@ use material, only: & use lattice, only: & lattice_sd, & lattice_st, & - lattice_mu, & - lattice_nu, & lattice_structure, & LATTICE_bcc_ID, & LATTICE_fcc_ID @@ -1314,16 +1277,16 @@ myInteractionMatrix = 0.0_pReal myInteractionMatrix(1:ns,1:ns) = prm%interactionSlipSlip(1:ns,1:ns) if (lattice_structure(ph) == LATTICE_bcc_ID .or. lattice_structure(ph) == LATTICE_fcc_ID) then ! only fcc and bcc do s = 1_pInt,ns - myRhoForest = max(rhoForest(s),significantRho(instance)) - correction = ( 1.0_pReal - linetensionEffect(instance) & - + linetensionEffect(instance) & - * log(0.35_pReal * burgers(s,instance) * sqrt(myRhoForest)) & - / log(0.35_pReal * burgers(s,instance) * 1e6_pReal)) ** 2.0_pReal + myRhoForest = max(rhoForest(s),prm%significantRho) + correction = ( 1.0_pReal - prm%linetensionEffect & + + prm%linetensionEffect & + * log(0.35_pReal * prm%burgers(s) * sqrt(myRhoForest)) & + / log(0.35_pReal * prm%burgers(s) * 1e6_pReal)) ** 2.0_pReal myInteractionMatrix(s,1:ns) = correction * myInteractionMatrix(s,1:ns) enddo endif forall (s = 1_pInt:ns) & - tauThreshold(s) = lattice_mu(ph) * burgers(s,instance) & + tauThreshold(s) = prm%mu * prm%burgers(s) & * sqrt(dot_product((sum(abs(rhoSgl),2) + sum(abs(rhoDip),2)), myInteractionMatrix(s,1:ns))) @@ -1349,12 +1312,8 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then np = phaseAt(1,neighbor_ip,neighbor_el) no = phasememberAt(1,neighbor_ip,neighbor_el) if (neighbor_el > 0 .and. neighbor_ip > 0) then - neighbor_phase = material_phase(1,neighbor_ip,neighbor_el) - neighbor_instance = phase_plasticityInstance(neighbor_phase) - neighbor_ns = totalNslip(neighbor_instance) - if (.not. phase_localPlasticity(neighbor_phase) & - .and. neighbor_instance == instance) then ! same instance should be same structure - if (neighbor_ns == ns) then + neighbor_instance = phase_plasticityInstance(material_phase(1,neighbor_ip,neighbor_el)) + if (neighbor_instance == instance) then ! same instance should be same structure nRealNeighbors = nRealNeighbors + 1_pInt forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) @@ -1376,10 +1335,6 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then if (math_mul3x3(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) & ! neighboring connection points in opposite direction to face normal: must be periodic image connection_latticeConf(1:3,n) = normal_latticeConf * mesh_ipVolume(ip,el) & / mesh_ipArea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell - else - ! different number of active slip systems - call IO_error(-1_pInt,ext_msg='different number of active slip systems in neighboring IPs of same crystal structure') - endif else ! local neighbor or different lattice structure or different constitution instance -> use central values instead connection_latticeConf(1:3,n) = 0.0_pReal @@ -1438,8 +1393,8 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then !* gives the local stress correction when multiplied with a factor - tauBack(s) = - lattice_mu(ph) * burgers(s,instance) / (2.0_pReal * pi) & - * (rhoExcessGradient_over_rho(1) / (1.0_pReal - lattice_nu(ph)) & + tauBack(s) = - prm%mu * prm%burgers(s) / (2.0_pReal * pi) & + * (rhoExcessGradient_over_rho(1) / (1.0_pReal - prm%nu) & + rhoExcessGradient_over_rho(2)) enddo @@ -1528,6 +1483,7 @@ real(pReal) tauRel_P, & instance = phase_plasticityInstance(material_phase(1_pInt,ip,el)) ns = totalNslip(instance) +associate(prm => param(instance)) v = 0.0_pReal dv_dtau = 0.0_pReal dv_dtauNS = 0.0_pReal @@ -1549,7 +1505,7 @@ if (Temperature > 0.0_pReal) then criticalStress_P = peierlsStress(s,c,instance) activationEnergy_P = criticalStress_P * activationVolume_P tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one - tPeierls = 1.0_pReal / fattack(instance) & + tPeierls = 1.0_pReal / prm%fattack & * exp(activationEnergy_P / (KB * Temperature) & * (1.0_pReal - tauRel_P**pParam(instance))**qParam(instance)) if (tauEff < criticalStress_P) then @@ -1572,7 +1528,7 @@ if (Temperature > 0.0_pReal) then activationEnergy_S = solidSolutionEnergy(instance) criticalStress_S = activationEnergy_S / activationVolume_S tauRel_S = min(1.0_pReal, tauEff / criticalStress_S) ! ensure that the activation probability cannot become greater than one - tSolidSolution = 1.0_pReal / fattack(instance) & + tSolidSolution = 1.0_pReal / prm%fattack & * exp(activationEnergy_S / (KB * Temperature) & * (1.0_pReal - tauRel_S**pParam(instance))**qParam(instance)) if (tauEff < criticalStress_S) then @@ -1588,7 +1544,7 @@ if (Temperature > 0.0_pReal) then !* viscous glide velocity tauEff = abs(tau(s)) - tauThreshold(s) - mobility = burgers(s,instance) / viscosity(instance) + mobility = burgers(s,instance) / prm%viscosity vViscous = mobility * tauEff @@ -1620,6 +1576,7 @@ endif endif #endif +end associate end subroutine plastic_nonlocal_kinetics !-------------------------------------------------------------------------------------------------- @@ -1667,8 +1624,7 @@ integer(pInt) instance, & ph, & !phase number of, & !offset t, & !< dislocation type - s, & !< index of my current slip system - sLattice !< index of my current slip system according to lattice order + s !< index of my current slip system real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),8) :: & rhoSgl !< single dislocation densities (including blocked) real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),4) :: & @@ -1698,8 +1654,8 @@ forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) rhoSgl(s,t) = max(plasticState(ph)%state(iRhoU(s,t,instance),of), 0.0_pReal) ! ensure positive single mobile densities rhoSgl(s,t+4_pInt) = plasticState(ph)%state(iRhoB(s,t,instance),of) endforall -where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoSgl) < significantRho(instance)) & +where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal tauBack = plasticState(ph)%state(iTauB(1:ns,instance),of) @@ -1818,8 +1774,6 @@ use debug, only: debug_level, & debug_e use math, only: pi, & math_mul33xx33 -use lattice, only: lattice_mu, & - lattice_nu use mesh, only: mesh_ipVolume use material, only: material_phase, & plasticState, & @@ -1887,11 +1841,11 @@ forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) endforall tauBack = plasticState(ph)%state(iTauB(1:ns,instance),of) -where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoSgl) < significantRho(instance)) & +where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal -where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoDip) < significantRho(instance)) & +where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoDip) < prm%significantRho) & rhoDip = 0.0_pReal @@ -1919,14 +1873,14 @@ enddo !*** calculate limits for stable dipole height -do s = 1_pInt,ns +do s = 1_pInt,prm%totalNslip tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo dLower = minDipoleHeight(1:ns,1:2,instance) -dUpper(1:ns,1) = lattice_mu(ph) * burgers(1:ns,instance) & - / (8.0_pReal * pi * (1.0_pReal - lattice_nu(ph)) * abs(tau)) -dUpper(1:ns,2) = lattice_mu(ph) * burgers(1:ns,instance) / (4.0_pReal * pi * abs(tau)) +dUpper(1:ns,1) = prm%mu * prm%burgers & + / (8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) +dUpper(1:ns,2) = prm%mu * prm%burgers / (4.0_pReal * PI * abs(tau)) forall (c = 1_pInt:2_pInt) @@ -1995,7 +1949,6 @@ use, intrinsic :: & use prec, only: dNeq0, & dNeq, & dEq0 -use numerics, only: numerics_timeSyncing use IO, only: IO_error use debug, only: debug_level, & debug_constitutive, & @@ -2013,7 +1966,6 @@ use math, only: math_mul3x3, & math_det33, & pi use mesh, only: theMesh, & - mesh_element, & mesh_ipNeighborhood, & mesh_ipVolume, & mesh_ipArea, & @@ -2069,8 +2021,7 @@ integer(pInt) :: ph, & p,& !< phase shortcut np,& !< neighbour phase shortcut topp, & !< type of dislocation with opposite sign to t - s, & !< index of my current slip system - sLattice !< index of my current slip system according to lattice order + s !< index of my current slip system real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),10) :: & rhoDot, & !< density evolution rhoDotMultiplication, & !< density evolution by multiplication @@ -2086,7 +2037,6 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt my_rhoSgl !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),4) :: & v, & !< current dislocation glide velocity - v0, & !< dislocation glide velocity at start of cryst inc my_v, & !< dislocation glide velocity of central ip neighbor_v, & !< dislocation glide velocity of enighboring ip gdot !< shear rates @@ -2161,26 +2111,13 @@ tauBack = plasticState(p)%state(iTauB(1:ns,instance),o) rhoSglOriginal = rhoSgl rhoDipOriginal = rhoDip -where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoSgl) < significantRho(instance)) & +where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal -where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoDip) < significantRho(instance)) & +where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & + .or. abs(rhoDip) < prm%significantRho) & rhoDip = 0.0_pReal -if (numerics_timeSyncing) then - forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) - rhoSgl0(s,t) = max(plasticState(p)%state0(iRhoU(s,t,instance),o), 0.0_pReal) - rhoSgl0(s,t+4_pInt) = plasticState(p)%state0(iRhoB(s,t,instance),o) - v0(s,t) = plasticState(p)%state0(iV (s,t,instance),o) - endforall - where (abs(rhoSgl0) * mesh_ipVolume(ip,el) ** 0.667_pReal < significantN(instance) & - .or. abs(rhoSgl0) < significantRho(instance)) & - rhoSgl0 = 0.0_pReal -endif - - - !*** sanity check for timestep if (timestep <= 0.0_pReal) then ! if illegal timestep... Why here and not on function entry?? @@ -2194,7 +2131,7 @@ endif !*** Calculate shear rate forall (t = 1_pInt:4_pInt) & - gdot(1_pInt:ns,t) = rhoSgl(1_pInt:ns,t) * burgers(1:ns,instance) * v(1:ns,t) + gdot(1_pInt:ns,t) = rhoSgl(1_pInt:ns,t) * prm%burgers(1:ns) * v(1:ns,t) #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt & @@ -2365,23 +2302,14 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then endif if (considerEnteringFlux) then - if(numerics_timeSyncing .and. (dNeq(subfrac(1,neighbor_ip,neighbor_el),subfrac(1,ip,el)))) then ! for timesyncing: in case of a timestep at the interface we have to use "state0" to make sure that fluxes n both sides are equal - forall (s = 1:ns, t = 1_pInt:4_pInt) - - neighbor_v(s,t) = plasticState(np)%state0(iV (s,t,neighbor_instance),no) - neighbor_rhoSgl(s,t) = max(plasticState(np)%state0(iRhoU(s,t,neighbor_instance),no),0.0_pReal) - - endforall - else forall (s = 1:ns, t = 1_pInt:4_pInt) neighbor_v(s,t) = plasticState(np)%state(iV (s,t,neighbor_instance),no) neighbor_rhoSgl(s,t) = max(plasticState(np)%state(iRhoU(s,t,neighbor_instance),no), & 0.0_pReal) endforall - endif - where (neighbor_rhoSgl * mesh_ipVolume(neighbor_ip,neighbor_el) ** 0.667_pReal < significantN(instance) & - .or. neighbor_rhoSgl < significantRho(instance)) & + where (neighbor_rhoSgl * mesh_ipVolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & + .or. neighbor_rhoSgl < prm%significantRho) & neighbor_rhoSgl = 0.0_pReal normal_neighbor2me_defConf = math_det33(Favg) * math_mul33x3(math_inv33(transpose(Favg)), & mesh_ipAreaNormal(1:3,neighbor_n,neighbor_ip,neighbor_el)) ! calculate the normal of the interface in (average) deformed configuration (now pointing from my neighbor to me!!!) @@ -2433,17 +2361,6 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then !* use "state0" to make sure that fluxes on both sides of the (potential) timestep are equal. my_rhoSgl = rhoSgl my_v = v - if(numerics_timeSyncing) then - if (dEq0(subfrac(1_pInt,ip,el))) then - my_rhoSgl = rhoSgl0 - my_v = v0 - elseif (neighbor_n > 0_pInt) then - if (dEq0(subfrac(1_pInt,neighbor_ip,neighbor_el))) then - my_rhoSgl = rhoSgl0 - my_v = v0 - endif - endif - endif normal_me2neighbor_defConf = math_det33(Favg) & * math_mul33x3(math_inv33(transpose(Favg)), & @@ -2483,20 +2400,20 @@ endif !*** formation by glide do c = 1_pInt,2_pInt - rhoDotSingle2DipoleGlide(1:ns,2*c-1) = -2.0_pReal * dUpper(1:ns,c) / burgers(1:ns,instance) & + rhoDotSingle2DipoleGlide(1:ns,2*c-1) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) & ! negative mobile --> positive mobile + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1)) & ! positive mobile --> negative mobile + abs(rhoSgl(1:ns,2*c+4)) * abs(gdot(1:ns,2*c-1))) ! positive mobile --> negative immobile - rhoDotSingle2DipoleGlide(1:ns,2*c) = -2.0_pReal * dUpper(1:ns,c) / burgers(1:ns,instance) & + rhoDotSingle2DipoleGlide(1:ns,2*c) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) & ! negative mobile --> positive mobile + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1)) & ! positive mobile --> negative mobile + abs(rhoSgl(1:ns,2*c+3)) * abs(gdot(1:ns,2*c))) ! negative mobile --> positive immobile - rhoDotSingle2DipoleGlide(1:ns,2*c+3) = -2.0_pReal * dUpper(1:ns,c) / burgers(1:ns,instance) & + rhoDotSingle2DipoleGlide(1:ns,2*c+3) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & * rhoSgl(1:ns,2*c+3) * abs(gdot(1:ns,2*c)) ! negative mobile --> positive immobile - rhoDotSingle2DipoleGlide(1:ns,2*c+4) = -2.0_pReal * dUpper(1:ns,c) / burgers(1:ns,instance) & + rhoDotSingle2DipoleGlide(1:ns,2*c+4) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns)& * rhoSgl(1:ns,2*c+4) * abs(gdot(1:ns,2*c-1)) ! positive mobile --> negative immobile rhoDotSingle2DipoleGlide(1:ns,c+8) = - rhoDotSingle2DipoleGlide(1:ns,2*c-1) & @@ -2511,7 +2428,7 @@ enddo rhoDotAthermalAnnihilation = 0.0_pReal forall (c=1_pInt:2_pInt) & - rhoDotAthermalAnnihilation(1:ns,c+8_pInt) = -2.0_pReal * dLower(1:ns,c) / burgers(1:ns,instance) & + rhoDotAthermalAnnihilation(1:ns,c+8_pInt) = -2.0_pReal * dLower(1:ns,c) / prm%burgers(1:ns) & * ( 2.0_pReal * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1))) & ! was single hitting single + 2.0_pReal * (abs(rhoSgl(1:ns,2*c+3)) * abs(gdot(1:ns,2*c)) + abs(rhoSgl(1:ns,2*c+4)) * abs(gdot(1:ns,2*c-1))) & ! was single hitting immobile single or was immobile single hit by single + rhoDip(1:ns,c) * (abs(gdot(1:ns,2*c-1)) + abs(gdot(1:ns,2*c)))) ! single knocks dipole constituent @@ -2519,16 +2436,16 @@ forall (c=1_pInt:2_pInt) & if (lattice_structure(ph) == LATTICE_fcc_ID) & ! only fcc forall (s = 1:ns, colinearSystem(s,instance) > 0_pInt) & rhoDotAthermalAnnihilation(colinearSystem(s,instance),1:2) = - rhoDotAthermalAnnihilation(s,10) & - * 0.25_pReal * sqrt(rhoForest(s)) * (dUpper(s,2) + dLower(s,2)) * edgeJogFactor(instance) + * 0.25_pReal * sqrt(rhoForest(s)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor !*** thermally activated annihilation of edge dipoles by climb rhoDotThermalAnnihilation = 0.0_pReal -selfDiffusion = Dsd0(instance) * exp(-selfDiffusionEnergy(instance) / (KB * Temperature)) -vClimb = atomicVolume(instance) * selfDiffusion / ( KB * Temperature ) & - * lattice_mu(ph) / ( 2.0_pReal * PI * (1.0_pReal-lattice_nu(ph)) ) & +selfDiffusion = prm%Dsd0 * exp(-prm%selfDiffusionEnergy / (KB * Temperature)) +vClimb = prm%atomicVolume * selfDiffusion / ( KB * Temperature ) & + * prm%mu / ( 2.0_pReal * PI * (1.0_pReal-prm%nu) ) & * 2.0_pReal / ( dUpper(1:ns,1) + dLower(1:ns,1) ) forall (s = 1_pInt:ns, dUpper(s,1) > dLower(s,1)) & rhoDotThermalAnnihilation(s,9) = max(- 4.0_pReal * rhoDip(s,1) * vClimb(s) / (dUpper(s,1) - dLower(s,1)), & @@ -2621,8 +2538,7 @@ use material, only: material_phase, & phase_localPlasticity, & phase_plasticityInstance, & homogenization_maxNgrains -use mesh, only: mesh_element, & - mesh_ipNeighborhood, & +use mesh, only: mesh_ipNeighborhood, & theMesh use lattice, only: lattice_sn, & lattice_sd, & @@ -2671,7 +2587,7 @@ instance = phase_plasticityInstance(ph) ns = totalNslip(instance) slipNormal(1:3,1:ns) = lattice_sn(1:3, slipSystemLattice(1:ns,instance), ph) slipDirection(1:3,1:ns) = lattice_sd(1:3, slipSystemLattice(1:ns,instance), ph) - +associate(prm => param(instance)) !*** start out fully compatible @@ -2689,7 +2605,7 @@ neighbors: do n = 1_pInt,Nneighbors !* Set surface transmissivity to the value specified in the material.config if (neighbor_e <= 0_pInt .or. neighbor_i <= 0_pInt) then - forall(s1 = 1_pInt:ns) my_compatibility(1:2,s1,s1,n) = sqrt(surfaceTransmissivity(instance)) + forall(s1 = 1_pInt:ns) my_compatibility(1:2,s1,s1,n) = sqrt(prm%surfaceTransmissivity) cycle endif @@ -2711,12 +2627,12 @@ neighbors: do n = 1_pInt,Nneighbors !* GRAIN BOUNDARY ! !* fixed transmissivity for adjacent ips with different texture (only if explicitly given in material.config) - if (grainboundaryTransmissivity(instance) >= 0.0_pReal) then + if (prm%grainboundaryTransmissivity >= 0.0_pReal) then neighbor_textureID = material_texture(1,neighbor_i,neighbor_e) if (neighbor_textureID /= textureID) then if (.not. phase_localPlasticity(neighbor_phase)) then forall(s1 = 1_pInt:ns) & - my_compatibility(1:2,s1,s1,n) = sqrt(grainboundaryTransmissivity(instance)) + my_compatibility(1:2,s1,s1,n) = sqrt(prm%grainboundaryTransmissivity) endif cycle endif @@ -2764,6 +2680,7 @@ enddo neighbors compatibility(1:2,1:ns,1:ns,1:Nneighbors,i,e) = my_compatibility +end associate end subroutine plastic_nonlocal_updateCompatibility @@ -2812,8 +2729,8 @@ function plastic_nonlocal_postResults(Mp,Fe,ip,el) o, & !< index of current output of,& !< offset shortcut t, & !< type of dislocation - s, & !< index of my current slip system - sLattice !< index of my current slip system according to lattice order + s !< index of my current slip system + real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),8) :: & rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) rhoDotSgl !< evolution rate of single dislocation densities (positive/negative screw and edge without dipoles) @@ -2835,8 +2752,6 @@ function plastic_nonlocal_postResults(Mp,Fe,ip,el) m_currentconf !< direction of dislocation motion for edge and screw (unit vector) in current configuration real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & n_currentconf !< slip system normal (unit vector) in current configuration - real(pReal), dimension(3,3) :: & - sigma ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) From 1a5711e2464b62886fbafcfce168fa9fb5cf0d92 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 18 Feb 2019 22:55:31 +0100 Subject: [PATCH 49/97] using more parameters from parameter structure --- src/plastic_nonlocal.f90 | 152 ++++++++++++--------------------------- 1 file changed, 46 insertions(+), 106 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 79b1df55a..c87fd9865 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -14,12 +14,6 @@ module plastic_nonlocal real(pReal), parameter, private :: & KB = 1.38e-23_pReal !< Physical parameter, Boltzmann constant in J/Kelvin - integer(pInt), dimension(:), allocatable, public, protected :: & - plastic_nonlocal_sizeDotState, & !< number of dotStates = number of basic state variables - plastic_nonlocal_sizeDependentState, & !< number of dependent state variables - plastic_nonlocal_sizeState !< total number of state variables - - integer(pInt), dimension(:,:), allocatable, target, public :: & plastic_nonlocal_sizePostResult !< size of each post result output @@ -51,23 +45,15 @@ module plastic_nonlocal real(pReal), dimension(:), allocatable, private :: & atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient - aTolRho, & !< absolute tolerance for dislocation density in state integration - aTolShear, & !< absolute tolerance for accumulated shear in state integration cutoffRadius, & !< cutoff radius for dislocation stress - doublekinkwidth, & !< width of a doubkle kink in multiples of the burgers vector length b - solidSolutionEnergy, & !< activation energy for solid solution in J - solidSolutionSize, & !< solid solution obstacle size in multiples of the burgers vector length - solidSolutionConcentration, & !< concentration of solid solution in atomic parts pParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) qParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) rhoSglScatter, & !< standard deviation of scatter in initial dislocation density surfaceTransmissivity, & !< transmissivity at free surface grainboundaryTransmissivity, & !< transmissivity at grain boundary (identified by different texture) - CFLfactor, & !< safety factor for CFL flux condition fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) rhoSglRandom, & - rhoSglRandomBinning, & - linetensionEffect + rhoSglRandomBinning real(pReal), dimension(:,:), allocatable, private :: & rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance @@ -77,9 +63,7 @@ module plastic_nonlocal rhoDipEdge0, & !< initial edge dipole dislocation density per slip system for each family and instance rhoDipScrew0, & !< initial screw dipole dislocation density per slip system for each family and instance lambda0PerSlipFamily, & !< mean free path prefactor for each family and instance - lambda0, & !< mean free path prefactor for each slip system and instance - burgersPerSlipFamily, & !< absolute length of burgers vector [m] for each family and instance - burgers !< absolute length of burgers vector [m] for each slip system and instance + lambda0 !< mean free path prefactor for each slip system and instance real(pReal), dimension(:,:,:), allocatable, private :: & @@ -209,8 +193,6 @@ module plastic_nonlocal integer(pInt) , dimension(:) ,allocatable , public:: & Nslip,& - slipFamily, & !< lookup table relating active slip system to slip family for each instance - slipSystemLattice, & !< lookup table relating active slip system index to lattice slip system index for each instance colinearSystem !< colinear system to the active slip system (only valid for fcc!) logical, private :: & @@ -329,9 +311,6 @@ integer(pInt) :: phase, & !*** memory allocation for global variables allocate(param(maxNinstances)) -allocate(plastic_nonlocal_sizeDotState(maxNinstances), source=0_pInt) -allocate(plastic_nonlocal_sizeDependentState(maxNinstances), source=0_pInt) -allocate(plastic_nonlocal_sizeState(maxNinstances), source=0_pInt) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) plastic_nonlocal_output = '' @@ -342,13 +321,7 @@ allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) allocate(atomicVolume(maxNinstances), source=0.0_pReal) allocate(Dsd0(maxNinstances), source=-1.0_pReal) -allocate(aTolRho(maxNinstances), source=0.0_pReal) -allocate(aTolShear(maxNinstances), source=0.0_pReal) allocate(cutoffRadius(maxNinstances), source=-1.0_pReal) -allocate(doublekinkwidth(maxNinstances), source=0.0_pReal) -allocate(solidSolutionEnergy(maxNinstances), source=0.0_pReal) -allocate(solidSolutionSize(maxNinstances), source=0.0_pReal) -allocate(solidSolutionConcentration(maxNinstances), source=0.0_pReal) allocate(pParam(maxNinstances), source=1.0_pReal) allocate(qParam(maxNinstances), source=1.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) @@ -356,9 +329,7 @@ allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) allocate(surfaceTransmissivity(maxNinstances), source=1.0_pReal) allocate(grainboundaryTransmissivity(maxNinstances), source=-1.0_pReal) -allocate(CFLfactor(maxNinstances), source=2.0_pReal) allocate(fEdgeMultiplication(maxNinstances), source=0.0_pReal) -allocate(linetensionEffect(maxNinstances), source=0.0_pReal) allocate(shortRangeStressCorrection(maxNinstances), source=.false.) allocate(probabilisticMultiplication(maxNinstances), source=.false.) @@ -368,7 +339,6 @@ allocate(rhoSglScrewPos0(lattice_maxNslipFamily,maxNinstances), s allocate(rhoSglScrewNeg0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(rhoDipEdge0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(rhoDipScrew0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(burgersPerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) allocate(minDipoleHeightPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=-1.0_pReal) allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=0.0_pReal) @@ -433,10 +403,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case ('burgers') - do f = 1_pInt, Nchunks_SlipFamilies - burgersPerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo case('cutoffradius','r') cutoffRadius(instance) = IO_floatValue(line,chunkPos,2_pInt) case('minimumdipoleheightedge','ddipminedge') @@ -451,12 +417,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s atomicVolume(instance) = IO_floatValue(line,chunkPos,2_pInt) case('selfdiffusionprefactor','dsd0') Dsd0(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('atol_rho','atol_density','absolutetolerancedensity','absolutetolerance_density') - aTolRho(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('atol_shear','atol_plasticshear','atol_accumulatedshear','absolutetoleranceshear','absolutetolerance_shear') - aTolShear(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('linetension','linetensioneffect','linetension_effect') - linetensionEffect(instance) = IO_floatValue(line,chunkPos,2_pInt) case('peierlsstressedge','peierlsstress_edge') do f = 1_pInt, Nchunks_SlipFamilies peierlsStressPerSlipFamily(f,1_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) @@ -465,14 +425,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies peierlsStressPerSlipFamily(f,2_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case('doublekinkwidth') - doublekinkwidth(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('solidsolutionenergy') - solidSolutionEnergy(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('solidsolutionsize') - solidSolutionSize(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('solidsolutionconcentration') - solidSolutionConcentration(instance) = IO_floatValue(line,chunkPos,2_pInt) case('p') pParam(instance) = IO_floatValue(line,chunkPos,2_pInt) case('q') @@ -487,8 +439,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s surfaceTransmissivity(instance) = IO_floatValue(line,chunkPos,2_pInt) case('grainboundarytransmissivity') grainboundaryTransmissivity(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('cflfactor') - CFLfactor(instance) = IO_floatValue(line,chunkPos,2_pInt) case('fedgemultiplication','edgemultiplicationfactor','edgemultiplication') fEdgeMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) case('shortrangestresscorrection') @@ -518,8 +468,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='rhoDipEdge0 ('//PLASTICITY_NONLOCAL_label//')') if (rhoDipScrew0(f,instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') - if (burgersPerSlipFamily(f,instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='Burgers ('//PLASTICITY_NONLOCAL_label//')') if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') if (minDipoleHeightPerSlipFamily(f,1,instance) < 0.0_pReal) & @@ -532,26 +480,12 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') endif enddo - if (linetensionEffect(instance) < 0.0_pReal .or. linetensionEffect(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='linetension ('//PLASTICITY_NONLOCAL_label//')') if (cutoffRadius(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='r ('//PLASTICITY_NONLOCAL_label//')') if (atomicVolume(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') if (Dsd0(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='selfDiffusionPrefactor ('//PLASTICITY_NONLOCAL_label//')') - if (aTolRho(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='aTol_rho ('//PLASTICITY_NONLOCAL_label//')') - if (aTolShear(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='aTol_shear ('//PLASTICITY_NONLOCAL_label//')') - if (doublekinkwidth(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='doublekinkwidth ('//PLASTICITY_NONLOCAL_label//')') - if (solidSolutionEnergy(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='solidSolutionEnergy ('//PLASTICITY_NONLOCAL_label//')') - if (solidSolutionSize(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='solidSolutionSize ('//PLASTICITY_NONLOCAL_label//')') - if (solidSolutionConcentration(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='solidSolutionConcentration ('//PLASTICITY_NONLOCAL_label//')') if (pParam(instance) <= 0.0_pReal .or. pParam(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='p ('//PLASTICITY_NONLOCAL_label//')') if (qParam(instance) < 1.0_pReal .or. qParam(instance) > 2.0_pReal) & @@ -566,8 +500,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='surfaceTransmissivity ('//PLASTICITY_NONLOCAL_label//')') if (grainboundaryTransmissivity(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='grainboundaryTransmissivity ('//PLASTICITY_NONLOCAL_label//')') - if (CFLfactor(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='CFLfactor ('//PLASTICITY_NONLOCAL_label//')') if (fEdgeMultiplication(instance) < 0.0_pReal .or. fEdgeMultiplication(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='edgemultiplicationfactor ('//PLASTICITY_NONLOCAL_label//')') @@ -593,7 +525,6 @@ allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(burgers(maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(minDipoleHeight(maxTotalNslip,2,maxNinstances), source=-1.0_pReal) allocate(forestProjectionEdge(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) @@ -738,7 +669,6 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), !*** burgers vector, mean free path prefactor and minimum dipole distance for each slip system - burgers(s1,instance) = burgersPerSlipFamily(f,instance) lambda0(s1,instance) = lambda0PerSlipFamily(f,instance) minDipoleHeight(s1,1:2,instance) = minDipoleHeightPerSlipFamily(f,1:2,instance) peierlsStress(s1,1:2,instance) = peierlsStressPerSlipFamily(f,1:2,instance) @@ -832,9 +762,9 @@ param(instance)%probabilisticMultiplication = .false. prm%lambda0 = math_expand(prm%lambda0,prm%Nslip) - prm%burgers = config_phase(p)%getFloats('burgers') + prm%burgers = config_phase(p)%getFloats('burgers', requiredSize=size(prm%Nslip)) - if (size(prm%burgers) /= size(prm%Nslip)) call IO_error(150_pInt,ext_msg='burgers') + prm%burgers = math_expand(prm%burgers,prm%Nslip) @@ -848,8 +778,8 @@ param(instance)%probabilisticMultiplication = .false. prm%Dsd0 = config_phase(p)%getFloat('selfdiffusionprefactor') !,'dsd0') prm%selfDiffusionEnergy = config_phase(p)%getFloat('selfdiffusionenergy') !,'qsd') - prm%aTolRho = config_phase(p)%getFloat('atol_rho') !,'atol_density','absolutetolerancedensity','absolutetolerance_density') - prm%aTolShear = config_phase(p)%getFloat('atol_shear') !,'atol_plasticshear','atol_accumulatedshear','absolutetoleranceshear','absolutetolerance_shear') + prm%aTolRho = config_phase(p)%getFloat('atol_rho') + prm%aTolShear = config_phase(p)%getFloat('atol_shear') prm%significantRho = config_phase(p)%getFloat('significantrho')!,'significant_rho','significantdensity','significant_density') @@ -882,21 +812,29 @@ param(instance)%probabilisticMultiplication = .false. prm%surfaceTransmissivity = config_phase(p)%getFloat('surfacetransmissivity') prm%grainboundaryTransmissivity = config_phase(p)%getFloat('grainboundarytransmissivity') - prm%CFLfactor = config_phase(p)%getFloat('cflfactor') + prm%CFLfactor = config_phase(p)%getFloat('cflfactor',defaultVal=2.0_pReal) prm%fEdgeMultiplication = config_phase(p)%getFloat('edgemultiplication')!,'edgemultiplicationfactor','fedgemultiplication') prm%shortRangeStressCorrection = config_phase(p)%getInt('shortrangestresscorrection' ) > 0_pInt prm%probabilisticMultiplication = config_phase(p)%keyExists('/probabilisticmultiplication/' )!,'randomsources','randommultiplication','discretesources') - ! sanity checks + if ( any(prm%burgers <= 0.0_pReal)) extmsg = trim(extmsg)//' burgers' if ( prm%viscosity <= 0.0_pReal) extmsg = trim(extmsg)//' viscosity' if ( prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' if ( prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' if ( prm%selfDiffusionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' selfDiffusionEnergy' if ( prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' if (prm%edgeJogFactor < 0.0_pReal .or. prm%edgeJogFactor > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' - + if ( prm%solidSolutionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionEnergy' + if ( prm%solidSolutionSize <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionSize' + if ( prm%solidSolutionConcentration <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionConcentration' + if ( prm%CFLfactor < 0.0_pReal) extmsg = trim(extmsg)//' CFLfactor' + if ( prm%doublekinkwidth <= 0.0_pReal) extmsg = trim(extmsg)//' doublekinkwidth' + if ( prm%atolshear <= 0.0_pReal) extmsg = trim(extmsg)//' atolshear' + if ( prm%atolrho <= 0.0_pReal) extmsg = trim(extmsg)//' atolrho' + if (prm%linetensionEffect < 0.0_pReal .or. prm%linetensionEffect > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -1122,16 +1060,18 @@ subroutine plastic_nonlocal_aTolState(ph,instance) ns, & t, c +associate (prm => param(instance)) ns = totalNslip(instance) forall (t = 1_pInt:4_pInt) - plasticState(ph)%aTolState(iRhoU(1:ns,t,instance)) = aTolRho(instance) - plasticState(ph)%aTolState(iRhoB(1:ns,t,instance)) = aTolRho(instance) + plasticState(ph)%aTolState(iRhoU(1:ns,t,instance)) = prm%aTolRho + plasticState(ph)%aTolState(iRhoB(1:ns,t,instance)) = prm%aTolRho end forall forall (c = 1_pInt:2_pInt) & - plasticState(ph)%aTolState(iRhoD(1:ns,c,instance)) = aTolRho(instance) + plasticState(ph)%aTolState(iRhoD(1:ns,c,instance)) = prm%aTolRho - plasticState(ph)%aTolState(iGamma(1:ns,instance)) = aTolShear(instance) + plasticState(ph)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear +end associate end subroutine plastic_nonlocal_aTolState !-------------------------------------------------------------------------------------------------- @@ -1498,10 +1438,10 @@ if (Temperature > 0.0_pReal) then !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity tauEff = max(0.0_pReal, abs(tauNS(s)) - tauThreshold(s)) ! ensure that the effective stress is positive - meanfreepath_P = burgers(s,instance) - jumpWidth_P = burgers(s,instance) - activationLength_P = doublekinkwidth(instance) * burgers(s,instance) - activationVolume_P = activationLength_P * jumpWidth_P * burgers(s,instance) + meanfreepath_P = prm%burgers(s) + jumpWidth_P = prm%burgers(s) + activationLength_P = prm%doublekinkwidth *prm%burgers(s) + activationVolume_P = activationLength_P * jumpWidth_P * prm%burgers(s) criticalStress_P = peierlsStress(s,c,instance) activationEnergy_P = criticalStress_P * activationVolume_P tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one @@ -1521,11 +1461,11 @@ if (Temperature > 0.0_pReal) then !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity tauEff = abs(tau(s)) - tauThreshold(s) - meanfreepath_S = burgers(s,instance) / sqrt(solidSolutionConcentration(instance)) - jumpWidth_S = solidSolutionSize(instance) * burgers(s,instance) - activationLength_S = burgers(s,instance) / sqrt(solidSolutionConcentration(instance)) - activationVolume_S = activationLength_S * jumpWidth_S * burgers(s,instance) - activationEnergy_S = solidSolutionEnergy(instance) + meanfreepath_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) + jumpWidth_S = prm%solidSolutionSize * prm%burgers(s) + activationLength_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) + activationVolume_S = activationLength_S * jumpWidth_S * prm%burgers(s) + activationEnergy_S = prm%solidSolutionEnergy criticalStress_S = activationEnergy_S / activationVolume_S tauRel_S = min(1.0_pReal, tauEff / criticalStress_S) ! ensure that the activation probability cannot become greater than one tSolidSolution = 1.0_pReal / prm%fattack & @@ -1544,7 +1484,7 @@ if (Temperature > 0.0_pReal) then !* viscous glide velocity tauEff = abs(tau(s)) - tauThreshold(s) - mobility = burgers(s,instance) / prm%viscosity + mobility = prm%burgers(s) / prm%viscosity vViscous = mobility * tauEff @@ -2153,9 +2093,9 @@ do s = 1_pInt,ns ! loop over slip systems enddo dLower = minDipoleHeight(1:ns,1:2,instance) -dUpper(1:ns,1) = lattice_mu(ph) * burgers(1:ns,instance) & +dUpper(1:ns,1) = lattice_mu(ph) * prm%burgers(1:ns) & / (8.0_pReal * pi * (1.0_pReal - lattice_nu(ph)) * abs(tau)) -dUpper(1:ns,2) = lattice_mu(ph) * burgers(1:ns,instance) & +dUpper(1:ns,2) = lattice_mu(ph) * prm%burgers(1:ns) & / (4.0_pReal * pi * abs(tau)) forall (c = 1_pInt:2_pInt) where(dNeq0(sqrt(rhoSgl(1:ns,2*c-1)+rhoSgl(1:ns,2*c)+abs(rhoSgl(1:ns,2*c+3))& @@ -2172,10 +2112,10 @@ dUpper = max(dUpper,dLower) rhoDotMultiplication = 0.0_pReal if (lattice_structure(ph) == LATTICE_bcc_ID) then ! BCC forall (s = 1:ns, sum(abs(v(s,1:4))) > 0.0_pReal) - rhoDotMultiplication(s,1:2) = sum(abs(gdot(s,3:4))) / burgers(s,instance) & ! assuming double-cross-slip of screws to be decisive for multiplication + rhoDotMultiplication(s,1:2) = sum(abs(gdot(s,3:4))) / prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication * sqrt(rhoForest(s)) / lambda0(s,instance) ! & ! mean free path ! * 2.0_pReal * sum(abs(v(s,3:4))) / sum(abs(v(s,1:4))) ! ratio of screw to overall velocity determines edge generation - rhoDotMultiplication(s,3:4) = sum(abs(gdot(s,3:4))) / burgers(s,instance) & ! assuming double-cross-slip of screws to be decisive for multiplication + rhoDotMultiplication(s,3:4) = sum(abs(gdot(s,3:4))) /prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication * sqrt(rhoForest(s)) / lambda0(s,instance) ! & ! mean free path ! * 2.0_pReal * sum(abs(v(s,1:2))) / sum(abs(v(s,1:4))) ! ratio of edge to overall velocity determines screw generation endforall @@ -2203,7 +2143,7 @@ else sourceProbability(s,1_pInt,ip,el) = 2.0_pReal rhoDotMultiplication(s,1:4) = & (sum(abs(gdot(s,1:2))) * fEdgeMultiplication(instance) + sum(abs(gdot(s,3:4)))) & - / burgers(s,instance) * sqrt(rhoForest(s)) / lambda0(s,instance) + /prm%burgers(s) * sqrt(rhoForest(s)) / lambda0(s,instance) endif enddo #ifdef DEBUG @@ -2215,7 +2155,7 @@ else else rhoDotMultiplication(1:ns,1:4) = spread( & (sum(abs(gdot(1:ns,1:2)),2) * fEdgeMultiplication(instance) + sum(abs(gdot(1:ns,3:4)),2)) & - * sqrt(rhoForest(1:ns)) / lambda0(1:ns,instance) / burgers(1:ns,instance), 2, 4) + * sqrt(rhoForest(1:ns)) / lambda0(1:ns,instance) / prm%burgers(1:ns), 2, 4) endif endif @@ -2231,14 +2171,14 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then !*** check CFL (Courant-Friedrichs-Lewy) condition for flux if (any( abs(gdot) > 0.0_pReal & ! any active slip system ... - .and. CFLfactor(instance) * abs(v) * timestep & + .and. prm%CFLfactor * abs(v) * timestep & > mesh_ipVolume(ip,el) / maxval(mesh_ipArea(:,ip,el)))) then ! ...with velocity above critical value (we use the reference volume and area for simplicity here) #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt) then write(6,'(a,i5,a,i2)') '<< CONST >> CFL condition not fullfilled at el ',el,' ip ',ip write(6,'(a,e10.3,a,e10.3)') '<< CONST >> velocity is at ', & maxval(abs(v), abs(gdot) > 0.0_pReal & - .and. CFLfactor(instance) * abs(v) * timestep & + .and. prm%CFLfactor * abs(v) * timestep & > mesh_ipVolume(ip,el) / maxval(mesh_ipArea(:,ip,el))), & ' at a timestep of ',timestep write(6,'(a)') '<< CONST >> enforcing cutback !!!' @@ -2497,8 +2437,8 @@ rhoDotEdgeJogsOutput(1:ns,1_pInt,ip,el) = 2.0_pReal * rhoDotThermalAnnihilation( #endif -if ( any(rhoSglOriginal(1:ns,1:4) + rhoDot(1:ns,1:4) * timestep < -aTolRho(instance)) & - .or. any(rhoDipOriginal(1:ns,1:2) + rhoDot(1:ns,9:10) * timestep < -aTolRho(instance))) then +if ( any(rhoSglOriginal(1:ns,1:4) + rhoDot(1:ns,1:4) * timestep < -prm%aTolRho) & + .or. any(rhoDipOriginal(1:ns,1:2) + rhoDot(1:ns,9:10) * timestep < -prm%aTolRho)) then #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt) then write(6,'(a,i5,a,i2)') '<< CONST >> evolution rate leads to negative density at el ',el,' ip ',ip @@ -2782,7 +2722,7 @@ tauBack = plasticState(ph)%State(iTauB(1:ns,instance),of) !* Calculate shear rate forall (t = 1_pInt:4_pInt) & - gdot(1:ns,t) = rhoSgl(1:ns,t) * burgers(1:ns,instance) * v(1:ns,t) + gdot(1:ns,t) = rhoSgl(1:ns,t) * prm%burgers(1:ns) * v(1:ns,t) !* calculate limits for stable dipole height @@ -2793,9 +2733,9 @@ do s = 1_pInt,ns enddo dLower = minDipoleHeight(1:ns,1:2,instance) -dUpper(1:ns,1) = lattice_mu(ph) * burgers(1:ns,instance) & +dUpper(1:ns,1) = lattice_mu(ph) * prm%burgers(1:ns) & / (8.0_pReal * pi * (1.0_pReal - lattice_nu(ph)) * abs(tau)) -dUpper(1:ns,2) = lattice_mu(ph) * burgers(1:ns,instance) & +dUpper(1:ns,2) = lattice_mu(ph) * prm%burgers(1:ns) & / (4.0_pReal * pi * abs(tau)) forall (c = 1_pInt:2_pInt) where(dNeq0(sqrt(rhoSgl(1:ns,2*c-1)+rhoSgl(1:ns,2*c)+abs(rhoSgl(1:ns,2*c+3))& From 6bcd4a77d2aa8c548533ab52f167d71402159a64 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 19 Feb 2019 09:43:48 +0100 Subject: [PATCH 50/97] complex pointer structure for state --- src/plastic_nonlocal.f90 | 126 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 2 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index c87fd9865..58aeb4e12 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -203,6 +203,43 @@ module plastic_nonlocal outputID !< ID of each post result output end type tParameters + type, private :: tNonlocalState + + real(pReal), pointer, dimension(:,:) :: & + rho, & ! < all dislocations + rhoSgl, & + rhoSglMobile, & ! iRhoU + rhoSglEdgeMobile, & + rhoSglEdgeMobilePos, & + rhoSglEdgeMobileNeg, & + rhoSglScrewMobile, & + rhoSglScrewMobilePos, & + rhoSglScrewMobileNeg, & + rhoSglImmobile, & ! iRhoB + rhoSglEdgeImmobile, & + rhoSglEdgeImmobilePos, & + rhoSglEdgeImmobileNeg, & + rhoSglScrewImmobile, & + rhoSglScrewImmobilePos, & + rhoSglScrewImmobileNeg, & + rhoSglPos, & + rhoSglMobilePos, & + rhoSglImmobilePos, & + rhoSglNeg, & + rhoSglMobileNeg, & + rhoSglImmobileNeg, & + rhoDip, & ! iRhoD + rhoDipEdge, & + rhoDipScrew, & + rhoSglScrew, & + rhoSglEdge, & + accumulatedshear + end type tNonlocalState + type(tNonlocalState), allocatable, dimension(:), private :: & + deltaState, & + dotState, & + state + type(tParameters), dimension(:), allocatable, target, private :: param !< containers of constitutive parameters (len Ninstance) @@ -310,6 +347,9 @@ integer(pInt) :: phase, & !*** memory allocation for global variables allocate(param(maxNinstances)) +allocate(state(maxNinstances)) +allocate(dotState(maxNinstances)) +allocate(deltaState(maxNinstances)) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) @@ -721,6 +761,9 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle instance = phase_plasticityInstance(p) associate(prm => param(instance), & + dot => dotState(instance), & + stt => state(instance), & + del => deltaState(instance), & config => config_phase(p)) prm%mu = lattice_mu(p) @@ -925,12 +968,91 @@ param(instance)%probabilisticMultiplication = .false. endif enddo - end associate + plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) + stt%rho => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + dot%rho => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + del%rho => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + plasticState(p)%aTolState(1:10_pInt*prm%totalNslip) = prm%aTolRho + + stt%rhoSglEdge => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt:06_pInt*prm%totalNslip:2*prm%totalNslip,:) + stt%rhoSglScrew => plasticState(p)%state (2_pInt*prm%totalNslip+1_pInt:08_pInt*prm%totalNslip:2*prm%totalNslip,:) + + stt%rhoSgl => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + dot%rhoSgl => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + del%rhoSgl => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + + stt%rhoSglMobile => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + dot%rhoSglMobile => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + del%rhoSglMobile => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) - enddo + stt%rhoSglEdgeMobile => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + dot%rhoSglEdgeMobile => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + del%rhoSglEdgeMobile => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + + stt%rhoSglEdgeMobilePos => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt: 1_pInt*prm%totalNslip,:) + dot%rhoSglEdgeMobilePos => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt: 1_pInt*prm%totalNslip,:) + del%rhoSglEdgeMobilePos => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt: 1_pInt*prm%totalNslip,:) + + stt%rhoSglEdgeMobileNeg => plasticState(p)%state (1_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + dot%rhoSglEdgeMobileNeg => plasticState(p)%dotState (1_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + del%rhoSglEdgeMobileNeg => plasticState(p)%deltaState (1_pInt*prm%totalNslip+1_pInt: 2_pInt*prm%totalNslip,:) + + stt%rhoSglScrewMobile => plasticState(p)%state (2_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + dot%rhoSglScrewMobile => plasticState(p)%dotState (2_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + del%rhoSglScrewMobile => plasticState(p)%deltaState (2_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + + stt%rhoSglScrewMobilePos => plasticState(p)%state (2_pInt*prm%totalNslip+1_pInt: 3_pInt*prm%totalNslip,:) + dot%rhoSglScrewMobilePos => plasticState(p)%dotState (2_pInt*prm%totalNslip+1_pInt: 3_pInt*prm%totalNslip,:) + del%rhoSglScrewMobilePos => plasticState(p)%deltaState (2_pInt*prm%totalNslip+1_pInt: 3_pInt*prm%totalNslip,:) + stt%rhoSglScrewMobileNeg => plasticState(p)%state (3_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + dot%rhoSglScrewMobileNeg => plasticState(p)%dotState (3_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + del%rhoSglScrewMobileNeg => plasticState(p)%deltaState (3_pInt*prm%totalNslip+1_pInt: 4_pInt*prm%totalNslip,:) + + stt%rhoSglImmobile => plasticState(p)%state (4_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + dot%rhoSglImmobile => plasticState(p)%dotState (4_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + del%rhoSglImmobile => plasticState(p)%deltaState (4_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + + stt%rhoSglEdgeImmobile => plasticState(p)%state (4_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + dot%rhoSglEdgeImmobile => plasticState(p)%dotState (4_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + del%rhoSglEdgeImmobile => plasticState(p)%deltaState (4_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + + stt%rhoSglEdgeImmobilePos => plasticState(p)%state (4_pInt*prm%totalNslip+1_pInt: 5_pInt*prm%totalNslip,:) + dot%rhoSglEdgeImmobilePos => plasticState(p)%dotState (4_pInt*prm%totalNslip+1_pInt: 5_pInt*prm%totalNslip,:) + del%rhoSglEdgeImmobilePos => plasticState(p)%deltaState (4_pInt*prm%totalNslip+1_pInt: 5_pInt*prm%totalNslip,:) + + stt%rhoSglEdgeImmobileNeg => plasticState(p)%state (5_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + dot%rhoSglEdgeImmobileNeg => plasticState(p)%dotState (5_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + del%rhoSglEdgeImmobileNeg => plasticState(p)%deltaState (5_pInt*prm%totalNslip+1_pInt: 6_pInt*prm%totalNslip,:) + + stt%rhoSglScrewImmobile => plasticState(p)%state (6_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + dot%rhoSglScrewImmobile => plasticState(p)%dotState (6_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + del%rhoSglScrewImmobile => plasticState(p)%deltaState (6_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + + stt%rhoSglScrewImmobilePos => plasticState(p)%state (6_pInt*prm%totalNslip+1_pInt: 7_pInt*prm%totalNslip,:) + dot%rhoSglScrewImmobilePos => plasticState(p)%dotState(6_pInt*prm%totalNslip+1_pInt: 7_pInt*prm%totalNslip,:) + del%rhoSglScrewImmobilePos => plasticState(p)%deltaState(6_pInt*prm%totalNslip+1_pInt: 7_pInt*prm%totalNslip,:) + + stt%rhoSglScrewImmobileNeg => plasticState(p)%state (7_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + dot%rhoSglScrewImmobileNeg => plasticState(p)%dotState(7_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + del%rhoSglScrewImmobileNeg => plasticState(p)%deltaState(7_pInt*prm%totalNslip+1_pInt: 8_pInt*prm%totalNslip,:) + + stt%rhoDip => plasticState(p)%state (8_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + dot%rhoDip => plasticState(p)%dotState (8_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + del%rhoDip => plasticState(p)%deltaState (8_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + + stt%rhoDipEdge => plasticState(p)%state (8_pInt*prm%totalNslip+1_pInt: 9_pInt*prm%totalNslip,:) + dot%rhoDipEdge => plasticState(p)%dotState (8_pInt*prm%totalNslip+1_pInt: 9_pInt*prm%totalNslip,:) + del%rhoDipEdge => plasticState(p)%deltaState (8_pInt*prm%totalNslip+1_pInt: 9_pInt*prm%totalNslip,:) + + stt%rhoDipScrew => plasticState(p)%state (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + dot%rhoDipScrew => plasticState(p)%dotState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) +plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear + end associate + enddo end subroutine plastic_nonlocal_init !-------------------------------------------------------------------------------------------------- From 41899f6d3329502d7ec41cef2cdda916c035d9d4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 19 Feb 2019 10:31:14 +0100 Subject: [PATCH 51/97] using more parameters from smart structure --- src/plastic_nonlocal.f90 | 91 +++++++++++++--------------------------- 1 file changed, 30 insertions(+), 61 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 58aeb4e12..622302b92 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -45,12 +45,7 @@ module plastic_nonlocal real(pReal), dimension(:), allocatable, private :: & atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient - cutoffRadius, & !< cutoff radius for dislocation stress - pParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) - qParam, & !< parameter for kinetic law (Kocks,Argon,Ashby) rhoSglScatter, & !< standard deviation of scatter in initial dislocation density - surfaceTransmissivity, & !< transmissivity at free surface - grainboundaryTransmissivity, & !< transmissivity at grain boundary (identified by different texture) fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) rhoSglRandom, & rhoSglRandomBinning @@ -75,7 +70,6 @@ module plastic_nonlocal forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance real(pReal), dimension(:,:,:,:), allocatable, private :: & - lattice2slip, & !< orthogonal transformation matrix from lattice coordinate system to slip coordinate system (passive rotation !!!) rhoDotEdgeJogsOutput, & sourceProbability @@ -146,7 +140,6 @@ module plastic_nonlocal aTolShear, & !< absolute tolerance for accumulated shear in state integration significantRho, & !< density considered significant significantN, & !< number of dislocations considered significant - cutoffRadius, & !< cutoff radius for dislocation stress doublekinkwidth, & !< width of a doubkle kink in multiples of the burgers vector length b solidSolutionEnergy, & !< activation energy for solid solution in J solidSolutionSize, & !< solid solution obstacle size in multiples of the burgers vector length @@ -361,14 +354,9 @@ allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) allocate(atomicVolume(maxNinstances), source=0.0_pReal) allocate(Dsd0(maxNinstances), source=-1.0_pReal) -allocate(cutoffRadius(maxNinstances), source=-1.0_pReal) -allocate(pParam(maxNinstances), source=1.0_pReal) -allocate(qParam(maxNinstances), source=1.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) -allocate(surfaceTransmissivity(maxNinstances), source=1.0_pReal) -allocate(grainboundaryTransmissivity(maxNinstances), source=-1.0_pReal) allocate(fEdgeMultiplication(maxNinstances), source=0.0_pReal) allocate(shortRangeStressCorrection(maxNinstances), source=.false.) allocate(probabilisticMultiplication(maxNinstances), source=.false.) @@ -443,8 +431,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case('cutoffradius','r') - cutoffRadius(instance) = IO_floatValue(line,chunkPos,2_pInt) case('minimumdipoleheightedge','ddipminedge') do f = 1_pInt, Nchunks_SlipFamilies minDipoleHeightPerSlipFamily(f,1_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) @@ -465,20 +451,12 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies peierlsStressPerSlipFamily(f,2_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case('p') - pParam(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('q') - qParam(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglscatter') rhoSglScatter(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandom') rhoSglRandom(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandombinning') rhoSglRandomBinning(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('surfacetransmissivity') - surfaceTransmissivity(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('grainboundarytransmissivity') - grainboundaryTransmissivity(instance) = IO_floatValue(line,chunkPos,2_pInt) case('fedgemultiplication','edgemultiplicationfactor','edgemultiplication') fEdgeMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) case('shortrangestresscorrection') @@ -520,26 +498,16 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') endif enddo - if (cutoffRadius(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='r ('//PLASTICITY_NONLOCAL_label//')') if (atomicVolume(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') if (Dsd0(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='selfDiffusionPrefactor ('//PLASTICITY_NONLOCAL_label//')') - if (pParam(instance) <= 0.0_pReal .or. pParam(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='p ('//PLASTICITY_NONLOCAL_label//')') - if (qParam(instance) < 1.0_pReal .or. qParam(instance) > 2.0_pReal) & - call IO_error(211_pInt,ext_msg='q ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglScatter(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandom(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandomBinning(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - if (surfaceTransmissivity(instance) < 0.0_pReal .or. surfaceTransmissivity(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='surfaceTransmissivity ('//PLASTICITY_NONLOCAL_label//')') - if (grainboundaryTransmissivity(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='grainboundaryTransmissivity ('//PLASTICITY_NONLOCAL_label//')') if (fEdgeMultiplication(instance) < 0.0_pReal .or. fEdgeMultiplication(instance) > 1.0_pReal) & call IO_error(211_pInt,ext_msg='edgemultiplicationfactor ('//PLASTICITY_NONLOCAL_label//')') @@ -565,11 +533,11 @@ allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) + allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(minDipoleHeight(maxTotalNslip,2,maxNinstances), source=-1.0_pReal) allocate(forestProjectionEdge(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(forestProjectionScrew(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) -allocate(lattice2slip(1:3, 1:3, maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & source=2.0_pReal) @@ -595,15 +563,6 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), NofMyPhase=count(material_phase==phase) myPhase2: if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then instance = phase_plasticityInstance(phase) - !*** Inverse lookup of my slip system family and the slip system in lattice - - l = 0_pInt - do f = 1_pInt,lattice_maxNslipFamily - do s = 1_pInt,Nslip(f,instance) - l = l + 1_pInt - slipFamily(l,instance) = f - slipSystemLattice(l,instance) = sum(lattice_NslipSystem(1:f-1_pInt, phase)) + s - enddo; enddo !*** determine size of state array @@ -704,6 +663,18 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), plasticState(phase)%accumulatedSlip => & plasticState(phase)%state (iGamma(1,instance):iGamma(ns,instance),1:NofMyPhase) + + !*** Inverse lookup of my slip system family and the slip system in lattice + + l = 0_pInt + do f = 1_pInt,lattice_maxNslipFamily + do s = 1_pInt,Nslip(f,instance) + l = l + 1_pInt + slipFamily(l,instance) = f + slipSystemLattice(l,instance) = sum(lattice_NslipSystem(1:f-1_pInt, phase)) + s + enddo; enddo + + do s1 = 1_pInt,ns f = slipFamily(s1,instance) @@ -733,13 +704,7 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), -1.0_pReal* lattice_sd(1:3,slipSystemLattice(s2,instance),phase)))) .and. s1 /= s2) & colinearSystem(s1,instance) = s2 enddo - - !*** rotation matrix from lattice configuration to slip system - - lattice2slip(1:3,1:3,s1,instance) & - = transpose( reshape([ lattice_sd(1:3, slipSystemLattice(s1,instance), phase), & - -lattice_st(1:3, slipSystemLattice(s1,instance), phase), & - lattice_sn(1:3, slipSystemLattice(s1,instance), phase)], [3,3])) + enddo @@ -817,7 +782,6 @@ param(instance)%probabilisticMultiplication = .false. peierlsStressPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloat('peierlsstressscrew')!,'peierlsstress_screw') prm%atomicVolume = config_phase(p)%getFloat('atomicvolume') - prm%cutoffRadius = config_phase(p)%getFloat('r')!,cutoffradius') prm%Dsd0 = config_phase(p)%getFloat('selfdiffusionprefactor') !,'dsd0') prm%selfDiffusionEnergy = config_phase(p)%getFloat('selfdiffusionenergy') !,'qsd') @@ -853,8 +817,8 @@ param(instance)%probabilisticMultiplication = .false. prm%rhoSglRandomBinning = config_phase(p)%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? - prm%surfaceTransmissivity = config_phase(p)%getFloat('surfacetransmissivity') - prm%grainboundaryTransmissivity = config_phase(p)%getFloat('grainboundarytransmissivity') + prm%surfaceTransmissivity = config_phase(p)%getFloat('surfacetransmissivity',defaultVal=1.0_pReal) + prm%grainboundaryTransmissivity = config_phase(p)%getFloat('grainboundarytransmissivity',defaultVal=-1.0_pReal) prm%CFLfactor = config_phase(p)%getFloat('cflfactor',defaultVal=2.0_pReal) prm%fEdgeMultiplication = config_phase(p)%getFloat('edgemultiplication')!,'edgemultiplicationfactor','fedgemultiplication') @@ -877,7 +841,12 @@ param(instance)%probabilisticMultiplication = .false. if ( prm%atolshear <= 0.0_pReal) extmsg = trim(extmsg)//' atolshear' if ( prm%atolrho <= 0.0_pReal) extmsg = trim(extmsg)//' atolrho' if (prm%linetensionEffect < 0.0_pReal .or. prm%linetensionEffect > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' - + if (prm%p <= 0.0_pReal .or. prm%p > 1.0_pReal) extmsg = trim(extmsg)//' p' + if (prm%q < 1.0_pReal .or. prm%q > 2.0_pReal) extmsg = trim(extmsg)//' q' + if (prm%surfaceTransmissivity < 0.0_pReal .or. prm%surfaceTransmissivity > 1.0_pReal) & +extmsg = trim(extmsg)//' surfaceTransmissivity' + if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -1569,11 +1538,11 @@ if (Temperature > 0.0_pReal) then tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one tPeierls = 1.0_pReal / prm%fattack & * exp(activationEnergy_P / (KB * Temperature) & - * (1.0_pReal - tauRel_P**pParam(instance))**qParam(instance)) + * (1.0_pReal - tauRel_P**prm%p)**prm%q) if (tauEff < criticalStress_P) then - dtPeierls_dtau = tPeierls * pParam(instance) * qParam(instance) * activationVolume_P / (KB * Temperature) & - * (1.0_pReal - tauRel_P**pParam(instance))**(qParam(instance)-1.0_pReal) & - * tauRel_P**(pParam(instance)-1.0_pReal) + dtPeierls_dtau = tPeierls * prm%p * prm%q * activationVolume_P / (KB * Temperature) & + * (1.0_pReal - tauRel_P**prm%p)**(prm%q-1.0_pReal) & + * tauRel_P**(prm%p-1.0_pReal) else dtPeierls_dtau = 0.0_pReal endif @@ -1592,12 +1561,12 @@ if (Temperature > 0.0_pReal) then tauRel_S = min(1.0_pReal, tauEff / criticalStress_S) ! ensure that the activation probability cannot become greater than one tSolidSolution = 1.0_pReal / prm%fattack & * exp(activationEnergy_S / (KB * Temperature) & - * (1.0_pReal - tauRel_S**pParam(instance))**qParam(instance)) + * (1.0_pReal - tauRel_S**prm%p)**prm%q) if (tauEff < criticalStress_S) then - dtSolidSolution_dtau = tSolidSolution * pParam(instance) * qParam(instance) & + dtSolidSolution_dtau = tSolidSolution * prm%p * prm%q & * activationVolume_S / (KB * Temperature) & - * (1.0_pReal - tauRel_S**pParam(instance))**(qParam(instance)-1.0_pReal) & - * tauRel_S**(pParam(instance)-1.0_pReal) + * (1.0_pReal - tauRel_S**prm%p)**(prm%q-1.0_pReal) & + * tauRel_S**(prm%p-1.0_pReal) else dtSolidSolution_dtau = 0.0_pReal endif From e8ac2d0d975245a2681c10d53ac34e9961ddfec6 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 19 Feb 2019 10:43:04 +0100 Subject: [PATCH 52/97] limiting inter-module dependencies --- src/constitutive.f90 | 4 +++- src/plastic_nonlocal.f90 | 35 ++++++++++++----------------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index e5adaf4cf..beeae9e87 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -424,6 +424,8 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, & PLASTICITY_DISLOTWIN_ID, & PLASTICITY_DISLOUCLA_ID, & PLASTICITY_NONLOCAL_ID + use mesh, only: & + mesh_ipVolume use plastic_isotropic, only: & plastic_isotropic_LpAndItsTangent use plastic_phenopowerlaw, only: & @@ -488,7 +490,7 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, & case (PLASTICITY_NONLOCAL_ID) plasticityType call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, & - temperature(ho)%p(tme),ip,el) + temperature(ho)%p(tme),mesh_ipVolume(ip,el),ip,el) case (PLASTICITY_DISLOTWIN_ID) plasticityType of = phasememberAt(ipc,ip,el) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 622302b92..43611f034 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -46,7 +46,6 @@ module plastic_nonlocal atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient rhoSglScatter, & !< standard deviation of scatter in initial dislocation density - fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) rhoSglRandom, & rhoSglRandomBinning @@ -357,7 +356,6 @@ allocate(Dsd0(maxNinstances), source=-1.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) -allocate(fEdgeMultiplication(maxNinstances), source=0.0_pReal) allocate(shortRangeStressCorrection(maxNinstances), source=.false.) allocate(probabilisticMultiplication(maxNinstances), source=.false.) @@ -457,8 +455,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s rhoSglRandom(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandombinning') rhoSglRandomBinning(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('fedgemultiplication','edgemultiplicationfactor','edgemultiplication') - fEdgeMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) case('shortrangestresscorrection') shortRangeStressCorrection(instance) = IO_floatValue(line,chunkPos,2_pInt) > 0.0_pReal case('probabilisticmultiplication','randomsources','randommultiplication','discretesources') @@ -508,8 +504,7 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandomBinning(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - if (fEdgeMultiplication(instance) < 0.0_pReal .or. fEdgeMultiplication(instance) > 1.0_pReal) & - call IO_error(211_pInt,ext_msg='edgemultiplicationfactor ('//PLASTICITY_NONLOCAL_label//')') + !*** determine total number of active slip systems @@ -846,6 +841,9 @@ param(instance)%probabilisticMultiplication = .false. if (prm%surfaceTransmissivity < 0.0_pReal .or. prm%surfaceTransmissivity > 1.0_pReal) & extmsg = trim(extmsg)//' surfaceTransmissivity' if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' + if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & +extmsg = trim(extmsg)//' surfaceTransmissivity' + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) @@ -1614,30 +1612,21 @@ end subroutine plastic_nonlocal_kinetics !> @brief calculates plastic velocity gradient and its tangent !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & - Mp, Temperature, ip, el) + Mp, Temperature, volume, ip, el) -use math, only: math_3333to99, & - math_mul6x6, & - math_mul33xx33, & - math_6toSym33 -use debug, only: debug_level, & - debug_constitutive, & - debug_levelExtensive, & - debug_levelSelective, & - debug_i, & - debug_e +use math, only: math_mul33xx33 use material, only: material_phase, & plasticState, & phaseAt, phasememberAt,& phase_plasticityInstance -use mesh, only: mesh_ipVolume implicit none !*** input variables integer(pInt), intent(in) :: ip, & !< current integration point el !< current element number -real(pReal), intent(in) :: Temperature !< temperature +real(pReal), intent(in) :: Temperature, & !< temperature +volume !< volume of the materialpoint real(pReal), dimension(3,3), intent(in) :: Mp @@ -1685,7 +1674,7 @@ forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) rhoSgl(s,t) = max(plasticState(ph)%state(iRhoU(s,t,instance),of), 0.0_pReal) ! ensure positive single mobile densities rhoSgl(s,t+4_pInt) = plasticState(ph)%state(iRhoB(s,t,instance),of) endforall -where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & +where (abs(rhoSgl) * volume ** 0.667_pReal < prm%significantN & .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal @@ -2215,7 +2204,7 @@ else if (probabilisticMultiplication(instance)) then meshlength = mesh_ipVolume(ip,el)**0.333_pReal where(sum(rhoSgl(1:ns,1:4),2) > 0.0_pReal) - nSources = (sum(rhoSgl(1:ns,1:2),2) * fEdgeMultiplication(instance) + sum(rhoSgl(1:ns,3:4),2)) & + nSources = (sum(rhoSgl(1:ns,1:2),2) * prm%fEdgeMultiplication + sum(rhoSgl(1:ns,3:4),2)) & / sum(rhoSgl(1:ns,1:4),2) * meshlength / lambda0(1:ns,instance)*sqrt(rhoForest(1:ns)) elsewhere nSources = meshlength / lambda0(1:ns,instance) * sqrt(rhoForest(1:ns)) @@ -2233,7 +2222,7 @@ else else sourceProbability(s,1_pInt,ip,el) = 2.0_pReal rhoDotMultiplication(s,1:4) = & - (sum(abs(gdot(s,1:2))) * fEdgeMultiplication(instance) + sum(abs(gdot(s,3:4)))) & + (sum(abs(gdot(s,1:2))) * prm%fEdgeMultiplication + sum(abs(gdot(s,3:4)))) & /prm%burgers(s) * sqrt(rhoForest(s)) / lambda0(s,instance) endif enddo @@ -2245,7 +2234,7 @@ else #endif else rhoDotMultiplication(1:ns,1:4) = spread( & - (sum(abs(gdot(1:ns,1:2)),2) * fEdgeMultiplication(instance) + sum(abs(gdot(1:ns,3:4)),2)) & + (sum(abs(gdot(1:ns,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(1:ns,3:4)),2)) & * sqrt(rhoForest(1:ns)) / lambda0(1:ns,instance) / prm%burgers(1:ns), 2, 4) endif endif From 649750a1c9a2d7fefce014a60b835bfc1754c8d3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 19 Feb 2019 23:55:59 +0100 Subject: [PATCH 53/97] let lattice to the work --- src/lattice.f90 | 154 +++++++++++++++++++++++++++++++++++++-- src/plastic_nonlocal.f90 | 35 +++------ 2 files changed, 160 insertions(+), 29 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index b9fb71065..0c9ed52cf 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -498,6 +498,31 @@ module lattice integer(kind(LATTICE_undefined_ID)), dimension(:), allocatable, public, protected :: & lattice_structure, trans_lattice_structure + + interface lattice_forestProjection ! DEPRECATED, use lattice_forestProjection_edge + module procedure slipProjection_transverse + end interface lattice_forestProjection + + interface lattice_forestProjection_edge + module procedure slipProjection_transverse + end interface lattice_forestProjection_edge + + interface lattice_forestProjection_screw + module procedure slipProjection_direction + end interface lattice_forestProjection_screw + + interface lattice_slipProjection_modeI + module procedure slipProjection_normal + end interface lattice_slipProjection_modeI + + interface lattice_slipProjection_modeII + module procedure slipProjection_direction + end interface lattice_slipProjection_modeII + + interface lattice_slipProjection_modeIII + module procedure slipProjection_transverse + end interface lattice_slipProjection_modeIII + public :: & lattice_init, & @@ -517,10 +542,16 @@ module lattice lattice_interaction_SlipTwin, & lattice_interaction_SlipTrans, & lattice_interaction_TwinSlip, & - lattice_forestProjection, & lattice_characteristicShear_Twin, & lattice_C66_twin, & - lattice_C66_trans + lattice_C66_trans, & + lattice_forestProjection, & + lattice_forestProjection_edge, & + lattice_forestProjection_screw, & + lattice_slipProjection_modeI, & + lattice_slipProjection_modeII, & + lattice_slipProjection_modeIII + contains @@ -2181,9 +2212,11 @@ end function lattice_SchmidMatrix_cleavage !-------------------------------------------------------------------------------------------------- -!> @brief Forest projection (for edge dislocations) +!> @brief Projection of the transverse direction onto the slip plane +!> @details: This projection is used to calculate forest hardening for edge dislocations and for +! mode III failure (ToDo: MD I am not 100% sure about mode III) !-------------------------------------------------------------------------------------------------- -function lattice_forestProjection(Nslip,structure,cOverA) result(projection) +function slipProjection_transverse(Nslip,structure,cOverA) result(projection) use math, only: & math_mul3x3 use IO, only: & @@ -2231,7 +2264,118 @@ function lattice_forestProjection(Nslip,structure,cOverA) result(projection) projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,3,j))) enddo; enddo -end function lattice_forestProjection +end function slipProjection_transverse + + +!-------------------------------------------------------------------------------------------------- +!> @brief Projection of the slip direction onto the slip plane +!> @details: This projection is used to calculate forest hardening for screw dislocations and for +! mode II failure (ToDo: MD I am not 100% sure about mode II) +!-------------------------------------------------------------------------------------------------- +function slipProjection_direction(Nslip,structure,cOverA) result(projection) + use math, only: & + math_mul3x3 + use IO, only: & + IO_error + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(sum(Nslip),sum(Nslip)) :: projection + + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + real(pReal), dimension(:,:), allocatable :: slipSystems + integer(pInt), dimension(:), allocatable :: NslipMax + integer(pInt) :: i, j + + if (len_trim(structure) /= 3_pInt) & + call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + + select case(structure(1:3)) + case('fcc') + NslipMax = LATTICE_FCC_NSLIPSYSTEM + slipSystems = LATTICE_FCC_SYSTEMSLIP + case('bcc') + NslipMax = LATTICE_BCC_NSLIPSYSTEM + slipSystems = LATTICE_BCC_SYSTEMSLIP + case('hex') + NslipMax = LATTICE_HEX_NSLIPSYSTEM + slipSystems = LATTICE_HEX_SYSTEMSLIP + case('bct') + NslipMax = LATTICE_BCT_NSLIPSYSTEM + slipSystems = LATTICE_BCT_SYSTEMSLIP + case default + call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + end select + + if (any(NslipMax(1:size(Nslip)) - Nslip < 0_pInt)) & + call IO_error(145_pInt,ext_msg='Nslip '//trim(structure)) + if (any(Nslip < 0_pInt)) & + call IO_error(144_pInt,ext_msg='Nslip '//trim(structure)) + + coordinateSystem = buildCoordinateSystem(Nslip,NslipMax,slipSystems,structure,cOverA) + + do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) + projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,1,j))) + enddo; enddo + +end function slipProjection_direction + + +!-------------------------------------------------------------------------------------------------- +!> @brief Projection of the slip plane onto itself +!> @details: This projection is used for mode I failure +!-------------------------------------------------------------------------------------------------- +function slipProjection_normal(Nslip,structure,cOverA) result(projection) + use math, only: & + math_mul3x3 + use IO, only: & + IO_error + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(sum(Nslip),sum(Nslip)) :: projection + + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + real(pReal), dimension(:,:), allocatable :: slipSystems + integer(pInt), dimension(:), allocatable :: NslipMax + integer(pInt) :: i, j + + if (len_trim(structure) /= 3_pInt) & + call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + + select case(structure(1:3)) + case('fcc') + NslipMax = LATTICE_FCC_NSLIPSYSTEM + slipSystems = LATTICE_FCC_SYSTEMSLIP + case('bcc') + NslipMax = LATTICE_BCC_NSLIPSYSTEM + slipSystems = LATTICE_BCC_SYSTEMSLIP + case('hex') + NslipMax = LATTICE_HEX_NSLIPSYSTEM + slipSystems = LATTICE_HEX_SYSTEMSLIP + case('bct') + NslipMax = LATTICE_BCT_NSLIPSYSTEM + slipSystems = LATTICE_BCT_SYSTEMSLIP + case default + call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + end select + + if (any(NslipMax(1:size(Nslip)) - Nslip < 0_pInt)) & + call IO_error(145_pInt,ext_msg='Nslip '//trim(structure)) + if (any(Nslip < 0_pInt)) & + call IO_error(144_pInt,ext_msg='Nslip '//trim(structure)) + + coordinateSystem = buildCoordinateSystem(Nslip,NslipMax,slipSystems,structure,cOverA) + + do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) + projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,2,j))) + enddo; enddo + +end function slipProjection_normal !-------------------------------------------------------------------------------------------------- diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 43611f034..49b550fee 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -64,10 +64,8 @@ module plastic_nonlocal minDipoleHeightPerSlipFamily, & !< minimum stable edge/screw dipole height for each family and instance minDipoleHeight, & !< minimum stable edge/screw dipole height for each slip system and instance peierlsStressPerSlipFamily, & !< Peierls stress (edge and screw) - peierlsStress, & !< Peierls stress (edge and screw) - forestProjectionEdge, & !< matrix of forest projections of edge dislocations for each instance - forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance - + peierlsStress !< Peierls stress (edge and screw) + real(pReal), dimension(:,:,:,:), allocatable, private :: & rhoDotEdgeJogsOutput, & sourceProbability @@ -172,8 +170,8 @@ module plastic_nonlocal real(pReal), dimension(:,:), allocatable :: & interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance - forestProjectionEdge, & !< matrix of forest projections of edge dislocations for each instance - forestProjectionScrew !< matrix of forest projections of screw dislocations for each instance + forestProjection_Edge, & !< matrix of forest projections of edge dislocations for each instance + forestProjection_Screw !< matrix of forest projections of screw dislocations for each instance real(pReal), dimension(:), allocatable, private :: & nonSchmidCoeff integer(pInt) :: totalNslip @@ -531,8 +529,6 @@ allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(minDipoleHeight(maxTotalNslip,2,maxNinstances), source=-1.0_pReal) -allocate(forestProjectionEdge(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) -allocate(forestProjectionScrew(maxTotalNslip,maxTotalNslip,maxNinstances), source=0.0_pReal) allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & source=2.0_pReal) @@ -680,18 +676,7 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), peierlsStress(s1,1:2,instance) = peierlsStressPerSlipFamily(f,1:2,instance) do s2 = 1_pInt,ns - - !*** calculation of forest projections for edge and screw dislocations. s2 acts as forest for s1 - - forestProjectionEdge(s1,s2,instance) & - = abs(math_mul3x3(lattice_sn(1:3,slipSystemLattice(s1,instance),phase), & - lattice_st(1:3,slipSystemLattice(s2,instance),phase))) ! forest projection of edge dislocations is the projection of (t = b x n) onto the slip normal of the respective slip plane - - forestProjectionScrew(s1,s2,instance) & - = abs(math_mul3x3(lattice_sn(1:3,slipSystemLattice(s1,instance),phase), & - lattice_sd(1:3,slipSystemLattice(s2,instance),phase))) ! forest projection of screw dislocations is the projection of b onto the slip normal of the respective splip plane - - + !*** colinear slip system (only makes sense for fcc like it is defined here) if ((all(dEq(lattice_sd(1:3,slipSystemLattice(s1,instance),phase), & @@ -769,8 +754,10 @@ param(instance)%probabilisticMultiplication = .false. prm%burgers = math_expand(prm%burgers,prm%Nslip) - - + prm%forestProjection_edge = lattice_forestProjection_edge (prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%forestProjection_screw = lattice_forestProjection_screw (prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) minDipoleHeightPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightedge')!,'ddipminedge') minDipoleHeightPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightscrew')!,'ddipminscrew') peierlsStressPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloat('peierlsstressedge')!,'peierlsstress_edge') @@ -1293,9 +1280,9 @@ where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & forall (s = 1_pInt:ns) & rhoForest(s) = dot_product((sum(abs(rhoSgl(1:ns,[1,2,5,6])),2) + rhoDip(1:ns,1)), & - forestProjectionEdge(s,1:ns,instance)) & + prm%forestProjection_Edge(s,1:ns)) & + dot_product((sum(abs(rhoSgl(1:ns,[3,4,7,8])),2) + rhoDip(1:ns,2)), & - forestProjectionScrew(s,1:ns,instance)) + prm%forestProjection_Screw(s,1:ns)) !*** calculate the threshold shear stress for dislocation slip From d0b0e3be3b428e2459fec1bbfe6c1fb79d4ca38c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 00:41:44 +0100 Subject: [PATCH 54/97] simplified --- src/plastic_nonlocal.f90 | 82 ++++++++++------------------------------ 1 file changed, 19 insertions(+), 63 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 49b550fee..7f4788b79 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -44,7 +44,6 @@ module plastic_nonlocal real(pReal), dimension(:), allocatable, private :: & atomicVolume, & !< atomic volume - Dsd0, & !< prefactor for self-diffusion coefficient rhoSglScatter, & !< standard deviation of scatter in initial dislocation density rhoSglRandom, & rhoSglRandomBinning @@ -80,11 +79,6 @@ module plastic_nonlocal real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & compatibility !< slip system compatibility between me and my neighbors - - logical, dimension(:), allocatable, private :: & - shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term - probabilisticMultiplication - enum, bind(c) enumerator :: undefined_ID, & rho_sgl_edge_pos_mobile_ID, & @@ -350,12 +344,9 @@ allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) allocate(atomicVolume(maxNinstances), source=0.0_pReal) -allocate(Dsd0(maxNinstances), source=-1.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) -allocate(shortRangeStressCorrection(maxNinstances), source=.false.) -allocate(probabilisticMultiplication(maxNinstances), source=.false.) allocate(rhoSglEdgePos0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(rhoSglEdgeNeg0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) @@ -427,36 +418,14 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case('minimumdipoleheightedge','ddipminedge') - do f = 1_pInt, Nchunks_SlipFamilies - minDipoleHeightPerSlipFamily(f,1_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case('minimumdipoleheightscrew','ddipminscrew') - do f = 1_pInt, Nchunks_SlipFamilies - minDipoleHeightPerSlipFamily(f,2_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo case('atomicvolume') atomicVolume(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('selfdiffusionprefactor','dsd0') - Dsd0(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('peierlsstressedge','peierlsstress_edge') - do f = 1_pInt, Nchunks_SlipFamilies - peierlsStressPerSlipFamily(f,1_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case('peierlsstressscrew','peierlsstress_screw') - do f = 1_pInt, Nchunks_SlipFamilies - peierlsStressPerSlipFamily(f,2_pInt,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo case('rhosglscatter') rhoSglScatter(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandom') rhoSglRandom(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandombinning') rhoSglRandomBinning(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('shortrangestresscorrection') - shortRangeStressCorrection(instance) = IO_floatValue(line,chunkPos,2_pInt) > 0.0_pReal - case('probabilisticmultiplication','randomsources','randommultiplication','discretesources') - probabilisticMultiplication(instance) = IO_floatValue(line,chunkPos,2_pInt) > 0.0_pReal end select endif; endif enddo parsingFile @@ -482,20 +451,11 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') - if (minDipoleHeightPerSlipFamily(f,1,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='minimumDipoleHeightEdge ('//PLASTICITY_NONLOCAL_label//')') - if (minDipoleHeightPerSlipFamily(f,2,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='minimumDipoleHeightScrew ('//PLASTICITY_NONLOCAL_label//')') - if (peierlsStressPerSlipFamily(f,1,instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='peierlsStressEdge ('//PLASTICITY_NONLOCAL_label//')') - if (peierlsStressPerSlipFamily(f,2,instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') + endif enddo if (atomicVolume(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') - if (Dsd0(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='selfDiffusionPrefactor ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglScatter(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandom(instance) < 0.0_pReal) & @@ -830,8 +790,18 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & extmsg = trim(extmsg)//' surfaceTransmissivity' + if ( prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' +! if (minDipoleHeightPerSlipFamily(f,1,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='minimumDipoleHeightEdge ('//PLASTICITY_NONLOCAL_label//')') +! if (minDipoleHeightPerSlipFamily(f,2,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='minimumDipoleHeightScrew ('//PLASTICITY_NONLOCAL_label//')') +! if (peierlsStressPerSlipFamily(f,1,instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='peierlsStressEdge ('//PLASTICITY_NONLOCAL_label//')') +! if (peierlsStressPerSlipFamily(f,2,instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -1007,6 +977,7 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear end associate enddo + end subroutine plastic_nonlocal_init !-------------------------------------------------------------------------------------------------- @@ -1150,6 +1121,7 @@ associate (prm => param(instance)) end associate end subroutine plastic_nonlocal_aTolState + !-------------------------------------------------------------------------------------------------- !> @brief calculates quantities characterizing the microstructure !-------------------------------------------------------------------------------------------------- @@ -1733,31 +1705,14 @@ Lp = 0.0_pReal dLp_dMp = 0.0_pReal do s = 1_pInt,ns - Lp = Lp + gdotTotal(s) * prm%Schmid(1:3,1:3,s) - ! Schmid contributions to tangent forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & + prm%Schmid(i,j,s) * prm%Schmid(k,l,s) & - * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * prm%burgers(s) - - - ! non Schmid contributions to tangent - if (tau(s) > 0.0_pReal) then - forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & - + prm%Schmid(i,j,s) & - * ( prm%nonSchmid_pos(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & - - prm%nonSchmid_neg(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & - * prm%burgers(s) - else - forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & - + prm%Schmid(i,j,s) & - * ( prm%nonSchmid_neg(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & - - prm%nonSchmid_pos(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4) ) & - * prm%burgers(s) - endif + * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * prm%burgers(s) & + + prm%Schmid(i,j,s) & + * ( prm%nonSchmid_pos(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & + - prm%nonSchmid_neg(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4)) * prm%burgers(s) enddo @@ -1946,6 +1901,7 @@ forall (s = 1:ns, c = 1_pInt:2_pInt) & end subroutine plastic_nonlocal_deltaState + !--------------------------------------------------------------------------------------------------- !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- @@ -2188,7 +2144,7 @@ if (lattice_structure(ph) == LATTICE_bcc_ID) then endforall else ! ALL OTHER STRUCTURES - if (probabilisticMultiplication(instance)) then + if (prm%probabilisticMultiplication) then meshlength = mesh_ipVolume(ip,el)**0.333_pReal where(sum(rhoSgl(1:ns,1:4),2) > 0.0_pReal) nSources = (sum(rhoSgl(1:ns,1:2),2) * prm%fEdgeMultiplication + sum(rhoSgl(1:ns,3:4),2)) & From a896ed91f859ce3f25a4e18376e139ee22a1b4e8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 07:33:19 +0100 Subject: [PATCH 55/97] simplified/not needed --- src/constitutive.f90 | 2 +- src/plastic_nonlocal.f90 | 135 +++++++++++++++------------------------ 2 files changed, 52 insertions(+), 85 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index beeae9e87..d49fcec6e 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -1108,7 +1108,7 @@ function constitutive_postResults(S, Fi, FeArray, ipc, ip, el) case (PLASTICITY_NONLOCAL_ID) plasticityType constitutive_postResults(startPos:endPos) = & - plastic_nonlocal_postResults (Mp,FeArray,ip,el) + plastic_nonlocal_postResults (Mp,ip,el) end select plasticityType SourceLoop: do i = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 7f4788b79..0aa254fb2 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -463,11 +463,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s if (rhoSglRandomBinning(instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - - - !*** determine total number of active slip systems - Nslip(1:lattice_maxNslipFamily,instance) = min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase), & - Nslip(1:lattice_maxNslipFamily,instance) ) ! we can't use more slip systems per family than specified in lattice totalNslip(instance) = sum(Nslip(1:lattice_maxNslipFamily,instance)) endif myPhase enddo sanityChecks @@ -1943,8 +1938,6 @@ use material, only: homogenization_maxNgrains, & PLASTICITY_NONLOCAL_ID use lattice, only: lattice_sd, & lattice_st ,& - lattice_mu, & - lattice_nu, & lattice_structure, & LATTICE_bcc_ID, & LATTICE_fcc_ID @@ -2116,9 +2109,9 @@ do s = 1_pInt,ns ! loop over slip systems enddo dLower = minDipoleHeight(1:ns,1:2,instance) -dUpper(1:ns,1) = lattice_mu(ph) * prm%burgers(1:ns) & - / (8.0_pReal * pi * (1.0_pReal - lattice_nu(ph)) * abs(tau)) -dUpper(1:ns,2) = lattice_mu(ph) * prm%burgers(1:ns) & +dUpper(1:ns,1) = prm%mu * prm%burgers(1:ns) & + / (8.0_pReal * pi * (1.0_pReal - prm%nu) * abs(tau)) +dUpper(1:ns,2) = prm%mu * prm%burgers(1:ns) & / (4.0_pReal * pi * abs(tau)) forall (c = 1_pInt:2_pInt) where(dNeq0(sqrt(rhoSgl(1:ns,2*c-1)+rhoSgl(1:ns,2*c)+abs(rhoSgl(1:ns,2*c+3))& @@ -2650,7 +2643,7 @@ end subroutine plastic_nonlocal_updateCompatibility !-------------------------------------------------------------------------------------------------- !> @brief return array of constitutive results !-------------------------------------------------------------------------------------------------- -function plastic_nonlocal_postResults(Mp,Fe,ip,el) +function plastic_nonlocal_postResults(Mp,ip,el) result(postResults) use prec, only: & dNeq0 use math, only: & @@ -2660,28 +2653,19 @@ function plastic_nonlocal_postResults(Mp,Fe,ip,el) use mesh, only: & theMesh use material, only: & - homogenization_maxNgrains, & material_phase, & phaseAt, phasememberAt, & plasticState, & phase_plasticityInstance - use lattice, only: & - lattice_sd, & - lattice_st, & - lattice_sn, & - lattice_mu, & - lattice_nu implicit none real(pReal), dimension(3,3), intent(in) :: Mp !< MandelStress - real(pReal), dimension(3,3,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & - Fe !< elastic deformation gradient integer(pInt), intent(in) :: & ip, & !< integration point el !< element real(pReal), dimension(sum(plastic_nonlocal_sizePostResult(:,phase_plasticityInstance(material_phase(1_pInt,ip,el))))) :: & - plastic_nonlocal_postResults + postResults integer(pInt) :: & ph, & @@ -2709,20 +2693,14 @@ function plastic_nonlocal_postResults(Mp,Fe,ip,el) rhoDip, & !< current dipole dislocation densities (screw and edge dipoles) rhoDotDip, & !< evolution rate of dipole dislocation densities (screw and edge dipoles) dLower, & !< minimum stable dipole distance for edges and screws - dUpper !< current maximum stable dipole distance for edges and screws - real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),2) :: & - m, & !< direction of dislocation motion for edge and screw (unit vector) - m_currentconf !< direction of dislocation motion for edge and screw (unit vector) in current configuration - real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & - n_currentconf !< slip system normal (unit vector) in current configuration - + dUpper !< current maximum stable dipole distance for edges and screws + ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) ns = totalNslip(instance) cs = 0_pInt -plastic_nonlocal_postResults = 0.0_pReal associate(prm => param(instance)) !* short hand notations for state variables @@ -2756,9 +2734,9 @@ do s = 1_pInt,ns enddo dLower = minDipoleHeight(1:ns,1:2,instance) -dUpper(1:ns,1) = lattice_mu(ph) * prm%burgers(1:ns) & - / (8.0_pReal * pi * (1.0_pReal - lattice_nu(ph)) * abs(tau)) -dUpper(1:ns,2) = lattice_mu(ph) * prm%burgers(1:ns) & +dUpper(1:ns,1) = prm%mu * prm%burgers(1:ns) & + / (8.0_pReal * pi * (1.0_pReal - prm%nu) * abs(tau)) +dUpper(1:ns,2) = prm%mu * prm%burgers(1:ns) & / (4.0_pReal * pi * abs(tau)) forall (c = 1_pInt:2_pInt) where(dNeq0(sqrt(rhoSgl(1:ns,2*c-1)+rhoSgl(1:ns,2*c)+abs(rhoSgl(1:ns,2*c+3))& @@ -2770,177 +2748,166 @@ end forall dUpper = max(dUpper,dLower) -!*** dislocation motion - -m(1:3,1:ns,1) = lattice_sd(1:3,slipSystemLattice(1:ns,instance),ph) -m(1:3,1:ns,2) = -lattice_st(1:3,slipSystemLattice(1:ns,instance),ph) -forall (c = 1_pInt:2_pInt, s = 1_pInt:ns) & - m_currentconf(1:3,s,c) = math_mul33x3(Fe(1:3,1:3,1_pInt,ip,el), m(1:3,s,c)) -forall (s = 1_pInt:ns) & - n_currentconf(1:3,s) = math_mul33x3(Fe(1:3,1:3,1_pInt,ip,el), & - lattice_sn(1:3,slipSystemLattice(s,instance),ph)) - - outputsLoop: do o = 1_pInt,size(param(instance)%outputID) select case(param(instance)%outputID(o)) case (rho_sgl_edge_pos_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,1) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,1) cs = cs + ns case (rho_sgl_edge_pos_immobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,5) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,5) cs = cs + ns case (rho_sgl_edge_neg_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,2) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,2) cs = cs + ns case (rho_sgl_edge_neg_immobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,6) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,6) cs = cs + ns case (rho_dip_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDip(1:ns,1) + postResults(cs+1_pInt:cs+ns) = rhoDip(1:ns,1) cs = cs + ns case (rho_sgl_screw_pos_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,3) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,3) cs = cs + ns case (rho_sgl_screw_pos_immobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,7) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,7) cs = cs + ns case (rho_sgl_screw_neg_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,4) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,4) cs = cs + ns case (rho_sgl_screw_neg_immobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,8) + postResults(cs+1_pInt:cs+ns) = rhoSgl(1:ns,8) cs = cs + ns case (rho_dip_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDip(1:ns,2) + postResults(cs+1_pInt:cs+ns) = rhoDip(1:ns,2) cs = cs + ns case (rho_forest_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoForest + postResults(cs+1_pInt:cs+ns) = rhoForest cs = cs + ns case (shearrate_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(gdot,2) + postResults(cs+1_pInt:cs+ns) = sum(gdot,2) cs = cs + ns case (resolvedstress_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = tau + postResults(cs+1_pInt:cs+ns) = tau cs = cs + ns case (resolvedstress_back_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = tauBack + postResults(cs+1_pInt:cs+ns) = tauBack cs = cs + ns case (resolvedstress_external_ID) do s = 1_pInt,ns - plastic_nonlocal_postResults(cs+s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + postResults(cs+s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) enddo cs = cs + ns case (resistance_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = tauThreshold + postResults(cs+1_pInt:cs+ns) = tauThreshold cs = cs + ns case (rho_dot_sgl_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) & - + sum(rhoDotSgl(1:ns,5:8)*sign(1.0_pReal,rhoSgl(1:ns,5:8)),2) + postResults(cs+1_pInt:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) & + + sum(rhoDotSgl(1:ns,5:8)*sign(1.0_pReal,rhoSgl(1:ns,5:8)),2) cs = cs + ns case (rho_dot_sgl_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) + postResults(cs+1_pInt:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) cs = cs + ns case (rho_dot_dip_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotDip,2) + postResults(cs+1_pInt:cs+ns) = sum(rhoDotDip,2) cs = cs + ns case (rho_dot_gen_ID) ! Obsolete - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) & + + rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_gen_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) cs = cs + ns case (rho_dot_gen_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_sgl2dip_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,1,1_pInt,ip,el) cs = cs + ns case (rho_dot_sgl2dip_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_ann_ath_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotAthermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotAthermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotAthermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) & + + rhoDotAthermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_ann_the_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) cs = cs + ns case (rho_dot_ann_the_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) cs = cs + ns case (rho_dot_edgejogs_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = rhoDotEdgeJogsOutput(1:ns,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = rhoDotEdgeJogsOutput(1:ns,1_pInt,ip,el) cs = cs + ns case (rho_dot_flux_mobile_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:4,1_pInt,ip,el),2) + postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:4,1_pInt,ip,el),2) cs = cs + ns case (rho_dot_flux_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:2,1_pInt,ip,el),2) & + postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:2,1_pInt,ip,el),2) & + sum(rhoDotFluxOutput(1:ns,5:6,1_pInt,ip,el)*sign(1.0_pReal,rhoSgl(1:ns,5:6)),2) cs = cs + ns case (rho_dot_flux_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,3:4,1_pInt,ip,el),2) & + postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,3:4,1_pInt,ip,el),2) & + sum(rhoDotFluxOutput(1:ns,7:8,1_pInt,ip,el)*sign(1.0_pReal,rhoSgl(1:ns,7:8)),2) cs = cs + ns case (velocity_edge_pos_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = v(1:ns,1) + postResults(cs+1_pInt:cs+ns) = v(1:ns,1) cs = cs + ns case (velocity_edge_neg_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = v(1:ns,2) + postResults(cs+1_pInt:cs+ns) = v(1:ns,2) cs = cs + ns case (velocity_screw_pos_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = v(1:ns,3) + postResults(cs+1_pInt:cs+ns) = v(1:ns,3) cs = cs + ns case (velocity_screw_neg_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = v(1:ns,4) + postResults(cs+1_pInt:cs+ns) = v(1:ns,4) cs = cs + ns case (maximumdipoleheight_edge_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = dUpper(1:ns,1) + postResults(cs+1_pInt:cs+ns) = dUpper(1:ns,1) cs = cs + ns case (maximumdipoleheight_screw_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = dUpper(1:ns,2) + postResults(cs+1_pInt:cs+ns) = dUpper(1:ns,2) cs = cs + ns case(accumulatedshear_ID) - plastic_nonlocal_postResults(cs+1_pInt:cs+ns) = plasticState(ph)%state(iGamma(1:ns,instance),of) + postResults(cs+1_pInt:cs+ns) = plasticState(ph)%state(iGamma(1:ns,instance),of) cs = cs + ns end select From d29b37f517556c12e3ed72ee9d6acb9296b662c0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 07:53:34 +0100 Subject: [PATCH 56/97] provide slip system components as functions --- src/lattice.f90 | 169 +++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 75 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 0c9ed52cf..ee4273a53 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -698,7 +698,7 @@ subroutine lattice_initializeStructure(myPhase,CoverA) real(pReal), dimension(3,lattice_maxNslip) :: & sd, sn integer(pInt) :: & - j, i, & + i, & myNslip, myNcleavage lattice_C66(1:6,1:6,myPhase) = lattice_symmetrizeC66(lattice_structure(myPhase),& @@ -2211,6 +2211,64 @@ function lattice_SchmidMatrix_cleavage(Ncleavage,structure,cOverA) result(Schmid end function lattice_SchmidMatrix_cleavage +!-------------------------------------------------------------------------------------------------- +!> @brief Normal direction of slip systems (n) +!-------------------------------------------------------------------------------------------------- +function lattice_slip_normal(Nslip,structure,cOverA) result(n) + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(3,sum(Nslip)) :: n + + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) + n = coordinateSystem(1:3,1,1:sum(Nslip)) + +end function lattice_slip_normal + + +!-------------------------------------------------------------------------------------------------- +!> @brief Slip direction of slip systems (|| b) +!> @details: t = b x n +!-------------------------------------------------------------------------------------------------- +function lattice_slip_direction(Nslip,structure,cOverA) result(d) + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(3,sum(Nslip)) :: d + + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) + d = coordinateSystem(1:3,2,1:sum(Nslip)) + +end function lattice_slip_direction + + +!-------------------------------------------------------------------------------------------------- +!> @brief Transverse direction of slip systems (||t, t = b x n) +!-------------------------------------------------------------------------------------------------- +function lattice_slip_transverse(Nslip,structure,cOverA) result(t) + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(3,sum(Nslip)) :: t + + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) + t = coordinateSystem(1:3,3,1:sum(Nslip)) + +end function lattice_slip_transverse + + !-------------------------------------------------------------------------------------------------- !> @brief Projection of the transverse direction onto the slip plane !> @details: This projection is used to calculate forest hardening for edge dislocations and for @@ -2219,8 +2277,6 @@ end function lattice_SchmidMatrix_cleavage function slipProjection_transverse(Nslip,structure,cOverA) result(projection) use math, only: & math_mul3x3 - use IO, only: & - IO_error implicit none integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family @@ -2229,36 +2285,9 @@ function slipProjection_transverse(Nslip,structure,cOverA) result(projection) real(pReal), dimension(sum(Nslip),sum(Nslip)) :: projection real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem - real(pReal), dimension(:,:), allocatable :: slipSystems - integer(pInt), dimension(:), allocatable :: NslipMax integer(pInt) :: i, j - - if (len_trim(structure) /= 3_pInt) & - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) - - select case(structure(1:3)) - case('fcc') - NslipMax = LATTICE_FCC_NSLIPSYSTEM - slipSystems = LATTICE_FCC_SYSTEMSLIP - case('bcc') - NslipMax = LATTICE_BCC_NSLIPSYSTEM - slipSystems = LATTICE_BCC_SYSTEMSLIP - case('hex') - NslipMax = LATTICE_HEX_NSLIPSYSTEM - slipSystems = LATTICE_HEX_SYSTEMSLIP - case('bct') - NslipMax = LATTICE_BCT_NSLIPSYSTEM - slipSystems = LATTICE_BCT_SYSTEMSLIP - case default - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) - end select - - if (any(NslipMax(1:size(Nslip)) - Nslip < 0_pInt)) & - call IO_error(145_pInt,ext_msg='Nslip '//trim(structure)) - if (any(Nslip < 0_pInt)) & - call IO_error(144_pInt,ext_msg='Nslip '//trim(structure)) - - coordinateSystem = buildCoordinateSystem(Nslip,NslipMax,slipSystems,structure,cOverA) + + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,3,j))) @@ -2275,8 +2304,6 @@ end function slipProjection_transverse function slipProjection_direction(Nslip,structure,cOverA) result(projection) use math, only: & math_mul3x3 - use IO, only: & - IO_error implicit none integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family @@ -2285,36 +2312,9 @@ function slipProjection_direction(Nslip,structure,cOverA) result(projection) real(pReal), dimension(sum(Nslip),sum(Nslip)) :: projection real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem - real(pReal), dimension(:,:), allocatable :: slipSystems - integer(pInt), dimension(:), allocatable :: NslipMax integer(pInt) :: i, j - - if (len_trim(structure) /= 3_pInt) & - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) - - select case(structure(1:3)) - case('fcc') - NslipMax = LATTICE_FCC_NSLIPSYSTEM - slipSystems = LATTICE_FCC_SYSTEMSLIP - case('bcc') - NslipMax = LATTICE_BCC_NSLIPSYSTEM - slipSystems = LATTICE_BCC_SYSTEMSLIP - case('hex') - NslipMax = LATTICE_HEX_NSLIPSYSTEM - slipSystems = LATTICE_HEX_SYSTEMSLIP - case('bct') - NslipMax = LATTICE_BCT_NSLIPSYSTEM - slipSystems = LATTICE_BCT_SYSTEMSLIP - case default - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) - end select - - if (any(NslipMax(1:size(Nslip)) - Nslip < 0_pInt)) & - call IO_error(145_pInt,ext_msg='Nslip '//trim(structure)) - if (any(Nslip < 0_pInt)) & - call IO_error(144_pInt,ext_msg='Nslip '//trim(structure)) - - coordinateSystem = buildCoordinateSystem(Nslip,NslipMax,slipSystems,structure,cOverA) + + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,1,j))) @@ -2330,8 +2330,6 @@ end function slipProjection_direction function slipProjection_normal(Nslip,structure,cOverA) result(projection) use math, only: & math_mul3x3 - use IO, only: & - IO_error implicit none integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family @@ -2340,12 +2338,37 @@ function slipProjection_normal(Nslip,structure,cOverA) result(projection) real(pReal), dimension(sum(Nslip),sum(Nslip)) :: projection real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem - real(pReal), dimension(:,:), allocatable :: slipSystems - integer(pInt), dimension(:), allocatable :: NslipMax integer(pInt) :: i, j + coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) + + do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) + projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,2,j))) + enddo; enddo + +end function slipProjection_normal + + +!-------------------------------------------------------------------------------------------------- +!> @brief build a local coordinate system on slip systems +!> @details Order: Direction, plane (normal), and common perpendicular +!-------------------------------------------------------------------------------------------------- +function coordinateSystem_slip(Nslip,structure,cOverA) result(coordinateSystem) + use math, only: & + math_mul3x3 + use IO, only: & + IO_error + + implicit none + integer(pInt), dimension(:), intent(in) :: Nslip !< number of active slip systems per family + character(len=*), intent(in) :: structure !< lattice structure + real(pReal), intent(in) :: cOverA !< c/a ratio + real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem + real(pReal), dimension(:,:), allocatable :: slipSystems + integer(pInt), dimension(:), allocatable :: NslipMax + if (len_trim(structure) /= 3_pInt) & - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + call IO_error(137_pInt,ext_msg='coordinateSystem_slip: '//trim(structure)) select case(structure(1:3)) case('fcc') @@ -2361,7 +2384,7 @@ function slipProjection_normal(Nslip,structure,cOverA) result(projection) NslipMax = LATTICE_BCT_NSLIPSYSTEM slipSystems = LATTICE_BCT_SYSTEMSLIP case default - call IO_error(137_pInt,ext_msg='lattice_forestProjection: '//trim(structure)) + call IO_error(137_pInt,ext_msg='coordinateSystem_slip: '//trim(structure)) end select if (any(NslipMax(1:size(Nslip)) - Nslip < 0_pInt)) & @@ -2371,11 +2394,7 @@ function slipProjection_normal(Nslip,structure,cOverA) result(projection) coordinateSystem = buildCoordinateSystem(Nslip,NslipMax,slipSystems,structure,cOverA) - do i=1_pInt, sum(Nslip); do j=1_pInt, sum(Nslip) - projection(i,j) = abs(math_mul3x3(coordinateSystem(1:3,2,i),coordinateSystem(1:3,2,j))) - enddo; enddo - -end function slipProjection_normal +end function coordinateSystem_slip !-------------------------------------------------------------------------------------------------- @@ -2417,7 +2436,7 @@ end function buildInteraction !-------------------------------------------------------------------------------------------------- -!> @brief build a local coordinate system in a slip, twin, trans, cleavage system +!> @brief build a local coordinate system on slip, twin, trans, cleavage systems !> @details Order: Direction, plane (normal), and common perpendicular !-------------------------------------------------------------------------------------------------- function buildCoordinateSystem(active,complete,system,structure,cOverA) From e6e019e48a3cb14283e1529235ee4c1e390f7d02 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 09:13:50 +0100 Subject: [PATCH 57/97] transition to param structure --- src/plastic_nonlocal.f90 | 66 ++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 0aa254fb2..42ed24ad2 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -43,7 +43,6 @@ module plastic_nonlocal colinearSystem !< colinear system to the active slip system (only valid for fcc!) real(pReal), dimension(:), allocatable, private :: & - atomicVolume, & !< atomic volume rhoSglScatter, & !< standard deviation of scatter in initial dislocation density rhoSglRandom, & rhoSglRandomBinning @@ -58,13 +57,6 @@ module plastic_nonlocal lambda0PerSlipFamily, & !< mean free path prefactor for each family and instance lambda0 !< mean free path prefactor for each slip system and instance - - real(pReal), dimension(:,:,:), allocatable, private :: & - minDipoleHeightPerSlipFamily, & !< minimum stable edge/screw dipole height for each family and instance - minDipoleHeight, & !< minimum stable edge/screw dipole height for each slip system and instance - peierlsStressPerSlipFamily, & !< Peierls stress (edge and screw) - peierlsStress !< Peierls stress (edge and screw) - real(pReal), dimension(:,:,:,:), allocatable, private :: & rhoDotEdgeJogsOutput, & sourceProbability @@ -152,7 +144,10 @@ module plastic_nonlocal nu real(pReal), dimension(:), allocatable :: & - + minDipoleHeight_edge, & !< minimum stable edge dipole height + minDipoleHeight_screw, & !< minimum stable screw dipole height + peierlsstress_edge, & + peierlsstress_screw, & rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance rhoSglEdgeNeg0, & !< initial edge_neg dislocation density per slip system for each family and instance rhoSglScrewPos0, & !< initial screw_pos dislocation density per slip system for each family and instance @@ -163,6 +158,8 @@ module plastic_nonlocal burgers !< absolute length of burgers vector [m] for each slip system and instance real(pReal), dimension(:,:), allocatable :: & + minDipoleHeight, & ! edge and screw + peierlsstress, & ! edge and screw interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance forestProjection_Edge, & !< matrix of forest projections of edge dislocations for each instance forestProjection_Screw !< matrix of forest projections of screw dislocations for each instance @@ -343,7 +340,6 @@ allocate(Nslip(lattice_maxNslipFamily,maxNinstances), source=0_pInt) allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) -allocate(atomicVolume(maxNinstances), source=0.0_pReal) allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) @@ -355,8 +351,6 @@ allocate(rhoSglScrewNeg0(lattice_maxNslipFamily,maxNinstances), s allocate(rhoDipEdge0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(rhoDipScrew0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) -allocate(minDipoleHeightPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=-1.0_pReal) -allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), source=0.0_pReal) rewind(fileUnit) @@ -418,8 +412,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) enddo - case('atomicvolume') - atomicVolume(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglscatter') rhoSglScatter(instance) = IO_floatValue(line,chunkPos,2_pInt) case('rhosglrandom') @@ -454,8 +446,6 @@ allocate(peierlsStressPerSlipFamily(lattice_maxNslipFamily,2,maxNinstances), s endif enddo - if (atomicVolume(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglScatter(instance) < 0.0_pReal) & call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') if (rhoSglRandom(instance) < 0.0_pReal) & @@ -483,7 +473,6 @@ allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) -allocate(minDipoleHeight(maxTotalNslip,2,maxNinstances), source=-1.0_pReal) allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & source=2.0_pReal) @@ -502,7 +491,6 @@ allocate(rhoDotEdgeJogsOutput(maxTotalNslip,homogenization_maxNgrains,theMesh%el allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) -allocate(peierlsStress(maxTotalNslip,2,maxNinstances), source=0.0_pReal) allocate(colinearSystem(maxTotalNslip,maxNinstances), source=0_pInt) initializeInstances: do phase = 1_pInt, size(phase_plasticity) @@ -627,8 +615,6 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), !*** burgers vector, mean free path prefactor and minimum dipole distance for each slip system lambda0(s1,instance) = lambda0PerSlipFamily(f,instance) - minDipoleHeight(s1,1:2,instance) = minDipoleHeightPerSlipFamily(f,1:2,instance) - peierlsStress(s1,1:2,instance) = peierlsStressPerSlipFamily(f,1:2,instance) do s2 = 1_pInt,ns @@ -713,10 +699,12 @@ param(instance)%probabilisticMultiplication = .false. config%getFloat('c/a',defaultVal=0.0_pReal)) prm%forestProjection_screw = lattice_forestProjection_screw (prm%Nslip,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - minDipoleHeightPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightedge')!,'ddipminedge') - minDipoleHeightPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloats('minimumdipoleheightscrew')!,'ddipminscrew') - peierlsStressPerSlipFamily(:,1_pInt,instance) = config_phase(p)%getFloat('peierlsstressedge')!,'peierlsstress_edge') - peierlsStressPerSlipFamily(:,2_pInt,instance) = config_phase(p)%getFloat('peierlsstressscrew')!,'peierlsstress_screw') + + prm%minDipoleHeight_edge = config_phase(p)%getFloats('minimumdipoleheightedge')!,'ddipminedge') + prm%minDipoleHeight_screw = config_phase(p)%getFloats('minimumdipoleheightscrew')!,'ddipminscrew') + + prm%peierlsstress_edge = config_phase(p)%getFloats('peierlsstressedge')!,'peierlsstress_edge') + prm%peierlsstress_screw = config_phase(p)%getFloats('peierlsstressscrew')!,'peierlsstress_screw') prm%atomicVolume = config_phase(p)%getFloat('atomicvolume') prm%Dsd0 = config_phase(p)%getFloat('selfdiffusionprefactor') !,'dsd0') @@ -744,6 +732,18 @@ param(instance)%probabilisticMultiplication = .false. prm%q = config_phase(p)%getFloat('q') + prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge,prm%Nslip) + prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,prm%Nslip) + allocate(prm%minDipoleHeight(prm%totalNslip,2)) + prm%minDipoleHeight(:,1) = prm%minDipoleHeight_edge + prm%minDipoleHeight(:,2) = prm%minDipoleHeight_screw + + prm%peierlsstress_edge = math_expand(prm%peierlsstress_edge,prm%Nslip) + prm%peierlsstress_screw = math_expand(prm%peierlsstress_screw,prm%Nslip) + allocate(prm%peierlsstress(prm%totalNslip,2)) + prm%peierlsstress(:,1) = prm%peierlsstress_edge + prm%peierlsstress(:,2) = prm%peierlsstress_screw + prm%viscosity = config_phase(p)%getFloat('viscosity')!,'glideviscosity') prm%fattack = config_phase(p)%getFloat('attackfrequency')!,'fattack') @@ -787,7 +787,8 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' extmsg = trim(extmsg)//' surfaceTransmissivity' if ( prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' - + ! if (atomicVolume(instance) <= 0.0_pReal) & + ! call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') ! if (minDipoleHeightPerSlipFamily(f,1,instance) < 0.0_pReal) & ! call IO_error(211_pInt,ext_msg='minimumDipoleHeightEdge ('//PLASTICITY_NONLOCAL_label//')') ! if (minDipoleHeightPerSlipFamily(f,2,instance) < 0.0_pReal) & @@ -1485,7 +1486,7 @@ if (Temperature > 0.0_pReal) then jumpWidth_P = prm%burgers(s) activationLength_P = prm%doublekinkwidth *prm%burgers(s) activationVolume_P = activationLength_P * jumpWidth_P * prm%burgers(s) - criticalStress_P = peierlsStress(s,c,instance) + criticalStress_P = prm%peierlsStress(s,c) activationEnergy_P = criticalStress_P * activationVolume_P tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one tPeierls = 1.0_pReal / prm%fattack & @@ -1834,7 +1835,7 @@ do s = 1_pInt,prm%totalNslip tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo -dLower = minDipoleHeight(1:ns,1:2,instance) +dLower = prm%minDipoleHeight(1:ns,1:2) dUpper(1:ns,1) = prm%mu * prm%burgers & / (8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) dUpper(1:ns,2) = prm%mu * prm%burgers / (4.0_pReal * PI * abs(tau)) @@ -2108,7 +2109,7 @@ do s = 1_pInt,ns ! loop over slip systems if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo -dLower = minDipoleHeight(1:ns,1:2,instance) +dLower = prm%minDipoleHeight(1:ns,1:2) dUpper(1:ns,1) = prm%mu * prm%burgers(1:ns) & / (8.0_pReal * pi * (1.0_pReal - prm%nu) * abs(tau)) dUpper(1:ns,2) = prm%mu * prm%burgers(1:ns) & @@ -2138,6 +2139,13 @@ if (lattice_structure(ph) == LATTICE_bcc_ID) then else ! ALL OTHER STRUCTURES if (prm%probabilisticMultiplication) then + !################################################################################################# + !################################################################################################# + ! ToDo: MD: to me, this whole procedure looks extremly time step and integrator dependent + ! Just using FPI instead of Euler gives you a higher chance of multiplication if I understand it correctly + ! I suggest to remove + !################################################################################################# + !################################################################################################# meshlength = mesh_ipVolume(ip,el)**0.333_pReal where(sum(rhoSgl(1:ns,1:4),2) > 0.0_pReal) nSources = (sum(rhoSgl(1:ns,1:2),2) * prm%fEdgeMultiplication + sum(rhoSgl(1:ns,3:4),2)) & @@ -2733,7 +2741,7 @@ do s = 1_pInt,ns if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo -dLower = minDipoleHeight(1:ns,1:2,instance) +dLower = prm%minDipoleHeight(1:ns,1:2) dUpper(1:ns,1) = prm%mu * prm%burgers(1:ns) & / (8.0_pReal * pi * (1.0_pReal - prm%nu) * abs(tau)) dUpper(1:ns,2) = prm%mu * prm%burgers(1:ns) & From 838faca8191dcd982663e329f82290a92ea2fafb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 13:32:08 +0100 Subject: [PATCH 58/97] using structure for output avoids waste of memory in case of multiple instances avoids explicit dependence on ip and el --- src/plastic_nonlocal.f90 | 123 ++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 42ed24ad2..477bfee04 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -37,7 +37,7 @@ module plastic_nonlocal totalNslip !< total number of active slip systems for each instance integer(pInt), dimension(:,:), allocatable, private :: & - Nslip, & !< number of active slip systems for each family and instance + Nslip, & !< number of active slip systems slipFamily, & !< lookup table relating active slip system to slip family for each instance slipSystemLattice, & !< lookup table relating active slip system index to lattice slip system index for each instance colinearSystem !< colinear system to the active slip system (only valid for fcc!) @@ -48,26 +48,18 @@ module plastic_nonlocal rhoSglRandomBinning real(pReal), dimension(:,:), allocatable, private :: & - rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance - rhoSglEdgeNeg0, & !< initial edge_neg dislocation density per slip system for each family and instance - rhoSglScrewPos0, & !< initial screw_pos dislocation density per slip system for each family and instance - rhoSglScrewNeg0, & !< initial screw_neg dislocation density per slip system for each family and instance - rhoDipEdge0, & !< initial edge dipole dislocation density per slip system for each family and instance - rhoDipScrew0, & !< initial screw dipole dislocation density per slip system for each family and instance - lambda0PerSlipFamily, & !< mean free path prefactor for each family and instance - lambda0 !< mean free path prefactor for each slip system and instance + rhoSglEdgePos0, & !< initial edge_pos dislocation density + rhoSglEdgeNeg0, & !< initial edge_neg dislocation density + rhoSglScrewPos0, & !< initial screw_pos dislocation density + rhoSglScrewNeg0, & !< initial screw_neg dislocation density + rhoDipEdge0, & !< initial edge dipole dislocation density + rhoDipScrew0, & !< initial screw dipole dislocation density + lambda0PerSlipFamily, & !< mean free path prefactor + lambda0 !< mean free path prefactor real(pReal), dimension(:,:,:,:), allocatable, private :: & - rhoDotEdgeJogsOutput, & sourceProbability - real(pReal), dimension(:,:,:,:,:), allocatable, private :: & - rhoDotFluxOutput, & - rhoDotMultiplicationOutput, & - rhoDotSingle2DipoleGlideOutput, & - rhoDotAthermalAnnihilationOutput, & - rhoDotThermalAnnihilationOutput !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) - real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & compatibility !< slip system compatibility between me and my neighbors @@ -182,8 +174,21 @@ module plastic_nonlocal integer(kind(undefined_ID)), dimension(:), allocatable :: & outputID !< ID of each post result output + end type tParameters + type, private :: tOutput !< container type for storage of output results + real(pReal), dimension(:,:), allocatable, private :: & + rhoDotEdgeJogs + real(pReal), dimension(:,:,:), allocatable, private :: & + rhoDotFlux, & + rhoDotMultiplication, & + rhoDotSingle2DipoleGlide, & + rhoDotAthermalAnnihilation, & + rhoDotThermalAnnihilation + end type + + type, private :: tNonlocalState real(pReal), pointer, dimension(:,:) :: & @@ -216,13 +221,15 @@ module plastic_nonlocal rhoSglEdge, & accumulatedshear end type tNonlocalState + type(tNonlocalState), allocatable, dimension(:), private :: & deltaState, & dotState, & state - type(tParameters), dimension(:), allocatable, target, private :: param !< containers of constitutive parameters (len Ninstance) + type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance) + type(tOutput), dimension(:), allocatable, private :: results integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & plastic_nonlocal_outputID !< ID of each post result output @@ -331,6 +338,7 @@ allocate(param(maxNinstances)) allocate(state(maxNinstances)) allocate(dotState(maxNinstances)) allocate(deltaState(maxNinstances)) +allocate(results(maxNinstances)) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) @@ -476,19 +484,6 @@ allocate(lambda0(maxTotalNslip,maxNinstances), allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & source=2.0_pReal) -allocate(rhoDotFluxOutput(maxTotalNslip,8,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) -allocate(rhoDotMultiplicationOutput(maxTotalNslip,2,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) -allocate(rhoDotSingle2DipoleGlideOutput(maxTotalNslip,2,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) -allocate(rhoDotAthermalAnnihilationOutput(maxTotalNslip,2,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) -allocate(rhoDotThermalAnnihilationOutput(maxTotalNslip,2,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) -allocate(rhoDotEdgeJogsOutput(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) - allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) allocate(colinearSystem(maxTotalNslip,maxNinstances), source=0_pInt) @@ -651,7 +646,7 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), stt => state(instance), & del => deltaState(instance), & config => config_phase(p)) - + NofMyPhase=count(material_phase==p) prm%mu = lattice_mu(p) prm%nu = lattice_nu(p) structure = config_phase(p)%getString('lattice_structure') @@ -971,7 +966,17 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' dot%rhoDipScrew => plasticState(p)%dotState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear + + allocate(results(instance)%rhoDotFlux(prm%totalNslip,8,NofMyPhase)) + allocate(results(instance)%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase)) + allocate(results(instance)%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase)) + allocate(results(instance)%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase)) + allocate(results(instance)%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase)) + allocate(results(instance)%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase)) end associate + + + enddo end subroutine plastic_nonlocal_init @@ -1421,7 +1426,7 @@ use material, only: material_phase, & implicit none -!*** input variables + integer(pInt), intent(in) :: ip, & !< current integration point el, & !< current element number c !< dislocation character (1:edge, 2:screw) @@ -1431,13 +1436,11 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt tauNS, & !< resolved external shear stress (including non Schmid effects) tauThreshold !< threshold shear stress -!*** output variables real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))), & intent(out) :: v, & !< velocity dv_dtau, & !< velocity derivative with respect to resolved shear stress (without non Schmid contributions) dv_dtauNS !< velocity derivative with respect to resolved shear stress (including non Schmid contributions) -!*** local variables integer(pInt) :: instance, & !< current instance of this plasticity ns, & !< short notation for the total number of active slip systems s !< index of my current slip system @@ -1577,7 +1580,7 @@ use material, only: material_phase, & implicit none -!*** input variables + integer(pInt), intent(in) :: ip, & !< current integration point el !< current element number real(pReal), intent(in) :: Temperature, & !< temperature @@ -1585,11 +1588,10 @@ volume !< volume of the materialpoint real(pReal), dimension(3,3), intent(in) :: Mp -!*** output variables real(pReal), dimension(3,3), intent(out) :: Lp !< plastic velocity gradient real(pReal), dimension(3,3,3,3), intent(out) :: dLp_dMp !< derivative of Lp with respect to Tstar (9x9 matrix) -!*** local variables + integer(pInt) instance, & !< current instance of this plasticity ns, & !< short notation for the total number of active slip systems i, & @@ -2429,12 +2431,13 @@ rhoDot = rhoDotFlux & + rhoDotAthermalAnnihilation & + rhoDotThermalAnnihilation -rhoDotFluxOutput(1:ns,1:8,1_pInt,ip,el) = rhoDotFlux(1:ns,1:8) -rhoDotMultiplicationOutput(1:ns,1:2,1_pInt,ip,el) = rhoDotMultiplication(1:ns,[1,3]) -rhoDotSingle2DipoleGlideOutput(1:ns,1:2,1_pInt,ip,el) = rhoDotSingle2DipoleGlide(1:ns,9:10) -rhoDotAthermalAnnihilationOutput(1:ns,1:2,1_pInt,ip,el) = rhoDotAthermalAnnihilation(1:ns,9:10) -rhoDotThermalAnnihilationOutput(1:ns,1:2,1_pInt,ip,el) = rhoDotThermalAnnihilation(1:ns,9:10) -rhoDotEdgeJogsOutput(1:ns,1_pInt,ip,el) = 2.0_pReal * rhoDotThermalAnnihilation(1:ns,1) +results(instance)%rhoDotFlux(1:ns,1:8,o) = rhoDotFlux(1:ns,1:8) + +results(instance)%rhoDotMultiplication(1:ns,1:2,o) = rhoDotMultiplication(1:ns,[1,3]) +results(instance)%rhoDotSingle2DipoleGlide(1:ns,1:2,o) = rhoDotSingle2DipoleGlide(1:ns,9:10) +results(instance)%rhoDotAthermalAnnihilation(1:ns,1:2,o) = rhoDotAthermalAnnihilation(1:ns,9:10) +results(instance)%rhoDotThermalAnnihilation(1:ns,1:2,o) = rhoDotThermalAnnihilation(1:ns,9:10) +results(instance)%rhoDotEdgeJogs(1:ns,o) = 2.0_pReal * rhoDotThermalAnnihilation(1:ns,1) #ifdef DEBUG @@ -2839,55 +2842,55 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) cs = cs + ns case (rho_dot_gen_ID) ! Obsolete - postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotMultiplication(1:ns,1,of) & + + results(instance)%rhoDotMultiplication(1:ns,2,of) cs = cs + ns case (rho_dot_gen_edge_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotMultiplication(1:ns,1,of) cs = cs + ns case (rho_dot_gen_screw_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotMultiplicationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotMultiplication(1:ns,2,of) cs = cs + ns case (rho_dot_sgl2dip_edge_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotSingle2DipoleGlide(1:ns,1,of) cs = cs + ns case (rho_dot_sgl2dip_screw_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotSingle2DipoleGlideOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotSingle2DipoleGlide(1:ns,2,of) cs = cs + ns case (rho_dot_ann_ath_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotAthermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) & - + rhoDotAthermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotAthermalAnnihilation(1:ns,1,of) & + + results(instance)%rhoDotAthermalAnnihilation(1:ns,2,of) cs = cs + ns case (rho_dot_ann_the_edge_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,1,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotThermalAnnihilation(1:ns,1,of) cs = cs + ns case (rho_dot_ann_the_screw_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotThermalAnnihilationOutput(1:ns,2,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotThermalAnnihilation(1:ns,2,of) cs = cs + ns case (rho_dot_edgejogs_ID) - postResults(cs+1_pInt:cs+ns) = rhoDotEdgeJogsOutput(1:ns,1_pInt,ip,el) + postResults(cs+1_pInt:cs+ns) = results(instance)%rhoDotEdgeJogs(1:ns,of) cs = cs + ns case (rho_dot_flux_mobile_ID) - postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:4,1_pInt,ip,el),2) + postResults(cs+1_pInt:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,1:4,of),2) cs = cs + ns case (rho_dot_flux_edge_ID) - postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,1:2,1_pInt,ip,el),2) & - + sum(rhoDotFluxOutput(1:ns,5:6,1_pInt,ip,el)*sign(1.0_pReal,rhoSgl(1:ns,5:6)),2) + postResults(cs+1_pInt:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,1:2,of),2) & + + sum(results(instance)%rhoDotFlux(1:ns,5:6,of)*sign(1.0_pReal,rhoSgl(1:ns,5:6)),2) cs = cs + ns case (rho_dot_flux_screw_ID) - postResults(cs+1_pInt:cs+ns) = sum(rhoDotFluxOutput(1:ns,3:4,1_pInt,ip,el),2) & - + sum(rhoDotFluxOutput(1:ns,7:8,1_pInt,ip,el)*sign(1.0_pReal,rhoSgl(1:ns,7:8)),2) + postResults(cs+1_pInt:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,3:4,of),2) & + + sum(results(instance)%rhoDotFlux(1:ns,7:8,of)*sign(1.0_pReal,rhoSgl(1:ns,7:8)),2) cs = cs + ns case (velocity_edge_pos_ID) From eb394b3139368253ad77f8bebd21ef2f06309a7a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 14:54:26 +0100 Subject: [PATCH 59/97] same name in all models --- src/constitutive.f90 | 2 +- src/plastic_nonlocal.f90 | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index d49fcec6e..7e6cdee7a 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -358,7 +358,7 @@ subroutine constitutive_microstructure(orientations, Fe, Fp, ipc, ip, el) PLASTICITY_disloucla_ID, & PLASTICITY_nonlocal_ID use plastic_nonlocal, only: & - plastic_nonlocal_microstructure + plastic_nonlocal_dependentState use plastic_dislotwin, only: & plastic_dislotwin_dependentState use plastic_disloUCLA, only: & diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 477bfee04..8652baf88 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -238,7 +238,7 @@ module plastic_nonlocal plastic_nonlocal_init, & plastic_nonlocal_stateInit, & plastic_nonlocal_aTolState, & - plastic_nonlocal_microstructure, & + plastic_nonlocal_dependentState, & plastic_nonlocal_LpAndItsTangent, & plastic_nonlocal_dotState, & plastic_nonlocal_deltaState, & @@ -1126,7 +1126,7 @@ end subroutine plastic_nonlocal_aTolState !-------------------------------------------------------------------------------------------------- !> @brief calculates quantities characterizing the microstructure !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_microstructure(Fe, Fp, ip, el) +subroutine plastic_nonlocal_dependentState(Fe, Fp, ip, el) use prec, only: & dEq0 use IO, only: & @@ -1284,6 +1284,13 @@ forall (s = 1_pInt:ns) & tauBack = 0.0_pReal + !################################################################################################# + !################################################################################################# + ! ToDo: MD: this is most likely only correct for F_i = I + !################################################################################################# + !################################################################################################# + + if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then invFe = math_inv33(Fe) invFp = math_inv33(Fp) @@ -1406,7 +1413,7 @@ plasticState(ph)%state(iTauB(1:ns,instance),of) = tauBack endif #endif end associate -end subroutine plastic_nonlocal_microstructure +end subroutine plastic_nonlocal_dependentState !-------------------------------------------------------------------------------------------------- From 871ba90654c1de4af9bb057594b88c02e6c0bad0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 17:50:26 +0100 Subject: [PATCH 60/97] initialization can be done internally --- src/constitutive.f90 | 8 +- src/plastic_nonlocal.f90 | 305 +++++++++++++-------------------------- 2 files changed, 106 insertions(+), 207 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 7e6cdee7a..6f07446f9 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -150,10 +150,8 @@ subroutine constitutive_init() if (any(phase_plasticity == PLASTICITY_KINEHARDENING_ID)) call plastic_kinehardening_init if (any(phase_plasticity == PLASTICITY_DISLOTWIN_ID)) call plastic_dislotwin_init if (any(phase_plasticity == PLASTICITY_DISLOUCLA_ID)) call plastic_disloucla_init - if (any(phase_plasticity == PLASTICITY_NONLOCAL_ID)) then - call plastic_nonlocal_init(FILEUNIT) - call plastic_nonlocal_stateInit() - endif + if (any(phase_plasticity == PLASTICITY_NONLOCAL_ID)) call plastic_nonlocal_init(FILEUNIT) + !-------------------------------------------------------------------------------------------------- ! parse source mechanisms from config file @@ -392,7 +390,7 @@ subroutine constitutive_microstructure(orientations, Fe, Fp, ipc, ip, el) instance = phase_plasticityInstance(material_phase(ipc,ip,el)) call plastic_disloUCLA_dependentState(instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_microstructure (Fe,Fp,ip,el) + call plastic_nonlocal_dependentState (Fe,Fp,ip,el) end select plasticityType end subroutine constitutive_microstructure diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 8652baf88..a70bdafeb 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -48,12 +48,6 @@ module plastic_nonlocal rhoSglRandomBinning real(pReal), dimension(:,:), allocatable, private :: & - rhoSglEdgePos0, & !< initial edge_pos dislocation density - rhoSglEdgeNeg0, & !< initial edge_neg dislocation density - rhoSglScrewPos0, & !< initial screw_pos dislocation density - rhoSglScrewNeg0, & !< initial screw_neg dislocation density - rhoDipEdge0, & !< initial edge dipole dislocation density - rhoDipScrew0, & !< initial screw dipole dislocation density lambda0PerSlipFamily, & !< mean free path prefactor lambda0 !< mean free path prefactor @@ -236,8 +230,6 @@ module plastic_nonlocal public :: & plastic_nonlocal_init, & - plastic_nonlocal_stateInit, & - plastic_nonlocal_aTolState, & plastic_nonlocal_dependentState, & plastic_nonlocal_LpAndItsTangent, & plastic_nonlocal_dotState, & @@ -352,12 +344,6 @@ allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) -allocate(rhoSglEdgePos0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(rhoSglEdgeNeg0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(rhoSglScrewPos0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(rhoSglScrewNeg0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(rhoDipEdge0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) -allocate(rhoDipScrew0(lattice_maxNslipFamily,maxNinstances), source=-1.0_pReal) allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) @@ -392,30 +378,6 @@ allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), s do f = 1_pInt, Nchunks_SlipFamilies Nslip(f,instance) = IO_intValue(line,chunkPos,1_pInt+f) enddo - case ('rhosgledgepos0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoSglEdgePos0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case ('rhosgledgeneg0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoSglEdgeNeg0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case ('rhosglscrewpos0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoSglScrewPos0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case ('rhosglscrewneg0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoSglScrewNeg0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case ('rhodipedge0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoDipEdge0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case ('rhodipscrew0') - do f = 1_pInt, Nchunks_SlipFamilies - rhoDipScrew0(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo case ('lambda0') do f = 1_pInt, Nchunks_SlipFamilies lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) @@ -437,21 +399,8 @@ allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), s call IO_error(211_pInt,ext_msg='Nslip ('//PLASTICITY_NONLOCAL_label//')') do f = 1_pInt,lattice_maxNslipFamily if (Nslip(f,instance) > 0_pInt) then - if (rhoSglEdgePos0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglEdgePos0 ('//PLASTICITY_NONLOCAL_label//')') - if (rhoSglEdgeNeg0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglEdgeNeg0 ('//PLASTICITY_NONLOCAL_label//')') - if (rhoSglScrewPos0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglScrewPos0 ('//PLASTICITY_NONLOCAL_label//')') - if (rhoSglScrewNeg0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglScrewNeg0 ('//PLASTICITY_NONLOCAL_label//')') - if (rhoDipEdge0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoDipEdge0 ('//PLASTICITY_NONLOCAL_label//')') - if (rhoDipScrew0(f,instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') - endif enddo if (rhoSglScatter(instance) < 0.0_pReal) & @@ -622,17 +571,7 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), enddo enddo - - !*** combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) - !* four types t: - !* 1) positive screw at positive resolved stress - !* 2) positive screw at negative resolved stress - !* 3) negative screw at positive resolved stress - !* 4) negative screw at negative resolved stress - - - call plastic_nonlocal_aTolState(phase,instance) endif myPhase2 enddo initializeInstances @@ -793,6 +732,20 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' ! if (peierlsStressPerSlipFamily(f,2,instance) <= 0.0_pReal) & ! call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') + +! if (rhoSglEdgePos0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglEdgePos0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglEdgeNeg0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglEdgeNeg0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglScrewPos0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglScrewPos0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglScrewNeg0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglScrewNeg0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoDipEdge0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoDipEdge0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoDipScrew0(f,instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) do i=1_pInt, size(outputs) @@ -976,151 +929,99 @@ plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear end associate - + if (NofMyPhase > 0_pInt) call stateInit(p,NofMyPhase) + plasticState(p)%state0 = plasticState(p)%state enddo + + contains + +subroutine stateInit(phase,NofMyPhase) + use math, only: & + math_sampleGaussVar + use mesh, only: & + theMesh, & + mesh_ipVolume + use material, only: & + material_phase, & + phase_plasticityInstance, & + phasememberAt + implicit none + + integer(pInt),intent(in) ::& + phase, & + NofMyPhase + integer(pInt) :: & + e, & + i, & + f, & + from, & + upto, & + s, & + instance, & + phasemember + real(pReal), dimension(2) :: & + noise, & + rnd + real(pReal) :: & + meanDensity, & + totalVolume, & + densityBinning, & + minimumIpVolume + real(pReal), dimension(NofMyPhase) :: & + volume + + + instance = phase_plasticityInstance(phase) + associate(prm => param(instance), stt => state(instance)) + + ! randomly distribute dislocation segments on random slip system and of random type in the volume + if (prm%rhoSglRandom > 0.0_pReal) then + + ! get the total volume of the instance + do e = 1_pInt,theMesh%nElems + do i = 1_pInt,theMesh%elem%nIPs + if (material_phase(1,i,e) == phase) volume(phasememberAt(1,i,e)) = mesh_ipVolume(i,e) + enddo + enddo + totalVolume = sum(volume) + minimumIPVolume = minval(volume) + densityBinning = prm%rhoSglRandomBinning / minimumIpVolume ** (2.0_pReal / 3.0_pReal) + + ! subsequently fill random ips with dislocation segments until we reach the desired overall density + meanDensity = 0.0_pReal + do while(meanDensity < prm%rhoSglRandom) + call random_number(rnd) + phasemember = nint(rnd(1)*real(NofMyPhase,pReal) + 0.5_pReal,pInt) + s = nint(rnd(2)*real(prm%totalNslip,pReal)*4.0_pReal + 0.5_pReal,pInt) + meanDensity = meanDensity + densityBinning * volume(phasemember) / totalVolume + stt%rhoSglMobile(s,phasemember) = densityBinning + enddo + ! homogeneous distribution of density with some noise + else + do e = 1_pInt, NofMyPhase + do f = 1_pInt,size(prm%Nslip,1) + from = 1_pInt + sum(prm%Nslip(1:f-1_pInt)) + upto = sum(prm%Nslip(1:f)) + do s = from,upto + noise = [math_sampleGaussVar(0.0_pReal, prm%rhoSglScatter), & + math_sampleGaussVar(0.0_pReal, prm%rhoSglScatter)] + stt%rhoSglEdgeMobilePos(s,e) = prm%rhoSglEdgePos0(f) + noise(1) + stt%rhoSglEdgeMobileNeg(s,e) = prm%rhoSglEdgeNeg0(f) + noise(1) + stt%rhoSglScrewMobilePos(s,e) = prm%rhoSglScrewPos0(f) + noise(2) + stt%rhoSglScrewMobileNeg(s,e) = prm%rhoSglScrewNeg0(f) + noise(2) + enddo + stt%rhoDipEdge(from:upto,e) = prm%rhoDipEdge0(f) + stt%rhoDipScrew(from:upto,e) = prm%rhoDipScrew0(f) + enddo + enddo + endif + + end associate + +end subroutine stateInit end subroutine plastic_nonlocal_init -!-------------------------------------------------------------------------------------------------- -!> @brief sets the initial microstructural state for a given instance of this plasticity -!-------------------------------------------------------------------------------------------------- - -subroutine plastic_nonlocal_stateInit() -use IO, only: IO_error -use lattice, only: lattice_maxNslipFamily -use math, only: math_sampleGaussVar -use mesh, only: mesh_ipVolume, & - theMesh -use material, only: material_phase, & - phase_plasticityInstance, & - plasticState, & - phaseAt, phasememberAt, & - phase_plasticity ,& - PLASTICITY_NONLOCAL_ID -implicit none - -integer(pInt) :: e, & - i, & - ns, & ! short notation for total number of active slip systems - f, & ! index of lattice family - from, & - upto, & - s, & ! index of slip system - t, & - j, & - instance, & - maxNinstances -real(pReal), dimension(2) :: noise -real(pReal), dimension(4) :: rnd -real(pReal) meanDensity, & - totalVolume, & - densityBinning, & - minimumIpVolume - -maxNinstances = int(count(phase_plasticity == PLASTICITY_NONLOCAL_ID),pInt) - -do instance = 1_pInt,maxNinstances - ns = totalNslip(instance) - - ! randomly distribute dislocation segments on random slip system and of random type in the volume - if (rhoSglRandom(instance) > 0.0_pReal) then - - ! get the total volume of the instance - - minimumIpVolume = huge(1.0_pReal) - totalVolume = 0.0_pReal - do e = 1_pInt,theMesh%nElems - do i = 1_pInt,theMesh%elem%nIPs - if (PLASTICITY_NONLOCAL_ID == phase_plasticity(material_phase(1,i,e)) & - .and. instance == phase_plasticityInstance(material_phase(1,i,e))) then - totalVolume = totalVolume + mesh_ipVolume(i,e) - minimumIpVolume = min(minimumIpVolume, mesh_ipVolume(i,e)) - endif - enddo - enddo - densityBinning = rhoSglRandomBinning(instance) / minimumIpVolume ** (2.0_pReal / 3.0_pReal) - - ! subsequently fill random ips with dislocation segments until we reach the desired overall density - - meanDensity = 0.0_pReal - do while(meanDensity < rhoSglRandom(instance)) - call random_number(rnd) - e = nint(rnd(1)*real(theMesh%nElems,pReal)+0.5_pReal,pInt) - i = nint(rnd(2)*real(theMesh%elem%nIPs,pReal)+0.5_pReal,pInt) - if (PLASTICITY_NONLOCAL_ID == phase_plasticity(material_phase(1,i,e)) & - .and. instance == phase_plasticityInstance(material_phase(1,i,e))) then - s = nint(rnd(3)*real(ns,pReal)+0.5_pReal,pInt) - t = nint(rnd(4)*4.0_pReal+0.5_pReal,pInt) - meanDensity = meanDensity + densityBinning * mesh_ipVolume(i,e) / totalVolume - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,t,instance),phaseAt(1,i,e)) = & - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,t,instance),phaseAt(1,i,e)) & - + densityBinning - endif - enddo - ! homogeneous distribution of density with some noise - else - do e = 1_pInt,theMesh%nElems - do i = 1_pInt,theMesh%elem%nIPs - if (PLASTICITY_NONLOCAL_ID == phase_plasticity(material_phase(1,i,e)) & - .and. instance == phase_plasticityInstance(material_phase(1,i,e))) then - do f = 1_pInt,lattice_maxNslipFamily - from = 1_pInt + sum(Nslip(1:f-1_pInt,instance)) - upto = sum(Nslip(1:f,instance)) - do s = from,upto - do j = 1_pInt,2_pInt - noise(j) = math_sampleGaussVar(0.0_pReal, rhoSglScatter(instance)) - enddo - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,1,instance),phasememberAt(1,i,e)) = & - rhoSglEdgePos0(f,instance) + noise(1) - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,2,instance),phasememberAt(1,i,e)) = & - rhoSglEdgeNeg0(f,instance) + noise(1) - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,3,instance),phasememberAt(1,i,e)) = & - rhoSglScrewPos0(f,instance) + noise(2) - plasticState(phaseAt(1,i,e))%state0(iRhoU(s,4,instance),phasememberAt(1,i,e)) = & - rhoSglScrewNeg0(f,instance) + noise(2) - enddo - plasticState(phaseAt(1,i,e))%state0(iRhoD(from:upto,1,instance),phasememberAt(1,i,e)) = & - rhoDipEdge0(f,instance) - plasticState(phaseAt(1,i,e))%state0(iRhoD(from:upto,2,instance),phasememberAt(1,i,e)) = & - rhoDipScrew0(f,instance) - enddo - endif - enddo - enddo - endif -enddo - -end subroutine plastic_nonlocal_stateInit - - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this plasticity -!-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_aTolState(ph,instance) - use material, only: & - plasticState - - implicit none - integer(pInt), intent(in) :: & - instance, & !< number specifying the instance of the plasticity - ph - integer(pInt) :: & - ns, & - t, c - -associate (prm => param(instance)) - ns = totalNslip(instance) - forall (t = 1_pInt:4_pInt) - plasticState(ph)%aTolState(iRhoU(1:ns,t,instance)) = prm%aTolRho - plasticState(ph)%aTolState(iRhoB(1:ns,t,instance)) = prm%aTolRho - end forall - forall (c = 1_pInt:2_pInt) & - plasticState(ph)%aTolState(iRhoD(1:ns,c,instance)) = prm%aTolRho - - plasticState(ph)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear - -end associate -end subroutine plastic_nonlocal_aTolState !-------------------------------------------------------------------------------------------------- From 6f135ea632a1e1ad6a067f9b94f176cae9df5a73 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 17:58:11 +0100 Subject: [PATCH 61/97] no random-multiplication anymore from our current understanding, the implementation of random nucleation was strongly dependent on the numerical method and the time stepping --- src/plastic_nonlocal.f90 | 51 ++-------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index a70bdafeb..3248e6928 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -50,9 +50,6 @@ module plastic_nonlocal real(pReal), dimension(:,:), allocatable, private :: & lambda0PerSlipFamily, & !< mean free path prefactor lambda0 !< mean free path prefactor - - real(pReal), dimension(:,:,:,:), allocatable, private :: & - sourceProbability real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & compatibility !< slip system compatibility between me and my neighbors @@ -430,8 +427,7 @@ allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) -allocate(sourceProbability(maxTotalNslip,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), & - source=2.0_pReal) + allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) @@ -591,7 +587,6 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), structure = config_phase(p)%getString('lattice_structure') param(instance)%shortRangeStressCorrection = .false. -param(instance)%probabilisticMultiplication = .false. prm%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) prm%totalNslip = sum(prm%Nslip) @@ -694,7 +689,6 @@ param(instance)%probabilisticMultiplication = .false. prm%fEdgeMultiplication = config_phase(p)%getFloat('edgemultiplication')!,'edgemultiplicationfactor','fedgemultiplication') prm%shortRangeStressCorrection = config_phase(p)%getInt('shortrangestresscorrection' ) > 0_pInt - prm%probabilisticMultiplication = config_phase(p)%keyExists('/probabilisticmultiplication/' )!,'randomsources','randommultiplication','discretesources') ! sanity checks if ( any(prm%burgers <= 0.0_pReal)) extmsg = trim(extmsg)//' burgers' @@ -2035,7 +2029,6 @@ dUpper = max(dUpper,dLower) !**************************************************************************** !*** calculate dislocation multiplication - rhoDotMultiplication = 0.0_pReal if (lattice_structure(ph) == LATTICE_bcc_ID) then ! BCC forall (s = 1:ns, sum(abs(v(s,1:4))) > 0.0_pReal) @@ -2048,49 +2041,9 @@ if (lattice_structure(ph) == LATTICE_bcc_ID) then endforall else ! ALL OTHER STRUCTURES - if (prm%probabilisticMultiplication) then - !################################################################################################# - !################################################################################################# - ! ToDo: MD: to me, this whole procedure looks extremly time step and integrator dependent - ! Just using FPI instead of Euler gives you a higher chance of multiplication if I understand it correctly - ! I suggest to remove - !################################################################################################# - !################################################################################################# - meshlength = mesh_ipVolume(ip,el)**0.333_pReal - where(sum(rhoSgl(1:ns,1:4),2) > 0.0_pReal) - nSources = (sum(rhoSgl(1:ns,1:2),2) * prm%fEdgeMultiplication + sum(rhoSgl(1:ns,3:4),2)) & - / sum(rhoSgl(1:ns,1:4),2) * meshlength / lambda0(1:ns,instance)*sqrt(rhoForest(1:ns)) - elsewhere - nSources = meshlength / lambda0(1:ns,instance) * sqrt(rhoForest(1:ns)) - endwhere - do s = 1_pInt,ns - if (nSources(s) < 1.0_pReal) then - if (sourceProbability(s,1_pInt,ip,el) > 1.0_pReal) then - call random_number(rnd) - sourceProbability(s,1_pInt,ip,el) = rnd - !$OMP FLUSH(sourceProbability) - endif - if (sourceProbability(s,1_pInt,ip,el) > 1.0_pReal - nSources(s)) then - rhoDotMultiplication(s,1:4) = sum(rhoSglOriginal(s,1:4) * abs(v(s,1:4))) / meshlength - endif - else - sourceProbability(s,1_pInt,ip,el) = 2.0_pReal - rhoDotMultiplication(s,1:4) = & - (sum(abs(gdot(s,1:2))) * prm%fEdgeMultiplication + sum(abs(gdot(s,3:4)))) & - /prm%burgers(s) * sqrt(rhoForest(s)) / lambda0(s,instance) - endif - enddo -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0_pInt )) & - write(6,'(a,/,4(12x,12(f12.5,1x),/,/))') '<< CONST >> sources', nSources -#endif - else - rhoDotMultiplication(1:ns,1:4) = spread( & + rhoDotMultiplication(1:ns,1:4) = spread( & (sum(abs(gdot(1:ns,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(1:ns,3:4)),2)) & * sqrt(rhoForest(1:ns)) / lambda0(1:ns,instance) / prm%burgers(1:ns), 2, 4) - endif endif From 2d51c0595bd69d944e06cdee4c3d1f07834dc336 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 19:03:20 +0100 Subject: [PATCH 62/97] don't parse material.config any more --- src/constitutive.f90 | 15 ++- src/lattice.f90 | 5 +- src/plastic_nonlocal.f90 | 225 ++++++++++++--------------------------- 3 files changed, 80 insertions(+), 165 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 6f07446f9..e5dc6a1cc 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -137,11 +137,6 @@ subroutine constitutive_init() logical :: knownPlasticity, knownSource, nonlocalConstitutionPresent nonlocalConstitutionPresent = .false. -!-------------------------------------------------------------------------------------------------- -! open material.config - if (.not. IO_open_jobFile_stat(FILEUNIT,material_localFileExt)) & ! no local material configuration present... - call IO_open_file(FILEUNIT,material_configFile) ! ... open material.config file - !-------------------------------------------------------------------------------------------------- ! parse plasticities from config file if (any(phase_plasticity == PLASTICITY_NONE_ID)) call plastic_none_init @@ -150,12 +145,16 @@ subroutine constitutive_init() if (any(phase_plasticity == PLASTICITY_KINEHARDENING_ID)) call plastic_kinehardening_init if (any(phase_plasticity == PLASTICITY_DISLOTWIN_ID)) call plastic_dislotwin_init if (any(phase_plasticity == PLASTICITY_DISLOUCLA_ID)) call plastic_disloucla_init - if (any(phase_plasticity == PLASTICITY_NONLOCAL_ID)) call plastic_nonlocal_init(FILEUNIT) - + if (any(phase_plasticity == PLASTICITY_NONLOCAL_ID)) call plastic_nonlocal_init + + +!-------------------------------------------------------------------------------------------------- +! open material.config + if (.not. IO_open_jobFile_stat(FILEUNIT,material_localFileExt)) & ! no local material configuration present... + call IO_open_file(FILEUNIT,material_configFile) ! ... open material.config file !-------------------------------------------------------------------------------------------------- ! parse source mechanisms from config file - call IO_checkAndRewind(FILEUNIT) if (any(phase_source == SOURCE_thermal_dissipation_ID)) call source_thermal_dissipation_init(FILEUNIT) if (any(phase_source == SOURCE_thermal_externalheat_ID)) call source_thermal_externalheat_init(FILEUNIT) if (any(phase_source == SOURCE_damage_isoBrittle_ID)) call source_damage_isoBrittle_init diff --git a/src/lattice.f90 b/src/lattice.f90 index ee4273a53..7ec4c5470 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -550,7 +550,10 @@ module lattice lattice_forestProjection_screw, & lattice_slipProjection_modeI, & lattice_slipProjection_modeII, & - lattice_slipProjection_modeIII + lattice_slipProjection_modeIII, & + lattice_slip_normal, & + lattice_slip_direction, & + lattice_slip_transverse contains diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 3248e6928..85800f7d7 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -41,15 +41,7 @@ module plastic_nonlocal slipFamily, & !< lookup table relating active slip system to slip family for each instance slipSystemLattice, & !< lookup table relating active slip system index to lattice slip system index for each instance colinearSystem !< colinear system to the active slip system (only valid for fcc!) - - real(pReal), dimension(:), allocatable, private :: & - rhoSglScatter, & !< standard deviation of scatter in initial dislocation density - rhoSglRandom, & - rhoSglRandomBinning - - real(pReal), dimension(:,:), allocatable, private :: & - lambda0PerSlipFamily, & !< mean free path prefactor - lambda0 !< mean free path prefactor + real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & compatibility !< slip system compatibility between me and my neighbors @@ -141,6 +133,9 @@ module plastic_nonlocal burgers !< absolute length of burgers vector [m] for each slip system and instance real(pReal), dimension(:,:), allocatable :: & + slip_normal, & + slip_direction, & + slip_transverse, & minDipoleHeight, & ! edge and screw peierlsstress, & ! edge and screw interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance @@ -244,28 +239,18 @@ contains !> @brief module initialization !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_init(fileUnit) +subroutine plastic_nonlocal_init use prec, only: dEq use math, only: math_Voigt66to3333, & math_mul3x3, & math_expand -use IO, only: IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_EOF +use IO, only: IO_error + use debug, only: debug_level, & debug_constitutive, & debug_levelBasic use mesh, only: theMesh use material, only: phase_plasticity, & - homogenization_maxNgrains, & phase_plasticityInstance, & phase_Noutput, & PLASTICITY_NONLOCAL_label, & @@ -279,30 +264,24 @@ use lattice implicit none -integer(pInt), intent(in) :: fileUnit character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] integer(pInt), dimension(0), parameter :: emptyInt = [integer(pInt)::] real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] !*** local variables -integer(pInt), allocatable, dimension(:) :: chunkPos -integer(pInt) :: phase, & +integer(pInt) :: ns, phase, & maxNinstances, & maxTotalNslip, p, i, & f, & ! index of my slip family instance, & ! index of my instance of this plasticity l, & - ns, & ! short notation for total number of active slip systems for the current instance o, & ! index of my output s, & ! index of my slip system s1, & ! index of my slip system s2, & ! index of my slip system t, & ! index of dislocation type - c, & ! index of dislocation character - Nchunks_SlipFamilies - character(len=65536) :: & - tag = '', & - line = '' + c ! index of dislocation character + integer(pInt) :: sizeState, sizeDotState,sizeDependentState, sizeDeltaState integer(kind(undefined_ID)) :: & @@ -337,80 +316,16 @@ allocate(Nslip(lattice_maxNslipFamily,maxNinstances), source=0_pInt) allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) -allocate(rhoSglScatter(maxNinstances), source=0.0_pReal) -allocate(rhoSglRandom(maxNinstances), source=0.0_pReal) -allocate(rhoSglRandomBinning(maxNinstances), source=1.0_pReal) - -allocate(lambda0PerSlipFamily(lattice_maxNslipFamily,maxNinstances), source=0.0_pReal) - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through phases of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase - phase = phase + 1_pInt ! advance phase section counter - if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) & - Nchunks_SlipFamilies = count(lattice_NslipSystem(:,phase) > 0_pInt) - cycle - endif - if (phase > 0_pInt ) then; if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then ! one of my phases. do not short-circuit here (.and. with next if statement). It's not safe in Fortran - instance = phase_plasticityInstance(phase) ! which instance of my plasticity is present phase - chunkPos = IO_stringPos(line) - tag = IO_lc(IO_stringValue(line,chunkPos,1_pInt)) ! extract key - select case(tag) - case ('nslip') - if (chunkPos(1) < 1_pInt + Nchunks_SlipFamilies) & - call IO_warning(50_pInt,ext_msg=trim(tag)//' ('//PLASTICITY_NONLOCAL_LABEL//')') - Nchunks_SlipFamilies = chunkPos(1) - 1_pInt - do f = 1_pInt, Nchunks_SlipFamilies - Nslip(f,instance) = IO_intValue(line,chunkPos,1_pInt+f) - enddo - case ('lambda0') - do f = 1_pInt, Nchunks_SlipFamilies - lambda0PerSlipFamily(f,instance) = IO_floatValue(line,chunkPos,1_pInt+f) - enddo - case('rhosglscatter') - rhoSglScatter(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('rhosglrandom') - rhoSglRandom(instance) = IO_floatValue(line,chunkPos,2_pInt) - case('rhosglrandombinning') - rhoSglRandomBinning(instance) = IO_floatValue(line,chunkPos,2_pInt) - end select - endif; endif - enddo parsingFile - - sanityChecks: do phase = 1_pInt, size(phase_plasticity) - myPhase: if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then - instance = phase_plasticityInstance(phase) - if (sum(Nslip(:,instance)) <= 0_pInt) & - call IO_error(211_pInt,ext_msg='Nslip ('//PLASTICITY_NONLOCAL_label//')') - do f = 1_pInt,lattice_maxNslipFamily - if (Nslip(f,instance) > 0_pInt) then - if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') - endif - enddo - if (rhoSglScatter(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') - if (rhoSglRandom(instance) < 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') - if (rhoSglRandomBinning(instance) <= 0.0_pReal) & - call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - - totalNslip(instance) = sum(Nslip(1:lattice_maxNslipFamily,instance)) - endif myPhase -enddo sanityChecks - + do p=1_pInt, size(config_phase) + if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle + instance = phase_plasticityInstance(p) + param(instance)%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) + Nslip(1:size(param(instance)%Nslip),instance) = param(instance)%Nslip + totalNslip(instance) = sum(Nslip(1:lattice_maxNslipFamily,instance)) + enddo + !*** allocation of variables whose size depends on the total number of active slip systems @@ -426,8 +341,6 @@ allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(lambda0(maxTotalNslip,maxNinstances), source=0.0_pReal) - allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) @@ -551,10 +464,6 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), do s1 = 1_pInt,ns f = slipFamily(s1,instance) - - !*** burgers vector, mean free path prefactor and minimum dipole distance for each slip system - - lambda0(s1,instance) = lambda0PerSlipFamily(f,instance) do s2 = 1_pInt,ns @@ -588,7 +497,7 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), param(instance)%shortRangeStressCorrection = .false. - prm%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) + prm%totalNslip = sum(prm%Nslip) prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,structure(1:3),& config%getFloat('c/a',defaultVal=0.0_pReal)) @@ -661,6 +570,13 @@ param(instance)%shortRangeStressCorrection = .false. prm%q = config_phase(p)%getFloat('q') + prm%slip_direction = lattice_slip_direction(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%slip_transverse = lattice_slip_transverse(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + + prm%slip_normal = lattice_slip_normal(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge,prm%Nslip) prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,prm%Nslip) allocate(prm%minDipoleHeight(prm%totalNslip,2)) @@ -726,7 +642,12 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' ! if (peierlsStressPerSlipFamily(f,2,instance) <= 0.0_pReal) & ! call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') - +! do f = 1_pInt,lattice_maxNslipFamily +! if (Nslip(f,instance) > 0_pInt) then +! if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') +! endif +! enddo ! if (rhoSglEdgePos0(f,instance) < 0.0_pReal) & ! call IO_error(211_pInt,ext_msg='rhoSglEdgePos0 ('//PLASTICITY_NONLOCAL_label//')') ! if (rhoSglEdgeNeg0(f,instance) < 0.0_pReal) & @@ -739,6 +660,14 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' ! call IO_error(211_pInt,ext_msg='rhoDipEdge0 ('//PLASTICITY_NONLOCAL_label//')') ! if (rhoDipScrew0(f,instance) < 0.0_pReal) & ! call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglScatter(instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglRandom(instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') + + outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) @@ -1052,11 +981,9 @@ use material, only: & phaseAt, phasememberAt, & phase_plasticityInstance use lattice, only: & - lattice_sd, & - lattice_st, & - lattice_structure, & LATTICE_bcc_ID, & - LATTICE_fcc_ID + LATTICE_fcc_ID, & + lattice_structure implicit none @@ -1072,13 +999,10 @@ real(pReal), dimension(3,3), intent(in) :: & np, & !< neighbor phase no !< nieghbor offset -integer(pInt) neighbor_el, & ! element number of neighboring material point +integer(pInt) ns, neighbor_el, & ! element number of neighboring material point neighbor_ip, & ! integration point of neighboring material point instance, & ! my instance of this plasticity neighbor_instance, & ! instance of this plasticity of neighboring material point - neighbor_phase, & - ns, & ! total number of active slip systems at my material point - neighbor_ns, & ! total number of active slip systems at neighboring material point c, & ! index of dilsocation character (edge, screw) s, & ! slip system index t, & ! index of dilsocation type (e+, e-, s+, s-, used e+, used e-, used s+, used s-) @@ -1243,8 +1167,8 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then !* 1. interpolation of the excess density in the neighorhood !* 2. interpolation of the dead dislocation density in the central volume - m(1:3,1:ns,1) = lattice_sd(1:3,slipSystemLattice(1:ns,instance),ph) - m(1:3,1:ns,2) = -lattice_st(1:3,slipSystemLattice(1:ns,instance),ph) + m(1:3,1:ns,1) = prm%slip_direction + m(1:3,1:ns,2) = -prm%slip_transverse do s = 1_pInt,ns @@ -1656,8 +1580,7 @@ integer(pInt) ::instance, & ! current instance of this plasticity ns, & ! short notation for the total number of active slip systems c, & ! character of dislocation t, & ! type of dislocation - s, & ! index of my current slip system - sLattice ! index of my current slip system according to lattice order + s ! index of my current slip system real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,el))),10) :: & deltaRho, & ! density increment deltaRhoRemobilization, & ! density increment by remobilization @@ -1841,9 +1764,7 @@ use material, only: homogenization_maxNgrains, & phaseAt, phasememberAt, & phase_plasticity ,& PLASTICITY_NONLOCAL_ID -use lattice, only: lattice_sd, & - lattice_st ,& - lattice_structure, & +use lattice, only: lattice_structure, & LATTICE_bcc_ID, & LATTICE_fcc_ID @@ -1894,7 +1815,6 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) rhoSglOriginal, & neighbor_rhoSgl, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) - rhoSgl0, & !< single dislocation densities at start of cryst inc (positive/negative screw and edge without dipoles) my_rhoSgl !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),4) :: & v, & !< current dislocation glide velocity @@ -1906,8 +1826,8 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt tauThreshold, & !< threshold shear stress tau, & !< current resolved shear stress tauBack, & !< current back stress from pileups on same slip system - vClimb, & !< climb velocity of edge dipoles - nSources + vClimb !< climb velocity of edge dipoles + real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),2) :: & rhoDip, & !< current dipole dislocation densities (screw and edge dipoles) rhoDipOriginal, & @@ -1927,9 +1847,8 @@ real(pReal), dimension(3) :: normal_neighbor2me, & real(pReal) area, & !< area of the current interface transmissivity, & !< overall transmissivity of dislocation flux to neighboring material point lineLength, & !< dislocation line length leaving the current interface - selfDiffusion, & !< self diffusion - rnd, & - meshlength + selfDiffusion !< self diffusion + logical considerEnteringFlux, & considerLeavingFlux @@ -2033,17 +1952,17 @@ rhoDotMultiplication = 0.0_pReal if (lattice_structure(ph) == LATTICE_bcc_ID) then ! BCC forall (s = 1:ns, sum(abs(v(s,1:4))) > 0.0_pReal) rhoDotMultiplication(s,1:2) = sum(abs(gdot(s,3:4))) / prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication - * sqrt(rhoForest(s)) / lambda0(s,instance) ! & ! mean free path + * sqrt(rhoForest(s)) / prm%lambda0(s) ! & ! mean free path ! * 2.0_pReal * sum(abs(v(s,3:4))) / sum(abs(v(s,1:4))) ! ratio of screw to overall velocity determines edge generation rhoDotMultiplication(s,3:4) = sum(abs(gdot(s,3:4))) /prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication - * sqrt(rhoForest(s)) / lambda0(s,instance) ! & ! mean free path + * sqrt(rhoForest(s)) / prm%lambda0(s) ! & ! mean free path ! * 2.0_pReal * sum(abs(v(s,1:2))) / sum(abs(v(s,1:4))) ! ratio of edge to overall velocity determines screw generation endforall else ! ALL OTHER STRUCTURES rhoDotMultiplication(1:ns,1:4) = spread( & (sum(abs(gdot(1:ns,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(1:ns,3:4)),2)) & - * sqrt(rhoForest(1:ns)) / lambda0(1:ns,instance) / prm%burgers(1:ns), 2, 4) + * sqrt(rhoForest(1:ns)) / prm%lambda0 / prm%burgers(1:ns), 2, 4) endif @@ -2079,10 +1998,10 @@ if (.not. phase_localPlasticity(material_phase(1_pInt,ip,el))) then !*** be aware of the definition of lattice_st = lattice_sd x lattice_sn !!! !*** opposite sign to our p vector in the (s,p,n) triplet !!! - m(1:3,1:ns,1) = lattice_sd(1:3, slipSystemLattice(1:ns,instance), ph) - m(1:3,1:ns,2) = -lattice_sd(1:3, slipSystemLattice(1:ns,instance), ph) - m(1:3,1:ns,3) = -lattice_st(1:3, slipSystemLattice(1:ns,instance), ph) - m(1:3,1:ns,4) = lattice_st(1:3, slipSystemLattice(1:ns,instance), ph) + m(1:3,1:ns,1) = prm%slip_direction + m(1:3,1:ns,2) = -prm%slip_direction + m(1:3,1:ns,3) = -prm%slip_transverse + m(1:3,1:ns,4) = prm%slip_transverse my_Fe = Fe(1:3,1:3,1_pInt,ip,el) my_F = math_mul33x33(my_Fe, Fp(1:3,1:3,1_pInt,ip,el)) @@ -2293,7 +2212,6 @@ rhoDot = rhoDotFlux & + rhoDotThermalAnnihilation results(instance)%rhoDotFlux(1:ns,1:8,o) = rhoDotFlux(1:ns,1:8) - results(instance)%rhoDotMultiplication(1:ns,1:2,o) = rhoDotMultiplication(1:ns,[1,3]) results(instance)%rhoDotSingle2DipoleGlide(1:ns,1:2,o) = rhoDotSingle2DipoleGlide(1:ns,9:10) results(instance)%rhoDotAthermalAnnihilation(1:ns,1:2,o) = rhoDotAthermalAnnihilation(1:ns,9:10) @@ -2368,9 +2286,7 @@ use material, only: material_phase, & homogenization_maxNgrains use mesh, only: mesh_ipNeighborhood, & theMesh -use lattice, only: lattice_sn, & - lattice_sd, & - lattice_qDisorientation +use lattice, only: lattice_qDisorientation implicit none @@ -2397,11 +2313,8 @@ real(pReal), dimension(4) :: absoluteMisorientation real(pReal), dimension(2,totalNslip(phase_plasticityInstance(material_phase(1,i,e))),& totalNslip(phase_plasticityInstance(material_phase(1,i,e))),& theMesh%elem%nIPneighbors) :: & - my_compatibility ! my_compatibility for current element and ip -real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1,i,e)))) :: & - slipNormal, & - slipDirection -real(pReal) my_compatibilitySum, & + my_compatibility ! my_compatibility for current element and ip +real(pReal) :: my_compatibilitySum, & thresholdValue, & nThresholdValues logical, dimension(totalNslip(phase_plasticityInstance(material_phase(1,i,e)))) :: & @@ -2413,8 +2326,6 @@ ph = material_phase(1,i,e) textureID = material_texture(1,i,e) instance = phase_plasticityInstance(ph) ns = totalNslip(instance) -slipNormal(1:3,1:ns) = lattice_sn(1:3, slipSystemLattice(1:ns,instance), ph) -slipDirection(1:3,1:ns) = lattice_sd(1:3, slipSystemLattice(1:ns,instance), ph) associate(prm => param(instance)) !*** start out fully compatible @@ -2480,10 +2391,14 @@ neighbors: do n = 1_pInt,Nneighbors orientation(1:4,1,neighbor_i,neighbor_e)) ! no symmetry mySlipSystems: do s1 = 1_pInt,ns neighborSlipSystems: do s2 = 1_pInt,ns - my_compatibility(1,s2,s1,n) = math_mul3x3(slipNormal(1:3,s1), math_qRot(absoluteMisorientation, slipNormal(1:3,s2))) & - * abs(math_mul3x3(slipDirection(1:3,s1), math_qRot(absoluteMisorientation, slipDirection(1:3,s2)))) - my_compatibility(2,s2,s1,n) = abs(math_mul3x3(slipNormal(1:3,s1), math_qRot(absoluteMisorientation, slipNormal(1:3,s2)))) & - * abs(math_mul3x3(slipDirection(1:3,s1), math_qRot(absoluteMisorientation, slipDirection(1:3,s2)))) + my_compatibility(1,s2,s1,n) = math_mul3x3(prm%slip_normal(1:3,s1), & + math_qRot(absoluteMisorientation, prm%slip_normal(1:3,s2))) & + * abs(math_mul3x3(prm%slip_direction(1:3,s1), & + math_qRot(absoluteMisorientation, prm%slip_direction(1:3,s2)))) + my_compatibility(2,s2,s1,n) = abs(math_mul3x3(prm%slip_normal(1:3,s1), & + math_qRot(absoluteMisorientation, prm%slip_normal(1:3,s2)))) & + * abs(math_mul3x3(prm%slip_direction(1:3,s1), & + math_qRot(absoluteMisorientation, prm%slip_direction(1:3,s2)))) enddo neighborSlipSystems my_compatibilitySum = 0.0_pReal @@ -2522,8 +2437,6 @@ function plastic_nonlocal_postResults(Mp,ip,el) result(postResults) math_mul33x3, & math_mul33xx33, & pi - use mesh, only: & - theMesh use material, only: & material_phase, & phaseAt, phasememberAt, & From 3fa699ad2200e1e6d57bdd94c8d7558e454a9757 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 20 Feb 2019 20:17:55 +0100 Subject: [PATCH 63/97] indices were mixed up --- src/lattice.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lattice.f90 b/src/lattice.f90 index 7ec4c5470..c3cb9d489 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -2228,7 +2228,7 @@ function lattice_slip_normal(Nslip,structure,cOverA) result(n) real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) - n = coordinateSystem(1:3,1,1:sum(Nslip)) + n = coordinateSystem(1:3,2,1:sum(Nslip)) end function lattice_slip_normal @@ -2248,7 +2248,7 @@ function lattice_slip_direction(Nslip,structure,cOverA) result(d) real(pReal), dimension(3,3,sum(Nslip)) :: coordinateSystem coordinateSystem = coordinateSystem_slip(Nslip,structure,cOverA) - d = coordinateSystem(1:3,2,1:sum(Nslip)) + d = coordinateSystem(1:3,1,1:sum(Nslip)) end function lattice_slip_direction From cb2d2b02dcaec30554ead5e11c37077478764021 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 00:24:35 +0100 Subject: [PATCH 64/97] re-ordered and cleaned --- src/math.f90 | 5 + src/plastic_nonlocal.f90 | 797 +++++++++++++++++++-------------------- 2 files changed, 397 insertions(+), 405 deletions(-) diff --git a/src/math.f90 b/src/math.f90 index a6339d9c1..1fff21016 100644 --- a/src/math.f90 +++ b/src/math.f90 @@ -70,6 +70,10 @@ module math !-------------------------------------------------------------------------------------------------- ! Provide deprecated names for compatibility + interface math_cross + module procedure math_crossproduct + end interface math_cross + ! ToDo MD: Our naming scheme was a little bit odd: We use essentially the re-ordering according to Nye ! (convenient because Abaqus and Marc want to have 12 on position 4) ! but weight the shear components according to Mandel (convenient for matrix multiplications) @@ -119,6 +123,7 @@ module math math_identity4th, & math_civita, & math_delta, & + math_cross, & math_crossproduct, & math_tensorproduct33, & math_mul3x3, & diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 85800f7d7..1ef0a22c7 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -240,107 +240,400 @@ contains !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_init -use prec, only: dEq -use math, only: math_Voigt66to3333, & - math_mul3x3, & - math_expand -use IO, only: IO_error + use prec, only: & + dEq0, dNeq0, dEq + use math, only: & + math_expand, math_cross + use IO, only: & + IO_error + use debug, only: & + debug_level, & + debug_constitutive, & + debug_levelBasic + use mesh, only: & + theMesh + use material, only: & + phase_plasticity, & + phase_plasticityInstance, & + phase_Noutput, & + PLASTICITY_NONLOCAL_label, & + PLASTICITY_NONLOCAL_ID, & + plasticState, & + material_phase, & + material_allocatePlasticState + use config + use lattice -use debug, only: debug_level, & - debug_constitutive, & - debug_levelBasic -use mesh, only: theMesh -use material, only: phase_plasticity, & - phase_plasticityInstance, & - phase_Noutput, & - PLASTICITY_NONLOCAL_label, & - PLASTICITY_NONLOCAL_ID, & - plasticState, & - material_phase, & - material_allocatePlasticState -use config -use lattice + implicit none + character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] + integer(pInt), dimension(0), parameter :: emptyIntArray = [integer(pInt)::] + real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] + integer(pInt) :: & + ns, phase, & + maxNinstances, & + maxTotalNslip, p, i, & + f, & ! index of my slip family + instance, & ! index of my instance of this plasticity + l, & + o, & ! index of my output + s, & ! index of my slip system + s1, & ! index of my slip system + s2, & ! index of my slip system + t, & ! index of dislocation type + c ! index of dislocation character - -implicit none - - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(pInt), dimension(0), parameter :: emptyInt = [integer(pInt)::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] -!*** local variables -integer(pInt) :: ns, phase, & - maxNinstances, & - maxTotalNslip, p, i, & - f, & ! index of my slip family - instance, & ! index of my instance of this plasticity - l, & - o, & ! index of my output - s, & ! index of my slip system - s1, & ! index of my slip system - s2, & ! index of my slip system - t, & ! index of dislocation type - c ! index of dislocation character - - - integer(pInt) :: sizeState, sizeDotState,sizeDependentState, sizeDeltaState - integer(kind(undefined_ID)) :: & - outputID !< ID of each post result output - character(len=512) :: & - extmsg = '', & - structure - character(len=65536), dimension(:), allocatable :: outputs - - integer(pInt) :: NofMyPhase + integer(pInt) :: sizeState, sizeDotState,sizeDependentState, sizeDeltaState + integer(kind(undefined_ID)) :: & + outputID + character(len=512) :: & + extmsg = '', & + structure + character(len=65536), dimension(:), allocatable :: outputs + integer(pInt) :: NofMyPhase - write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>' maxNinstances = int(count(phase_plasticity == PLASTICITY_NONLOCAL_ID),pInt) - if (maxNinstances == 0) return ! we don't have to do anything if there's no instance for this constitutive law + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstances - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstances -!*** memory allocation for global variables -allocate(param(maxNinstances)) -allocate(state(maxNinstances)) -allocate(dotState(maxNinstances)) -allocate(deltaState(maxNinstances)) -allocate(results(maxNinstances)) + allocate(param(maxNinstances)) + allocate(state(maxNinstances)) + allocate(dotState(maxNinstances)) + allocate(deltaState(maxNinstances)) + allocate(results(maxNinstances)) -allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) -allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) - plastic_nonlocal_output = '' -allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) -allocate(Nslip(lattice_maxNslipFamily,maxNinstances), source=0_pInt) -allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) -allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) -allocate(totalNslip(maxNinstances), source=0_pInt) + allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) + allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) + plastic_nonlocal_output = '' + allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) + allocate(Nslip(lattice_maxNslipFamily,maxNinstances), source=0_pInt) + allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) + allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) + allocate(totalNslip(maxNinstances), source=0_pInt) do p=1_pInt, size(config_phase) - if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle - instance = phase_plasticityInstance(p) - param(instance)%Nslip = config_phase(p)%getInts('nslip',defaultVal=emptyInt) - Nslip(1:size(param(instance)%Nslip),instance) = param(instance)%Nslip - totalNslip(instance) = sum(Nslip(1:lattice_maxNslipFamily,instance)) - enddo + if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle + associate(prm => param(phase_plasticityInstance(p)), & + dot => dotState(phase_plasticityInstance(p)), & + stt => state(phase_plasticityInstance(p)), & + del => deltaState(phase_plasticityInstance(p)), & + res => results(phase_plasticityInstance(p)), & + config => config_phase(p)) + + prm%aTolRho = config%getFloat('atol_rho', defaultVal=0.0_pReal) + prm%aTolShear = config%getFloat('atol_shear', defaultVal=0.0_pReal) + + structure = config%getString('lattice_structure') + + ! This data is read in already in lattice + prm%mu = lattice_mu(p) + prm%nu = lattice_nu(p) + + + prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray) + prm%totalNslip = sum(prm%Nslip) + slipActive: if (prm%totalNslip > 0_pInt) then + prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + + if(trim(config%getString('lattice_structure')) == 'bcc') then + prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& + defaultVal = emptyRealArray) + prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1_pInt) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1_pInt) + else + prm%nonSchmid_pos = prm%Schmid + prm%nonSchmid_neg = prm%Schmid + endif + + prm%interactionSlipSlip = lattice_interaction_SlipSlip(prm%Nslip, & + config%getFloats('interaction_slipslip'), & + config%getString('lattice_structure')) + + prm%forestProjection_edge = lattice_forestProjection_edge (prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%forestProjection_screw = lattice_forestProjection_screw(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + + prm%slip_direction = lattice_slip_direction (prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%slip_transverse = lattice_slip_transverse(prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%slip_normal = lattice_slip_normal (prm%Nslip,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + + ! collinear systems (only for octahedral slip systems in fcc) + allocate(prm%colinearSystem(prm%totalNslip)) + do s1 = 1_pInt, prm%totalNslip + do s2 = 1_pInt, prm%totalNslip + if (all(dEq0 (math_cross(prm%slip_direction(1:3,s1),prm%slip_direction(1:3,s2)))) .and. & + all(dNeq0(math_cross(prm%slip_normal (1:3,s1),prm%slip_normal (1:3,s2))))) & + prm%colinearSystem(s1) = s2 + enddo + enddo + + prm%rhoSglEdgePos0 = config%getFloats('rhosgledgepos0', requiredSize=size(prm%Nslip)) + prm%rhoSglEdgeNeg0 = config%getFloats('rhosgledgeneg0', requiredSize=size(prm%Nslip)) + prm%rhoSglScrewPos0 = config%getFloats('rhosglscrewpos0', requiredSize=size(prm%Nslip)) + prm%rhoSglScrewNeg0 = config%getFloats('rhosglscrewneg0', requiredSize=size(prm%Nslip)) + prm%rhoDipEdge0 = config%getFloats('rhodipedge0', requiredSize=size(prm%Nslip)) + prm%rhoDipScrew0 = config%getFloats('rhodipscrew0', requiredSize=size(prm%Nslip)) + + prm%lambda0 = config%getFloats('lambda0', requiredSize=size(prm%Nslip)) + prm%burgers = config%getFloats('burgers', requiredSize=size(prm%Nslip)) + + prm%lambda0 = math_expand(prm%lambda0,prm%Nslip) + prm%burgers = math_expand(prm%burgers,prm%Nslip) + + prm%minDipoleHeight_edge = config%getFloats('minimumdipoleheightedge', requiredSize=size(prm%Nslip)) + prm%minDipoleHeight_screw = config%getFloats('minimumdipoleheightscrew', requiredSize=size(prm%Nslip)) + prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge,prm%Nslip) + prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,prm%Nslip) + allocate(prm%minDipoleHeight(prm%totalNslip,2)) + prm%minDipoleHeight(:,1) = prm%minDipoleHeight_edge + prm%minDipoleHeight(:,2) = prm%minDipoleHeight_screw + + prm%peierlsstress_edge = config%getFloats('peierlsstressedge', requiredSize=size(prm%Nslip)) + prm%peierlsstress_screw = config%getFloats('peierlsstressscrew', requiredSize=size(prm%Nslip)) + prm%peierlsstress_edge = math_expand(prm%peierlsstress_edge,prm%Nslip) + prm%peierlsstress_screw = math_expand(prm%peierlsstress_screw,prm%Nslip) + allocate(prm%peierlsstress(prm%totalNslip,2)) + prm%peierlsstress(:,1) = prm%peierlsstress_edge + prm%peierlsstress(:,2) = prm%peierlsstress_screw + + prm%significantRho = config%getFloat('significantrho') + prm%significantN = config%getFloat('significantn', 0.0_pReal) + prm%CFLfactor = config%getFloat('cflfactor',defaultVal=2.0_pReal) + + prm%atomicVolume = config%getFloat('atomicvolume') + prm%Dsd0 = config%getFloat('selfdiffusionprefactor') !,'dsd0') + prm%selfDiffusionEnergy = config%getFloat('selfdiffusionenergy') !,'qsd') + prm%linetensionEffect = config%getFloat('linetension') + prm%edgeJogFactor = config%getFloat('edgejog')!,'edgejogs' + prm%doublekinkwidth = config%getFloat('doublekinkwidth') + prm%solidSolutionEnergy = config%getFloat('solidsolutionenergy') + prm%solidSolutionSize = config%getFloat('solidsolutionsize') + prm%solidSolutionConcentration = config%getFloat('solidsolutionconcentration') + + prm%p = config%getFloat('p') + prm%q = config%getFloat('q') + prm%viscosity = config%getFloat('viscosity') + prm%fattack = config%getFloat('attackfrequency') + + prm%rhoSglScatter = config%getFloat('rhosglscatter') + prm%rhoSglRandom = config%getFloat('rhosglrandom',0.0_pReal) + if (config%keyExists('rhosglrandom')) & + prm%rhoSglRandomBinning = config%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? + + prm%surfaceTransmissivity = config%getFloat('surfacetransmissivity',defaultVal=1.0_pReal) + prm%grainboundaryTransmissivity = config%getFloat('grainboundarytransmissivity',defaultVal=-1.0_pReal) + prm%fEdgeMultiplication = config%getFloat('edgemultiplication') + prm%shortRangeStressCorrection = config%getInt('shortrangestresscorrection',defaultVal=0_pInt ) > 0_pInt ! ToDo: use /flag/ type key + +!-------------------------------------------------------------------------------------------------- +! sanity checks + if (any(prm%burgers < 0.0_pReal)) extmsg = trim(extmsg)//' burgers' + if (any(prm%rhoSglEdgePos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgePos0' + if (any(prm%rhoSglEdgeNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgeNeg0' + if (any(prm%rhoSglScrewPos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewPos0' + if (any(prm%rhoSglScrewNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewNeg0' + if (any(prm%rhoDipEdge0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipEdge0' + if (any(prm%rhoDipScrew0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipScrew0' + if (any(prm%peierlsstress < 0.0_pReal)) extmsg = trim(extmsg)//' peierlsstress' + if (any(prm%minDipoleHeight < 0.0_pReal)) extmsg = trim(extmsg)//' minDipoleHeight' + + if (prm%viscosity <= 0.0_pReal) extmsg = trim(extmsg)//' viscosity' + if (prm%selfDiffusionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' selfDiffusionEnergy' + if (prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' + if (prm%doublekinkwidth <= 0.0_pReal) extmsg = trim(extmsg)//' doublekinkwidth' + if (prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' + + if (prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' + if (prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' + if (prm%atolshear <= 0.0_pReal) extmsg = trim(extmsg)//' atolshear' + if (prm%atolrho <= 0.0_pReal) extmsg = trim(extmsg)//' atolrho' + if (prm%CFLfactor < 0.0_pReal) extmsg = trim(extmsg)//' CFLfactor' + + if (prm%p <= 0.0_pReal .or. prm%p > 1.0_pReal) extmsg = trim(extmsg)//' p' + if (prm%q < 1.0_pReal .or. prm%q > 2.0_pReal) extmsg = trim(extmsg)//' q' + + if (prm%linetensionEffect < 0.0_pReal .or. prm%linetensionEffect > 1.0_pReal) & + extmsg = trim(extmsg)//' edgeJogFactor' + if (prm%edgeJogFactor < 0.0_pReal .or. prm%edgeJogFactor > 1.0_pReal) & + extmsg = trim(extmsg)//' edgeJogFactor' + + if (prm%solidSolutionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionEnergy' + if (prm%solidSolutionSize <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionSize' + if (prm%solidSolutionConcentration <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionConcentration' + + + + if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' + if (prm%surfaceTransmissivity < 0.0_pReal .or. prm%surfaceTransmissivity > 1.0_pReal) & + extmsg = trim(extmsg)//' surfaceTransmissivity' + if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & +extmsg = trim(extmsg)//' fEdgeMultiplication' -!*** allocation of variables whose size depends on the total number of active slip systems -maxTotalNslip = maxval(totalNslip) + ! if (atomicVolume(instance) <= 0.0_pReal) & -allocate(iRhoU(maxTotalNslip,4,maxNinstances), source=0_pInt) -allocate(iRhoB(maxTotalNslip,4,maxNinstances), source=0_pInt) -allocate(iRhoD(maxTotalNslip,2,maxNinstances), source=0_pInt) -allocate(iV(maxTotalNslip,4,maxNinstances), source=0_pInt) -allocate(iD(maxTotalNslip,2,maxNinstances), source=0_pInt) -allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) -allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) +! do f = 1_pInt,lattice_maxNslipFamily +! if (Nslip(f,instance) > 0_pInt) then +! if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') +! endif +! enddo +! if (rhoSglScatter(instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglRandom(instance) < 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') +! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & +! call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') + + endif slipActive + +!-------------------------------------------------------------------------------------------------- +! output pararameters + outputs = config%getStrings('(output)',defaultVal=emptyStringArray) + allocate(prm%outputID(0)) + do i=1_pInt, size(outputs) + outputID = undefined_ID + select case(trim(outputs(i))) + case ('rho_sgl_edge_pos_mobile') + outputID = merge(rho_sgl_edge_pos_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_edge_neg_mobile') + outputID = merge(rho_sgl_edge_neg_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_screw_pos_mobile') + outputID = merge(rho_sgl_screw_pos_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_screw_neg_mobile') + outputID = merge(rho_sgl_screw_neg_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_edge_pos_immobile') + outputID = merge(rho_sgl_edge_pos_immobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_edge_neg_immobile') + outputID = merge(rho_sgl_edge_neg_immobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_screw_pos_immobile') + outputID = merge(rho_sgl_screw_pos_immobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_sgl_screw_neg_immobile') + outputID = merge(rho_sgl_screw_neg_immobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dip_edge') + outputID = merge(rho_dip_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dip_screw') + outputID = merge(rho_dip_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_forest') + outputID = merge(rho_forest_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('shearrate') + outputID = merge(shearrate_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('resolvedstress') + outputID = merge(resolvedstress_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('resolvedstress_external') + outputID = merge(resolvedstress_external_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('resolvedstress_back') + outputID = merge(resolvedstress_back_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('resistance') + outputID = merge(resistance_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_sgl') + outputID = merge(rho_dot_sgl_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_sgl_mobile') + outputID = merge(rho_dot_sgl_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_dip') + outputID = merge(rho_dot_dip_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_gen') + outputID = merge(rho_dot_gen_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_gen_edge') + outputID = merge(rho_dot_gen_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_gen_screw') + outputID = merge(rho_dot_gen_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_sgl2dip_edge') + outputID = merge(rho_dot_sgl2dip_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_sgl2dip_screw') + outputID = merge(rho_dot_sgl2dip_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_ann_ath') + outputID = merge(rho_dot_ann_ath_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_ann_the_edge') + outputID = merge(rho_dot_ann_the_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_ann_the_screw') + outputID = merge(rho_dot_ann_the_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_edgejogs') + outputID = merge(rho_dot_edgejogs_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_flux_mobile') + outputID = merge(rho_dot_flux_mobile_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_flux_edge') + outputID = merge(rho_dot_flux_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('rho_dot_flux_screw') + outputID = merge(rho_dot_flux_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('velocity_edge_pos') + outputID = merge(velocity_edge_pos_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('velocity_edge_neg') + outputID = merge(velocity_edge_neg_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('velocity_screw_pos') + outputID = merge(velocity_screw_pos_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('velocity_screw_neg') + outputID = merge(velocity_screw_neg_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('maximumdipoleheight_edge') + outputID = merge(maximumdipoleheight_edge_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('maximumdipoleheight_screw') + outputID = merge(maximumdipoleheight_screw_ID,undefined_ID,prm%totalNslip>0_pInt) + case ('accumulatedshear','accumulated_shear') + outputID = merge(accumulatedshear_ID,undefined_ID,prm%totalNslip>0_pInt) + end select + + if (outputID /= undefined_ID) then + plastic_nonlocal_output(i,phase_plasticityInstance(p)) = outputs(i) + plastic_nonlocal_sizePostResult(i,phase_plasticityInstance(p)) = prm%totalNslip + prm%outputID = [prm%outputID , outputID] + endif + + enddo + +!-------------------------------------------------------------------------------------------------- +! allocate state arrays + NofMyPhase=count(material_phase==p) + sizeDotState = int(size([ 'rhoSglEdgePosMobile ','rhoSglEdgeNegMobile ', & + 'rhoSglScrewPosMobile ','rhoSglScrewNegMobile ', & + 'rhoSglEdgePosImmobile ','rhoSglEdgeNegImmobile ', & + 'rhoSglScrewPosImmobile','rhoSglScrewNegImmobile', & + 'rhoDipEdge ','rhoDipScrew ', & + 'accumulatedshear ' ]),pInt) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables + + sizeDependentState = int(size([ 'rhoForest ', 'tauThreshold', & + 'tauBack ' ]),pInt) * prm%totalNslip !< microstructural state variables that depend on other state variables + + sizeState = sizeDotState + sizeDependentState & + + int(size([ 'velocityEdgePos ','velocityEdgeNeg ', & + 'velocityScrewPos ','velocityScrewNeg ', & + 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]),pInt) * prm%totalNslip !< other dependent state variables that are not updated by microstructure + + sizeDeltaState = sizeDotState + call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & + prm%totalNslip,0_pInt,0_pInt) + plasticState(p)%nonlocal = .true. + plasticState(p)%offsetDeltaState = 0_pInt ! ToDo: state structure does not follow convention + + Nslip(1:size(prm%Nslip),phase_plasticityInstance(p)) = prm%Nslip ! ToDo: DEPRECATED + totalNslip(phase_plasticityInstance(p)) = sum(Nslip(1:size(prm%Nslip),phase_plasticityInstance(p))) ! ToDo: DEPRECATED + + end associate + + enddo + +! BEGIN DEPRECATED---------------------------------------------------------------------------------- + maxTotalNslip = maxval(totalNslip) + allocate(iRhoU(maxTotalNslip,4,maxNinstances), source=0_pInt) + allocate(iRhoB(maxTotalNslip,4,maxNinstances), source=0_pInt) + allocate(iRhoD(maxTotalNslip,2,maxNinstances), source=0_pInt) + allocate(iV(maxTotalNslip,4,maxNinstances), source=0_pInt) + allocate(iD(maxTotalNslip,2,maxNinstances), source=0_pInt) + allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) + allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) + allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) + allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) +! END DEPRECATED------------------------------------------------------------------------------------ allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) @@ -350,40 +643,8 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), NofMyPhase=count(material_phase==phase) myPhase2: if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then instance = phase_plasticityInstance(phase) - - - !*** determine size of state array - - ns = totalNslip(instance) +ns = param(instance)%totalNslip - sizeDotState = int(size(& - ['rhoSglEdgePosMobile ', & - 'rhoSglEdgeNegMobile ', & - 'rhoSglScrewPosMobile ', & - 'rhoSglScrewNegMobile ', & - 'rhoSglEdgePosImmobile ', & - 'rhoSglEdgeNegImmobile ', & - 'rhoSglScrewPosImmobile', & - 'rhoSglScrewNegImmobile', & - 'rhoDipEdge ', & - 'rhoDipScrew ', & - 'accumulatedshear ' ] & !< list of "basic" microstructural state variables that are independent from other state variables - &),pInt) * ns - sizeDependentState = int(size(& - ['rhoForest ', & - 'tauThreshold ', & - 'tauBack ' ]& !< list of microstructural state variables that depend on other state variables - &),pInt) * ns - sizeState = sizeDotState + sizeDependentState & - + int(size(& - ['velocityEdgePos ', & - 'velocityEdgeNeg ', & - 'velocityScrewPos ', & - 'velocityScrewNeg ', & - 'maxDipoleHeightEdge ', & - 'maxDipoleHeightScrew' ] & !< list of other dependent state variables that are not updated by microstructure - &),pInt) * ns - sizeDeltaState = sizeDotState !*** determine indices to state array @@ -434,17 +695,10 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), iD(s,c,instance) = l enddo enddo - if (iD(ns,2,instance) /= sizeState) & ! check if last index is equal to size of state + if (iD(ns,2,instance) /= plasticState(phase)%sizeState) & ! check if last index is equal to size of state call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') - - plasticState(phase)%nonlocal = .true. - call material_allocatePlasticState(phase,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & - totalNslip(instance),0_pInt,0_pInt) - - plasticState(phase)%offsetDeltaState = 0_pInt - plasticState(phase)%slipRate => & plasticState(phase)%dotState(iGamma(1,instance):iGamma(ns,instance),1:NofMyPhase) plasticState(phase)%accumulatedSlip => & @@ -485,280 +739,13 @@ allocate(colinearSystem(maxTotalNslip,maxNinstances), do p=1_pInt, size(config_phase) if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle instance = phase_plasticityInstance(p) - associate(prm => param(instance), & - dot => dotState(instance), & - stt => state(instance), & - del => deltaState(instance), & - config => config_phase(p)) - NofMyPhase=count(material_phase==p) - prm%mu = lattice_mu(p) - prm%nu = lattice_nu(p) - structure = config_phase(p)%getString('lattice_structure') - -param(instance)%shortRangeStressCorrection = .false. - - - prm%totalNslip = sum(prm%Nslip) - prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,structure(1:3),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - if(structure=='bcc') then - prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& - defaultVal = emptyRealArray) - prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1_pInt) - prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1_pInt) - else - prm%nonSchmid_pos = prm%Schmid - prm%nonSchmid_neg = prm%Schmid - endif - prm%interactionSlipSlip = lattice_interaction_SlipSlip(prm%Nslip, & - config%getFloats('interaction_slipslip'), & - structure(1:3)) - - - - prm%rhoSglEdgePos0 = config_phase(p)%getFloats('rhosgledgepos0') - prm%rhoSglEdgeNeg0 = config_phase(p)%getFloats('rhosgledgeneg0') - prm%rhoSglScrewPos0 = config_phase(p)%getFloats('rhosglscrewpos0') - prm%rhoSglScrewNeg0 = config_phase(p)%getFloats('rhosglscrewneg0') - - prm%rhoDipEdge0 = config_phase(p)%getFloats('rhodipedge0') - prm%rhoDipScrew0 = config_phase(p)%getFloats('rhodipscrew0') - prm%lambda0 = config_phase(p)%getFloats('lambda0') - - if(size(prm%lambda0)/= size(prm%Nslip)) call IO_error(211_pInt,ext_msg='lambda0') - prm%lambda0 = math_expand(prm%lambda0,prm%Nslip) - - - prm%burgers = config_phase(p)%getFloats('burgers', requiredSize=size(prm%Nslip)) - - - prm%burgers = math_expand(prm%burgers,prm%Nslip) - prm%forestProjection_edge = lattice_forestProjection_edge (prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%forestProjection_screw = lattice_forestProjection_screw (prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - - prm%minDipoleHeight_edge = config_phase(p)%getFloats('minimumdipoleheightedge')!,'ddipminedge') - prm%minDipoleHeight_screw = config_phase(p)%getFloats('minimumdipoleheightscrew')!,'ddipminscrew') - - prm%peierlsstress_edge = config_phase(p)%getFloats('peierlsstressedge')!,'peierlsstress_edge') - prm%peierlsstress_screw = config_phase(p)%getFloats('peierlsstressscrew')!,'peierlsstress_screw') - - prm%atomicVolume = config_phase(p)%getFloat('atomicvolume') - prm%Dsd0 = config_phase(p)%getFloat('selfdiffusionprefactor') !,'dsd0') - prm%selfDiffusionEnergy = config_phase(p)%getFloat('selfdiffusionenergy') !,'qsd') - - prm%aTolRho = config_phase(p)%getFloat('atol_rho') - prm%aTolShear = config_phase(p)%getFloat('atol_shear') - - - prm%significantRho = config_phase(p)%getFloat('significantrho')!,'significant_rho','significantdensity','significant_density') - prm%significantN = config_phase(p)%getFloat('significantn', 0.0_pReal)!,'significant_n','significantdislocations','significant_dislcations') - - - - prm%linetensionEffect = config_phase(p)%getFloat('linetension')!,'linetensioneffect','linetension_effect') - prm%edgeJogFactor = config_phase(p)%getFloat('edgejog')!,'edgejogs','edgejogeffect','edgejog_effect') - prm%doublekinkwidth = config_phase(p)%getFloat('doublekinkwidth') - - prm%solidSolutionEnergy = config_phase(p)%getFloat('solidsolutionenergy') - prm%solidSolutionSize = config_phase(p)%getFloat('solidsolutionsize') - prm%solidSolutionConcentration = config_phase(p)%getFloat('solidsolutionconcentration') - - - prm%p = config_phase(p)%getFloat('p') - prm%q = config_phase(p)%getFloat('q') - - - prm%slip_direction = lattice_slip_direction(prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%slip_transverse = lattice_slip_transverse(prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - - prm%slip_normal = lattice_slip_normal(prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge,prm%Nslip) - prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,prm%Nslip) - allocate(prm%minDipoleHeight(prm%totalNslip,2)) - prm%minDipoleHeight(:,1) = prm%minDipoleHeight_edge - prm%minDipoleHeight(:,2) = prm%minDipoleHeight_screw - - prm%peierlsstress_edge = math_expand(prm%peierlsstress_edge,prm%Nslip) - prm%peierlsstress_screw = math_expand(prm%peierlsstress_screw,prm%Nslip) - allocate(prm%peierlsstress(prm%totalNslip,2)) - prm%peierlsstress(:,1) = prm%peierlsstress_edge - prm%peierlsstress(:,2) = prm%peierlsstress_screw - - prm%viscosity = config_phase(p)%getFloat('viscosity')!,'glideviscosity') - prm%fattack = config_phase(p)%getFloat('attackfrequency')!,'fattack') - - prm%rhoSglScatter = config_phase(p)%getFloat('rhosglscatter') - prm%rhoSglRandom = config_phase(p)%getFloat('rhosglrandom',0.0_pReal) - - if (config_phase(p)%keyExists('rhosglrandom')) & - prm%rhoSglRandomBinning = config_phase(p)%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? - - - prm%surfaceTransmissivity = config_phase(p)%getFloat('surfacetransmissivity',defaultVal=1.0_pReal) - prm%grainboundaryTransmissivity = config_phase(p)%getFloat('grainboundarytransmissivity',defaultVal=-1.0_pReal) - prm%CFLfactor = config_phase(p)%getFloat('cflfactor',defaultVal=2.0_pReal) - - prm%fEdgeMultiplication = config_phase(p)%getFloat('edgemultiplication')!,'edgemultiplicationfactor','fedgemultiplication') - prm%shortRangeStressCorrection = config_phase(p)%getInt('shortrangestresscorrection' ) > 0_pInt - - ! sanity checks - if ( any(prm%burgers <= 0.0_pReal)) extmsg = trim(extmsg)//' burgers' - if ( prm%viscosity <= 0.0_pReal) extmsg = trim(extmsg)//' viscosity' - if ( prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' - if ( prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' - if ( prm%selfDiffusionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' selfDiffusionEnergy' - if ( prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' - if (prm%edgeJogFactor < 0.0_pReal .or. prm%edgeJogFactor > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' - if ( prm%solidSolutionEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionEnergy' - if ( prm%solidSolutionSize <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionSize' - if ( prm%solidSolutionConcentration <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionConcentration' - if ( prm%CFLfactor < 0.0_pReal) extmsg = trim(extmsg)//' CFLfactor' - if ( prm%doublekinkwidth <= 0.0_pReal) extmsg = trim(extmsg)//' doublekinkwidth' - if ( prm%atolshear <= 0.0_pReal) extmsg = trim(extmsg)//' atolshear' - if ( prm%atolrho <= 0.0_pReal) extmsg = trim(extmsg)//' atolrho' - if (prm%linetensionEffect < 0.0_pReal .or. prm%linetensionEffect > 1.0_pReal) extmsg = trim(extmsg)//' edgeJogFactor' - if (prm%p <= 0.0_pReal .or. prm%p > 1.0_pReal) extmsg = trim(extmsg)//' p' - if (prm%q < 1.0_pReal .or. prm%q > 2.0_pReal) extmsg = trim(extmsg)//' q' - if (prm%surfaceTransmissivity < 0.0_pReal .or. prm%surfaceTransmissivity > 1.0_pReal) & -extmsg = trim(extmsg)//' surfaceTransmissivity' - if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' - if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & -extmsg = trim(extmsg)//' surfaceTransmissivity' - if ( prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' - - ! if (atomicVolume(instance) <= 0.0_pReal) & - ! call IO_error(211_pInt,ext_msg='atomicVolume ('//PLASTICITY_NONLOCAL_label//')') -! if (minDipoleHeightPerSlipFamily(f,1,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='minimumDipoleHeightEdge ('//PLASTICITY_NONLOCAL_label//')') -! if (minDipoleHeightPerSlipFamily(f,2,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='minimumDipoleHeightScrew ('//PLASTICITY_NONLOCAL_label//')') -! if (peierlsStressPerSlipFamily(f,1,instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='peierlsStressEdge ('//PLASTICITY_NONLOCAL_label//')') -! if (peierlsStressPerSlipFamily(f,2,instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='peierlsStressScrew ('//PLASTICITY_NONLOCAL_label//')') - -! do f = 1_pInt,lattice_maxNslipFamily -! if (Nslip(f,instance) > 0_pInt) then -! if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') -! endif -! enddo -! if (rhoSglEdgePos0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglEdgePos0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglEdgeNeg0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglEdgeNeg0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglScrewPos0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglScrewPos0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglScrewNeg0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglScrewNeg0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoDipEdge0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoDipEdge0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoDipScrew0(f,instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoDipScrew0 ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglScatter(instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglRandom(instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - - - - outputs = config_phase(p)%getStrings('(output)',defaultVal=emptyStringArray) - allocate(prm%outputID(0)) - do i=1_pInt, size(outputs) - outputID = undefined_ID - select case(trim(outputs(i))) - case ('rho_sgl_edge_pos_mobile') - outputID = rho_sgl_edge_pos_mobile_ID - case ('rho_sgl_edge_neg_mobile') - outputID = rho_sgl_edge_neg_mobile_ID - case ('rho_sgl_screw_pos_mobile') - outputID = rho_sgl_screw_pos_mobile_ID - case ('rho_sgl_screw_neg_mobile') - outputID = rho_sgl_screw_neg_mobile_ID - case ('rho_sgl_edge_pos_immobile') - outputID = rho_sgl_edge_pos_immobile_ID - case ('rho_sgl_edge_neg_immobile') - outputID = rho_sgl_edge_neg_immobile_ID - case ('rho_sgl_screw_pos_immobile') - outputID = rho_sgl_screw_pos_immobile_ID - case ('rho_sgl_screw_neg_immobile') - outputID = rho_sgl_screw_neg_immobile_ID - case ('rho_dip_edge') - outputID = rho_dip_edge_ID - case ('rho_dip_screw') - outputID = rho_dip_screw_ID - case ('rho_forest') - outputID = rho_forest_ID - case ('shearrate') - outputID = shearrate_ID - case ('resolvedstress') - outputID = resolvedstress_ID - case ('resolvedstress_external') - outputID = resolvedstress_external_ID - case ('resolvedstress_back') - outputID = resolvedstress_back_ID - case ('resistance') - outputID = resistance_ID - case ('rho_dot_sgl') - outputID = rho_dot_sgl_ID - case ('rho_dot_sgl_mobile') - outputID = rho_dot_sgl_mobile_ID - case ('rho_dot_dip') - outputID = rho_dot_dip_ID - case ('rho_dot_gen') - outputID = rho_dot_gen_ID - case ('rho_dot_gen_edge') - outputID = rho_dot_gen_edge_ID - case ('rho_dot_gen_screw') - outputID = rho_dot_gen_screw_ID - case ('rho_dot_sgl2dip_edge') - outputID = rho_dot_sgl2dip_edge_ID - case ('rho_dot_sgl2dip_screw') - outputID = rho_dot_sgl2dip_screw_ID - case ('rho_dot_ann_ath') - outputID = rho_dot_ann_ath_ID - case ('rho_dot_ann_the_edge') - outputID = rho_dot_ann_the_edge_ID - case ('rho_dot_ann_the_screw') - outputID = rho_dot_ann_the_screw_ID - case ('rho_dot_edgejogs') - outputID = rho_dot_edgejogs_ID - case ('rho_dot_flux_mobile') - outputID = rho_dot_flux_mobile_ID - case ('rho_dot_flux_edge') - outputID = rho_dot_flux_edge_ID - case ('rho_dot_flux_screw') - outputID = rho_dot_flux_screw_ID - case ('velocity_edge_pos') - outputID = velocity_edge_pos_ID - case ('velocity_edge_neg') - outputID = velocity_edge_neg_ID - case ('velocity_screw_pos') - outputID = velocity_screw_pos_ID - case ('velocity_screw_neg') - outputID = velocity_screw_neg_ID - case ('maximumdipoleheight_edge') - outputID = maximumdipoleheight_edge_ID - case ('maximumdipoleheight_screw') - outputID = maximumdipoleheight_screw_ID - case ('accumulatedshear','accumulated_shear') - outputID = accumulatedshear_ID - end select - - if (outputID /= undefined_ID) then - plastic_nonlocal_output(i,instance) = outputs(i) - plastic_nonlocal_sizePostResult(i,instance) = prm%totalNslip - prm%outputID = [prm%outputID , outputID] - endif - - enddo + associate(prm => param(phase_plasticityInstance(p)), & + dot => dotState(phase_plasticityInstance(p)), & + stt => state(phase_plasticityInstance(p)), & + del => deltaState(phase_plasticityInstance(p)), & + res => results(phase_plasticityInstance(p)), & + config => config_phase(p)) + NofMyPhase=count(material_phase==p) plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) @@ -843,12 +830,12 @@ extmsg = trim(extmsg)//' surfaceTransmissivity' del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear - allocate(results(instance)%rhoDotFlux(prm%totalNslip,8,NofMyPhase)) - allocate(results(instance)%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase)) - allocate(results(instance)%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase)) - allocate(results(instance)%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase)) - allocate(results(instance)%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase)) - allocate(results(instance)%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase)) + allocate(res%rhoDotFlux(prm%totalNslip,8,NofMyPhase)) + allocate(res%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase)) + allocate(res%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase)) + allocate(res%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase)) + allocate(res%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase)) + allocate(res%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase)) end associate From 21d0ef2fb5888876377ad7ad58331e03068d0c9a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 05:55:03 +0100 Subject: [PATCH 65/97] use microstructure/dependent state introduced only partly, otherwise the uncommon calling sequence in nonlocal leads to a change in behavior --- src/plastic_nonlocal.f90 | 98 ++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 58 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 1ef0a22c7..653ed0027 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -23,9 +23,7 @@ module plastic_nonlocal integer(pInt), dimension(:,:), allocatable, private :: & iGamma, & !< state indices for accumulated shear - iRhoF, & !< state indices for forest density - iTauF, & !< state indices for critical resolved shear stress - iTauB !< state indices for backstress + iRhoF !< state indices for forest density integer(pInt), dimension(:,:,:), allocatable, private :: & iRhoU, & !< state indices for unblocked density iRhoB, & !< state indices for blocked density @@ -162,6 +160,13 @@ module plastic_nonlocal outputID !< ID of each post result output end type tParameters + + type, private :: tNonlocalMicrostructure + real(pReal), allocatable, dimension(:,:) :: & + tau_Threshold, & + tau_Back + + end type tNonlocalMicrostructure type, private :: tOutput !< container type for storage of output results real(pReal), dimension(:,:), allocatable, private :: & @@ -216,7 +221,7 @@ module plastic_nonlocal type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance) type(tOutput), dimension(:), allocatable, private :: results - + type(tNonlocalMicrostructure), dimension(:), allocatable, private :: microstructure integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & plastic_nonlocal_outputID !< ID of each post result output @@ -303,6 +308,7 @@ subroutine plastic_nonlocal_init allocate(state(maxNinstances)) allocate(dotState(maxNinstances)) allocate(deltaState(maxNinstances)) + allocate(microstructure(maxNinstances)) allocate(results(maxNinstances)) allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0_pInt) @@ -601,8 +607,7 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' 'rhoDipEdge ','rhoDipScrew ', & 'accumulatedshear ' ]),pInt) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables - sizeDependentState = int(size([ 'rhoForest ', 'tauThreshold', & - 'tauBack ' ]),pInt) * prm%totalNslip !< microstructural state variables that depend on other state variables + sizeDependentState = int(size([ 'rhoForest ']),pInt) * prm%totalNslip !< microstructural state variables that depend on other state variables sizeState = sizeDotState + sizeDependentState & + int(size([ 'velocityEdgePos ','velocityEdgeNeg ', & @@ -631,8 +636,6 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' allocate(iD(maxTotalNslip,2,maxNinstances), source=0_pInt) allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) - allocate(iTauF(maxTotalNslip,maxNinstances), source=0_pInt) - allocate(iTauB(maxTotalNslip,maxNinstances), source=0_pInt) ! END DEPRECATED------------------------------------------------------------------------------------ allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & @@ -675,14 +678,6 @@ ns = param(instance)%totalNslip l = l + 1_pInt iRhoF(s,instance) = l enddo - do s = 1_pInt,ns - l = l + 1_pInt - iTauF(s,instance) = l - enddo - do s = 1_pInt,ns - l = l + 1_pInt - iTauB(s,instance) = l - enddo do t = 1_pInt,4_pInt do s = 1_pInt,ns l = l + 1_pInt @@ -744,6 +739,7 @@ ns = param(instance)%totalNslip stt => state(phase_plasticityInstance(p)), & del => deltaState(phase_plasticityInstance(p)), & res => results(phase_plasticityInstance(p)), & + dst => microstructure(phase_plasticityInstance(p)), & config => config_phase(p)) NofMyPhase=count(material_phase==p) @@ -830,6 +826,10 @@ ns = param(instance)%totalNslip del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear + + allocate(dst%tau_Threshold(prm%totalNslip,NofMyPhase),source=0.0_pReal) + allocate(dst%tau_Back(prm%totalNslip,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotFlux(prm%totalNslip,8,NofMyPhase)) allocate(res%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase)) allocate(res%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase)) @@ -1006,9 +1006,7 @@ real(pReal), dimension(2) :: rhoExcessGradient, & real(pReal), dimension(3) :: rhoExcessDifferences, & normal_latticeConf real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & - rhoForest, & ! forest dislocation density - tauBack, & ! back stress from pileup on same slip system - tauThreshold ! threshold shear stress + rhoForest ! forest dislocation density real(pReal), dimension(3,3) :: invFe, & ! inverse of elastic deformation gradient invFp, & ! inverse of plastic deformation gradient connections, & @@ -1033,7 +1031,7 @@ real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phase(1_pI ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) -associate(prm => param(instance)) +associate(prm => param(instance),dst => microstructure(instance)) ns = prm%totalNslip @@ -1081,14 +1079,14 @@ if (lattice_structure(ph) == LATTICE_bcc_ID .or. lattice_structure(ph) == LATTI enddo endif forall (s = 1_pInt:ns) & - tauThreshold(s) = prm%mu * prm%burgers(s) & + dst%tau_threshold(s,of) = prm%mu * prm%burgers(s) & * sqrt(dot_product((sum(abs(rhoSgl),2) + sum(abs(rhoDip),2)), myInteractionMatrix(s,1:ns))) !*** calculate the dislocation stress of the neighboring excess dislocation densities !*** zero for material points of local plasticity -tauBack = 0.0_pReal + dst%tau_back(:,of) = 0.0_pReal !################################################################################################# !################################################################################################# @@ -1195,7 +1193,7 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then !* gives the local stress correction when multiplied with a factor - tauBack(s) = - prm%mu * prm%burgers(s) / (2.0_pReal * pi) & + dst%tau_back(s,of) = - prm%mu * prm%burgers(s) / (2.0_pReal * pi) & * (rhoExcessGradient_over_rho(1) / (1.0_pReal - prm%nu) & + rhoExcessGradient_over_rho(2)) @@ -1205,8 +1203,6 @@ endif !*** set dependent states plasticState(ph)%state(iRhoF(1:ns,instance),of) = rhoForest -plasticState(ph)%state(iTauF(1:ns,instance),of) = tauThreshold -plasticState(ph)%state(iTauB(1:ns,instance),of) = tauBack #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt & @@ -1214,8 +1210,8 @@ plasticState(ph)%state(iTauB(1:ns,instance),of) = tauBack .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0_pInt)) then write(6,'(/,a,i8,1x,i2,1x,i1,/)') '<< CONST >> nonlocal_microstructure at el ip ',el,ip write(6,'(a,/,12x,12(e10.3,1x))') '<< CONST >> rhoForest', rhoForest - write(6,'(a,/,12x,12(f10.5,1x))') '<< CONST >> tauThreshold / MPa', tauThreshold*1e-6 - write(6,'(a,/,12x,12(f10.5,1x),/)') '<< CONST >> tauBack / MPa', tauBack*1e-6 + write(6,'(a,/,12x,12(f10.5,1x))') '<< CONST >> tauThreshold / MPa', dst%tau_threshold(:,of)*1e-6 + write(6,'(a,/,12x,12(f10.5,1x),/)') '<< CONST >> tauBack / MPa', dst%tau_back(:,of)*1e-6 endif #endif end associate @@ -1424,9 +1420,8 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt dv_dtauNS !< velocity derivative with respect to the shear stress real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & tau, & !< resolved shear stress including backstress terms - gdotTotal, & !< shear rate - tauBack, & !< back stress from dislocation gradients on same slip system - tauThreshold !< threshold shear stress + gdotTotal !< shear rate + !*** shortcut for mapping ph = phaseAt(1_pInt,ip,el) of = phasememberAt(1_pInt,ip,el) @@ -1434,7 +1429,7 @@ of = phasememberAt(1_pInt,ip,el) instance = phase_plasticityInstance(ph) -associate(prm => param(instance)) +associate(prm => param(instance),dst=>microstructure(instance)) ns = prm%totalNslip !*** shortcut to state variables @@ -1448,9 +1443,6 @@ where (abs(rhoSgl) * volume ** 0.667_pReal < prm%significantN & .or. abs(rhoSgl) < prm%significantRho) & rhoSgl = 0.0_pReal -tauBack = plasticState(ph)%state(iTauB(1:ns,instance),of) -tauThreshold = plasticState(ph)%state(iTauF(1:ns,instance),of) - !*** get resolved shear stress !*** for screws possible non-schmid contributions are also taken into account @@ -1468,15 +1460,15 @@ do s = 1_pInt,ns endif enddo forall (t = 1_pInt:4_pInt) & - tauNS(1:ns,t) = tauNS(1:ns,t) + tauBack ! add backstress -tau = tau + tauBack ! add backstress + tauNS(1:ns,t) = tauNS(1:ns,t) + dst%tau_back(:,of) +tau = tau + dst%tau_back(:,of) !*** get dislocation velocity and its tangent and store the velocity in the state array ! edges call plastic_nonlocal_kinetics(v(1:ns,1), dv_dtau(1:ns,1), dv_dtauNS(1:ns,1), & - tau(1:ns), tauNS(1:ns,1), tauThreshold(1:ns), & + tau(1:ns), tauNS(1:ns,1), dst%tau_Threshold(1:ns,of), & 1_pInt, Temperature, ip, el) v(1:ns,2) = v(1:ns,1) dv_dtau(1:ns,2) = dv_dtau(1:ns,1) @@ -1492,7 +1484,7 @@ if (size(prm%nonSchmidCoeff) == 0_pInt) then else ! take non-Schmid contributions into account do t = 3_pInt,4_pInt call plastic_nonlocal_kinetics(v(1:ns,t), dv_dtau(1:ns,t), dv_dtauNS(1:ns,t), & - tau(1:ns), tauNS(1:ns,t), tauThreshold(1:ns), & + tau(1:ns), tauNS(1:ns,t), dst%tau_Threshold(1:ns,of), & 2_pInt , Temperature, ip, el) enddo endif @@ -1577,8 +1569,7 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,e real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,el))),4) :: & v ! dislocation glide velocity real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,el)))) :: & - tau, & ! current resolved shear stress - tauBack ! current back stress from pileups on same slip system + tau ! current resolved shear stress real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,el))),2) :: & rhoDip, & ! current dipole dislocation densities (screw and edge dipoles) dLower, & ! minimum stable dipole distance for edges and screws @@ -1596,7 +1587,7 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1,ip,e ph = phaseAt(1,ip,el) of = phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) - associate(prm => param(instance)) + associate(prm => param(instance),dst => microstructure(instance)) ns = totalNslip(instance) @@ -1611,7 +1602,6 @@ forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) rhoDip(s,c) = max(plasticState(ph)%state(iRhoD(s,c,instance),of), 0.0_pReal) ! ensure positive dipole densities dUpperOld(s,c) = plasticState(ph)%state(iD(s,c,instance),of) endforall - tauBack = plasticState(ph)%state(iTauB(1:ns,instance),of) where (abs(rhoSgl) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & .or. abs(rhoSgl) < prm%significantRho) & @@ -1646,7 +1636,7 @@ enddo !*** calculate limits for stable dipole height do s = 1_pInt,prm%totalNslip - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) +dst%tau_back(s,of) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo dLower = prm%minDipoleHeight(1:ns,1:2) @@ -1810,9 +1800,7 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt gdot !< shear rates real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & rhoForest, & !< forest dislocation density - tauThreshold, & !< threshold shear stress tau, & !< current resolved shear stress - tauBack, & !< current back stress from pileups on same slip system vClimb !< climb velocity of edge dipoles real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),2) :: & @@ -1854,7 +1842,7 @@ logical considerEnteringFlux, & ph = material_phase(1_pInt,ip,el) instance = phase_plasticityInstance(ph) -associate(prm => param(instance)) +associate(prm => param(instance),dst => microstructure(instance)) ns = totalNslip(instance) tau = 0.0_pReal @@ -1873,8 +1861,6 @@ forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) rhoDip(s,c) = max(plasticState(p)%state(iRhoD(s,c,instance),o), 0.0_pReal) ! ensure positive dipole densities endforall rhoForest = plasticState(p)%state(iRhoF(1:ns,instance),o) -tauThreshold = plasticState(p)%state(iTauF(1:ns,instance),o) -tauBack = plasticState(p)%state(iTauB(1:ns,instance),o) rhoSglOriginal = rhoSgl rhoDipOriginal = rhoDip @@ -1915,7 +1901,7 @@ forall (t = 1_pInt:4_pInt) & !*** calculate limits for stable dipole height do s = 1_pInt,ns ! loop over slip systems - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + dst%tau_back(s,o) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo @@ -2458,9 +2444,7 @@ function plastic_nonlocal_postResults(Mp,ip,el) result(postResults) v !< velocities real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))) :: & rhoForest, & !< forest dislocation density - tauThreshold, & !< threshold shear stress - tau, & !< current resolved shear stress - tauBack !< back stress from pileups on same slip system + tau !< current resolved shear stress real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el))),2) :: & rhoDip, & !< current dipole dislocation densities (screw and edge dipoles) rhoDotDip, & !< evolution rate of dipole dislocation densities (screw and edge dipoles) @@ -2474,7 +2458,7 @@ ns = totalNslip(instance) cs = 0_pInt -associate(prm => param(instance)) +associate(prm => param(instance),dst => microstructure(instance)) !* short hand notations for state variables forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) @@ -2489,8 +2473,6 @@ forall (s = 1_pInt:ns, c = 1_pInt:2_pInt) rhoDotDip(s,c) = plasticState(ph)%dotState(iRhoD(s,c,instance),of) endforall rhoForest = plasticState(ph)%State(iRhoF(1:ns,instance),of) -tauThreshold = plasticState(ph)%State(iTauF(1:ns,instance),of) -tauBack = plasticState(ph)%State(iTauB(1:ns,instance),of) !* Calculate shear rate @@ -2501,7 +2483,7 @@ forall (t = 1_pInt:4_pInt) & !* calculate limits for stable dipole height do s = 1_pInt,ns - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + tauBack(s) + tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + dst%tau_back(s,of) if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal enddo @@ -2576,7 +2558,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) cs = cs + ns case (resolvedstress_back_ID) - postResults(cs+1_pInt:cs+ns) = tauBack + postResults(cs+1_pInt:cs+ns) = dst%tau_back(:,of) cs = cs + ns case (resolvedstress_external_ID) @@ -2586,7 +2568,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) cs = cs + ns case (resistance_ID) - postResults(cs+1_pInt:cs+ns) = tauThreshold + postResults(cs+1_pInt:cs+ns) = dst%tau_Threshold(:,of) cs = cs + ns case (rho_dot_sgl_ID) From 907f7ca56045a2416f65f62c03fb26f66263d353 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 12:36:27 +0100 Subject: [PATCH 66/97] transition to new class --- python/damask/orientation.py | 441 ++++++++++++++++++++++++++++++++--- 1 file changed, 411 insertions(+), 30 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 442a98f6e..03c69291f 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -242,8 +242,11 @@ class Rotation: If a quaternion is given, it needs to comply with the convection. Use .fromQuaternion to check the input. """ - self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4]) - self.quaternion.homomorph() # ToDo: Needed? + if isinstance(quaternion,Quaternion2): + self.quaternion = quaternion.copy() + else: + self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4]) + self.quaternion.homomorph() # ToDo: Needed? def __repr__(self): """Value in selected representation""" @@ -253,6 +256,7 @@ class Rotation: 'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ), ]) + ################################################################################################ # convert to different orientation representations (numpy arrays) @@ -261,7 +265,11 @@ class Rotation: def asEulers(self, degrees = False): - return np.degrees(qu2eu(self.quaternion.asArray())) if degrees else qu2eu(self.quaternion.asArray()) + + eu = qu2eu(self.quaternion.asArray()) + if degrees: eu = np.degrees(eu) + + return eu def asAngleAxis(self, degrees = False): @@ -370,7 +378,7 @@ class Rotation: """ Multiplication - Rotation: Details needed (active/passive), more rotation of (3,3,3,3) should be considered + Rotation: Details needed (active/passive), rotation of (3,3,3,3)-matrix should be considered """ if isinstance(other, Rotation): # rotate a rotation return self.__class__((self.quaternion * other.quaternion).asArray()) @@ -416,7 +424,12 @@ class Rotation: def inversed(self): """In-place inverse rotation/backward rotation""" - return self.__class__(self.quaternion.conjugated().asArray()) + return self.__class__(self.quaternion.conjugated()) + + + def misorientation(self,other): + """Misorientation""" + return self.__class__(other.quaternion*self.quaternion.conjugated()) # ****************************************************************************************** @@ -810,11 +823,15 @@ class Quaternion: # ****************************************************************************************** class Symmetry: + """ + Symmetry operations for lattice systems + + https://en.wikipedia.org/wiki/Crystal_system + """ lattices = [None,'orthorhombic','tetragonal','hexagonal','cubic',] def __init__(self, symmetry = None): - """Lattice with given symmetry, defaults to None""" if isinstance(symmetry, str) and symmetry.lower() in Symmetry.lattices: self.lattice = symmetry.lower() else: @@ -927,25 +944,29 @@ class Symmetry: def inFZ(self,R): """Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" - if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentally passed quaternion # fundamental zone in Rodrigues space is point symmetric around origin - R = abs(R) + + if R.shape[0]==4: # transition old (length not stored separately) to new + Rabs = abs(R[0:3]*R[3]) + else: + Rabs = abs(R) + if self.lattice == 'cubic': - return math.sqrt(2.0)-1.0 >= R[0] \ - and math.sqrt(2.0)-1.0 >= R[1] \ - and math.sqrt(2.0)-1.0 >= R[2] \ - and 1.0 >= R[0] + R[1] + R[2] + return math.sqrt(2.0)-1.0 >= Rabs[0] \ + and math.sqrt(2.0)-1.0 >= Rabs[1] \ + and math.sqrt(2.0)-1.0 >= Rabs[2] \ + and 1.0 >= Rabs[0] + Rabs[1] + Rabs[2] elif self.lattice == 'hexagonal': - return 1.0 >= R[0] and 1.0 >= R[1] and 1.0 >= R[2] \ - and 2.0 >= math.sqrt(3)*R[0] + R[1] \ - and 2.0 >= math.sqrt(3)*R[1] + R[0] \ - and 2.0 >= math.sqrt(3) + R[2] + return 1.0 >= Rabs[0] and 1.0 >= Rabs[1] and 1.0 >= Rabs[2] \ + and 2.0 >= math.sqrt(3)*Rabs[0] + Rabs[1] \ + and 2.0 >= math.sqrt(3)*Rabs[1] + Rabs[0] \ + and 2.0 >= math.sqrt(3) + Rabs[2] elif self.lattice == 'tetragonal': - return 1.0 >= R[0] and 1.0 >= R[1] \ - and math.sqrt(2.0) >= R[0] + R[1] \ - and math.sqrt(2.0) >= R[2] + 1.0 + return 1.0 >= Rabs[0] and 1.0 >= Rabs[1] \ + and math.sqrt(2.0) >= Rabs[0] + Rabs[1] \ + and math.sqrt(2.0) >= Rabs[2] + 1.0 elif self.lattice == 'orthorhombic': - return 1.0 >= R[0] and 1.0 >= R[1] and 1.0 >= R[2] + return 1.0 >= Rabs[0] and 1.0 >= Rabs[1] and 1.0 >= Rabs[2] else: return True @@ -1067,6 +1088,373 @@ class Symmetry: # suggested reading: http://web.mit.edu/2.998/www/QuaternionReport1.pdf +# ****************************************************************************************** +class Lattice: + """ + Lattice system + + Currently, this contains only a mapping from Bravais lattice to symmetry + and orientation relationships. It could include twin and slip systems. + https://en.wikipedia.org/wiki/Bravais_lattice + """ + + lattices = { + 'triclinic':{'symmetry':None}, + 'bct':{'symmetry':'tetragonal'}, + 'hex':{'symmetry':'hexagonal'}, + 'fcc':{'symmetry':'cubic','c/a':1.0}, + 'bcc':{'symmetry':'cubic','c/a':1.0}, + } + + + def __init__(self, lattice): + self.lattice = lattice + self.symmetry = Symmetry(self.lattices[lattice]['symmetry']) + + + def __repr__(self): + """Report basic lattice information""" + return 'Bravais lattice {} ({} symmetry)'.format(self.lattice,self.symmetry) + + + # Kurdjomov--Sachs orientation relationship for fcc <-> bcc transformation + # from S. Morito et al./Journal of Alloys and Compounds 5775 (2013) S587-S592 + # also see K. Kitahara et al./Acta Materialia 54 (2006) 1279-1288 + KS = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 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],[ 0, 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],[ 0, 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],[ 0, 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],[ 0, 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]]],dtype='float'), + 'directions': np.array([ + [[ -1, 0, 1],[ -1, -1, 1]], + [[ -1, 0, 1],[ -1, 1, -1]], + [[ 0, 1, -1],[ -1, -1, 1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ 1, -1, 0],[ -1, -1, 1]], + [[ 1, -1, 0],[ -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]], + [[ 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, 1, 0],[ -1, -1, 1]], + [[ 1, 1, 0],[ -1, 1, -1]], + [[ -1, 1, 0],[ -1, -1, 1]], + [[ -1, 1, 0],[ -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]]],dtype='float')} + + # Greninger--Troiano orientation relationship for fcc <-> bcc transformation + # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 + GT = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 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],[ 0, -1, 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],[ 0, -1, 1]], + [[ 1, -1, 1],[ 1, 0, 1]]],dtype='float'), + 'directions': np.array([ + [[ -5,-12, 17],[-17, -7, 17]], + [[ 17, -5,-12],[ 17,-17, -7]], + [[-12, 17, -5],[ -7, 17,-17]], + [[ 5, 12, 17],[ 17, 7, 17]], + [[-17, 5,-12],[-17, 17, -7]], + [[ 12,-17, -5],[ 7,-17,-17]], + [[ -5, 12,-17],[-17, 7,-17]], + [[ 17, 5, 12],[ 17, 17, 7]], + [[-12,-17, 5],[ -7,-17, 17]], + [[ 5,-12,-17],[ 17, -7,-17]], + [[-17, -5, 12],[-17,-17, 7]], + [[ 12, 17, 5],[ 7, 17, 17]], + [[ -5, 17,-12],[-17, 17, -7]], + [[-12, -5, 17],[ -7,-17, 17]], + [[ 17,-12, -5],[ 17, -7,-17]], + [[ 5,-17,-12],[ 17,-17, -7]], + [[ 12, 5, 17],[ 7, 17, 17]], + [[-17, 12, -5],[-17, 7,-17]], + [[ -5,-17, 12],[-17,-17, 7]], + [[-12, 5,-17],[ -7, 17,-17]], + [[ 17, 12, 5],[ 17, 7, 17]], + [[ 5, 17, 12],[ 17, 17, 7]], + [[ 12, -5,-17],[ 7,-17,-17]], + [[-17,-12, 5],[-17, 7, 17]]],dtype='float')} + + # Greninger--Troiano' orientation relationship for fcc <-> bcc transformation + # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 + GTdash = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 7, 17, 17],[ 12, 5, 17]], + [[ 17, 7, 17],[ 17, 12, 5]], + [[ 17, 17, 7],[ 5, 17, 12]], + [[ -7,-17, 17],[-12, -5, 17]], + [[-17, -7, 17],[-17,-12, 5]], + [[-17,-17, 7],[ -5,-17, 12]], + [[ 7,-17,-17],[ 12, -5,-17]], + [[ 17, -7,-17],[ 17,-12, -5]], + [[ 17,-17, -7],[ 5,-17,-12]], + [[ -7, 17,-17],[-12, 5,-17]], + [[-17, 7,-17],[-17, 12, -5]], + [[-17, 17, -7],[ -5, 17,-12]], + [[ 7, 17, 17],[ 12, 17, 5]], + [[ 17, 7, 17],[ 5, 12, 17]], + [[ 17, 17, 7],[ 17, 5, 12]], + [[ -7,-17, 17],[-12,-17, 5]], + [[-17, -7, 17],[ -5,-12, 17]], + [[-17,-17, 7],[-17, -5, 12]], + [[ 7,-17,-17],[ 12,-17, -5]], + [[ 17, -7,-17],[ 5, -12,-17]], + [[ 17,-17, 7],[ 17, -5,-12]], + [[ -7, 17,-17],[-12, 17, -5]], + [[-17, 7,-17],[ -5, 12,-17]], + [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), + 'directions': np.array([ + [[ 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]], + [[ 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]]],dtype='float')} + + # Nishiyama--Wassermann orientation relationship for fcc <-> bcc transformation + # from H. Kitahara et al./Materials Characterization 54 (2005) 378-386 + NW = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 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],[ 0, 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],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]]],dtype='float'), + 'directions': np.array([ + [[ 2, -1, -1],[ 0, -1, 1]], + [[ -1, 2, -1],[ 0, -1, 1]], + [[ -1, -1, 2],[ 0, -1, 1]], + [[ -2, -1, -1],[ 0, -1, 1]], + [[ 1, 2, -1],[ 0, -1, 1]], + [[ 1, -1, 2],[ 0, -1, 1]], + [[ 2, 1, -1],[ 0, -1, 1]], + [[ -1, -2, -1],[ 0, -1, 1]], + [[ -1, 1, 2],[ 0, -1, 1]], + [[ -1, 2, 1],[ 0, -1, 1]], + [[ -1, 2, 1],[ 0, -1, 1]], + [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} + + # Pitsch orientation relationship for fcc <-> bcc transformation + # from Y. He et al./Acta Materialia 53 (2005) 1179-1190 + Pitsch = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 0, 1, 0],[ -1, 0, 1]], + [[ 0, 0, 1],[ 1, -1, 0]], + [[ 1, 0, 0],[ 0, 1, -1]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 1, 0, 0],[ 0, -1, 1]], + [[ 0, 1, 0],[ 1, 0, -1]], + [[ 0, 0, 1],[ -1, 1, 0]]],dtype='float'), + 'directions': np.array([ + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ -1, 0, 1],[ -1, -1, 1]], + [[ 1, -1, 0],[ 1, -1, -1]], + [[ 1, 0, -1],[ 1, -1, -1]], + [[ -1, 1, 0],[ -1, 1, -1]], + [[ 0, -1, 1],[ -1, -1, 1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} + + # Bain orientation relationship for fcc <-> bcc transformation + # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 + Bain = {'mapping':{'fcc':0,'bcc':1}, + 'planes': np.array([ + [[ 1, 0, 0],[ 1, 0, 0]], + [[ 0, 1, 0],[ 0, 1, 0]], + [[ 0, 0, 1],[ 0, 0, 1]]],dtype='float'), + 'directions': np.array([ + [[ 0, 1, 0],[ 0, 1, 1]], + [[ 0, 0, 1],[ 1, 0, 1]], + [[ 1, 0, 0],[ 1, 1, 0]]],dtype='float')} + + def relationOperations(self,model): + + models={'KS':self.KS, 'GT':self.GT, "GT'":self.GTdash, + 'NW':self.NW, 'Pitsch': self.Pitsch, 'Bain':self.Bain} + + relationship = models[model] + + r = {'lattice':Lattice((set(relationship['mapping'])-{self.lattice}).pop()), + 'rotations':[] } + + myPlane_id = relationship['mapping'][self.lattice] + otherPlane_id = (myPlane_id+1)%2 + myDir_id = myPlane_id +2 + otherDir_id = otherPlane_id +2 + for miller in np.hstack((relationship['planes'],relationship['directions'])): + myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) + myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) + otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) + otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) + + myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]).T + otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]).T + r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix,myMatrix.T))) + return r + + + +class Orientation2: + """ + Crystallographic orientation + + A crystallographic orientation contains a rotation and a lattice + """ + + __slots__ = ['rotation','lattice'] + + def __repr__(self): + """Report lattice type and orientation""" + return self.lattice.__repr__()+'\n'+self.rotation.__repr__() + + def __init__(self, rotation, lattice): + + if isinstance(lattice, Lattice): + self.lattice = lattice + else: + self.lattice = Lattice(lattice) # assume string + + if isinstance(rotation, Rotation): + self.rotation = rotation + else: + self.rotation = Rotation(rotation) # assume quaternion + + 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.lattice.symmetry != other.lattice.symmetry: + # raise NotImplementedError('disorientation between different symmetry classes not supported yet.') + + mis = other.rotation*self.rotation.inversed() + mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations()[:1] # take all or only first sym operation + otherSymEqs = other.equivalentOrientations() + + for i,sA in enumerate(mySymEqs): + for j,sB in enumerate(otherSymEqs): + theQ = sB.rotation*mis*sA.rotation.inversed() + for k in range(2): + theQ.inversed() + breaker = self.lattice.symmetry.inFZ(theQ.asRodriques()) #and (not SST or other.symmetry.inDisorientationSST(theQ)) + if breaker: break + if breaker: break + if breaker: break + +# disorientation, own sym, other sym, self-->other: True, self<--other: False + return theQ + + def inFZ(self): + return self.lattice.symmetry.inFZ(self.rotation.asRodrigues()) + + def equivalentOrientations(self): + """List of orientations which are symmetrically equivalent""" + q = self.lattice.symmetry.symmetryQuats() + q2 = [Quaternion2(q=a.asList()[0],p=a.asList()[1:4]) for a in q] # convert Quaternion to Quaternion2 + x = [self.__class__(q3*self.rotation.quaternion,self.lattice) for q3 in q2] + return x + + def relatedOrientations(self,model): + """List of orientations related by the given orientation relationship""" + r = self.lattice.relationOperations(model) + return [self.__class__(self.rotation*o,r['lattice']) for o in r['rotations']] + + def reduced(self): + """Transform orientation to fall into fundamental zone according to symmetry""" + for me in self.equivalentOrientations(): + if self.lattice.symmetry.inFZ(me.rotation.asRodrigues()): break + + return self.__class__(me.rotation,self.lattice) # ****************************************************************************************** class Orientation: @@ -1173,7 +1561,8 @@ class Orientation: (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.') + if self.symmetry != other.symmetry: + raise NotImplementedError('disorientation between different symmetry classes not supported yet.') misQ = other.quaternion*self.quaternion.conjugated() mySymQs = self.symmetry.symmetryQuats() if SST else self.symmetry.symmetryQuats()[:1] # take all or only first sym operation @@ -1266,14 +1655,6 @@ class Orientation: if relationModel not in ['KS','GT','GTdash','NW','Pitsch','Bain']: return None if int(direction) == 0: return None - # KS from S. Morito et al./Journal of Alloys and Compounds 5775 (2013) S587-S592 - # for KS rotation matrices also check K. Kitahara et al./Acta Materialia 54 (2006) 1279-1288 - # GT from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 - # GT' from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 - # NW from H. Kitahara et al./Materials Characterization 54 (2005) 378-386 - # Pitsch from Y. He et al./Acta Materialia 53 (2005) 1179-1190 - # Bain from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 - variant = int(abs(direction))-1 (me,other) = (0,1) if direction > 0 else (1,0) @@ -1789,7 +2170,7 @@ def om2qu(om): if om[2,1] < om[1,2]: qu[1] *= -1.0 if om[0,2] < om[2,0]: qu[2] *= -1.0 if om[1,0] < om[0,1]: qu[3] *= -1.0 - if any(om2ax(om)[0:3]*qu[1:4] < 0.0): print(om2ax(om),qu) # something is wrong here + if any(om2ax(om)[0:3]*qu[1:4] < 0.0): print('sign problem',om2ax(om),qu) # something is wrong here return qu From d686384d17121ce975f068e9934f20a70385f372 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 19:18:06 +0100 Subject: [PATCH 67/97] let lattice.f90 do the job --- src/plastic_nonlocal.f90 | 161 ++++++++++++--------------------------- 1 file changed, 47 insertions(+), 114 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 653ed0027..3777f2246 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -36,9 +36,8 @@ module plastic_nonlocal integer(pInt), dimension(:,:), allocatable, private :: & Nslip, & !< number of active slip systems - slipFamily, & !< lookup table relating active slip system to slip family for each instance - slipSystemLattice, & !< lookup table relating active slip system index to lattice slip system index for each instance - colinearSystem !< colinear system to the active slip system (only valid for fcc!) + slipFamily !< lookup table relating active slip system to slip family for each instance + real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & @@ -121,24 +120,23 @@ module plastic_nonlocal minDipoleHeight_screw, & !< minimum stable screw dipole height peierlsstress_edge, & peierlsstress_screw, & - rhoSglEdgePos0, & !< initial edge_pos dislocation density per slip system for each family and instance - rhoSglEdgeNeg0, & !< initial edge_neg dislocation density per slip system for each family and instance - rhoSglScrewPos0, & !< initial screw_pos dislocation density per slip system for each family and instance - rhoSglScrewNeg0, & !< initial screw_neg dislocation density per slip system for each family and instance - rhoDipEdge0, & !< initial edge dipole dislocation density per slip system for each family and instance - rhoDipScrew0,& !< initial screw dipole dislocation density per slip system for each family and instance - lambda0, & !< mean free path prefactor for each slip system and instance - burgers !< absolute length of burgers vector [m] for each slip system and instance - + rhoSglEdgePos0, & !< initial edge_pos dislocation density + rhoSglEdgeNeg0, & !< initial edge_neg dislocation density + rhoSglScrewPos0, & !< initial screw_pos dislocation density + rhoSglScrewNeg0, & !< initial screw_neg dislocation density + rhoDipEdge0, & !< initial edge dipole dislocation density + rhoDipScrew0,& !< initial screw dipole dislocation density + lambda0, & !< mean free path prefactor for each + burgers !< absolute length of burgers vector [m] real(pReal), dimension(:,:), allocatable :: & slip_normal, & slip_direction, & slip_transverse, & minDipoleHeight, & ! edge and screw peierlsstress, & ! edge and screw - interactionSlipSlip ,& !< coefficients for slip-slip interaction for each interaction type and instance - forestProjection_Edge, & !< matrix of forest projections of edge dislocations for each instance - forestProjection_Screw !< matrix of forest projections of screw dislocations for each instance + interactionSlipSlip ,& !< coefficients for slip-slip interaction + forestProjection_Edge, & !< matrix of forest projections of edge dislocations + forestProjection_Screw !< matrix of forest projections of screw dislocations real(pReal), dimension(:), allocatable, private :: & nonSchmidCoeff integer(pInt) :: totalNslip @@ -317,7 +315,6 @@ subroutine plastic_nonlocal_init allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) allocate(Nslip(lattice_maxNslipFamily,maxNinstances), source=0_pInt) allocate(slipFamily(lattice_maxNslip,maxNinstances), source=0_pInt) - allocate(slipSystemLattice(lattice_maxNslip,maxNinstances), source=0_pInt) allocate(totalNslip(maxNinstances), source=0_pInt) @@ -373,11 +370,11 @@ subroutine plastic_nonlocal_init config%getFloat('c/a',defaultVal=0.0_pReal)) ! collinear systems (only for octahedral slip systems in fcc) - allocate(prm%colinearSystem(prm%totalNslip)) + allocate(prm%colinearSystem(prm%totalNslip), source = -1_pInt) do s1 = 1_pInt, prm%totalNslip do s2 = 1_pInt, prm%totalNslip if (all(dEq0 (math_cross(prm%slip_direction(1:3,s1),prm%slip_direction(1:3,s2)))) .and. & - all(dNeq0(math_cross(prm%slip_normal (1:3,s1),prm%slip_normal (1:3,s2))))) & + any(dNeq0(math_cross(prm%slip_normal (1:3,s1),prm%slip_normal (1:3,s2))))) & prm%colinearSystem(s1) = s2 enddo enddo @@ -430,10 +427,13 @@ subroutine plastic_nonlocal_init prm%viscosity = config%getFloat('viscosity') prm%fattack = config%getFloat('attackfrequency') + ! ToDo: discuss logic prm%rhoSglScatter = config%getFloat('rhosglscatter') prm%rhoSglRandom = config%getFloat('rhosglrandom',0.0_pReal) if (config%keyExists('rhosglrandom')) & prm%rhoSglRandomBinning = config%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? + ! if (rhoSglRandom(instance) < 0.0_pReal) & + ! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & prm%surfaceTransmissivity = config%getFloat('surfacetransmissivity',defaultVal=1.0_pReal) prm%grainboundaryTransmissivity = config%getFloat('grainboundarytransmissivity',defaultVal=-1.0_pReal) @@ -443,12 +443,15 @@ subroutine plastic_nonlocal_init !-------------------------------------------------------------------------------------------------- ! sanity checks if (any(prm%burgers < 0.0_pReal)) extmsg = trim(extmsg)//' burgers' + if (any(prm%lambda0 <= 0.0_pReal)) extmsg = trim(extmsg)//' lambda0' + if (any(prm%rhoSglEdgePos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgePos0' if (any(prm%rhoSglEdgeNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgeNeg0' if (any(prm%rhoSglScrewPos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewPos0' if (any(prm%rhoSglScrewNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewNeg0' if (any(prm%rhoDipEdge0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipEdge0' if (any(prm%rhoDipScrew0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipScrew0' + if (any(prm%peierlsstress < 0.0_pReal)) extmsg = trim(extmsg)//' peierlsstress' if (any(prm%minDipoleHeight < 0.0_pReal)) extmsg = trim(extmsg)//' minDipoleHeight' @@ -457,6 +460,7 @@ subroutine plastic_nonlocal_init if (prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' if (prm%doublekinkwidth <= 0.0_pReal) extmsg = trim(extmsg)//' doublekinkwidth' if (prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' + if (prm%atomicVolume <= 0.0_pReal) extmsg = trim(extmsg)//' atomicVolume' ! ToDo: in disloUCLA/dislotwin, the atomic volume is given as a factor if (prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' if (prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' @@ -468,7 +472,7 @@ subroutine plastic_nonlocal_init if (prm%q < 1.0_pReal .or. prm%q > 2.0_pReal) extmsg = trim(extmsg)//' q' if (prm%linetensionEffect < 0.0_pReal .or. prm%linetensionEffect > 1.0_pReal) & - extmsg = trim(extmsg)//' edgeJogFactor' + extmsg = trim(extmsg)//' linetensionEffect' if (prm%edgeJogFactor < 0.0_pReal .or. prm%edgeJogFactor > 1.0_pReal) & extmsg = trim(extmsg)//' edgeJogFactor' @@ -476,8 +480,6 @@ subroutine plastic_nonlocal_init if (prm%solidSolutionSize <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionSize' if (prm%solidSolutionConcentration <= 0.0_pReal) extmsg = trim(extmsg)//' solidSolutionConcentration' - - if (prm%grainboundaryTransmissivity > 1.0_pReal) extmsg = trim(extmsg)//' grainboundaryTransmissivity' if (prm%surfaceTransmissivity < 0.0_pReal .or. prm%surfaceTransmissivity > 1.0_pReal) & extmsg = trim(extmsg)//' surfaceTransmissivity' @@ -485,23 +487,6 @@ subroutine plastic_nonlocal_init if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & extmsg = trim(extmsg)//' fEdgeMultiplication' - - ! if (atomicVolume(instance) <= 0.0_pReal) & - -! do f = 1_pInt,lattice_maxNslipFamily -! if (Nslip(f,instance) > 0_pInt) then -! if (lambda0PerSlipFamily(f,instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='lambda0 ('//PLASTICITY_NONLOCAL_label//')') -! endif -! enddo - -! if (rhoSglScatter(instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglScatter ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglRandom(instance) < 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglRandom ('//PLASTICITY_NONLOCAL_label//')') -! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & -! call IO_error(211_pInt,ext_msg='rhoSglRandomBinning ('//PLASTICITY_NONLOCAL_label//')') - endif slipActive !-------------------------------------------------------------------------------------------------- @@ -606,14 +591,11 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' 'rhoSglScrewPosImmobile','rhoSglScrewNegImmobile', & 'rhoDipEdge ','rhoDipScrew ', & 'accumulatedshear ' ]),pInt) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables - sizeDependentState = int(size([ 'rhoForest ']),pInt) * prm%totalNslip !< microstructural state variables that depend on other state variables - sizeState = sizeDotState + sizeDependentState & + int(size([ 'velocityEdgePos ','velocityEdgeNeg ', & 'velocityScrewPos ','velocityScrewNeg ', & 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]),pInt) * prm%totalNslip !< other dependent state variables that are not updated by microstructure - sizeDeltaState = sizeDotState call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & prm%totalNslip,0_pInt,0_pInt) @@ -640,7 +622,6 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) -allocate(colinearSystem(maxTotalNslip,maxNinstances), source=0_pInt) initializeInstances: do phase = 1_pInt, size(phase_plasticity) NofMyPhase=count(material_phase==phase) @@ -699,32 +680,6 @@ ns = param(instance)%totalNslip plasticState(phase)%accumulatedSlip => & plasticState(phase)%state (iGamma(1,instance):iGamma(ns,instance),1:NofMyPhase) - - !*** Inverse lookup of my slip system family and the slip system in lattice - - l = 0_pInt - do f = 1_pInt,lattice_maxNslipFamily - do s = 1_pInt,Nslip(f,instance) - l = l + 1_pInt - slipFamily(l,instance) = f - slipSystemLattice(l,instance) = sum(lattice_NslipSystem(1:f-1_pInt, phase)) + s - enddo; enddo - - - do s1 = 1_pInt,ns - f = slipFamily(s1,instance) - - do s2 = 1_pInt,ns - - !*** colinear slip system (only makes sense for fcc like it is defined here) - - if ((all(dEq(lattice_sd(1:3,slipSystemLattice(s1,instance),phase), & - lattice_sd(1:3,slipSystemLattice(s2,instance),phase))) .or. all(dEq(lattice_sd(1:3,slipSystemLattice(s1,instance),phase), & - -1.0_pReal* lattice_sd(1:3,slipSystemLattice(s2,instance),phase)))) .and. s1 /= s2) & - colinearSystem(s1,instance) = s2 - enddo - - enddo endif myPhase2 @@ -947,6 +902,7 @@ use math, only: & math_mul33x3, & math_mul3x3, & math_inv33 +#ifdef DEBUG use debug, only: & debug_level, & debug_constitutive, & @@ -954,6 +910,7 @@ use debug, only: & debug_levelSelective, & debug_i, & debug_e +#endif use mesh, only: & theMesh, & mesh_ipNeighborhood, & @@ -1036,8 +993,6 @@ associate(prm => param(instance),dst => microstructure(instance)) ns = prm%totalNslip !*** get basic states - - forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) rhoSgl(s,t) = max(plasticState(ph)%state(iRhoU(s,t,instance),of), 0.0_pReal) ! ensure positive single mobile densities rhoSgl(s,t+4_pInt) = plasticState(ph)%state(iRhoB(s,t,instance),of) @@ -1157,8 +1112,7 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then do s = 1_pInt,ns - !* gradient from interpolation of neighboring excess density - + ! gradient from interpolation of neighboring excess density ... do c = 1_pInt,2_pInt do dir = 1_pInt,3_pInt neighbors(1) = 2_pInt * dir - 1_pInt @@ -1175,15 +1129,13 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then math_mul33x3(invConnections,rhoExcessDifferences)) enddo - !* plus gradient from deads - + ! ... plus gradient from deads ... do t = 1_pInt,4_pInt c = (t - 1_pInt) / 2_pInt + 1_pInt rhoExcessGradient(c) = rhoExcessGradient(c) + rhoSgl(s,t+4_pInt) / FVsize enddo - !* normalized with the total density - + ! ... normalized with the total density ... rhoExcessGradient_over_rho = 0.0_pReal forall (c = 1_pInt:2_pInt) & rhoTotal(c) = (sum(abs(rhoSgl(s,[2*c-1,2*c,2*c+3,2*c+4]))) + rhoDip(s,c) & @@ -1191,8 +1143,7 @@ if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then forall (c = 1_pInt:2_pInt, rhoTotal(c) > 0.0_pReal) & rhoExcessGradient_over_rho(c) = rhoExcessGradient(c) / rhoTotal(c) - !* gives the local stress correction when multiplied with a factor - + ! ... gives the local stress correction when multiplied with a factor dst%tau_back(s,of) = - prm%mu * prm%burgers(s) / (2.0_pReal * pi) & * (rhoExcessGradient_over_rho(1) / (1.0_pReal - prm%nu) & + rhoExcessGradient_over_rho(2)) @@ -1214,7 +1165,9 @@ plasticState(ph)%state(iRhoF(1:ns,instance),of) = rhoForest write(6,'(a,/,12x,12(f10.5,1x),/)') '<< CONST >> tauBack / MPa', dst%tau_back(:,of)*1e-6 endif #endif + end associate + end subroutine plastic_nonlocal_dependentState @@ -1223,13 +1176,6 @@ end subroutine plastic_nonlocal_dependentState !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, & tauThreshold, c, Temperature, ip, el) - -use debug, only: debug_level, & - debug_constitutive, & - debug_levelExtensive, & - debug_levelSelective, & - debug_i, & - debug_e use material, only: material_phase, & phase_plasticityInstance @@ -1358,11 +1304,7 @@ if (Temperature > 0.0_pReal) then endif -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0_pInt)) then - write(6,'(/,a,i8,1x,i2,1x,i1,/)') '<< CONST >> nonlocal_kinetics at el ip',el,ip +#ifdef DEBUGTODO write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tauThreshold / MPa', tauThreshold * 1e-6_pReal write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tau / MPa', tau * 1e-6_pReal write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tauNS / MPa', tauNS * 1e-6_pReal @@ -1381,15 +1323,15 @@ end subroutine plastic_nonlocal_kinetics subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & Mp, Temperature, volume, ip, el) -use math, only: math_mul33xx33 -use material, only: material_phase, & + use math, only: & + math_mul33xx33 + use material, only: & + material_phase, & plasticState, & phaseAt, phasememberAt,& phase_plasticityInstance implicit none - - integer(pInt), intent(in) :: ip, & !< current integration point el !< current element number real(pReal), intent(in) :: Temperature, & !< temperature @@ -1426,8 +1368,6 @@ real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt ph = phaseAt(1_pInt,ip,el) of = phasememberAt(1_pInt,ip,el) - - instance = phase_plasticityInstance(ph) associate(prm => param(instance),dst=>microstructure(instance)) ns = prm%totalNslip @@ -1520,8 +1460,8 @@ enddo end associate -end subroutine plastic_nonlocal_LpAndItsTangent +end subroutine plastic_nonlocal_LpAndItsTangent !-------------------------------------------------------------------------------------------------- @@ -1537,7 +1477,7 @@ use debug, only: debug_level, & debug_levelSelective, & debug_i, & debug_e -use math, only: pi, & +use math, only: PI, & math_mul33xx33 use mesh, only: mesh_ipVolume use material, only: material_phase, & @@ -1713,14 +1653,15 @@ use prec, only: dNeq0, & dNeq, & dEq0 use IO, only: IO_error +#ifdef DEBUG use debug, only: debug_level, & debug_constitutive, & debug_levelBasic, & debug_levelExtensive, & debug_levelSelective, & - debug_g, & debug_i, & debug_e +#endif use math, only: math_mul3x3, & math_mul33x3, & math_mul33xx33, & @@ -1831,7 +1772,10 @@ logical considerEnteringFlux, & p = phaseAt(1,ip,el) o = phasememberAt(1,ip,el) - +if (timestep <= 0.0_pReal) then ! if illegal timestep... Why here and not on function entry?? + plasticState(p)%dotState = 0.0_pReal ! ...return without doing anything (-> zero dotState) + return +endif #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt & @@ -1849,9 +1793,6 @@ tau = 0.0_pReal gdot = 0.0_pReal -!*** shortcut to state variables - - forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) rhoSgl(s,t) = max(plasticState(p)%state(iRhoU(s,t,instance),o), 0.0_pReal) ! ensure positive single mobile densities rhoSgl(s,t+4_pInt) = plasticState(p)%state(iRhoB(s,t,instance),o) @@ -1871,14 +1812,6 @@ where (abs(rhoDip) * mesh_ipVolume(ip,el) ** 0.667_pReal < prm%significantN & .or. abs(rhoDip) < prm%significantRho) & rhoDip = 0.0_pReal -!*** sanity check for timestep - -if (timestep <= 0.0_pReal) then ! if illegal timestep... Why here and not on function entry?? - plasticState(p)%dotState = 0.0_pReal ! ...return without doing anything (-> zero dotState) - return -endif - - !**************************************************************************** !*** Calculate shear rate @@ -2153,8 +2086,8 @@ forall (c=1_pInt:2_pInt) & + rhoDip(1:ns,c) * (abs(gdot(1:ns,2*c-1)) + abs(gdot(1:ns,2*c)))) ! single knocks dipole constituent ! annihilated screw dipoles leave edge jogs behind on the colinear system if (lattice_structure(ph) == LATTICE_fcc_ID) & ! only fcc - forall (s = 1:ns, colinearSystem(s,instance) > 0_pInt) & - rhoDotAthermalAnnihilation(colinearSystem(s,instance),1:2) = - rhoDotAthermalAnnihilation(s,10) & + forall (s = 1:ns, prm%colinearSystem(s) > 0_pInt) & + rhoDotAthermalAnnihilation(prm%colinearSystem(s),1:2) = - rhoDotAthermalAnnihilation(s,10) & * 0.25_pReal * sqrt(rhoForest(s)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor @@ -2194,7 +2127,7 @@ results(instance)%rhoDotEdgeJogs(1:ns,o) = 2.0_pReal * rhoDotThermalAnnihilation #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0_pInt & - .and. ((debug_e == el .and. debug_i == ip .and. debug_g == 1_pInt)& + .and. ((debug_e == el .and. debug_i == ip)& .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0_pInt )) then write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & rhoDotMultiplication(1:ns,1:4) * timestep From 6938864c4bb2b8bcd64e3d64f573b5f93dfe213a Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 20:37:49 +0100 Subject: [PATCH 68/97] pointers allow easier access to state variables --- src/plastic_nonlocal.f90 | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 3777f2246..4c294db20 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -779,18 +779,27 @@ ns = param(instance)%totalNslip stt%rhoDipScrew => plasticState(p)%state (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) dot%rhoDipScrew => plasticState(p)%dotState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) -plasticState(p)%aTolState(iGamma(1:ns,instance)) = prm%aTolShear + + s1 = 10_pInt*prm%totalNslip + 1_pInt + s2 = s1 + prm%totalNslip - 1_pInt + + stt%accumulatedshear => plasticState(p)%state (s1:s2,:) + dot%accumulatedshear => plasticState(p)%dotState (s1:s2,:) + del%accumulatedshear => plasticState(p)%deltaState (s1:s2,:) + plasticState(p)%aTolState(s1:s2) = prm%aTolShear + plasticState(p)%slipRate => plasticState(p)%dotState(s1:s2,1:NofMyPhase) + plasticState(p)%accumulatedSlip => plasticState(p)%state (s1:s2,1:NofMyPhase) allocate(dst%tau_Threshold(prm%totalNslip,NofMyPhase),source=0.0_pReal) allocate(dst%tau_Back(prm%totalNslip,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotFlux(prm%totalNslip,8,NofMyPhase)) - allocate(res%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase)) - allocate(res%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase)) - allocate(res%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase)) - allocate(res%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase)) - allocate(res%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase)) + allocate(res%rhoDotFlux(prm%totalNslip,8,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) + allocate(res%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase),source=0.0_pReal) end associate From da8a1d59731a26969726bdedfe27ed3ff3f8318f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 21 Feb 2019 21:32:22 +0100 Subject: [PATCH 69/97] leaner interface --- src/plastic_nonlocal.f90 | 41 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 4c294db20..f0abdc179 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -20,7 +20,6 @@ module plastic_nonlocal character(len=64), dimension(:,:), allocatable, target, public :: & plastic_nonlocal_output !< name of each post result output - integer(pInt), dimension(:,:), allocatable, private :: & iGamma, & !< state indices for accumulated shear iRhoF !< state indices for forest density @@ -325,6 +324,7 @@ subroutine plastic_nonlocal_init stt => state(phase_plasticityInstance(p)), & del => deltaState(phase_plasticityInstance(p)), & res => results(phase_plasticityInstance(p)), & + dst => microstructure(phase_plasticityInstance(p)), & config => config_phase(p)) prm%aTolRho = config%getFloat('atol_rho', defaultVal=0.0_pReal) @@ -597,10 +597,12 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' 'velocityScrewPos ','velocityScrewNeg ', & 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]),pInt) * prm%totalNslip !< other dependent state variables that are not updated by microstructure sizeDeltaState = sizeDotState + call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & prm%totalNslip,0_pInt,0_pInt) plasticState(p)%nonlocal = .true. plasticState(p)%offsetDeltaState = 0_pInt ! ToDo: state structure does not follow convention + plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,phase_plasticityInstance(p))) Nslip(1:size(prm%Nslip),phase_plasticityInstance(p)) = prm%Nslip ! ToDo: DEPRECATED totalNslip(phase_plasticityInstance(p)) = sum(Nslip(1:size(prm%Nslip),phase_plasticityInstance(p))) ! ToDo: DEPRECATED @@ -674,12 +676,6 @@ ns = param(instance)%totalNslip if (iD(ns,2,instance) /= plasticState(phase)%sizeState) & ! check if last index is equal to size of state call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') - - plasticState(phase)%slipRate => & - plasticState(phase)%dotState(iGamma(1,instance):iGamma(ns,instance),1:NofMyPhase) - plasticState(phase)%accumulatedSlip => & - plasticState(phase)%state (iGamma(1,instance):iGamma(ns,instance),1:NofMyPhase) - endif myPhase2 @@ -698,9 +694,8 @@ ns = param(instance)%totalNslip config => config_phase(p)) NofMyPhase=count(material_phase==p) - - plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,instance)) - stt%rho => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) + + stt%rho => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) dot%rho => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) del%rho => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) plasticState(p)%aTolState(1:10_pInt*prm%totalNslip) = prm%aTolRho @@ -1184,29 +1179,28 @@ end subroutine plastic_nonlocal_dependentState !> @brief calculates kinetics !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, & - tauThreshold, c, Temperature, ip, el) + tauThreshold, c, Temperature, instance, of) + use material, only: material_phase, & phase_plasticityInstance implicit none -integer(pInt), intent(in) :: ip, & !< current integration point - el, & !< current element number - c !< dislocation character (1:edge, 2:screw) +integer(pInt), intent(in) :: c, & !< dislocation character (1:edge, 2:screw) + instance, of real(pReal), intent(in) :: Temperature !< temperature -real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))), & +real(pReal), dimension(param(instance)%totalNslip), & intent(in) :: tau, & !< resolved external shear stress (without non Schmid effects) tauNS, & !< resolved external shear stress (including non Schmid effects) tauThreshold !< threshold shear stress -real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phase(1_pInt,ip,el)))), & +real(pReal), dimension(param(instance)%totalNslip), & intent(out) :: v, & !< velocity dv_dtau, & !< velocity derivative with respect to resolved shear stress (without non Schmid contributions) dv_dtauNS !< velocity derivative with respect to resolved shear stress (including non Schmid contributions) -integer(pInt) :: instance, & !< current instance of this plasticity - ns, & !< short notation for the total number of active slip systems +integer(pInt) :: ns, & !< short notation for the total number of active slip systems s !< index of my current slip system real(pReal) tauRel_P, & tauRel_S, & @@ -1230,11 +1224,8 @@ real(pReal) tauRel_P, & criticalStress_S, & !< maximum obstacle strength mobility !< dislocation mobility - -instance = phase_plasticityInstance(material_phase(1_pInt,ip,el)) -ns = totalNslip(instance) - associate(prm => param(instance)) +ns = prm%totalNslip v = 0.0_pReal dv_dtau = 0.0_pReal dv_dtauNS = 0.0_pReal @@ -1418,7 +1409,7 @@ tau = tau + dst%tau_back(:,of) ! edges call plastic_nonlocal_kinetics(v(1:ns,1), dv_dtau(1:ns,1), dv_dtauNS(1:ns,1), & tau(1:ns), tauNS(1:ns,1), dst%tau_Threshold(1:ns,of), & - 1_pInt, Temperature, ip, el) + 1_pInt, Temperature, instance, of) v(1:ns,2) = v(1:ns,1) dv_dtau(1:ns,2) = dv_dtau(1:ns,1) dv_dtauNS(1:ns,2) = dv_dtauNS(1:ns,1) @@ -1434,7 +1425,7 @@ else do t = 3_pInt,4_pInt call plastic_nonlocal_kinetics(v(1:ns,t), dv_dtau(1:ns,t), dv_dtauNS(1:ns,t), & tau(1:ns), tauNS(1:ns,t), dst%tau_Threshold(1:ns,of), & - 2_pInt , Temperature, ip, el) + 2_pInt , Temperature, instance, of) enddo endif @@ -1795,7 +1786,7 @@ endif ph = material_phase(1_pInt,ip,el) instance = phase_plasticityInstance(ph) -associate(prm => param(instance),dst => microstructure(instance)) +associate(prm => param(instance),dst => microstructure(instance),dot => dotState(instance)) ns = totalNslip(instance) tau = 0.0_pReal From beb73c78821485f3aa48480901a574295e89b754 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 22 Feb 2019 07:37:08 +0100 Subject: [PATCH 70/97] not needed --- src/constitutive.f90 | 2 +- src/plastic_nonlocal.f90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index e5dc6a1cc..b51ba27bf 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -882,7 +882,7 @@ subroutine constitutive_collectDotState(S, FeArray, Fi, FpArray, subdt, subfracA case (PLASTICITY_NONLOCAL_ID) plasticityType call plastic_nonlocal_dotState (Mp,FeArray,FpArray,temperature(ho)%p(tme), & - subdt,subfracArray,ip,el) + subdt,ip,el) end select plasticityType SourceLoop: do i = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index f0abdc179..8bac6f7a3 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -1646,7 +1646,7 @@ end subroutine plastic_nonlocal_deltaState !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & - timestep,subfrac, ip,el) + timestep,ip,el) use, intrinsic :: & IEEE_arithmetic use prec, only: dNeq0, & From 5e369aa2208a820caac0da7df9160ebfb9a4b225 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 22 Feb 2019 08:32:12 +0100 Subject: [PATCH 71/97] avoid use of new variables in deprecated code --- src/plastic_nonlocal.f90 | 65 +++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 8bac6f7a3..0a0bae79b 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -272,13 +272,9 @@ subroutine plastic_nonlocal_init real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] integer(pInt) :: & - ns, phase, & maxNinstances, & - maxTotalNslip, p, i, & - f, & ! index of my slip family - instance, & ! index of my instance of this plasticity + p, i, & l, & - o, & ! index of my output s, & ! index of my slip system s1, & ! index of my slip system s2, & ! index of my slip system @@ -612,68 +608,64 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' enddo ! BEGIN DEPRECATED---------------------------------------------------------------------------------- - maxTotalNslip = maxval(totalNslip) - allocate(iRhoU(maxTotalNslip,4,maxNinstances), source=0_pInt) - allocate(iRhoB(maxTotalNslip,4,maxNinstances), source=0_pInt) - allocate(iRhoD(maxTotalNslip,2,maxNinstances), source=0_pInt) - allocate(iV(maxTotalNslip,4,maxNinstances), source=0_pInt) - allocate(iD(maxTotalNslip,2,maxNinstances), source=0_pInt) - allocate(iGamma(maxTotalNslip,maxNinstances), source=0_pInt) - allocate(iRhoF(maxTotalNslip,maxNinstances), source=0_pInt) + allocate(iRhoU(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iRhoB(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iRhoD(maxval(totalNslip),2,maxNinstances), source=0_pInt) + allocate(iV(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iD(maxval(totalNslip),2,maxNinstances), source=0_pInt) + allocate(iGamma(maxval(totalNslip),maxNinstances), source=0_pInt) + allocate(iRhoF(maxval(totalNslip),maxNinstances), source=0_pInt) ! END DEPRECATED------------------------------------------------------------------------------------ -allocate(compatibility(2,maxTotalNslip,maxTotalNslip,theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & +allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & source=0.0_pReal) - initializeInstances: do phase = 1_pInt, size(phase_plasticity) - NofMyPhase=count(material_phase==phase) - myPhase2: if (phase_plasticity(phase) == PLASTICITY_NONLOCAL_ID) then - instance = phase_plasticityInstance(phase) -ns = param(instance)%totalNslip - + initializeInstances: do p = 1_pInt, size(phase_plasticity) + NofMyPhase=count(material_phase==p) + myPhase2: if (phase_plasticity(p) == PLASTICITY_NONLOCAL_ID) then !*** determine indices to state array l = 0_pInt do t = 1_pInt,4_pInt - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iRhoU(s,t,instance) = l + iRhoU(s,t,phase_plasticityInstance(p)) = l enddo enddo do t = 1_pInt,4_pInt - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iRhoB(s,t,instance) = l + iRhoB(s,t,phase_plasticityInstance(p)) = l enddo enddo do c = 1_pInt,2_pInt - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iRhoD(s,c,instance) = l + iRhoD(s,c,phase_plasticityInstance(p)) = l enddo enddo - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iGamma(s,instance) = l + iGamma(s,phase_plasticityInstance(p)) = l enddo - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iRhoF(s,instance) = l + iRhoF(s,phase_plasticityInstance(p)) = l enddo do t = 1_pInt,4_pInt - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iV(s,t,instance) = l + iV(s,t,phase_plasticityInstance(p)) = l enddo enddo do c = 1_pInt,2_pInt - do s = 1_pInt,ns + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip l = l + 1_pInt - iD(s,c,instance) = l + iD(s,c,phase_plasticityInstance(p)) = l enddo enddo - if (iD(ns,2,instance) /= plasticState(phase)%sizeState) & ! check if last index is equal to size of state + if (iD(param(phase_plasticityInstance(p))%totalNslip,2,phase_plasticityInstance(p)) /= plasticState(p)%sizeState) & ! check if last index is equal to size of state call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') @@ -684,7 +676,6 @@ ns = param(instance)%totalNslip do p=1_pInt, size(config_phase) if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle - instance = phase_plasticityInstance(p) associate(prm => param(phase_plasticityInstance(p)), & dot => dotState(phase_plasticityInstance(p)), & stt => state(phase_plasticityInstance(p)), & @@ -1694,8 +1685,6 @@ integer(pInt), intent(in) :: ip, & real(pReal), intent(in) :: Temperature, & !< temperature timestep !< substepped crystallite time increment real(pReal), dimension(3,3), intent(in) :: Mp !< MandelStress -real(pReal), dimension(homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & - subfrac !< fraction of timestep at the beginning of the substepped crystallite time increment real(pReal), dimension(3,3,homogenization_maxNgrains,theMesh%elem%nIPs,theMesh%nElems), intent(in) :: & Fe, & !< elastic deformation gradient Fp !< plastic deformation gradient From 4d45038358f0895bb926f3875f3b7a6c6721a6fc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 22 Feb 2019 09:21:04 +0100 Subject: [PATCH 72/97] better readable --- src/plastic_nonlocal.f90 | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 0a0bae79b..68e059508 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -275,9 +275,8 @@ subroutine plastic_nonlocal_init maxNinstances, & p, i, & l, & + s1, s2, & s, & ! index of my slip system - s1, & ! index of my slip system - s2, & ! index of my slip system t, & ! index of dislocation type c ! index of dislocation character @@ -766,15 +765,12 @@ allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),theMesh%elem%nIPn dot%rhoDipScrew => plasticState(p)%dotState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) del%rhoDipScrew => plasticState(p)%deltaState (9_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) - s1 = 10_pInt*prm%totalNslip + 1_pInt - s2 = s1 + prm%totalNslip - 1_pInt - - stt%accumulatedshear => plasticState(p)%state (s1:s2,:) - dot%accumulatedshear => plasticState(p)%dotState (s1:s2,:) - del%accumulatedshear => plasticState(p)%deltaState (s1:s2,:) - plasticState(p)%aTolState(s1:s2) = prm%aTolShear - plasticState(p)%slipRate => plasticState(p)%dotState(s1:s2,1:NofMyPhase) - plasticState(p)%accumulatedSlip => plasticState(p)%state (s1:s2,1:NofMyPhase) + stt%accumulatedshear => plasticState(p)%state (10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ,1:NofMyPhase) + dot%accumulatedshear => plasticState(p)%dotState (10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ,1:NofMyPhase) + del%accumulatedshear => plasticState(p)%deltaState (10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ,1:NofMyPhase) + plasticState(p)%aTolState(10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ) = prm%aTolShear + plasticState(p)%slipRate => plasticState(p)%dotState(10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ,1:NofMyPhase) + plasticState(p)%accumulatedSlip => plasticState(p)%state (10_pInt*prm%totalNslip + 1_pInt:11_pInt*prm%totalNslip ,1:NofMyPhase) allocate(dst%tau_Threshold(prm%totalNslip,NofMyPhase),source=0.0_pReal) @@ -1172,12 +1168,7 @@ end subroutine plastic_nonlocal_dependentState subroutine plastic_nonlocal_kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, & tauThreshold, c, Temperature, instance, of) -use material, only: material_phase, & - phase_plasticityInstance - implicit none - - integer(pInt), intent(in) :: c, & !< dislocation character (1:edge, 2:screw) instance, of real(pReal), intent(in) :: Temperature !< temperature @@ -2156,7 +2147,7 @@ else forall (s = 1:ns, c = 1_pInt:2_pInt) & plasticState(p)%dotState(iRhoD(s,c,instance),o) = rhoDot(s,c+8_pInt) forall (s = 1:ns) & - plasticState(p)%dotState(iGamma(s,instance),o) = sum(gdot(s,1:4)) + dot%accumulatedshear(s,o) = sum(gdot(s,1:4)) endif end associate end subroutine plastic_nonlocal_dotState @@ -2380,7 +2371,7 @@ ns = totalNslip(instance) cs = 0_pInt -associate(prm => param(instance),dst => microstructure(instance)) +associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance)) !* short hand notations for state variables forall (s = 1_pInt:ns, t = 1_pInt:4_pInt) @@ -2583,7 +2574,7 @@ outputsLoop: do o = 1_pInt,size(param(instance)%outputID) cs = cs + ns case(accumulatedshear_ID) - postResults(cs+1_pInt:cs+ns) = plasticState(ph)%state(iGamma(1:ns,instance),of) + postResults(cs+1_pInt:cs+ns) = stt%accumulatedshear(:,of) cs = cs + ns end select From db9016d146b622a103f2f40eaba6bca87eb56ba9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 22 Feb 2019 10:02:43 +0100 Subject: [PATCH 73/97] avoid repeated loops --- src/plastic_nonlocal.f90 | 151 +++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 85 deletions(-) diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 68e059508..eb3e4e694 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -21,7 +21,6 @@ module plastic_nonlocal plastic_nonlocal_output !< name of each post result output integer(pInt), dimension(:,:), allocatable, private :: & - iGamma, & !< state indices for accumulated shear iRhoF !< state indices for forest density integer(pInt), dimension(:,:,:), allocatable, private :: & iRhoU, & !< state indices for unblocked density @@ -602,89 +601,7 @@ extmsg = trim(extmsg)//' fEdgeMultiplication' Nslip(1:size(prm%Nslip),phase_plasticityInstance(p)) = prm%Nslip ! ToDo: DEPRECATED totalNslip(phase_plasticityInstance(p)) = sum(Nslip(1:size(prm%Nslip),phase_plasticityInstance(p))) ! ToDo: DEPRECATED - end associate - - enddo - -! BEGIN DEPRECATED---------------------------------------------------------------------------------- - allocate(iRhoU(maxval(totalNslip),4,maxNinstances), source=0_pInt) - allocate(iRhoB(maxval(totalNslip),4,maxNinstances), source=0_pInt) - allocate(iRhoD(maxval(totalNslip),2,maxNinstances), source=0_pInt) - allocate(iV(maxval(totalNslip),4,maxNinstances), source=0_pInt) - allocate(iD(maxval(totalNslip),2,maxNinstances), source=0_pInt) - allocate(iGamma(maxval(totalNslip),maxNinstances), source=0_pInt) - allocate(iRhoF(maxval(totalNslip),maxNinstances), source=0_pInt) -! END DEPRECATED------------------------------------------------------------------------------------ - -allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & - source=0.0_pReal) - - initializeInstances: do p = 1_pInt, size(phase_plasticity) - NofMyPhase=count(material_phase==p) - myPhase2: if (phase_plasticity(p) == PLASTICITY_NONLOCAL_ID) then - - !*** determine indices to state array - - l = 0_pInt - do t = 1_pInt,4_pInt - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iRhoU(s,t,phase_plasticityInstance(p)) = l - enddo - enddo - do t = 1_pInt,4_pInt - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iRhoB(s,t,phase_plasticityInstance(p)) = l - enddo - enddo - do c = 1_pInt,2_pInt - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iRhoD(s,c,phase_plasticityInstance(p)) = l - enddo - enddo - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iGamma(s,phase_plasticityInstance(p)) = l - enddo - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iRhoF(s,phase_plasticityInstance(p)) = l - enddo - do t = 1_pInt,4_pInt - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iV(s,t,phase_plasticityInstance(p)) = l - enddo - enddo - do c = 1_pInt,2_pInt - do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip - l = l + 1_pInt - iD(s,c,phase_plasticityInstance(p)) = l - enddo - enddo - if (iD(param(phase_plasticityInstance(p))%totalNslip,2,phase_plasticityInstance(p)) /= plasticState(p)%sizeState) & ! check if last index is equal to size of state - call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') - - - endif myPhase2 - - enddo initializeInstances - - - do p=1_pInt, size(config_phase) - if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle - associate(prm => param(phase_plasticityInstance(p)), & - dot => dotState(phase_plasticityInstance(p)), & - stt => state(phase_plasticityInstance(p)), & - del => deltaState(phase_plasticityInstance(p)), & - res => results(phase_plasticityInstance(p)), & - dst => microstructure(phase_plasticityInstance(p)), & - config => config_phase(p)) - NofMyPhase=count(material_phase==p) - - + ! ToDo: Not really sure if this large number of mostly overlapping pointers is useful stt%rho => plasticState(p)%state (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) dot%rho => plasticState(p)%dotState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) del%rho => plasticState(p)%deltaState (0_pInt*prm%totalNslip+1_pInt:10_pInt*prm%totalNslip,:) @@ -787,7 +704,71 @@ allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),theMesh%elem%nIPn if (NofMyPhase > 0_pInt) call stateInit(p,NofMyPhase) plasticState(p)%state0 = plasticState(p)%state - enddo + + enddo + +! BEGIN DEPRECATED---------------------------------------------------------------------------------- + allocate(iRhoU(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iRhoB(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iRhoD(maxval(totalNslip),2,maxNinstances), source=0_pInt) + allocate(iV(maxval(totalNslip),4,maxNinstances), source=0_pInt) + allocate(iD(maxval(totalNslip),2,maxNinstances), source=0_pInt) + allocate(iRhoF(maxval(totalNslip),maxNinstances), source=0_pInt) +! END DEPRECATED------------------------------------------------------------------------------------ + +allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),theMesh%elem%nIPneighbors,theMesh%elem%nIPs,theMesh%nElems), & + source=0.0_pReal) + + initializeInstances: do p = 1_pInt, size(phase_plasticity) + NofMyPhase=count(material_phase==p) + myPhase2: if (phase_plasticity(p) == PLASTICITY_NONLOCAL_ID) then + + !*** determine indices to state array + + l = 0_pInt + do t = 1_pInt,4_pInt + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iRhoU(s,t,phase_plasticityInstance(p)) = l + enddo + enddo + do t = 1_pInt,4_pInt + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iRhoB(s,t,phase_plasticityInstance(p)) = l + enddo + enddo + do c = 1_pInt,2_pInt + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iRhoD(s,c,phase_plasticityInstance(p)) = l + enddo + enddo + l = l + param(phase_plasticityInstance(p))%totalNslip + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iRhoF(s,phase_plasticityInstance(p)) = l + enddo + do t = 1_pInt,4_pInt + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iV(s,t,phase_plasticityInstance(p)) = l + enddo + enddo + do c = 1_pInt,2_pInt + do s = 1_pInt,param(phase_plasticityInstance(p))%totalNslip + l = l + 1_pInt + iD(s,c,phase_plasticityInstance(p)) = l + enddo + enddo + if (iD(param(phase_plasticityInstance(p))%totalNslip,2,phase_plasticityInstance(p)) /= plasticState(p)%sizeState) & ! check if last index is equal to size of state + call IO_error(0_pInt, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') + + + endif myPhase2 + + enddo initializeInstances + contains From 43376c39d8cc705c313f863945bd4ef8349f531c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 22 Feb 2019 11:25:39 +0100 Subject: [PATCH 74/97] addGrainID parses in quaternion --- python/damask/orientation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 03c69291f..3ab7cd044 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -944,6 +944,7 @@ class Symmetry: def inFZ(self,R): """Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" + if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentally passed quaternion # fundamental zone in Rodrigues space is point symmetric around origin if R.shape[0]==4: # transition old (length not stored separately) to new From 7903e2b65f60ad187bb58bce55ec49ad564d0185 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 11:31:53 +0100 Subject: [PATCH 75/97] dependencies got mixed up --- PRIVATE | 2 +- src/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PRIVATE b/PRIVATE index e86418193..dc9722c3c 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit e86418193f202364e068de2dffee36f99c846856 +Subproject commit dc9722c3c9787bbb0f63308a7015b6709e6d4f94 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c50688f1e..cdd9b1d02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,7 +59,7 @@ add_dependencies(FEsolving DEBUG) list(APPEND OBJECTFILES $) add_library(MATH OBJECT "math.f90") -add_dependencies(MATH DEBUG) +add_dependencies(MATH NUMERICS) list(APPEND OBJECTFILES $) add_library(QUATERNIONS OBJECT "quaternions.f90") @@ -93,7 +93,7 @@ elseif (PROJECT_NAME STREQUAL "DAMASK_FEM") endif() add_library(MATERIAL OBJECT "material.f90") -add_dependencies(MATERIAL MESH DAMASK_CONFIG) +add_dependencies(MATERIAL MESH DAMASK_CONFIG ROTATIONS) list(APPEND OBJECTFILES $) add_library(LATTICE OBJECT "lattice.f90") From e4bb61c9d96b233383638763d1a112d87dcd484e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 11:37:09 +0100 Subject: [PATCH 76/97] transition to new orientation class/DREAM.3D --- PRIVATE | 2 +- processing/misc/OIMgrainFile_toTable.py | 48 ---------- processing/pre/3DRVEfrom2Dang.py | 119 ------------------------ 3 files changed, 1 insertion(+), 168 deletions(-) delete mode 100755 processing/misc/OIMgrainFile_toTable.py delete mode 100755 processing/pre/3DRVEfrom2Dang.py diff --git a/PRIVATE b/PRIVATE index dc9722c3c..35bed9722 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit dc9722c3c9787bbb0f63308a7015b6709e6d4f94 +Subproject commit 35bed9722ddecc342719bafac32590e9ab94d053 diff --git a/processing/misc/OIMgrainFile_toTable.py b/processing/misc/OIMgrainFile_toTable.py deleted file mode 100755 index 063adb0db..000000000 --- a/processing/misc/OIMgrainFile_toTable.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os,sys -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 [file[s]]', description = """ -Adds header to OIM grain file type 1 to make it accesible as ASCII table - -""", version = scriptID) - - -(options, filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, - labeled = False) - except: continue - damask.util.report(scriptName,name) - table.head_read() - data = [] - while table.data_read(): - data.append(table.data[0:9]) - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['1_euler','2_euler','3_euler','1_pos','2_pos','IQ','CI','Fit','GrainID']) - table.head_write() - for i in data: - table.data = i - table.data_write() - -# --- output finalization -------------------------------------------------------------------------- - - table.close() # close ASCII table diff --git a/processing/pre/3DRVEfrom2Dang.py b/processing/pre/3DRVEfrom2Dang.py deleted file mode 100755 index 58607c4be..000000000 --- a/processing/pre/3DRVEfrom2Dang.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os,sys,math -from optparse import OptionParser -import damask -import pipes - -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 3D RVE from .ang files of EBSD slices .', - version = scriptID) - -parser.add_option('--offset', - dest='offset', - type='float', - help='offset of EBSD slices [%default]', - metavar='float') -parser.add_option('--outname', - dest='outName', - type='string', - help='output file name [%default]', metavar='string') -parser.add_option('--vtr', - action="store_true", - dest='vtr') -parser.add_option('--geom', - action="store_true", - dest='geom') -parser.set_defaults(offset = 1.0, - outName = 'RVE3D') - -(options,filenames) = parser.parse_args() - -numFiles = len(filenames) -formatwidth = 1+int(math.log10(numFiles)) - -# copy original files to tmp files to not alter originals -for i in range(numFiles): - sliceID = 'slice' + str(i).zfill(formatwidth) + '.tmp' - strCommand = 'cp ' + pipes.quote(filenames[i]) + ' ' + sliceID - os.system(strCommand) - -# modify tmp files -print('Add z-coordinates') -for i in range(numFiles): - sliceID = 'slice' + str(i).zfill(formatwidth) + '.tmp' - strCommand = 'OIMgrainFile_toTable ' + sliceID - os.system(strCommand) - strCommand = 'addCalculation --label 3Dpos --formula "np.array(#pos#.tolist()+[' + str(i*options.offset) + '])" ' + sliceID - os.system(strCommand) - -# join temp files into one - -print('\n Colocate files') -fileOut = open(options.outName + '.ang','w') - -# take header information from 1st file -sliceID = 'slice' + str(0).zfill(formatwidth) + '.tmp' -fileRead = open(sliceID) -data = fileRead.readlines() -fileRead.close() -headerLines = int(data[0].split()[0]) -fileOut.write(str(headerLines+1) + '\t header\n') -for line in data[1:headerLines]: - fileOut.write(line) -fileOut.write(scriptID + '\t' + ' '.join(sys.argv[1:]) + '\n') -for line in data[headerLines:]: - fileOut.write(line) - -# append other files content without header -for i in range(numFiles-1): - sliceID = 'slice' + str(i+1).zfill(formatwidth) + '.tmp' - fileRead = open(sliceID) - data = fileRead.readlines() - fileRead.close() - headerLines = int(data[0].split()[0]) - for line in data[headerLines+1:]: - fileOut.write(line) -fileOut.close() - -# tidy up and add phase column -print('\n Remove temp data and add phase info') -strCommand = 'filterTable --black pos ' + options.outName + '.ang' -os.system(strCommand) -strCommand = 'reLabel --label 3Dpos --substitute pos ' + options.outName + '.ang' -os.system(strCommand) -strCommand = 'addCalculation -l phase -f 1 ' + options.outName + '.ang' -os.system(strCommand) - - -# create geom file when asked for -if options.geom: - print('\n Build geometry file') - strCommand = 'geom_fromTable --phase phase --eulers euler --coordinates pos ' + pipes.quote(options.outName) + '.ang' - os.system(strCommand) - -# create paraview file when asked for - -if options.vtr: - print('\n Build Paraview file') - strCommand = 'addIPFcolor --eulers euler --pole 0.0 0.0 1.0 ' + options.outName + '.ang' - os.system(strCommand) - strCommand = 'vtk_rectilinearGrid ' + pipes.quote(options.outName) + '.ang' - os.system(strCommand) - os.rename(pipes.quote(options.outName) + '_pos(cell)'+'.vtr', pipes.quote(options.outName) + '.vtr') - strCommand = 'vtk_addRectilinearGridData --vtk '+ pipes.quote(options.outName) + '.vtr --color IPF_001_cubic '\ - + pipes.quote(options.outName) + '.ang' - os.system(strCommand) - -# delete tmp files -for i in range(numFiles): - sliceID = 'slice' + str(i).zfill(formatwidth) + '.tmp' - os.remove(sliceID) \ No newline at end of file From affe65eb55204d37aa2c1b27c264651b5a481315 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 16:50:21 +0100 Subject: [PATCH 77/97] does not exist anymore --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9b992136c..368888436 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -508,7 +508,7 @@ Processing: stage: createDocumentation script: - cd $DAMASKROOT/processing/pre - - rm 3DRVEfrom2Dang.py abq_addUserOutput.py marc_addUserOutput.py + - rm abq_addUserOutput.py marc_addUserOutput.py - $DAMASKROOT/PRIVATE/documenting/scriptHelpToWiki.py --debug *.py - cd $DAMASKROOT/processing/post - rm marc_to_vtk.py vtk2ang.py From b3455c825e8fe98bac8b842611dc70548e4b886b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 21:47:16 +0100 Subject: [PATCH 78/97] transition to new orientation class forward-backward conversion quite stable --- PRIVATE | 2 +- processing/post/addOrientations.py | 6 +- processing/post/rotateData.py | 2 +- processing/pre/geom_addPrimitive.py | 2 +- python/damask/orientation.py | 365 ++++------------------------ 5 files changed, 57 insertions(+), 320 deletions(-) diff --git a/PRIVATE b/PRIVATE index 35bed9722..f0090997d 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 35bed9722ddecc342719bafac32590e9ab94d053 +Subproject commit f0090997df817f0a0b5a480a60e81929875b1010 diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index cc10dfb84..dfaa54196 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -109,8 +109,8 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.') crystalrotation = np.array(options.crystalrotation[1:4] + (options.crystalrotation[0],)) # Compatibility hack labrotation = np.array(options.labrotation[1:4] + (options.labrotation[0],)) # Compatibility hack -r = damask.Rotation.fromAngleAxis(crystalrotation,options.degrees) # crystal frame rotation -R = damask.Rotation.fromAngleAxis(labrotation,options.degrees) # lab frame rotation +r = damask.Rotation.fromAxisAngle(crystalrotation,options.degrees) # crystal frame rotation +R = damask.Rotation.fromAxisAngle(labrotation,options.degrees) # lab frame rotation # --- loop over input files ------------------------------------------------------------------------ @@ -183,7 +183,7 @@ for name in filenames: elif output == 'rodrigues': table.data_append(o.asRodrigues()) elif output == 'eulers': table.data_append(o.asEulers(degrees=options.degrees)) elif output == 'matrix': table.data_append(o.asMatrix()) - elif output == 'angleaxis': table.data_append(o.asAngleAxis(degrees=options.degrees)) + elif output == 'angleaxis': table.data_append(o.asAxisAngle(degrees=options.degrees)) outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 1438acb15..65f5aaaa2 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -41,7 +41,7 @@ if options.data is None: parser.error('no data column specified.') rotation = np.array(options.rotation[1:4]+(options.rotation[0],)) # Compatibility hack -r = damask.Rotation.fromAngleAxis(rotation,options.degrees,normalise=True) +r = damask.Rotation.fromAxisAngle(rotation,options.degrees,normalise=True) # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 88df1e62d..0b3356083 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -64,7 +64,7 @@ if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: ax = np.array(options.angleaxis[1:4] + (options.angleaxis[0],)) # Compatibility hack - rotation = damask.Rotation.fromAngleAxis(ax,options.degrees,normalise=True) + rotation = damask.Rotation.fromAxisAngle(ax,options.degrees,normalise=True) elif options.quaternion is not None: rotation = damask.Rotation.fromQuaternion(options.quaternion) else: diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 3ab7cd044..ffe6dd419 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -261,32 +261,34 @@ class Rotation: # convert to different orientation representations (numpy arrays) def asQuaternion(self): + """Unit quaternion: (q, [p_1, p_2, p_3])""" return self.quaternion.asArray() def asEulers(self, degrees = False): - + """Bunge-Euler angles: (φ_1, ϕ, φ_2)""" eu = qu2eu(self.quaternion.asArray()) if degrees: eu = np.degrees(eu) - return eu - def asAngleAxis(self, + def asAxisAngle(self, degrees = False): - + """Axis-angle pair: ([n_1, n_2, n_3], ω)""" ax = qu2ax(self.quaternion.asArray()) if degrees: ax[3] = np.degrees(ax[3]) - return ax def asMatrix(self): + """Rotation matrix""" return qu2om(self.quaternion.asArray()) def asRodrigues(self): + """Rodrigues-Frank vector: ([n_1, n_2, n_3], tan(ω/2))""" return qu2ro(self.quaternion.asArray()) def asHomochoric(self): - return qu2ho(self.quaternion.asArray()) + """Homochoric vector: (h_1, h_2, h_3)""" + return qu2ho(self.quaternion.asArray()) def asCubochoric(self): return qu2cu(self.quaternion.asArray()) @@ -322,7 +324,7 @@ class Rotation: return cls(eu2qu(eu)) @classmethod - def fromAngleAxis(cls, + def fromAxisAngle(cls, angleAxis, degrees = False, normalise = False, @@ -372,6 +374,27 @@ class Rotation: raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[3])) return cls(ro2qu(ro)) + + @classmethod + def fromHomochoric(cls, + homochoric, + P = -1): + + ho = homochoric if isinstance(homochoric, np.ndarray) else np.array(homochoric) + if P > 0: ho *= -1 # convert from P=1 to P=-1 + + return cls(ho2qu(ho)) + + @classmethod + def fromCubochoric(cls, + cubochoric, + P = -1): + + cu = cubochoric if isinstance(cubochoric, np.ndarray) else np.array(cubochoric) + ho = cu2ho(cu) + if P > 0: ho *= -1 # convert from P=1 to P=-1 + + return cls(ho2qu(ho)) def __mul__(self, other): @@ -672,28 +695,6 @@ class Quaternion: def asRodrigues(self): return np.inf*np.ones(3) if np.isclose(self.q,0.0) else self.p/self.q - def asEulers(self, - degrees = False): - """Orientation as Bunge-Euler angles.""" - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - q03 = self.q**2 + self.p[2]**2 - q12 = self.p[0]**2 + self.p[1]**2 - chi = np.sqrt(q03*q12) - - if np.isclose(chi,0.0) and np.isclose(q12,0.0): - eulers = np.array([math.atan2(-2*P*self.q*self.p[2],self.q**2-self.p[2]**2),0,0]) - elif np.isclose(chi,0.0) and np.isclose(q03,0.0): - eulers = np.array([math.atan2( 2 *self.p[0]*self.p[1],self.p[0]**2-self.p[1]**2),np.pi,0]) - else: - eulers = np.array([math.atan2((self.p[0]*self.p[2]-P*self.q*self.p[1])/chi,(-P*self.q*self.p[0]-self.p[1]*self.p[2])/chi), - math.atan2(2*chi,q03-q12), - math.atan2((P*self.q*self.p[1]+self.p[0]*self.p[2])/chi,( self.p[1]*self.p[2]-P*self.q*self.p[0])/chi), - ]) - - eulers %= 2.0*math.pi # enforce positive angles - return np.degrees(eulers) if degrees else eulers - # # Static constructors @classmethod @@ -1506,18 +1507,8 @@ class Orientation: 'Symmetry: {}'.format(self.symmetry), 'Quaternion: {}'.format(self.quaternion), 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ), - 'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ), ]) - def asQuaternion(self): - return self.quaternion.asList() - - def asEulers(self, - degrees = False, - ): - return self.quaternion.asEulers(degrees) - eulers = property(asEulers) - def asRodrigues(self): return self.quaternion.asRodrigues() rodrigues = property(asRodrigues) @@ -1526,7 +1517,6 @@ class Orientation: degrees = False, flat = False): return self.quaternion.asAngleAxis(degrees,flat) - angleAxis = property(asAngleAxis) def asMatrix(self): return self.quaternion.asMatrix() @@ -1643,251 +1633,6 @@ class Orientation: symmetry = reference.symmetry.lattice) - def related(self, - relationModel, - direction, - targetSymmetry = 'cubic'): - """ - Orientation relationship - - positive number: fcc --> bcc - negative number: bcc --> fcc - """ - if relationModel not in ['KS','GT','GTdash','NW','Pitsch','Bain']: return None - if int(direction) == 0: return None - - variant = int(abs(direction))-1 - (me,other) = (0,1) if direction > 0 else (1,0) - - planes = {'KS': \ - np.array([[[ 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],[ 0, 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],[ 0, 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],[ 0, 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],[ 0, 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]]]), - 'GT': \ - np.array([[[ 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],[ 0, -1, 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],[ 0, -1, 1]], - [[ 1, -1, 1],[ 1, 0, 1]]]), - 'GTdash': \ - np.array([[[ 7, 17, 17],[ 12, 5, 17]], - [[ 17, 7, 17],[ 17, 12, 5]], - [[ 17, 17, 7],[ 5, 17, 12]], - [[ -7,-17, 17],[-12, -5, 17]], - [[-17, -7, 17],[-17,-12, 5]], - [[-17,-17, 7],[ -5,-17, 12]], - [[ 7,-17,-17],[ 12, -5,-17]], - [[ 17, -7,-17],[ 17,-12, -5]], - [[ 17,-17, -7],[ 5,-17,-12]], - [[ -7, 17,-17],[-12, 5,-17]], - [[-17, 7,-17],[-17, 12, -5]], - [[-17, 17, -7],[ -5, 17,-12]], - [[ 7, 17, 17],[ 12, 17, 5]], - [[ 17, 7, 17],[ 5, 12, 17]], - [[ 17, 17, 7],[ 17, 5, 12]], - [[ -7,-17, 17],[-12,-17, 5]], - [[-17, -7, 17],[ -5,-12, 17]], - [[-17,-17, 7],[-17, -5, 12]], - [[ 7,-17,-17],[ 12,-17, -5]], - [[ 17, -7,-17],[ 5, -12,-17]], - [[ 17,-17, 7],[ 17, -5,-12]], - [[ -7, 17,-17],[-12, 17, -5]], - [[-17, 7,-17],[ -5, 12,-17]], - [[-17, 17, -7],[-17, 5,-12]]]), - 'NW': \ - np.array([[[ 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],[ 0, 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],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]]]), - 'Pitsch': \ - np.array([[[ 0, 1, 0],[ -1, 0, 1]], - [[ 0, 0, 1],[ 1, -1, 0]], - [[ 1, 0, 0],[ 0, 1, -1]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 1, 0, 0],[ 0, -1, 1]], - [[ 0, 1, 0],[ 1, 0, -1]], - [[ 0, 0, 1],[ -1, 1, 0]]]), - 'Bain': \ - np.array([[[ 1, 0, 0],[ 1, 0, 0]], - [[ 0, 1, 0],[ 0, 1, 0]], - [[ 0, 0, 1],[ 0, 0, 1]]]), - } - - normals = {'KS': \ - np.array([[[ -1, 0, 1],[ -1, -1, 1]], - [[ -1, 0, 1],[ -1, 1, -1]], - [[ 0, 1, -1],[ -1, -1, 1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ 1, -1, 0],[ -1, -1, 1]], - [[ 1, -1, 0],[ -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]], - [[ 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, 1, 0],[ -1, -1, 1]], - [[ 1, 1, 0],[ -1, 1, -1]], - [[ -1, 1, 0],[ -1, -1, 1]], - [[ -1, 1, 0],[ -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]]]), - 'GT': \ - np.array([[[ -5,-12, 17],[-17, -7, 17]], - [[ 17, -5,-12],[ 17,-17, -7]], - [[-12, 17, -5],[ -7, 17,-17]], - [[ 5, 12, 17],[ 17, 7, 17]], - [[-17, 5,-12],[-17, 17, -7]], - [[ 12,-17, -5],[ 7,-17,-17]], - [[ -5, 12,-17],[-17, 7,-17]], - [[ 17, 5, 12],[ 17, 17, 7]], - [[-12,-17, 5],[ -7,-17, 17]], - [[ 5,-12,-17],[ 17, -7,-17]], - [[-17, -5, 12],[-17,-17, 7]], - [[ 12, 17, 5],[ 7, 17, 17]], - [[ -5, 17,-12],[-17, 17, -7]], - [[-12, -5, 17],[ -7,-17, 17]], - [[ 17,-12, -5],[ 17, -7,-17]], - [[ 5,-17,-12],[ 17,-17, -7]], - [[ 12, 5, 17],[ 7, 17, 17]], - [[-17, 12, -5],[-17, 7,-17]], - [[ -5,-17, 12],[-17,-17, 7]], - [[-12, 5,-17],[ -7, 17,-17]], - [[ 17, 12, 5],[ 17, 7, 17]], - [[ 5, 17, 12],[ 17, 17, 7]], - [[ 12, -5,-17],[ 7,-17,-17]], - [[-17,-12, 5],[-17, 7, 17]]]), - 'GTdash': \ - np.array([[[ 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]], - [[ 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]]]), - 'NW': \ - np.array([[[ 2, -1, -1],[ 0, -1, 1]], - [[ -1, 2, -1],[ 0, -1, 1]], - [[ -1, -1, 2],[ 0, -1, 1]], - [[ -2, -1, -1],[ 0, -1, 1]], - [[ 1, 2, -1],[ 0, -1, 1]], - [[ 1, -1, 2],[ 0, -1, 1]], - [[ 2, 1, -1],[ 0, -1, 1]], - [[ -1, -2, -1],[ 0, -1, 1]], - [[ -1, 1, 2],[ 0, -1, 1]], - [[ -1, 2, 1],[ 0, -1, 1]], - [[ -1, 2, 1],[ 0, -1, 1]], - [[ -1, -1, -2],[ 0, -1, 1]]]), - 'Pitsch': \ - np.array([[[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ -1, 0, 1],[ -1, -1, 1]], - [[ 1, -1, 0],[ 1, -1, -1]], - [[ 1, 0, -1],[ 1, -1, -1]], - [[ -1, 1, 0],[ -1, 1, -1]], - [[ 0, -1, 1],[ -1, -1, 1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]]]), - 'Bain': \ - np.array([[[ 0, 1, 0],[ 0, 1, 1]], - [[ 0, 0, 1],[ 1, 0, 1]], - [[ 1, 0, 0],[ 1, 1, 0]]]), - } - myPlane = [float(i) for i in planes[relationModel][variant,me]] # map(float, planes[...]) does not work in python 3 - myPlane /= np.linalg.norm(myPlane) - myNormal = [float(i) for i in normals[relationModel][variant,me]] # map(float, planes[...]) does not work in python 3 - myNormal /= np.linalg.norm(myNormal) - myMatrix = np.array([myNormal,np.cross(myPlane,myNormal),myPlane]).T - - otherPlane = [float(i) for i in planes[relationModel][variant,other]] # map(float, planes[...]) does not work in python 3 - otherPlane /= np.linalg.norm(otherPlane) - otherNormal = [float(i) for i in normals[relationModel][variant,other]] # map(float, planes[...]) does not work in python 3 - otherNormal /= np.linalg.norm(otherNormal) - otherMatrix = np.array([otherNormal,np.cross(otherPlane,otherNormal),otherPlane]).T - - rot=np.dot(otherMatrix,myMatrix.T) - - return Orientation(matrix=np.dot(rot,self.asMatrix()),symmetry=targetSymmetry) - #################################################################################################### # Code below available according to the followin conditions on https://github.com/MarDiehl/3Drotations #################################################################################################### @@ -1920,10 +1665,10 @@ class Orientation: #################################################################################################### def isone(a): - return np.isclose(a,1.0,atol=1.0e-15,rtol=0.0) + return np.isclose(a,1.0,atol=1.0e-7,rtol=0.0) def iszero(a): - return np.isclose(a,0.0,atol=1.0e-300,rtol=0.0) + return np.isclose(a,0.0,atol=1.0e-12,rtol=0.0) def eu2om(eu): @@ -2063,8 +1808,7 @@ def ho2ax(ho): for i in range(2,16): hm *= hmag_squared s += tfit[i] * hm - ax = np.append(ho/np.sqrt(hmag_squared),2.0*np.arccos(s)) # ToDo: Check sanity check in reference implementation - + ax = np.append(ho/np.sqrt(hmag_squared),2.0*np.arccos(np.clip(s,-1.0,1.0))) return ax @@ -2155,32 +1899,16 @@ def qu2om(qu): return om if P > 0.0 else om.T -def om2qu(om): - """Orientation matrix to quaternion""" - s = [+om[0,0] +om[1,1] +om[2,2] +1.0, - +om[0,0] -om[1,1] -om[2,2] +1.0, - -om[0,0] +om[1,1] -om[2,2] +1.0, - -om[0,0] -om[1,1] +om[2,2] +1.0] - s = np.maximum(np.zeros(4),s) - qu = np.sqrt(s)*0.5*np.array([1.0,P,P,P]) - # verify the signs (q0 always positive) - #ToDo: Here I donot understand the original shortcut from paper to implementation - - qu /= np.linalg.norm(qu) - if any(isone(abs(qu))): qu[np.where(np.logical_not(isone(qu)))] = 0.0 - if om[2,1] < om[1,2]: qu[1] *= -1.0 - if om[0,2] < om[2,0]: qu[2] *= -1.0 - if om[1,0] < om[0,1]: qu[3] *= -1.0 - if any(om2ax(om)[0:3]*qu[1:4] < 0.0): print('sign problem',om2ax(om),qu) # something is wrong here - return qu - - def qu2ax(qu): - """Quaternion to axis angle""" - omega = 2.0 * np.arccos(qu[0]) - if iszero(omega): # return axis as [001] if the angle is zero + """ + Quaternion to axis angle + + Modified version of the original formulation, should be numerically more stable + """ + if isone(abs(qu[0])): # set axis to [001] if the angle is 0/360 ax = [ 0.0, 0.0, 1.0, 0.0 ] elif not iszero(qu[0]): + omega = 2.0 * np.arccos(qu[0]) s = np.sign(qu[0])/np.sqrt(qu[1]**2+qu[2]**2+qu[3]**2) ax = [ qu[1]*s, qu[2]*s, qu[3]*s, omega ] else: @@ -2196,14 +1924,14 @@ def qu2ro(qu): else: s = np.linalg.norm([qu[1],qu[2],qu[3]]) ro = [0.0,0.0,P,0.0] if iszero(s) else \ - [ qu[1]/s, qu[2]/s, qu[3]/s, np.tan(np.arccos(qu[0]))] + [ qu[1]/s, qu[2]/s, qu[3]/s, np.tan(np.arccos(np.clip(qu[0],-1.0,1.0)))] # avoid numerical difficulties return np.array(ro) def qu2ho(qu): """Quaternion to homochoric""" - omega = 2.0 * np.arccos(qu[0]) + omega = 2.0 * np.arccos(np.clip(qu[0],-1.0,1.0)) # avoid numerical difficulties if iszero(omega): ho = np.array([ 0.0, 0.0, 0.0 ]) @@ -2288,7 +2016,16 @@ def eu2cu(eu): def om2cu(om): """Orientation matrix to cubochoric""" return ho2cu(om2ho(om)) + +def om2qu(om): + """ + Orientation matrix to quaternion + + The original formulation (direct conversion) had numerical issues + """ + return ax2qu(om2ax(om)) + def ax2cu(ax): """Axis angle to cubochoric""" From fff377de7f2b5fb012e67514e4c0d90b2e8f6543 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 22:06:31 +0100 Subject: [PATCH 79/97] initial simplification. Should be able to generate from table containing either or and --- processing/pre/geom_fromTable.py | 141 +++---------------------------- 1 file changed, 14 insertions(+), 127 deletions(-) diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index e1157d325..f06f0e3d0 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -32,34 +32,6 @@ parser.add_option('--microstructure', dest = 'microstructure', type = 'string', metavar = 'string', help = 'microstructure label') -parser.add_option('-t', '--tolerance', - dest = 'tolerance', - type = 'float', metavar = 'float', - help = 'angular tolerance for orientation squashing [%default]') -parser.add_option('-e', '--eulers', - dest = 'eulers', - type = 'string', metavar = 'string', - help = 'Euler angles label') -parser.add_option('-d', '--degrees', - dest = 'degrees', - action = 'store_true', - help = 'all angles are in degrees') -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', @@ -68,10 +40,7 @@ parser.add_option('--axes', dest = 'axes', type = 'string', nargs = 3, metavar = ' '.join(['string']*3), help = 'orientation coordinate frame in terms of position coordinate frame [same]') -parser.add_option('-s', '--symmetry', - dest = 'symmetry', - action = 'extend', metavar = '', - help = 'crystal symmetry of each phase %default {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:]))) + parser.add_option('--homogenization', dest = 'homogenization', type = 'int', metavar = 'int', @@ -80,9 +49,7 @@ parser.add_option('--crystallite', dest = 'crystallite', type = 'int', metavar = 'int', help = 'crystallite index to be used [%default]') -parser.add_option('--verbose', - dest = 'verbose', action = 'store_true', - help = 'output extra info') + parser.set_defaults(symmetry = [damask.Symmetry.lattices[-1]], tolerance = 0.0, @@ -95,12 +62,7 @@ parser.set_defaults(symmetry = [damask.Symmetry.lattices[-1]], (options,filenames) = parser.parse_args() -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, +input = [ options.quaternion is not None, options.microstructure is not None, ] @@ -109,14 +71,9 @@ if np.sum(input) != 1: 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'), - ([options.a,options.b,options.c],[3,3,3],'frame'), - (options.matrix,9,'matrix'), - (options.quaternion,4,'quaternion'), +(label,dim,inputtype) = [(options.quaternion,4,'quaternion'), (options.microstructure,1,'microstructure'), ][np.where(input)[0][0]] # select input label that was requested -toRadians = math.pi/180.0 if options.degrees else 1.0 # rescale all angles to radians -threshold = np.cos(options.tolerance/2.*toRadians) # cosine of (half of) tolerance angle # --- loop over input files ------------------------------------------------------------------------- @@ -157,10 +114,8 @@ 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 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...') # --------------- figure out size and grid --------------------------------------------------------- @@ -196,17 +151,10 @@ for name in filenames: grain = table.data[:,colOri] nGrains = len(np.unique(grain)) - else: - - if options.verbose: bg = damask.util.backgroundMessage(); bg.start() # start background messaging + elif inputtype == 'quaternion': colPhase = -1 # column of phase data comes last - if options.verbose: bg.set_message('sorting positions...') index = np.lexsort((table.data[:,0],table.data[:,1],table.data[:,2])) # index of position when sorting x fast, z slow - if options.verbose: bg.set_message('building KD tree...') - KDTree = scipy.spatial.KDTree((table.data[index,:3]-mincorner) / delta) # build KDTree with dX = dY = dZ = 1 and origin 0,0,0 - - statistics = {'global': 0, 'local': 0} grain = -np.ones(N,dtype = 'int32') # initialize empty microstructure orientations = [] # orientations multiplicity = [] # orientation multiplicity (number of group members) @@ -215,87 +163,26 @@ for name in filenames: existingGrains = np.arange(nGrains) myPos = 0 # position (in list) of current grid point - tick = time.clock() - if options.verbose: bg.set_message('assigning grain IDs...') for z in range(grid[2]): for y in range(grid[1]): for x in range(grid[0]): - if (myPos+1)%(N/500.) < 1: - time_delta = (time.clock()-tick) * (N - myPos) / myPos - if options.verbose: bg.set_message('(%02i:%02i:%02i) processing point %i of %i (grain count %i)...' - %(time_delta//3600,time_delta%3600//60,time_delta%60,myPos,N,nGrains)) + myData = table.data[index[myPos]] # read data for current grid point myPhase = int(myData[colPhase]) - 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, - symmetry = mySym) - elif inputtype == 'matrix': - o = damask.Orientation(matrix = myData[colOri:colOri+9].reshape(3,3), - symmetry = mySym) - elif inputtype == 'frame': - o = damask.Orientation(matrix = np.hstack((myData[colOri[0]:colOri[0]+3], - myData[colOri[1]:colOri[1]+3], - myData[colOri[2]:colOri[2]+3], - )).reshape(3,3), - symmetry = mySym) - elif inputtype == 'quaternion': - o = damask.Orientation(quaternion = myData[colOri:colOri+4], - symmetry = mySym) + + o = damask.Rotation(myData[colOri:colOri+4]) - cos_disorientations = -np.ones(1,dtype=float) # largest possible disorientation - closest_grain = -1 # invalid neighbor - - 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)] - 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.q \ - for grainID in grains]) # store disorientation per grainID - 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)))] # other already identified grains (of my phase) - - if len(grains) > 0: - cos_disorientations = np.array([o.disorientation(orientations[grainID], - SST = False)[0].quaternion.q \ - for grainID in grains]) # store disorientation per grainID - 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? - grainID = grains[closest_grain] - grain[myPos] = grainID # assign myself to that grain ... - orientations[grainID] = damask.Orientation.average([orientations[grainID],o], - [multiplicity[grainID],1]) # update average orientation of best matching grain - multiplicity[grainID] += 1 - statistics[match] += 1 - else: - grain[myPos] = nGrains # assign new grain to me ... - nGrains += 1 # ... and update counter - orientations.append(o) # store new orientation for future comparison - multiplicity.append(1) # having single occurrence so far - phases.append(myPhase) # store phase info for future reporting - existingGrains = np.arange(nGrains) # update list of existing grains + grain[myPos] = nGrains # assign new grain to me ... + nGrains += 1 # ... and update counter + orientations.append(o) # store new orientation for future comparison + multiplicity.append(1) # having single occurrence so far + phases.append(myPhase) # store phase info for future reporting + existingGrains = np.arange(nGrains) # update list of existing grains myPos += 1 - if options.verbose: - bg.stop() - bg.join() - damask.util.croak("{} seconds total.\n{} local and {} global matches.".\ - format(time.clock()-tick,statistics['local'],statistics['global'])) grain += 1 # offset from starting index 0 to 1 From a8e8b75cc07d2af85fb86f2dbfc4ae1827ad2d49 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 22:13:24 +0100 Subject: [PATCH 80/97] use new rotation class --- processing/pre/geom_rotate.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/processing/pre/geom_rotate.py b/processing/pre/geom_rotate.py index eb70f7137..4da59cddf 100755 --- a/processing/pre/geom_rotate.py +++ b/processing/pre/geom_rotate.py @@ -52,13 +52,14 @@ parser.set_defaults(degrees = False, 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...') -eulers = np.array(damask.orientation.Orientation( - quaternion = np.array(options.quaternion) if options.quaternion else None, - angleAxis = np.array(options.rotation) if options.rotation else None, - matrix = np.array(options.matrix) if options.matrix else None, - Eulers = np.array(options.eulers) if options.eulers else None, - degrees = options.degrees, - ).asEulers(degrees=True)) +if options.quaternion is not None: + eulers = damask.Rotation.fromQuaternion(np.array(options.quaternion)).asEulers(degrees=True) +if options.rotation is not None: + eulers = damask.Rotation.fromAxisAngle(np.array(options.rotation,degrees=True)).asEulers(degrees=True) +if options.matrix is not None: + eulers = damask.Rotation.fromMatrix(np.array(options.Matrix)).asEulers(degrees=True) +if options.eulers is not None: + eulers = damask.Rotation.fromEulers(np.array(options.eulers),degrees=True).asEulers(degrees=True) # --- loop over input files ------------------------------------------------------------------------- From 9fa2553af4cbb90f10450004be83314bed0f8a07 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 22:14:55 +0100 Subject: [PATCH 81/97] task for DREAM.3D if needed pointwise takeover should not be a problem anymore as reading in takes no time (at least in comparison to addGrainID) --- processing/post/addGrainID.py | 176 ---------------------------------- 1 file changed, 176 deletions(-) delete mode 100755 processing/post/addGrainID.py diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py deleted file mode 100755 index 6493736d8..000000000 --- a/processing/post/addGrainID.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- - -import os,sys,copy -import numpy as np -import damask -from optparse import OptionParser -from scipy import spatial - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ -Add grain index based on similiarity of crystal lattice orientation. - -""", version = scriptID) - -parser.add_option('-r', - '--radius', - dest = 'radius', - type = 'float', metavar = 'float', - help = 'search radius') -parser.add_option('-d', - '--disorientation', - dest = 'disorientation', - type = 'float', metavar = 'float', - help = 'disorientation threshold in degrees [%default]') -parser.add_option('-s', - '--symmetry', - dest = 'symmetry', type = 'choice', choices = damask.Symmetry.lattices[1:], - metavar = 'string', - help = 'crystal symmetry [%default] {{{}}} '.format(', '.join(damask.Symmetry.lattices[1:]))) -parser.add_option('-o', - '--orientation', - dest = 'quaternion', - metavar = 'string', - help = 'label of crystal orientation given as unit quaternion [%default]') -parser.add_option('-p', - '--pos', '--position', - dest = 'pos', - metavar = 'string', - help = 'label of coordinates [%default]') -parser.add_option('--quiet', - dest='verbose', - action = 'store_false', - help = 'hide status bar (useful when piping to file)') - -parser.set_defaults(disorientation = 5, - verbose = True, - quaternion = 'orientation', - symmetry = damask.Symmetry.lattices[-1], - pos = 'pos', - ) - -(options, filenames) = parser.parse_args() - -if options.radius is None: - parser.error('no radius specified.') - -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) - except: continue - damask.util.report(scriptName,name) - -# ------------------------------------------ read header ------------------------------------------- - - table.head_read() - -# ------------------------------------------ sanity checks ----------------------------------------- - - errors = [] - remarks = [] - - if not 3 >= table.label_dimension(options.pos) >= 1: - errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - if not np.all(table.label_dimension(options.quaternion) == 4): - errors.append('input "{}" does not have dimension 4.'.format(options.quaternion)) - else: column = table.label_index(options.quaternion) - - 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:])) - table.labels_append('grainID_{}@{:g}'.format(options.quaternion,options.disorientation)) # report orientation source and disorientation - table.head_write() - -# ------------------------------------------ build KD tree ----------------------------------------- - - table.data_readArray(options.pos) # read position vectors - grainID = -np.ones(len(table.data),dtype=int) - Npoints = table.data.shape[0] - kdtree = spatial.KDTree(copy.deepcopy(table.data)) - -# ------------------------------------------ assign grain IDs -------------------------------------- - - orientations = [] # quaternions found for grain - memberCounts = [] # number of voxels in grain - p = 0 # point counter - g = 0 # grain counter - matchedID = -1 - lastDistance = np.dot(kdtree.data[-1]-kdtree.data[0],kdtree.data[-1]-kdtree.data[0]) # (arbitrarily) use diagonal of cloud - - table.data_rewind() - while table.data_read(): # read next data line of ASCII table - - if options.verbose and Npoints > 100 and p%(Npoints//100) == 0: # report in 1% steps if possible and avoid modulo by zero - damask.util.progressBar(iteration=p,total=Npoints) - - o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))), - symmetry = options.symmetry).reduced() - - matched = False - alreadyChecked = {} - candidates = [] - 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.q > cos_disorientation: # within threshold ... - candidates.append(gID) # remember as potential candidate - if disorientation.quaternion.q >= bestDisorientation.q: # ... and better than current best? - matched = True - matchedID = gID # remember that grain - bestDisorientation = disorientation.quaternion - - 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 - - grainID[p] = matchedID # remember grain index assigned to point - p += 1 # increment point - - 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 - damask.util.progressBar(iteration=1,total=1) - while outputAlive and table.data_read(): # read next data line of ASCII table - table.data_append(1+packingMap[grainID[p]]) # add (condensed) grain ID - outputAlive = table.data_write() # output processed line - p += 1 - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables From 9dc8dff4b10b302eaf5090ee903ae80108fb1c06 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 23 Feb 2019 22:33:21 +0100 Subject: [PATCH 82/97] cleaning and adding compatibility layer --- processing/pre/geom_fromTable.py | 4 ++-- python/damask/orientation.py | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index f06f0e3d0..c0c4cf4d1 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # -*- coding: UTF-8 no BOM -*- -import os,sys,math,time -import scipy.spatial, numpy as np +import os,sys,math +import numpy as np from optparse import OptionParser import damask diff --git a/python/damask/orientation.py b/python/damask/orientation.py index ffe6dd419..558e5f15d 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -973,7 +973,7 @@ class Symmetry: return True - def inDisorientationSST(self,R): + def inDisorientationSST(self,rodrigues): """ Check whether given Rodrigues vector (of misorientation) falls into standard stereographic triangle of own symmetry. @@ -981,7 +981,13 @@ class Symmetry: 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 + if isinstance(rodrigues, Quaternion): + R = rodrigues.asRodrigues() # translate accidentially passed quaternion + else: + R = rodrigues + + if R.shape[0]==4: # transition old (length not stored separately) to new + R = (R[0:3]*R[3]) epsilon = 0.0 if self.lattice == 'cubic': @@ -1428,7 +1434,8 @@ class Orientation2: theQ = sB.rotation*mis*sA.rotation.inversed() for k in range(2): theQ.inversed() - breaker = self.lattice.symmetry.inFZ(theQ.asRodriques()) #and (not SST or other.symmetry.inDisorientationSST(theQ)) + breaker = self.lattice.symmetry.inFZ(theQ.asRodrigues()) \ + and (not SST or other.lattice.symmetry.inDisorientationSST(theQ.asRodrigues())) if breaker: break if breaker: break if breaker: break @@ -1466,8 +1473,6 @@ class Orientation: def __init__(self, quaternion = Quaternion.fromIdentity(), Rodrigues = None, - angleAxis = None, - matrix = None, Eulers = None, random = False, # integer to have a fixed seed or True for real random symmetry = None, @@ -1480,10 +1485,6 @@ class Orientation: self.quaternion = Quaternion.fromRandom(randomSeed=random) elif isinstance(Eulers, np.ndarray) and Eulers.shape == (3,): # based on given Euler angles self.quaternion = Quaternion.fromEulers(Eulers,degrees=degrees) - elif isinstance(matrix, np.ndarray) : # based on given rotation matrix - self.quaternion = Quaternion.fromMatrix(matrix) - elif isinstance(angleAxis, np.ndarray) and angleAxis.shape == (4,): # based on given angle and rotation axis - self.quaternion = Quaternion.fromAngleAxis(angleAxis[0],angleAxis[1:4],degrees=degrees) elif isinstance(Rodrigues, np.ndarray) and Rodrigues.shape == (3,): # based on given Rodrigues vector self.quaternion = Quaternion.fromRodrigues(Rodrigues) elif isinstance(quaternion, Quaternion): # based on given quaternion @@ -1524,7 +1525,6 @@ class Orientation: def inFZ(self): return self.symmetry.inFZ(self.quaternion.asRodrigues()) - infz = property(inFZ) def equivalentQuaternions(self, who = []): From d3ac3cc0f50624522e61d800cd438b75dee2def7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 08:08:14 +0100 Subject: [PATCH 83/97] using new Orientation class --- .gitlab-ci.yml | 4 +- PRIVATE | 2 +- processing/post/addIPFcolor.py | 8 +- processing/post/addPole.py | 4 +- processing/post/rotateData.py | 2 +- processing/pre/geom_fromTable.py | 3 - python/damask/__init__.py | 2 +- python/damask/orientation.py | 946 ++++++++----------------------- 8 files changed, 244 insertions(+), 727 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 368888436..de2fa3906 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -207,7 +207,9 @@ Post_ParaviewRelated: Post_OrientationConversion: stage: postprocessing - script: OrientationConversion/test.py + script: + - OrientationConversion/test.py + - OrientationConversion/test2.py except: - master - release diff --git a/PRIVATE b/PRIVATE index f0090997d..8deb37dd4 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit f0090997df817f0a0b5a480a60e81929875b1010 +Subproject commit 8deb37dd4526fb5e1425fe1d2360508d01b6ac3e diff --git a/processing/post/addIPFcolor.py b/processing/post/addIPFcolor.py index 9c191b3ad..c5e4d8704 100755 --- a/processing/post/addIPFcolor.py +++ b/processing/post/addIPFcolor.py @@ -41,6 +41,10 @@ parser.set_defaults(pole = (0.0,0.0,1.0), (options, filenames) = parser.parse_args() +# damask.Orientation requires Bravais lattice, but we are only interested in symmetry +symmetry2lattice={'cubic':'bcc','hexagonal':'hex','tetragonal':'bct'} +lattice = symmetry2lattice[options.symmetry] + pole = np.array(options.pole) pole /= np.linalg.norm(pole) @@ -78,8 +82,8 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table - o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4]))), - symmetry = options.symmetry).reduced() + o = damask.Orientation(np.array(list(map(float,table.data[column:column+4]))), + lattice = lattice).reduced() table.data_append(o.IPFcolor(pole)) outputAlive = table.data_write() # output processed line diff --git a/processing/post/addPole.py b/processing/post/addPole.py index 628d64d5e..5116589b4 100755 --- a/processing/post/addPole.py +++ b/processing/post/addPole.py @@ -75,9 +75,9 @@ for name in filenames: # ------------------------------------------ process data ------------------------------------------ outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table - o = damask.Orientation(quaternion = np.array(list(map(float,table.data[column:column+4])))) + o = damask.Rotation(np.array(list(map(float,table.data[column:column+4])))) - rotatedPole = o.quaternion*pole # rotate pole according to crystal orientation + rotatedPole = o*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 diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index 65f5aaaa2..ae42cb54a 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -31,7 +31,7 @@ parser.add_option('--degrees', action = 'store_true', help = 'angles are given in degrees') -parser.set_defaults(rotation = (0.,1.,0.,0.), # no rotation about 1,0,0 +parser.set_defaults(rotation = (0.,1.,1.,1.), # no rotation about 1,1,1 degrees = False, ) diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index c0c4cf4d1..ad598d5b1 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -52,11 +52,8 @@ parser.add_option('--crystallite', parser.set_defaults(symmetry = [damask.Symmetry.lattices[-1]], - tolerance = 0.0, - degrees = False, homogenization = 1, crystallite = 1, - verbose = False, pos = 'pos', ) diff --git a/python/damask/__init__.py b/python/damask/__init__.py index a9209a1c6..d7ed4a9f9 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -13,7 +13,7 @@ from .asciitable import ASCIItable # noqa from .config import Material # noqa from .colormaps import Colormap, Color # noqa -from .orientation import Quaternion, Symmetry, Rotation, Orientation # noqa +from .orientation import Symmetry, Lattice, Rotation, Orientation # noqa #from .block import Block # only one class from .result import Result # noqa diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 558e5f15d..2f9731966 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -1,13 +1,13 @@ # -*- coding: UTF-8 no BOM -*- -import math,os +import math import numpy as np from . import Lambert P = -1 #################################################################################################### -class Quaternion2: +class Quaternion: u""" Quaternion with basic operations @@ -50,7 +50,7 @@ class Quaternion2: def __add__(self, other): """Addition""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): return self.__class__(q=self.q + other.q, p=self.p + other.p) else: @@ -58,7 +58,7 @@ class Quaternion2: def __iadd__(self, other): """In-place addition""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): self.q += other.q self.p += other.p return self @@ -72,7 +72,7 @@ class Quaternion2: def __sub__(self, other): """Subtraction""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): return self.__class__(q=self.q - other.q, p=self.p - other.p) else: @@ -80,7 +80,7 @@ class Quaternion2: def __isub__(self, other): """In-place subtraction""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): self.q -= other.q self.p -= other.p return self @@ -96,7 +96,7 @@ class Quaternion2: def __mul__(self, other): """Multiplication with quaternion or scalar""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): return self.__class__(q=self.q*other.q - np.dot(self.p,other.p), p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)) elif isinstance(other, (int, float)): @@ -107,7 +107,7 @@ class Quaternion2: def __imul__(self, other): """In-place multiplication with quaternion or scalar""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): self.q = self.q*other.q - np.dot(self.p,other.p) self.p = self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p) return self @@ -120,7 +120,7 @@ class Quaternion2: def __truediv__(self, other): """Divsion with quaternion or scalar""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): s = other.conjugate()/abs(other)**2. return self.__class__(q=self.q * s, p=self.p * s) @@ -133,7 +133,7 @@ class Quaternion2: def __itruediv__(self, other): """In-place divsion with quaternion or scalar""" - if isinstance(other, Quaternion2): + if isinstance(other, Quaternion): s = other.conjugate()/abs(other)**2. self *= s return self @@ -215,7 +215,8 @@ class Rotation: u""" Orientation stored as unit quaternion. - All methods and naming conventions based on Rowenhorst_etal2015 + Following: D Rowenhorst et al. Consistent representations of and conversions between 3D rotations + 10.1088/0965-0393/23/8/083501 Convention 1: coordinate frames are right-handed Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation when viewing from the end point of the rotation axis towards the origin @@ -242,10 +243,10 @@ class Rotation: If a quaternion is given, it needs to comply with the convection. Use .fromQuaternion to check the input. """ - if isinstance(quaternion,Quaternion2): + if isinstance(quaternion,Quaternion): self.quaternion = quaternion.copy() else: - self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4]) + self.quaternion = Quaternion(q=quaternion[0],p=quaternion[1:4]) self.quaternion.homomorph() # ToDo: Needed? def __repr__(self): @@ -453,374 +454,7 @@ class Rotation: def misorientation(self,other): """Misorientation""" return self.__class__(other.quaternion*self.quaternion.conjugated()) - - -# ****************************************************************************************** -class Quaternion: - u""" - Orientation represented as unit quaternion. - - All methods and naming conventions based on Rowenhorst_etal2015 - Convention 1: coordinate frames are right-handed - Convention 2: a rotation angle ω is taken to be positive for a counterclockwise rotation - when viewing from the end point of the rotation axis towards the origin - Convention 3: rotations will be interpreted in the passive sense - Convention 4: Euler angle triplets are implemented using the Bunge convention, - with the angular ranges as [0, 2π],[0, π],[0, 2π] - Convention 5: the rotation angle ω is limited to the interval [0, π] - Convention 6: P = -1 (as default) - - w is the real part, (x, y, z) are the imaginary parts. - - Vector "a" (defined in coordinate system "A") is passively rotated - resulting in new coordinates "b" when expressed in system "B". - b = Q * a - b = np.dot(Q.asMatrix(),a) - """ - - def __init__(self, - quat = None, - q = 1.0, - p = np.zeros(3,dtype=float)): - """Initializes to identity unless specified""" - self.q = quat[0] if quat is not None else q - self.p = np.array(quat[1:4]) if quat is not None else p - self.homomorph() - - def __iter__(self): - """Components""" - return iter(self.asList()) - - def __copy__(self): - """Copy""" - return self.__class__(q=self.q,p=self.p.copy()) - - copy = __copy__ - - def __repr__(self): - """Readable string""" - return 'Quaternion(real={q:+.6f}, imag=<{p[0]:+.6f}, {p[1]:+.6f}, {p[2]:+.6f}>)'.format(q=self.q,p=self.p) - - def __pow__(self, exponent): - """Power""" - omega = math.acos(self.q) - return self.__class__(q= math.cos(exponent*omega), - p=self.p * math.sin(exponent*omega)/math.sin(omega)) - - def __ipow__(self, exponent): - """In-place power""" - omega = math.acos(self.q) - self.q = math.cos(exponent*omega) - self.p *= math.sin(exponent*omega)/math.sin(omega) - return self - - def __mul__(self, other): - """Multiplication""" - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - try: # quaternion - return self.__class__(q=self.q*other.q - np.dot(self.p,other.p), - p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)) - except: pass - try: # vector (perform passive rotation) - ( x, y, z) = self.p - (Vx,Vy,Vz) = other[0:3] - A = self.q*self.q - np.dot(self.p,self.p) - B = 2.0 * (x*Vx + y*Vy + z*Vz) - C = 2.0 * P*self.q - - return np.array([ - A*Vx + B*x + C*(y*Vz - z*Vy), - A*Vy + B*y + C*(z*Vx - x*Vz), - A*Vz + B*z + C*(x*Vy - y*Vx), - ]) - except: pass - try: # scalar - return self.__class__(q=self.q*other, - p=self.p*other) - except: - return self.copy() - - def __imul__(self, other): - """In-place multiplication""" - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - try: # Quaternion - self.q = self.q*other.q - np.dot(self.p,other.p) - self.p = self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p) - except: pass - return self - - def __div__(self, other): - """Division""" - if isinstance(other, (int,float)): - return self.__class__(q=self.q / other, - p=self.p / other) - else: - return NotImplemented - - def __idiv__(self, other): - """In-place division""" - if isinstance(other, (int,float)): - self.q /= other - self.p /= other - return self - - def __add__(self, other): - """Addition""" - if isinstance(other, Quaternion): - return self.__class__(q=self.q + other.q, - p=self.p + other.p) - else: - return NotImplemented - - def __iadd__(self, other): - """In-place addition""" - if isinstance(other, Quaternion): - self.q += other.q - self.p += other.p - return self - - def __sub__(self, other): - """Subtraction""" - if isinstance(other, Quaternion): - return self.__class__(q=self.q - other.q, - p=self.p - other.p) - else: - return NotImplemented - - def __isub__(self, other): - """In-place subtraction""" - if isinstance(other, Quaternion): - self.q -= other.q - self.p -= other.p - return self - - def __neg__(self): - """Additive inverse""" - self.q = -self.q - self.p = -self.p - return self - - def __abs__(self): - """Norm""" - return math.sqrt(self.q ** 2 + np.dot(self.p,self.p)) - - magnitude = __abs__ - - def __eq__(self,other): - """Equal (sufficiently close) to each other""" - return np.isclose(( self-other).magnitude(),0.0) \ - or np.isclose((-self-other).magnitude(),0.0) - - def __ne__(self,other): - """Not equal (sufficiently close) to each other""" - return not self.__eq__(other) - - def __cmp__(self,other): - """Linear ordering""" - return (1 if np.linalg.norm(self.asRodrigues()) > np.linalg.norm(other.asRodrigues()) else 0) \ - - (1 if np.linalg.norm(self.asRodrigues()) < np.linalg.norm(other.asRodrigues()) else 0) - - def magnitude_squared(self): - return self.q ** 2 + np.dot(self.p,self.p) - - def normalize(self): - d = self.magnitude() - if d > 0.0: - self.q /= d - self.p /= d - return self - - def conjugate(self): - self.p = -self.p - return self - - def homomorph(self): - if self.q < 0.0: - self.q = -self.q - self.p = -self.p - return self - - def normalized(self): - return self.copy().normalize() - - def conjugated(self): - return self.copy().conjugate() - - def homomorphed(self): - return self.copy().homomorph() - - def asList(self): - return [self.q]+list(self.p) - - def asM(self): # to find Averaging Quaternions (see F. Landis Markley et al.) - return np.outer(self.asList(),self.asList()) - def asMatrix(self): - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - qbarhalf = 0.5*(self.q**2 - np.dot(self.p,self.p)) - return 2.0*np.array( - [[ qbarhalf + self.p[0]**2 , - self.p[0]*self.p[1] -P* self.q*self.p[2], - self.p[0]*self.p[2] +P* self.q*self.p[1] ], - [ self.p[0]*self.p[1] +P* self.q*self.p[2], - qbarhalf + self.p[1]**2 , - self.p[1]*self.p[2] -P* self.q*self.p[0] ], - [ self.p[0]*self.p[2] -P* self.q*self.p[1], - self.p[1]*self.p[2] +P* self.q*self.p[0], - qbarhalf + self.p[2]**2 ], - ]) - - def asAngleAxis(self, - degrees = False, - flat = False): - - angle = 2.0*math.acos(self.q) - - if np.isclose(angle,0.0): - angle = 0.0 - axis = np.array([0.0,0.0,1.0]) - elif np.isclose(self.q,0.0): - angle = math.pi - axis = self.p - else: - axis = np.sign(self.q)*self.p/np.linalg.norm(self.p) - - angle = np.degrees(angle) if degrees else angle - - return np.hstack((angle,axis)) if flat else (angle,axis) - - def asRodrigues(self): - return np.inf*np.ones(3) if np.isclose(self.q,0.0) else self.p/self.q - - -# # Static constructors - @classmethod - def fromIdentity(cls): - return cls() - - - @classmethod - def fromRandom(cls,randomSeed = None): - import binascii - if randomSeed is None: - randomSeed = int(binascii.hexlify(os.urandom(4)),16) - np.random.seed(randomSeed) - r = np.random.random(3) - A = math.sqrt(max(0.0,r[2])) - B = math.sqrt(max(0.0,1.0-r[2])) - w = math.cos(2.0*math.pi*r[0])*A - x = math.sin(2.0*math.pi*r[1])*B - y = math.cos(2.0*math.pi*r[1])*B - z = math.sin(2.0*math.pi*r[0])*A - return cls(quat=[w,x,y,z]) - - - @classmethod - def fromRodrigues(cls, rodrigues): - if not isinstance(rodrigues, np.ndarray): rodrigues = np.array(rodrigues) - norm = np.linalg.norm(rodrigues) - halfangle = math.atan(norm) - s = math.sin(halfangle) - c = math.cos(halfangle) - return cls(q=c,p=s*rodrigues/norm) - - - @classmethod - def fromAngleAxis(cls, - angle, - axis, - degrees = False): - if not isinstance(axis, np.ndarray): axis = np.array(axis,dtype=float) - axis = axis.astype(float)/np.linalg.norm(axis) - angle = np.radians(angle) if degrees else angle - s = math.sin(0.5 * angle) - c = math.cos(0.5 * angle) - return cls(q=c,p=axis*s) - - - @classmethod - def fromEulers(cls, - eulers, - degrees = False): - if not isinstance(eulers, np.ndarray): eulers = np.array(eulers,dtype=float) - eulers = np.radians(eulers) if degrees else eulers - - sigma = 0.5*(eulers[0]+eulers[2]) - delta = 0.5*(eulers[0]-eulers[2]) - c = np.cos(0.5*eulers[1]) - s = np.sin(0.5*eulers[1]) - - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - w = c * np.cos(sigma) - x = -P * s * np.cos(delta) - y = -P * s * np.sin(delta) - z = -P * c * np.sin(sigma) - return cls(quat=[w,x,y,z]) - - -# Modified Method to calculate Quaternion from Orientation Matrix, -# Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ - - @classmethod - def fromMatrix(cls, m): - if m.shape != (3,3) and np.prod(m.shape) == 9: - m = m.reshape(3,3) - - # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 - P = -1.0 - w = 0.5*math.sqrt(max(0.0,1.0+m[0,0]+m[1,1]+m[2,2])) - x = P*0.5*math.sqrt(max(0.0,1.0+m[0,0]-m[1,1]-m[2,2])) - y = P*0.5*math.sqrt(max(0.0,1.0-m[0,0]+m[1,1]-m[2,2])) - z = P*0.5*math.sqrt(max(0.0,1.0-m[0,0]-m[1,1]+m[2,2])) - - x *= -1 if m[2,1] < m[1,2] else 1 - y *= -1 if m[0,2] < m[2,0] else 1 - z *= -1 if m[1,0] < m[0,1] else 1 - - return cls(quat=np.array([w,x,y,z])/math.sqrt(w**2 + x**2 + y**2 + z**2)) - - - @classmethod - def new_interpolate(cls, q1, q2, t): - """ - 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() - - costheta = q1.q*q2.q + np.dot(q1.p,q2.p) - if costheta < 0.: - costheta = -costheta - q1 = q1.conjugated() - elif costheta > 1.: - costheta = 1. - - theta = math.acos(costheta) - if abs(theta) < 0.01: - Q.q = q2.q - Q.p = q2.p - return Q - - sintheta = math.sqrt(1.0 - costheta * costheta) - if abs(sintheta) < 0.01: - Q.q = (q1.q + q2.q) * 0.5 - Q.p = (q1.p + q2.p) * 0.5 - return Q - - ratio1 = math.sin((1.0 - t) * theta) / sintheta - ratio2 = math.sin( t * theta) / sintheta - - Q.q = q1.q * ratio1 + q2.q * ratio2 - Q.p = q1.p * ratio1 + q2.p * ratio2 - return Q - # ****************************************************************************************** class Symmetry: @@ -932,26 +566,16 @@ class Symmetry: [ 1.0,0.0,0.0,0.0 ], ] - return list(map(Quaternion, - np.array(symQuats)[np.atleast_1d(np.array(who)) if who != [] else range(len(symQuats))])) + return np.array(symQuats) - - def equivalentQuaternions(self, - quaternion, - who = []): - """List of symmetrically equivalent quaternions based on own symmetry.""" - return [q*quaternion for q in self.symmetryQuats(who)] - def inFZ(self,R): - """Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" - if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentally passed quaternion -# fundamental zone in Rodrigues space is point symmetric around origin - - if R.shape[0]==4: # transition old (length not stored separately) to new - Rabs = abs(R[0:3]*R[3]) - else: - Rabs = abs(R) + """ + Check whether given Rodrigues vector falls into fundamental zone of own symmetry. + + Fundamental zone in Rodrigues space is point symmetric around origin. + """ + Rabs = abs(R[0:3]*R[3]) if self.lattice == 'cubic': return math.sqrt(2.0)-1.0 >= Rabs[0] \ @@ -1184,181 +808,181 @@ class Lattice: # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 GT = {'mapping':{'fcc':0,'bcc':1}, 'planes': np.array([ - [[ 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],[ 0, -1, 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],[ 0, -1, 1]], - [[ 1, -1, 1],[ 1, 0, 1]]],dtype='float'), + [[ 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],[ 0, -1, 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],[ 0, -1, 1]], + [[ 1, -1, 1],[ 1, 0, 1]]],dtype='float'), 'directions': np.array([ - [[ -5,-12, 17],[-17, -7, 17]], - [[ 17, -5,-12],[ 17,-17, -7]], - [[-12, 17, -5],[ -7, 17,-17]], - [[ 5, 12, 17],[ 17, 7, 17]], - [[-17, 5,-12],[-17, 17, -7]], - [[ 12,-17, -5],[ 7,-17,-17]], - [[ -5, 12,-17],[-17, 7,-17]], - [[ 17, 5, 12],[ 17, 17, 7]], - [[-12,-17, 5],[ -7,-17, 17]], - [[ 5,-12,-17],[ 17, -7,-17]], - [[-17, -5, 12],[-17,-17, 7]], - [[ 12, 17, 5],[ 7, 17, 17]], - [[ -5, 17,-12],[-17, 17, -7]], - [[-12, -5, 17],[ -7,-17, 17]], - [[ 17,-12, -5],[ 17, -7,-17]], - [[ 5,-17,-12],[ 17,-17, -7]], - [[ 12, 5, 17],[ 7, 17, 17]], - [[-17, 12, -5],[-17, 7,-17]], - [[ -5,-17, 12],[-17,-17, 7]], - [[-12, 5,-17],[ -7, 17,-17]], - [[ 17, 12, 5],[ 17, 7, 17]], - [[ 5, 17, 12],[ 17, 17, 7]], - [[ 12, -5,-17],[ 7,-17,-17]], - [[-17,-12, 5],[-17, 7, 17]]],dtype='float')} + [[ -5,-12, 17],[-17, -7, 17]], + [[ 17, -5,-12],[ 17,-17, -7]], + [[-12, 17, -5],[ -7, 17,-17]], + [[ 5, 12, 17],[ 17, 7, 17]], + [[-17, 5,-12],[-17, 17, -7]], + [[ 12,-17, -5],[ 7,-17,-17]], + [[ -5, 12,-17],[-17, 7,-17]], + [[ 17, 5, 12],[ 17, 17, 7]], + [[-12,-17, 5],[ -7,-17, 17]], + [[ 5,-12,-17],[ 17, -7,-17]], + [[-17, -5, 12],[-17,-17, 7]], + [[ 12, 17, 5],[ 7, 17, 17]], + [[ -5, 17,-12],[-17, 17, -7]], + [[-12, -5, 17],[ -7,-17, 17]], + [[ 17,-12, -5],[ 17, -7,-17]], + [[ 5,-17,-12],[ 17,-17, -7]], + [[ 12, 5, 17],[ 7, 17, 17]], + [[-17, 12, -5],[-17, 7,-17]], + [[ -5,-17, 12],[-17,-17, 7]], + [[-12, 5,-17],[ -7, 17,-17]], + [[ 17, 12, 5],[ 17, 7, 17]], + [[ 5, 17, 12],[ 17, 17, 7]], + [[ 12, -5,-17],[ 7,-17,-17]], + [[-17,-12, 5],[-17, 7, 17]]],dtype='float')} # Greninger--Troiano' orientation relationship for fcc <-> bcc transformation # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 GTdash = {'mapping':{'fcc':0,'bcc':1}, 'planes': np.array([ - [[ 7, 17, 17],[ 12, 5, 17]], - [[ 17, 7, 17],[ 17, 12, 5]], - [[ 17, 17, 7],[ 5, 17, 12]], - [[ -7,-17, 17],[-12, -5, 17]], - [[-17, -7, 17],[-17,-12, 5]], - [[-17,-17, 7],[ -5,-17, 12]], - [[ 7,-17,-17],[ 12, -5,-17]], - [[ 17, -7,-17],[ 17,-12, -5]], - [[ 17,-17, -7],[ 5,-17,-12]], - [[ -7, 17,-17],[-12, 5,-17]], - [[-17, 7,-17],[-17, 12, -5]], - [[-17, 17, -7],[ -5, 17,-12]], - [[ 7, 17, 17],[ 12, 17, 5]], - [[ 17, 7, 17],[ 5, 12, 17]], - [[ 17, 17, 7],[ 17, 5, 12]], - [[ -7,-17, 17],[-12,-17, 5]], - [[-17, -7, 17],[ -5,-12, 17]], - [[-17,-17, 7],[-17, -5, 12]], - [[ 7,-17,-17],[ 12,-17, -5]], - [[ 17, -7,-17],[ 5, -12,-17]], - [[ 17,-17, 7],[ 17, -5,-12]], - [[ -7, 17,-17],[-12, 17, -5]], - [[-17, 7,-17],[ -5, 12,-17]], - [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), + [[ 7, 17, 17],[ 12, 5, 17]], + [[ 17, 7, 17],[ 17, 12, 5]], + [[ 17, 17, 7],[ 5, 17, 12]], + [[ -7,-17, 17],[-12, -5, 17]], + [[-17, -7, 17],[-17,-12, 5]], + [[-17,-17, 7],[ -5,-17, 12]], + [[ 7,-17,-17],[ 12, -5,-17]], + [[ 17, -7,-17],[ 17,-12, -5]], + [[ 17,-17, -7],[ 5,-17,-12]], + [[ -7, 17,-17],[-12, 5,-17]], + [[-17, 7,-17],[-17, 12, -5]], + [[-17, 17, -7],[ -5, 17,-12]], + [[ 7, 17, 17],[ 12, 17, 5]], + [[ 17, 7, 17],[ 5, 12, 17]], + [[ 17, 17, 7],[ 17, 5, 12]], + [[ -7,-17, 17],[-12,-17, 5]], + [[-17, -7, 17],[ -5,-12, 17]], + [[-17,-17, 7],[-17, -5, 12]], + [[ 7,-17,-17],[ 12,-17, -5]], + [[ 17, -7,-17],[ 5, -12,-17]], + [[ 17,-17, 7],[ 17, -5,-12]], + [[ -7, 17,-17],[-12, 17, -5]], + [[-17, 7,-17],[ -5, 12,-17]], + [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), 'directions': np.array([ - [[ 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]], - [[ 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]]],dtype='float')} + [[ 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]], + [[ 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]]],dtype='float')} # Nishiyama--Wassermann orientation relationship for fcc <-> bcc transformation # from H. Kitahara et al./Materials Characterization 54 (2005) 378-386 NW = {'mapping':{'fcc':0,'bcc':1}, 'planes': np.array([ - [[ 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],[ 0, 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],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]], - [[ -1, -1, 1],[ 0, 1, 1]]],dtype='float'), + [[ 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],[ 0, 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],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]], + [[ -1, -1, 1],[ 0, 1, 1]]],dtype='float'), 'directions': np.array([ - [[ 2, -1, -1],[ 0, -1, 1]], - [[ -1, 2, -1],[ 0, -1, 1]], - [[ -1, -1, 2],[ 0, -1, 1]], - [[ -2, -1, -1],[ 0, -1, 1]], - [[ 1, 2, -1],[ 0, -1, 1]], - [[ 1, -1, 2],[ 0, -1, 1]], - [[ 2, 1, -1],[ 0, -1, 1]], - [[ -1, -2, -1],[ 0, -1, 1]], - [[ -1, 1, 2],[ 0, -1, 1]], - [[ -1, 2, 1],[ 0, -1, 1]], - [[ -1, 2, 1],[ 0, -1, 1]], - [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} + [[ 2, -1, -1],[ 0, -1, 1]], + [[ -1, 2, -1],[ 0, -1, 1]], + [[ -1, -1, 2],[ 0, -1, 1]], + [[ -2, -1, -1],[ 0, -1, 1]], + [[ 1, 2, -1],[ 0, -1, 1]], + [[ 1, -1, 2],[ 0, -1, 1]], + [[ 2, 1, -1],[ 0, -1, 1]], + [[ -1, -2, -1],[ 0, -1, 1]], + [[ -1, 1, 2],[ 0, -1, 1]], + [[ -1, 2, 1],[ 0, -1, 1]], + [[ -1, 2, 1],[ 0, -1, 1]], + [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} # Pitsch orientation relationship for fcc <-> bcc transformation # from Y. He et al./Acta Materialia 53 (2005) 1179-1190 Pitsch = {'mapping':{'fcc':0,'bcc':1}, 'planes': np.array([ - [[ 0, 1, 0],[ -1, 0, 1]], - [[ 0, 0, 1],[ 1, -1, 0]], - [[ 1, 0, 0],[ 0, 1, -1]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 0, 1, 0],[ -1, 0, -1]], - [[ 0, 0, 1],[ -1, -1, 0]], - [[ 1, 0, 0],[ 0, -1, -1]], - [[ 1, 0, 0],[ 0, -1, 1]], - [[ 0, 1, 0],[ 1, 0, -1]], - [[ 0, 0, 1],[ -1, 1, 0]]],dtype='float'), + [[ 0, 1, 0],[ -1, 0, 1]], + [[ 0, 0, 1],[ 1, -1, 0]], + [[ 1, 0, 0],[ 0, 1, -1]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 0, 1, 0],[ -1, 0, -1]], + [[ 0, 0, 1],[ -1, -1, 0]], + [[ 1, 0, 0],[ 0, -1, -1]], + [[ 1, 0, 0],[ 0, -1, 1]], + [[ 0, 1, 0],[ 1, 0, -1]], + [[ 0, 0, 1],[ -1, 1, 0]]],dtype='float'), 'directions': np.array([ - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 0, 1, -1],[ -1, 1, -1]], - [[ -1, 0, 1],[ -1, -1, 1]], - [[ 1, -1, 0],[ 1, -1, -1]], - [[ 1, 0, -1],[ 1, -1, -1]], - [[ -1, 1, 0],[ -1, 1, -1]], - [[ 0, -1, 1],[ -1, -1, 1]], - [[ 0, 1, 1],[ -1, 1, 1]], - [[ 1, 0, 1],[ 1, -1, 1]], - [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 0, 1, -1],[ -1, 1, -1]], + [[ -1, 0, 1],[ -1, -1, 1]], + [[ 1, -1, 0],[ 1, -1, -1]], + [[ 1, 0, -1],[ 1, -1, -1]], + [[ -1, 1, 0],[ -1, 1, -1]], + [[ 0, -1, 1],[ -1, -1, 1]], + [[ 0, 1, 1],[ -1, 1, 1]], + [[ 1, 0, 1],[ 1, -1, 1]], + [[ 1, 1, 0],[ 1, 1, -1]]],dtype='float')} # Bain orientation relationship for fcc <-> bcc transformation # from Y. He et al./Journal of Applied Crystallography (2006). 39, 72-81 Bain = {'mapping':{'fcc':0,'bcc':1}, 'planes': np.array([ - [[ 1, 0, 0],[ 1, 0, 0]], - [[ 0, 1, 0],[ 0, 1, 0]], - [[ 0, 0, 1],[ 0, 0, 1]]],dtype='float'), + [[ 1, 0, 0],[ 1, 0, 0]], + [[ 0, 1, 0],[ 0, 1, 0]], + [[ 0, 0, 1],[ 0, 0, 1]]],dtype='float'), 'directions': np.array([ - [[ 0, 1, 0],[ 0, 1, 1]], - [[ 0, 0, 1],[ 1, 0, 1]], - [[ 1, 0, 0],[ 1, 1, 0]]],dtype='float')} + [[ 0, 1, 0],[ 0, 1, 1]], + [[ 0, 0, 1],[ 1, 0, 1]], + [[ 1, 0, 0],[ 1, 1, 0]]],dtype='float')} def relationOperations(self,model): @@ -1367,27 +991,30 @@ class Lattice: relationship = models[model] - r = {'lattice':Lattice((set(relationship['mapping'])-{self.lattice}).pop()), + r = {'lattice':Lattice((set(relationship['mapping'])-{self.lattice}).pop()), # target lattice 'rotations':[] } myPlane_id = relationship['mapping'][self.lattice] otherPlane_id = (myPlane_id+1)%2 myDir_id = myPlane_id +2 otherDir_id = otherPlane_id +2 + for miller in np.hstack((relationship['planes'],relationship['directions'])): - myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) - myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) - otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) - otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) - - myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]).T - otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]).T + myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) + myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) + myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]).T + + otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) + otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) + otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]).T + r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix,myMatrix.T))) + return r -class Orientation2: +class Orientation: """ Crystallographic orientation @@ -1426,32 +1053,28 @@ class Orientation2: # raise NotImplementedError('disorientation between different symmetry classes not supported yet.') mis = other.rotation*self.rotation.inversed() - mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations()[:1] # take all or only first sym operation + mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations()[:1] # take all or only first sym operation otherSymEqs = other.equivalentOrientations() for i,sA in enumerate(mySymEqs): for j,sB in enumerate(otherSymEqs): - theQ = sB.rotation*mis*sA.rotation.inversed() + r = sB.rotation*mis*sA.rotation.inversed() for k in range(2): - theQ.inversed() - breaker = self.lattice.symmetry.inFZ(theQ.asRodrigues()) \ - and (not SST or other.lattice.symmetry.inDisorientationSST(theQ.asRodrigues())) + r.inversed() + breaker = self.lattice.symmetry.inFZ(r.asRodrigues()) \ + and (not SST or other.lattice.symmetry.inDisorientationSST(r.asRodrigues())) if breaker: break if breaker: break if breaker: break -# disorientation, own sym, other sym, self-->other: True, self<--other: False - return theQ + return r def inFZ(self): return self.lattice.symmetry.inFZ(self.rotation.asRodrigues()) def equivalentOrientations(self): """List of orientations which are symmetrically equivalent""" - q = self.lattice.symmetry.symmetryQuats() - q2 = [Quaternion2(q=a.asList()[0],p=a.asList()[1:4]) for a in q] # convert Quaternion to Quaternion2 - x = [self.__class__(q3*self.rotation.quaternion,self.lattice) for q3 in q2] - return x + return [self.__class__(q*self.rotation.quaternion,self.lattice) for q in self.lattice.symmetry.symmetryQuats()] def relatedOrientations(self,model): """List of orientations related by the given orientation relationship""" @@ -1464,177 +1087,69 @@ class Orientation2: if self.lattice.symmetry.inFZ(me.rotation.asRodrigues()): break return self.__class__(me.rotation,self.lattice) - -# ****************************************************************************************** -class Orientation: - - __slots__ = ['quaternion','symmetry'] - - def __init__(self, - quaternion = Quaternion.fromIdentity(), - Rodrigues = None, - Eulers = None, - random = False, # integer to have a fixed seed or True for real random - symmetry = None, - degrees = False, - ): - if random: # produce random orientation - if isinstance(random, bool ): - self.quaternion = Quaternion.fromRandom() - else: - self.quaternion = Quaternion.fromRandom(randomSeed=random) - elif isinstance(Eulers, np.ndarray) and Eulers.shape == (3,): # based on given Euler angles - self.quaternion = Quaternion.fromEulers(Eulers,degrees=degrees) - elif isinstance(Rodrigues, np.ndarray) and Rodrigues.shape == (3,): # based on given Rodrigues vector - self.quaternion = Quaternion.fromRodrigues(Rodrigues) - elif isinstance(quaternion, Quaternion): # based on given quaternion - self.quaternion = quaternion.homomorphed() - elif (isinstance(quaternion, np.ndarray) and quaternion.shape == (4,)) or \ - (isinstance(quaternion, list) and len(quaternion) == 4 ): # based on given quaternion-like array - self.quaternion = Quaternion(quat=quaternion).homomorphed() - - 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 '\n'.join([ - 'Symmetry: {}'.format(self.symmetry), - 'Quaternion: {}'.format(self.quaternion), - 'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ), - ]) - - def asRodrigues(self): - return self.quaternion.asRodrigues() - rodrigues = property(asRodrigues) - - def asAngleAxis(self, - degrees = False, - flat = False): - return self.quaternion.asAngleAxis(degrees,flat) - - def asMatrix(self): - return self.quaternion.asMatrix() - matrix = property(asMatrix) - - def inFZ(self): - return self.symmetry.inFZ(self.quaternion.asRodrigues()) - - def equivalentQuaternions(self, - who = []): - return self.symmetry.equivalentQuaternions(self.quaternion,who) - - def equivalentOrientations(self, - who = []): - return [Orientation(quaternion = q, symmetry = self.symmetry.lattice) for q in self.equivalentQuaternions(who)] - - def reduced(self): - """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 - - return Orientation(quaternion=me,symmetry=self.symmetry.lattice) - - - 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 NotImplementedError('disorientation between different symmetry classes not supported yet.') - - misQ = other.quaternion*self.quaternion.conjugated() - mySymQs = self.symmetry.symmetryQuats() if SST else self.symmetry.symmetryQuats()[:1] # take all or only first sym operation - otherSymQs = other.symmetry.symmetryQuats() - for i,sA in enumerate(mySymQs): - for j,sB in enumerate(otherSymQs): - theQ = sB*misQ*sA.conjugated() - for k in range(2): - theQ.conjugate() - breaker = self.symmetry.inFZ(theQ) \ - and (not SST or other.symmetry.inDisorientationSST(theQ)) - if breaker: break - 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) - - def inversePole(self, axis, proper = False, SST = True): """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*axis # align crystal direction to axis - if self.symmetry.inSST(pole,proper): break # found SST version + for i,o in enumerate(self.equivalentOrientations()): # test all symmetric equivalent quaternions + pole = o.rotation*axis # align crystal direction to axis + if self.lattice.symmetry.inSST(pole,proper): break # found SST version else: - pole = self.quaternion*axis # align crystal direction to axis + pole = self.rotation*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""" color = np.zeros(3,'d') - for q in self.symmetry.equivalentQuaternions(self.quaternion): - pole = q*axis # align crystal direction to axis - inSST,color = self.symmetry.inSST(pole,color=True) + for o in self.equivalentOrientations(): + pole = o.rotation*axis # align crystal direction to axis + inSST,color = self.lattice.symmetry.inSST(pole,color=True) if inSST: break - return color + return color - @classmethod - def average(cls, - orientations, - multiplicity = []): - """ - 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. - doi: 10.2514/1.28949 - usage: - a = Orientation(Eulers=np.radians([10, 10, 0]), symmetry='hexagonal') - 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.") + # @classmethod + # def average(cls, + # orientations, + # multiplicity = []): + # """ + # Average orientation - N = len(orientations) - if multiplicity == [] or not multiplicity: - multiplicity = np.ones(N,dtype='i') + # 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. + # doi: 10.2514/1.28949 + # usage: + # a = Orientation(Eulers=np.radians([10, 10, 0]), symmetry='hexagonal') + # 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.") - 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 # noqa add (multiples) of this orientation to average noqa - eig, vec = np.linalg.eig(M/N) + # N = len(orientations) + # if multiplicity == [] or not multiplicity: + # multiplicity = np.ones(N,dtype='i') - return Orientation(quaternion = Quaternion(quat = np.real(vec.T[eig.argmax()])), - symmetry = reference.symmetry.lattice) + # 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 # noqa add (multiples) of this orientation to average noqa + # eig, vec = np.linalg.eig(M/N) + + # return Orientation(quaternion = Quaternion(quat = np.real(vec.T[eig.argmax()])), + # symmetry = reference.symmetry.lattice) #################################################################################################### -# Code below available according to the followin conditions on https://github.com/MarDiehl/3Drotations +# Code below available according to the following conditions on https://github.com/MarDiehl/3Drotations #################################################################################################### # Copyright (c) 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH # Copyright (c) 2013-2014, Marc De Graef/Carnegie Mellon University @@ -1725,7 +1240,7 @@ def eu2qu(eu): -P*sPhi*np.cos(ee[0]-ee[2]), -P*sPhi*np.sin(ee[0]-ee[2]), -P*cPhi*np.sin(ee[0]+ee[2]) ]) - #if qu[0] < 0.0: qu.homomorph() !ToDo: Check with original + #if qu[0] < 0.0: qu.homomorph() !ToDo: Check with original return qu @@ -1769,7 +1284,6 @@ def qu2eu(qu): eu = np.array([np.arctan2(-P*2.0*qu[0]*qu[3],qu[0]**2-qu[3]**2), 0.0, 0.0]) if iszero(q12) else \ np.array([np.arctan2(2.0*qu[1]*qu[2],qu[1]**2-qu[2]**2), np.pi, 0.0]) else: - #chiInv = 1.0/chi ToDo: needed for what? eu = np.array([np.arctan2((-P*qu[0]*qu[2]+qu[1]*qu[3])*chi, (-P*qu[0]*qu[1]-qu[2]*qu[3])*chi ), np.arctan2( 2.0*chi, q03-q12 ), np.arctan2(( P*qu[0]*qu[2]+qu[1]*qu[3])*chi, (-P*qu[0]*qu[1]+qu[2]*qu[3])*chi )]) From 73f6cb70205e272c73224ba32bf7353c2fffef35 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 09:12:21 +0100 Subject: [PATCH 84/97] fixed datatype --- python/damask/orientation.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 2f9731966..e11613020 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -499,7 +499,7 @@ class Symmetry: otherOrder = Symmetry.lattices.index(other.lattice) return (myOrder > otherOrder) - (myOrder < otherOrder) - def symmetryQuats(self,who = []): + def symmetryOperations(self): """List of symmetry operations as quaternions.""" if self.lattice == 'cubic': symQuats = [ @@ -566,7 +566,7 @@ class Symmetry: [ 1.0,0.0,0.0,0.0 ], ] - return np.array(symQuats) + return [Rotation(q) for q in symQuats] def inFZ(self,R): @@ -1074,7 +1074,8 @@ class Orientation: def equivalentOrientations(self): """List of orientations which are symmetrically equivalent""" - return [self.__class__(q*self.rotation.quaternion,self.lattice) for q in self.lattice.symmetry.symmetryQuats()] + return [self.__class__(q*self.rotation,self.lattice) \ + for q in self.lattice.symmetry.symmetryOperations()] def relatedOrientations(self,model): """List of orientations related by the given orientation relationship""" From 7115382729e0ed0dcb5ec90a5c3083b7ae687474 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 10:08:09 +0100 Subject: [PATCH 85/97] not used anymore --- src/crystallite.f90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/crystallite.f90 b/src/crystallite.f90 index d93950b99..e325ce443 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -91,7 +91,6 @@ module crystallite volume_ID, & orientation_ID, & grainrotation_ID, & - eulerangles_ID, & defgrad_ID, & fe_ID, & fp_ID, & From 903edcd4298b80a02355fdbb647c07d8c79c6b1d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 10:31:08 +0100 Subject: [PATCH 86/97] do not patronize the user, rather give hints --- processing/pre/seeds_fromRandom.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/processing/pre/seeds_fromRandom.py b/processing/pre/seeds_fromRandom.py index b17335e03..84c140933 100755 --- a/processing/pre/seeds_fromRandom.py +++ b/processing/pre/seeds_fromRandom.py @@ -90,11 +90,7 @@ group.add_option( '-s', '--selective', action = 'store_true', dest = 'selective', - help = 'selective picking of seed points from random seed points [%default]') -group.add_option( '--force', - action = 'store_true', - dest = 'force', - help = 'try selective picking despite large seed point number [%default]') + help = 'selective picking of seed points from random seed points') group.add_option( '--distance', dest = 'distance', type = 'float', metavar = 'float', @@ -115,7 +111,6 @@ parser.set_defaults(randomSeed = None, sigma = 0.05, microstructure = 1, selective = False, - force = False, distance = 0.2, numCandidates = 10, format = None, @@ -148,10 +143,11 @@ for name in filenames: errors = [] if gridSize == 0: errors.append('zero grid dimension for {}.'.format(', '.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.N > gridSize/10.: + remarks.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.append('maximum recommended seed point count for given distance is {}.{}'. + format(int(3./8./math.pi/(options.distance/2.)**3))) if remarks != []: damask.util.croak(remarks) if errors != []: From 56781dfa5bf27926e9a61405e979b561437a1dca Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 10:32:28 +0100 Subject: [PATCH 87/97] fiber was never used here and will be remove anyway more user friendly formatting --- python/damask/config/material.py | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/python/damask/config/material.py b/python/damask/config/material.py index 02658019d..408338313 100644 --- a/python/damask/config/material.py +++ b/python/damask/config/material.py @@ -77,18 +77,6 @@ class Texture(Section): ) ) - if multiKey == 'fiber': - self.add_multiKey(multiKey,'alpha1 %g\talpha2 %g\tbeta1 %g\tbeta2 %g\tscatter %g\tfraction %g'%( - properties['eulers'][0], - properties['eulers'][1], - properties['eulers'][2], - properties['eulers'][3], - scatter, - fraction, - ) - ) - - class Material(): """Reads, manipulates and writes material.config files""" @@ -97,10 +85,10 @@ class Material(): """Generates ordered list of parts""" self.parts = [ 'homogenization', - 'microstructure', 'crystallite', 'phase', 'texture', + 'microstructure', ] self.data = {\ 'homogenization': {'__order__': []}, @@ -117,15 +105,12 @@ class Material(): for part in self.parts: if self.verbose: print('processing <{}>'.format(part)) me += ['', - '#-----------------------------#', + '#'*100, '<{}>'.format(part), - '#-----------------------------#', + '#'*100, ] for section in self.data[part]['__order__']: - me += ['', - '[{}] {}'.format(section,'#'*max(0,27-len(section))), - '', - ] + me += ['[{}] {}'.format(section,'#'+'-'*max(0,96-len(section)))] for key in self.data[part][section]['__order__']: if key.startswith('(') and key.endswith(')'): # multiple (key) me += ['{}\t{}'.format(key,' '.join(values)) for values in self.data[part][section][key]] From 95be7ef938edd6e8e122aefa1a74e28f6746df31 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 10:33:30 +0100 Subject: [PATCH 88/97] directly convert to geom file + material config --- processing/misc/DREAM3D_toTable.py | 84 ------------------------------ 1 file changed, 84 deletions(-) delete mode 100755 processing/misc/DREAM3D_toTable.py diff --git a/processing/misc/DREAM3D_toTable.py b/processing/misc/DREAM3D_toTable.py deleted file mode 100755 index c09a77717..000000000 --- a/processing/misc/DREAM3D_toTable.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os,h5py -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 [dream3dfile[s]]', description = """ -Convert DREAM3D file to ASCIItable. Works for 3D datasets, but, hey, its not called DREAM2D ;) - -""", version = scriptID) - -parser.add_option('-d','--data', - dest = 'data', - action = 'extend', metavar = '', - help = 'data to extract from DREAM3D file') -parser.add_option('-c','--container', - dest = 'container', metavar = 'string', - help = 'root container(group) in which data is stored [%default]') - -parser.set_defaults(container="ImageDataContainer", - ) - -(options, filenames) = parser.parse_args() - -if options.data is None: - parser.error('No data selected') - -rootDir ='DataContainers/'+options.container - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: parser.error('no input file specified.') - -for name in filenames: - try: - table = damask.ASCIItable(outname = os.path.splitext(name)[0]+'.txt', - buffered = False - ) - except: continue - damask.util.report(scriptName,name) - - inFile = h5py.File(name, 'r') - try: - grid = inFile[rootDir+'/_SIMPL_GEOMETRY/DIMENSIONS'][...] - except: - damask.util.croak('Group {} not found'.format(options.container)) - table.close(dismiss = True) - continue - -# --- read comments -------------------------------------------------------------------------------- - - coords = (np.mgrid[0:grid[2], 0:grid[1], 0: grid[0]]).reshape(3, -1).T - table.data = (np.fliplr(coords)*inFile[rootDir+'/_SIMPL_GEOMETRY/SPACING'][...] \ - + inFile[rootDir+'/_SIMPL_GEOMETRY/ORIGIN'][...] \ - + inFile[rootDir+'/_SIMPL_GEOMETRY/SPACING'][...]*0.5) - labels = ['1_pos','2_pos','3_pos'] - for data in options.data: - try: - l = np.prod(inFile[rootDir+'/CellData/'+data].shape[3:]) - labels+=['{}_{}'.format(i+1,data.replace(' ','')) for i in range(l)] if l >1 else [data.replace(' ','')] - except KeyError: - damask.util.croak('Data {} not found'.format(data)) - pass - table.data = np.hstack((table.data, - inFile[rootDir+'/CellData/'+data][...].reshape(grid.prod(),l))) - -# ------------------------------------------ assemble header --------------------------------------- - table.labels_clear() - table.labels_append(labels,reset = True) - table.head_write() - -# ------------------------------------------ finalize output --------------------------------------- - table.data_writeArray() - table.close() From 0d7fd587e36f9aeae3b220d631b1d31143dadcc0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 12:57:57 +0100 Subject: [PATCH 89/97] direct translation from DREAM.3D to DAMASK geom needs test --- processing/pre/geom_fromDREAM3D.py | 189 +++++++++++++++++++++++++++++ processing/pre/geom_fromTable.py | 7 +- 2 files changed, 192 insertions(+), 4 deletions(-) create mode 100755 processing/pre/geom_fromDREAM3D.py diff --git a/processing/pre/geom_fromDREAM3D.py b/processing/pre/geom_fromDREAM3D.py new file mode 100755 index 000000000..6c2830372 --- /dev/null +++ b/processing/pre/geom_fromDREAM3D.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 no BOM -*- + +import os,sys,h5py +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 [dream3dfile[s]]', description = """ +Convert DREAM3D file to geometry file. This can be done from cell data (direct pointwise takeover) or +from grain data (individual grains are segmented). Requires orientation data as quaternion. + +""", version = scriptID) + +parser.add_option('-b','--basegroup', + dest = 'basegroup', metavar = 'string', + help = 'name of the group in "DataContainers" that contains all the data') +parser.add_option('-p','--pointwise', + dest = 'pointwise', metavar = 'string', + help = 'name of the group in "DataContainers/" that contains pointwise data [%default]') +parser.add_option('-a','--average', + dest = 'average', metavar = 'string', + help = 'name of the group in "DataContainers" that contains grain average data. '\ + + 'Leave empty for pointwise data') +parser.add_option('--phase', + dest = 'phase', + type = 'string', metavar = 'string', + help = 'name of the dataset containing pointwise/average phase IDs [%default]') +parser.add_option('--microstructure', + dest = 'microstructure', + type = 'string', metavar = 'string', + help = 'name of the dataset connecting pointwise and average data [%default]') +parser.add_option('-q', '--quaternion', + dest = 'quaternion', + type = 'string', metavar='string', + help = 'name of the dataset containing pointwise/average orientation as quaternion [%default]') + +parser.set_defaults(pointwise = 'CellData', + quaternion = 'Quats', + phase = 'Phases', + microstructure = 'FeatureIds', + crystallite = 1, + ) + +(options, filenames) = parser.parse_args() + +if options.basegroup is None: + parser.error('No base group selected') + +rootDir ='DataContainers' + +# --- loop over input files ------------------------------------------------------------------------- + +if filenames == []: parser.error('no input file specified.') + +for name in filenames: + try: + table = damask.ASCIItable(outname = os.path.splitext(name)[0]+'.geom', + buffered = False, labeled=False, + ) + except: continue + damask.util.report(scriptName,name) + + errors = [] + + info = {} + ori = [] + inFile = h5py.File(name, 'r') + group_geom = os.path.join(rootDir,options.basegroup,'_SIMPL_GEOMETRY') + try: + info['size'] = inFile[os.path.join(group_geom,'DIMENSIONS')][...] \ + * inFile[os.path.join(group_geom,'SPACING')][...] + info['grid'] = inFile[os.path.join(group_geom,'DIMENSIONS')][...] + info['origin'] = inFile[os.path.join(group_geom,'ORIGIN')][...] + except: + errors.append('Geometry data ({}) not found'.format(group_geom)) + + + group_pointwise = os.path.join(rootDir,options.basegroup,options.pointwise) + if options.average is None: + label = 'point' + N_microstructure = np.product(info['grid']) + + dataset = os.path.join(group_pointwise,options.quaternion) + try: + quats = np.reshape(inFile[dataset][...],(N_microstructure,3)) + except: + errors.append('Pointwise orientation data ({}) not found'.format(dataset)) + + texture = [damask.Rotation.fromQuaternion(q,P=+1) for q in quats] + + dataset = os.path.join(group_pointwise,options.phase) + try: + phase = np.reshape(inFile[dataset][...],(N_microstructure)) + except: + errors.append('Pointwise phase data ({}) not found'.format(dataset)) + + + else: + label = 'grain' + + dataset = os.path.join(group_pointwise,options.microstructure) + try: + microstructure = np.reshape(inFile[dataset][...],(np.product(info['grid']))) + N_microstructure = np.max(microstructure) + except: + errors.append('Link between pointwise and grain average data ({}) not found'.format(dataset)) + + group_average = os.path.join(rootDir,options.basegroup,options.average) + + dataset = os.path.join(group_average,options.quaternion) + try: + texture = [damask.Rotation.fromQuaternion(q,P=+1) for q in inFile[dataset][...][1:]] # skip first entry (unindexed) + except: + errors.append('Average orientation data ({}) not found'.format(dataset)) + + dataset = os.path.join(group_average,options.phase) + try: + phase = [i[0] for i in inFile[dataset][...]][1:] # skip first entry (unindexed) + except: + errors.append('Average phase data ({}) not found'.format(dataset)) + + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + + + mat = damask.Material() + mat.verbose = False + + # dummy + h = damask.config.material.Homogenization() + mat.add_section('Homogenization','none',h) + info['homogenization'] = 1 + + # placeholder (same for all microstructures at the moment) + c = damask.config.material.Crystallite() + mat.add_section('Crystallite','tbd',c) + + # placeholders + for i in range(np.max(phase)): + p = damask.config.material.Phase() + mat.add_section('phase','phase{}-tbd'.format(i+1),p) + + # + for i,o in enumerate(texture): + t = damask.config.material.Texture() + t.add_component('gauss',{'eulers':o.asEulers(degrees=True)}) + mat.add_section(part='texture', section='{}{}'.format(label,i+1),initialData=t) + + # + for i in range(N_microstructure): + m = damask.config.material.Microstructure() + mat.add_section('microstructure','{}{}'.format(label,i+1),m) + mat.add_microstructure('{}{}'.format(label,i+1), + {'phase': 'phase{}-tbd'.format(phase[i]), + 'texture':'{}{}'.format(label,i+1), + 'crystallite':'tbd', + 'fraction':1 + }) + + table.info_append([ + scriptID + ' ' + ' '.join(sys.argv[1:]), + "grid\ta {}\tb {}\tc {}".format(*info['grid']), + "size\tx {}\ty {}\tz {}".format(*info['size']), + "origin\tx {}\ty {}\tz {}".format(*info['origin']), + "homogenization\t{}".format(info['homogenization']), + str(mat).split('\n') + ]) + table.head_write() + + if options.average is None: + table.data = [1, 'to', format(N_microstructure)] + table.data_write() + else: + table.data = microstructure.reshape(info['grid'][1]*info['grid'][2],info['grid'][0]) + table.data_writeArray() + + + table.close() diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index ad598d5b1..8eb1ed8bf 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -39,7 +39,7 @@ parser.add_option('-q', '--quaternion', parser.add_option('--axes', dest = 'axes', type = 'string', nargs = 3, metavar = ' '.join(['string']*3), - help = 'orientation coordinate frame in terms of position coordinate frame [same]') + help = 'orientation coordinate frame in terms of position coordinate frame [+x +y +z]') parser.add_option('--homogenization', dest = 'homogenization', @@ -51,8 +51,7 @@ parser.add_option('--crystallite', help = 'crystallite index to be used [%default]') -parser.set_defaults(symmetry = [damask.Symmetry.lattices[-1]], - homogenization = 1, +parser.set_defaults(homogenization = 1, crystallite = 1, pos = 'pos', ) @@ -100,7 +99,7 @@ for name in filenames: if options.phase and table.label_dimension(options.phase) != 1: errors.append('phase column "{}" is not scalar.'.format(options.phase)) - if errors != []: + if errors != []: damask.util.croak(errors) table.close(dismiss = True) continue From e88182b0072ce7ba8461556f92d50b5a2f4049f5 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 24 Feb 2019 14:39:34 +0100 Subject: [PATCH 90/97] improved converte, now with test still needs to figure out how +P is handled --- PRIVATE | 2 +- processing/pre/geom_fromDREAM3D.py | 4 ++-- python/damask/orientation.py | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/PRIVATE b/PRIVATE index 8deb37dd4..144e72981 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 8deb37dd4526fb5e1425fe1d2360508d01b6ac3e +Subproject commit 144e729811024fd5f99225fa10b6d8fa40e7d492 diff --git a/processing/pre/geom_fromDREAM3D.py b/processing/pre/geom_fromDREAM3D.py index 6c2830372..f75694ef6 100755 --- a/processing/pre/geom_fromDREAM3D.py +++ b/processing/pre/geom_fromDREAM3D.py @@ -95,7 +95,7 @@ for name in filenames: except: errors.append('Pointwise orientation data ({}) not found'.format(dataset)) - texture = [damask.Rotation.fromQuaternion(q,P=+1) for q in quats] + texture = [damask.Rotation.fromQuaternion(q,True,P=+1) for q in quats] dataset = os.path.join(group_pointwise,options.phase) try: @@ -118,7 +118,7 @@ for name in filenames: dataset = os.path.join(group_average,options.quaternion) try: - texture = [damask.Rotation.fromQuaternion(q,P=+1) for q in inFile[dataset][...][1:]] # skip first entry (unindexed) + texture = [damask.Rotation.fromQuaternion(q,True,P=+1) for q in inFile[dataset][...][1:]] # skip first entry (unindexed) except: errors.append('Average orientation data ({}) not found'.format(dataset)) diff --git a/python/damask/orientation.py b/python/damask/orientation.py index e11613020..ad9877835 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -301,12 +301,16 @@ class Rotation: @classmethod def fromQuaternion(cls, quaternion, + acceptHomomorph = False, P = -1): qu = quaternion if isinstance(quaternion, np.ndarray) else np.array(quaternion) if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1 if qu[0] < 0.0: - raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0])) + if acceptHomomorph: + qu *= -1. + else: + raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0])) if not np.isclose(np.linalg.norm(qu), 1.0): raise ValueError('Quaternion is not of unit length.\n{} {} {} {}'.format(*qu)) From 43e7e06604a69647b476dd0457bac0dc6955138a Mon Sep 17 00:00:00 2001 From: Test User Date: Sun, 24 Feb 2019 18:57:33 +0000 Subject: [PATCH 91/97] [skip ci] updated version information after successful test of v2.0.2-1892-ge88182b0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7d075db3e..62cfd7a8f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.2-1837-g3bec76e7 +v2.0.2-1892-ge88182b0 From 81e27f4ff4ad6ae8b3f39cfaf677695f65f872b1 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 25 Feb 2019 21:43:22 +0000 Subject: [PATCH 92/97] [skip ci] updated version information after successful test of v2.0.2-1935-g6fab99bc --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 62cfd7a8f..47f55f88e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.2-1892-ge88182b0 +v2.0.2-1935-g6fab99bc From e401c21266ba5daab2c6b9c7c8e5f8396710e739 Mon Sep 17 00:00:00 2001 From: Eureka Pai Date: Mon, 25 Feb 2019 18:30:45 -0500 Subject: [PATCH 93/97] dropped obsolete option --inplace from geom_check --- processing/pre/geom_check.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/processing/pre/geom_check.sh b/processing/pre/geom_check.sh index 4342f93e6..2a690918e 100755 --- a/processing/pre/geom_check.sh +++ b/processing/pre/geom_check.sh @@ -18,8 +18,8 @@ do < $geom \ | \ vtk_addRectilinearGridData \ + --vtk ${geom%.*}.vtk \ --data microstructure \ - --inplace \ - --vtk ${geom%.*}.vtk + rm ${geom%.*}.vtk done From 2089726800645babc2ec7f84e9928ca04841d0c6 Mon Sep 17 00:00:00 2001 From: Eureka Pai Date: Mon, 25 Feb 2019 18:48:40 -0500 Subject: [PATCH 94/97] corrected output extension of vtk files to reflect binary format --- processing/post/vtk_addGridData.py | 11 +++++++---- processing/post/vtk_addPointCloudData.py | 9 ++++++--- processing/post/vtk_addRectilinearGridData.py | 8 +++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/processing/post/vtk_addGridData.py b/processing/post/vtk_addGridData.py index c458b1f07..34f01e7bf 100755 --- a/processing/post/vtk_addGridData.py +++ b/processing/post/vtk_addGridData.py @@ -53,19 +53,22 @@ parser.set_defaults(data = [], if not options.vtk: parser.error('No VTK file specified.') if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') -if os.path.splitext(options.vtk)[1] == '.vtr': +vtk_file,vtk_ext = os.path.splitext(options.vtk) + +if vtk_ext == '.vtr': reader = vtk.vtkXMLRectilinearGridReader() reader.SetFileName(options.vtk) reader.Update() rGrid = reader.GetOutput() writer = vtk.vtkXMLRectilinearGridWriter() -elif os.path.splitext(options.vtk)[1] == '.vtk': +elif vtk_ext == '.vtk': reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(options.vtk) reader.Update() rGrid = reader.GetRectilinearGridOutput() writer = vtk.vtkXMLRectilinearGridWriter() -elif os.path.splitext(options.vtk)[1] == '.vtu': + vtk_ext = '.vtr' +elif vtk_ext == '.vtu': reader = vtk.vtkXMLUnstructuredGridReader() reader.SetFileName(options.vtk) reader.Update() @@ -74,7 +77,7 @@ elif os.path.splitext(options.vtk)[1] == '.vtu': else: parser.error('Unsupported VTK file type extension.') -writer.SetFileName(options.vtk) +writer.SetFileName(vtk_file+vtk_ext) Npoints = rGrid.GetNumberOfPoints() Ncells = rGrid.GetNumberOfCells() diff --git a/processing/post/vtk_addPointCloudData.py b/processing/post/vtk_addPointCloudData.py index 5ab1d419e..0a1cb1231 100755 --- a/processing/post/vtk_addPointCloudData.py +++ b/processing/post/vtk_addPointCloudData.py @@ -49,16 +49,19 @@ parser.set_defaults(data = [], if not options.vtk: parser.error('no VTK file specified.') if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') -if os.path.splitext(options.vtk)[1] == '.vtp': +vtk_file,vtk_ext = os.path.splitext(options.vtk) + +if vtk_ext == '.vtp': reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(options.vtk) reader.Update() Polydata = reader.GetOutput() -elif os.path.splitext(options.vtk)[1] == '.vtk': +elif vtk_ext == '.vtk': reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(options.vtk) reader.Update() Polydata = reader.GetPolyDataOutput() + vtk_ext = '.vtp' else: parser.error('unsupported VTK file type extension.') @@ -149,7 +152,7 @@ for name in filenames: writer = vtk.vtkXMLPolyDataWriter() writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(options.vtk) + writer.SetFileName(vtk_file+vtk_ext) writer.SetInputData(Polydata) writer.Write() diff --git a/processing/post/vtk_addRectilinearGridData.py b/processing/post/vtk_addRectilinearGridData.py index e445214fd..868fdc387 100755 --- a/processing/post/vtk_addRectilinearGridData.py +++ b/processing/post/vtk_addRectilinearGridData.py @@ -53,16 +53,18 @@ parser.set_defaults(data = [], if not options.vtk: parser.error('no VTK file specified.') if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') -if os.path.splitext(options.vtk)[1] == '.vtr': +vtk_file,vtk_ext = os.path.splitext(options.vtk) +if vtk_ext == '.vtr': reader = vtk.vtkXMLRectilinearGridReader() reader.SetFileName(options.vtk) reader.Update() rGrid = reader.GetOutput() -elif os.path.splitext(options.vtk)[1] == '.vtk': +elif vtk_ext == '.vtk': reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(options.vtk) reader.Update() rGrid = reader.GetRectilinearGridOutput() + vtk_ext = '.vtr' else: parser.error('unsupported VTK file type extension.') @@ -159,7 +161,7 @@ for name in filenames: writer = vtk.vtkXMLRectilinearGridWriter() writer.SetDataModeToBinary() writer.SetCompressorTypeToZLib() - writer.SetFileName(options.vtk) + writer.SetFileName(vtk_file+vtk_ext) writer.SetInputData(rGrid) writer.Write() From f3d28034433b20c84938f04426e7d88e7f5ca756 Mon Sep 17 00:00:00 2001 From: Eureka Pai Date: Mon, 25 Feb 2019 19:29:12 -0500 Subject: [PATCH 95/97] addMises failed for single run of either --stress or --strain --- PRIVATE | 2 +- processing/post/addMises.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/PRIVATE b/PRIVATE index 144e72981..def4081e8 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 144e729811024fd5f99225fa10b6d8fa40e7d492 +Subproject commit def4081e837539dba7c4760abbb340553be66d3c diff --git a/processing/post/addMises.py b/processing/post/addMises.py index 35a6922c3..6593eeef8 100755 --- a/processing/post/addMises.py +++ b/processing/post/addMises.py @@ -38,9 +38,12 @@ parser.add_option('-s','--stress', action = 'extend', metavar = '', help = 'heading(s) of columns containing stress tensors') +parser.set_defaults(strain = [], + stress = [], + ) (options,filenames) = parser.parse_args() -if options.stress is None and options.strain is None: +if options.stress is [] and options.strain is []: parser.error('no data column specified...') # --- loop over input files ------------------------------------------------------------------------- From 7b5891a8d1d263e7b2bc7b44144a3d616bf17362 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 26 Feb 2019 02:05:38 +0000 Subject: [PATCH 96/97] [skip ci] updated version information after successful test of v2.0.2-1937-ge401c212 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 47f55f88e..49f0075ad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.2-1935-g6fab99bc +v2.0.2-1937-ge401c212 From e5b65ede89e28ce3618b86624e3537938f9e3297 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 26 Feb 2019 04:41:02 +0000 Subject: [PATCH 97/97] [skip ci] updated version information after successful test of v2.0.2-1938-g20897268 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 47f55f88e..f60e6836d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.2-1935-g6fab99bc +v2.0.2-1938-g20897268