From b9fec2a4cff7119977d034ae1cb02c084fa12391 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 22 Apr 2020 12:23:09 +0200 Subject: [PATCH 01/54] Public functions required --- src/IO.f90 | 108 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 23 deletions(-) diff --git a/src/IO.f90 b/src/IO.f90 index 6e467cb89..11ce664f8 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -31,6 +31,10 @@ module IO IO_stringValue, & IO_floatValue, & IO_intValue, & + IO_stringAsInt, & + IO_stringAsFloat, & + IO_stringAsBool, & + IO_rmComment, & IO_lc, & IO_error, & IO_warning @@ -250,7 +254,7 @@ integer function IO_intValue(string,chunkPos,myChunk) integer, dimension(:), intent(in) :: chunkPos !< positions of start and end of each tag/chunk in given string integer, intent(in) :: myChunk !< position number of desired chunk - IO_intValue = verifyIntValue(IO_stringValue(string,chunkPos,myChunk)) + IO_intValue = IO_stringAsInt(IO_stringValue(string,chunkPos,myChunk)) end function IO_intValue @@ -264,7 +268,7 @@ real(pReal) function IO_floatValue(string,chunkPos,myChunk) integer, dimension(:), intent(in) :: chunkPos !< positions of start and end of each tag/chunk in given string integer, intent(in) :: myChunk !< position number of desired chunk - IO_floatValue = verifyFloatValue(IO_stringValue(string,chunkPos,myChunk)) + IO_floatValue = IO_stringAsFloat(IO_stringValue(string,chunkPos,myChunk)) end function IO_floatValue @@ -335,7 +339,8 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg) msg = 'invalid character for int:' case (112) msg = 'invalid character for float:' - + case (113) + msg = 'invalid character for logical:' !-------------------------------------------------------------------------------------------------- ! lattice error messages case (130) @@ -607,12 +612,9 @@ end subroutine IO_warning !-------------------------------------------------------------------------------------------------- -! internal helper functions - +!> @brief return verified integer value in given string !-------------------------------------------------------------------------------------------------- -!> @brief returns verified integer value in given string -!-------------------------------------------------------------------------------------------------- -integer function verifyIntValue(string) +integer function IO_stringAsInt(string) character(len=*), intent(in) :: string !< string for conversion to int value @@ -620,20 +622,20 @@ integer function verifyIntValue(string) character(len=*), parameter :: VALIDCHARS = '0123456789+- ' valid: if (verify(string,VALIDCHARS) == 0) then - read(string,*,iostat=readStatus) verifyIntValue + read(string,*,iostat=readStatus) IO_stringAsInt if (readStatus /= 0) call IO_error(111,ext_msg=string) else valid - verifyIntValue = 0 + IO_stringAsInt = 0 call IO_error(111,ext_msg=string) endif valid -end function verifyIntValue +end function IO_stringAsInt !-------------------------------------------------------------------------------------------------- -!> @brief returns verified float value in given string +!> @brief return verified float value in given string !-------------------------------------------------------------------------------------------------- -real(pReal) function verifyFloatValue(string) +real(pReal) function IO_stringAsFloat(string) character(len=*), intent(in) :: string !< string for conversion to float value @@ -641,14 +643,54 @@ real(pReal) function verifyFloatValue(string) character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- ' valid: if (verify(string,VALIDCHARS) == 0) then - read(string,*,iostat=readStatus) verifyFloatValue + read(string,*,iostat=readStatus) IO_stringAsFloat if (readStatus /= 0) call IO_error(112,ext_msg=string) else valid - verifyFloatValue = 0.0_pReal + IO_stringAsFloat = 0.0_pReal call IO_error(112,ext_msg=string) endif valid -end function verifyFloatValue +end function IO_stringAsFloat + + +!-------------------------------------------------------------------------------------------------- +!> @brief return verified logical value in given string +!-------------------------------------------------------------------------------------------------- +logical function IO_stringAsBool(string) + + character(len=*), intent(in) :: string !< string for conversion to int value + + if (trim(adjustl(string)) == 'True') then + IO_stringAsBool = .true. + elseif (trim(adjustl(string)) == 'False') then + IO_stringAsBool = .false. + else + IO_stringAsBool = .false. + call IO_error(113,ext_msg=string) + endif + +end function IO_stringAsBool + + +!-------------------------------------------------------------------------------------------------- +! @brief Remove comments (characters beyond '#') and trailing space +! ToDo: Discuss name (the trim aspect is not clear) +!-------------------------------------------------------------------------------------------------- +function IO_rmComment(line) + + character(len=*), intent(in) :: line + character(len=:), allocatable :: IO_rmComment + integer :: split + + split = index(line,IO_COMMENT) + + if (split == 0) then + IO_rmComment = trim(line) + else + IO_rmComment = trim(line(:split-1)) + endif + +end function IO_rmComment !-------------------------------------------------------------------------------------------------- @@ -659,14 +701,19 @@ subroutine unitTest integer, dimension(:), allocatable :: chunkPos character(len=:), allocatable :: str - if(dNeq(1.0_pReal, verifyFloatValue('1.0'))) call IO_error(0,ext_msg='verifyFloatValue') - if(dNeq(1.0_pReal, verifyFloatValue('1e0'))) call IO_error(0,ext_msg='verifyFloatValue') - if(dNeq(0.1_pReal, verifyFloatValue('1e-1'))) call IO_error(0,ext_msg='verifyFloatValue') + if(dNeq(1.0_pReal, IO_stringAsFloat('1.0'))) call IO_error(0,ext_msg='IO_stringAsFloat') + if(dNeq(1.0_pReal, IO_stringAsFloat('1e0'))) call IO_error(0,ext_msg='IO_stringAsFloat') + if(dNeq(0.1_pReal, IO_stringAsFloat('1e-1'))) call IO_error(0,ext_msg='IO_stringAsFloat') - if(3112019 /= verifyIntValue( '3112019')) call IO_error(0,ext_msg='verifyIntValue') - if(3112019 /= verifyIntValue(' 3112019')) call IO_error(0,ext_msg='verifyIntValue') - if(-3112019 /= verifyIntValue('-3112019')) call IO_error(0,ext_msg='verifyIntValue') - if(3112019 /= verifyIntValue('+3112019 ')) call IO_error(0,ext_msg='verifyIntValue') + if(3112019 /= IO_stringAsInt( '3112019')) call IO_error(0,ext_msg='IO_stringAsInt') + if(3112019 /= IO_stringAsInt(' 3112019')) call IO_error(0,ext_msg='IO_stringAsInt') + if(-3112019 /= IO_stringAsInt('-3112019')) call IO_error(0,ext_msg='IO_stringAsInt') + if(3112019 /= IO_stringAsInt('+3112019 ')) call IO_error(0,ext_msg='IO_stringAsInt') + + if(.not. IO_stringAsBool(' True')) call IO_error(0,ext_msg='IO_stringAsBool') + if(.not. IO_stringAsBool(' True ')) call IO_error(0,ext_msg='IO_stringAsBool') + if( IO_stringAsBool(' False')) call IO_error(0,ext_msg='IO_stringAsBool') + if( IO_stringAsBool('False')) call IO_error(0,ext_msg='IO_stringAsBool') if(any([1,1,1] /= IO_stringPos('a'))) call IO_error(0,ext_msg='IO_stringPos') if(any([2,2,3,5,5] /= IO_stringPos(' aa b'))) call IO_error(0,ext_msg='IO_stringPos') @@ -683,6 +730,21 @@ subroutine unitTest if(.not. IO_isBlank(' #isBlank')) call IO_error(0,ext_msg='IO_isBlank/2') if( IO_isBlank(' i#s')) call IO_error(0,ext_msg='IO_isBlank/3') + str = IO_rmComment('#') + if (str /= '' .or. len(str) /= 0) call IO_error(0,ext_msg='IO_rmComment/1') + str = IO_rmComment(' #') + if (str /= '' .or. len(str) /= 0) call IO_error(0,ext_msg='IO_rmComment/2') + str = IO_rmComment(' # ') + if (str /= '' .or. len(str) /= 0) call IO_error(0,ext_msg='IO_rmComment/3') + str = IO_rmComment(' # a') + if (str /= '' .or. len(str) /= 0) call IO_error(0,ext_msg='IO_rmComment/4') + str = IO_rmComment(' # a') + if (str /= '' .or. len(str) /= 0) call IO_error(0,ext_msg='IO_rmComment/5') + str = IO_rmComment(' a#') + if (str /= ' a' .or. len(str) /= 2) call IO_error(0,ext_msg='IO_rmComment/6') + str = IO_rmComment(' ab #') + if (str /= ' ab'.or. len(str) /= 3) call IO_error(0,ext_msg='IO_rmComment/7') + end subroutine unitTest end module IO From a39e6b7af97b6760df7db973e3c2e52d5aebf114 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 22 Apr 2020 13:12:30 +0200 Subject: [PATCH 02/54] hide internal variables --- PRIVATE | 2 +- python/damask/_Lambert.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/PRIVATE b/PRIVATE index 232a094c7..3c52c31ca 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 232a094c715bcbbd1c6652c4dc4a4a50d402b82f +Subproject commit 3c52c31ca3272e0afe7967d2e59e0819f92e85c9 diff --git a/python/damask/_Lambert.py b/python/damask/_Lambert.py index a823764e9..8a0f043f3 100644 --- a/python/damask/_Lambert.py +++ b/python/damask/_Lambert.py @@ -32,9 +32,9 @@ 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.) +_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 cube_to_ball(cube): """ @@ -59,7 +59,7 @@ def cube_to_ball(cube): else: # get pyramide and scale by grid parameter ratio p = _get_order(cube_) - XYZ = cube_[p[0]] * sc + XYZ = cube_[p[0]] * _sc # intercept all the points along the z-axis if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): @@ -69,7 +69,7 @@ def cube_to_ball(cube): 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) + 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) @@ -101,7 +101,7 @@ def ball_to_cube(ball): https://doi.org/10.1088/0965-0393/22/7/075013 """ - ball_ = ball/np.linalg.norm(ball)*R1 if np.isclose(np.linalg.norm(ball),R1,atol=1e-6) else ball + ball_ = ball/np.linalg.norm(ball)*_R1 if np.isclose(np.linalg.norm(ball),_R1,atol=1e-6) else ball rs = np.linalg.norm(ball_) if np.allclose(ball_,0.0,rtol=0.0,atol=1.0e-16): @@ -121,14 +121,14 @@ def ball_to_cube(ball): 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)) + 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 + 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 # reverse the coordinates back to the regular order according to the original pyramid number cube = cube[p[1]] From 8ba547a1b5caec6fa9656c7e14041fed24678008 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 22 Apr 2020 13:23:33 +0200 Subject: [PATCH 03/54] no need for an extra file --- python/damask/_Lambert.py | 164 ------------------------------------- python/damask/_rotation.py | 125 ++++++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 169 deletions(-) delete mode 100644 python/damask/_Lambert.py diff --git a/python/damask/_Lambert.py b/python/damask/_Lambert.py deleted file mode 100644 index 8a0f043f3..000000000 --- a/python/damask/_Lambert.py +++ /dev/null @@ -1,164 +0,0 @@ -#################################################################################################### -# 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 -# 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 cube_to_ball(cube): - """ - Map a point in a uniform refinable cubical grid to a point on a uniform refinable grid on a ball. - - Parameters - ---------- - cube : numpy.ndarray - coordinates of a point in a uniform refinable cubical grid. - - References - ---------- - D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 - https://doi.org/10.1088/0965-0393/22/7/075013 - - """ - cube_ = np.clip(cube,None,np.pi**(2./3.) * 0.5) if np.isclose(np.abs(np.max(cube)),np.pi**(2./3.) * 0.5,atol=1e-6) else cube - - # 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-16): - ball = np.zeros(3) - else: - # get pyramide and scale by grid parameter ratio - p = _get_order(cube_) - XYZ = cube_[p[0]] * _sc - - # intercept all the points along the z-axis - if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): - 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[1]] - - return ball - - -def ball_to_cube(ball): - """ - Map a point on a uniform refinable grid on a ball to a point in a uniform refinable cubical grid. - - Parameters - ---------- - ball : numpy.ndarray - coordinates of a point on a uniform refinable grid on a ball. - - References - ---------- - D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 - https://doi.org/10.1088/0965-0393/22/7/075013 - - """ - ball_ = ball/np.linalg.norm(ball)*_R1 if np.isclose(np.linalg.norm(ball),_R1,atol=1e-6) else ball - rs = np.linalg.norm(ball_) - - if np.allclose(ball_,0.0,rtol=0.0,atol=1.0e-16): - cube = np.zeros(3) - else: - p = _get_order(ball_) - xyz3 = ball_[p[0]] - - # 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-16): - 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 - # reverse the coordinates back to the regular order according to the original pyramid number - cube = cube[p[1]] - - return cube - - -def _get_order(xyz): - """ - Get order of the coordinates. - - Depending on the pyramid in which the point is located, the order need to be adjusted. - - Parameters - ---------- - xyz : numpy.ndarray - coordinates of a point on a uniform refinable grid on a ball or - in a uniform refinable cubical grid. - - References - ---------- - D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 - https://doi.org/10.1088/0965-0393/22/7/075013 - - """ - 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],[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],[2,0,1]] - 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],[1,2,0]] diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 6076b4add..723664e18 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1,10 +1,14 @@ import numpy as np -from ._Lambert import ball_to_cube, cube_to_ball from . import mechanics _P = -1 +# parameters for conversion from/to cubochoric +_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 iszero(a): return np.isclose(a,0.0,atol=1.0e-12,rtol=0.0) @@ -1043,9 +1047,49 @@ class Rotation: @staticmethod def ho2cu(ho): - """Homochoric vector to cubochoric vector.""" + """ + Homochoric vector to cubochoric vector. + + References + ---------- + D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 + https://doi.org/10.1088/0965-0393/22/7/075013 + + """ if len(ho.shape) == 1: - return ball_to_cube(ho) + ball_ = ho/np.linalg.norm(ho)*_R1 if np.isclose(np.linalg.norm(ho),_R1,atol=1e-6) \ + else ho + rs = np.linalg.norm(ball_) + + if np.allclose(ball_,0.0,rtol=0.0,atol=1.0e-16): + cube = np.zeros(3) + else: + p = _get_order(ball_) + xyz3 = ball_[p[0]] + + # 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-16): + 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 + # reverse the coordinates back to the regular order according to the original pyramid number + cube = cube[p[1]] + + return cube else: raise NotImplementedError @@ -1078,8 +1122,79 @@ class Rotation: @staticmethod def cu2ho(cu): - """Cubochoric vector to homochoric vector.""" + """ + Cubochoric vector to homochoric vector. + + References + ---------- + D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 + https://doi.org/10.1088/0965-0393/22/7/075013 + + """ if len(cu.shape) == 1: - return cube_to_ball(cu) + + cube_ = np.clip(cu,None,np.pi**(2./3.) * 0.5) if np.isclose(np.abs(np.max(cu)),np.pi**(2./3.) * 0.5,atol=1e-6) \ + else cu + + # 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-16): + ball = np.zeros(3) + else: + # get pyramide and scale by grid parameter ratio + p = _get_order(cube_) + XYZ = cube_[p[0]] * _sc + + # intercept all the points along the z-axis + if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): + 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[1]] + + return ball else: raise NotImplementedError + + +def _get_order(xyz): + """ + Get order of the coordinates. + + Depending on the pyramid in which the point is located, the order need to be adjusted. + + Parameters + ---------- + xyz : numpy.ndarray + coordinates of a point on a uniform refinable grid on a ball or + in a uniform refinable cubical grid. + + References + ---------- + D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 + https://doi.org/10.1088/0965-0393/22/7/075013 + + """ + 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],[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],[2,0,1]] + 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],[1,2,0]] From c4bcd3b430268516fa788fa7257fe489628a4be8 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 22 Apr 2020 12:52:47 +0200 Subject: [PATCH 04/54] Functions needed to store and read yaml data --- src/CPFEM.f90 | 2 + src/CPFEM2.f90 | 2 + src/YAML_types.f90 | 977 +++++++++++++++++++++++++++++++++ src/commercialFEM_fileList.f90 | 1 + 4 files changed, 982 insertions(+) create mode 100644 src/YAML_types.f90 diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index c590a86b5..f26d4d064 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -10,6 +10,7 @@ module CPFEM use FEsolving use math use rotations + use types use discretization_marc use material use config @@ -83,6 +84,7 @@ subroutine CPFEM_initAll(el,ip) call config_init call math_init call rotations_init + call types_init call HDF5_utilities_init call results_init call discretization_marc_init(ip, el) diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 357bcce9f..2893b4759 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -11,6 +11,7 @@ module CPFEM2 use FEsolving use math use rotations + use types use material use lattice use IO @@ -50,6 +51,7 @@ subroutine CPFEM_initAll call config_init call math_init call rotations_init + call types_init call lattice_init call HDF5_utilities_init call results_init diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 new file mode 100644 index 000000000..165a34033 --- /dev/null +++ b/src/YAML_types.f90 @@ -0,0 +1,977 @@ +!-------------------------------------------------------------------------------------------------- +!> @brief yaml_types +!> @details module describes the various functions to store and get the yaml data. +!! tNode is the fundamental derived data type. It can be of tScalar, & +!! tList or tDict. +!! Every 'value' in a key: value pair is of tNode and is a pointer. +!! If 'value' is of tScalar, it can either be a string, real, integer or logical, & +!! functions exist to convert this scalar type to its respective primitive data type. +!-------------------------------------------------------------------------------------------------- + +module types + + use IO + use prec + + implicit none + + private + + public tNode + public tScalar + public tDict + public tList + public types_init + + type, abstract :: tNode + integer :: length = 0 + contains + procedure(asFormattedString), deferred :: asFormattedString + procedure :: & + asScalar => tNode_asScalar + procedure :: & + asList => tNode_asList + procedure :: & + asDict => tNode_asDict + procedure :: & + tNode_get_byIndex, & + tNode_get_byIndex_asFloat, & + tNode_get_byIndex_asFloats, & + tNode_get_byIndex_asInt, & + tNode_get_byIndex_asInts, & + tNode_get_byIndex_asBool, & + tNode_get_byIndex_asBools, & + tNode_get_byIndex_asString, & + tNode_get_byIndex_asStrings, & + tNode_get_byKey, & + tNode_get_byKey_asFloat, & + tNode_get_byKey_asFloats, & + tNode_get_byKey_asInt, & + tNode_get_byKey_asInts, & + tNode_get_byKey_asBool, & + tNode_get_byKey_asBools, & + tNode_get_byKey_asString, & + tNode_get_byKey_asStrings + generic :: & + get => tNode_get_byIndex, & + tNode_get_byKey + generic :: & + get_asFloat => tNode_get_byIndex_asFloat, & + tNode_get_byKey_asFloat + generic :: & + get_asFloats => tNode_get_byIndex_asFloats, & + tNode_get_byKey_asFloats + generic :: & + get_asInt => tNode_get_byIndex_asInt, & + tNode_get_byKey_asInt + generic :: & + get_asInts => tNode_get_byIndex_asInts, & + tNode_get_byKey_asInts + generic :: & + get_asBool => tNode_get_byIndex_asBool, & + tNode_get_byKey_asBool + generic :: & + get_asBools => tNode_get_byIndex_asBools, & + tNode_get_byKey_asBools + generic :: & + get_asString => tNode_get_byIndex_asString, & + tNode_get_byKey_asString + generic :: & + get_asStrings => tNode_get_byIndex_asStrings, & + tNode_get_byKey_asStrings + end type tNode + + + type, extends(tNode) :: tScalar + + character(len=:), allocatable, private :: value + + contains + procedure :: asFormattedString => tScalar_asFormattedString + procedure :: & + asFloat => tScalar_asFloat + procedure :: & + asInt => tScalar_asInt + procedure :: & + asBool => tScalar_asBool + procedure :: & + asString => tScalar_asString + end type tScalar + + type, extends(tNode) :: tList + + class(tItem), pointer :: first => null() + + contains + procedure :: asFormattedString => tList_asFormattedString + procedure :: append => tList_append + procedure :: & + asFloats => tList_asFloats + procedure :: & + asInts => tList_asInts + procedure :: & + asBools => tList_asBools + procedure :: & + asStrings => tList_asStrings + final :: tList_finalize + end type tList + + type, extends(tList) :: tDict + contains + procedure :: asFormattedString => tDict_asFormattedString + procedure :: set => tDict_set + final :: tDict_finalize + end type tDict + + + type :: tItem + character(len=:), allocatable :: key + class(tNode), allocatable :: node + class(tItem), pointer :: next => null() + end type tItem + + abstract interface + + recursive function asFormattedString(self,indent) + import tNode + character(len=:), allocatable :: asFormattedString + class(tNode), intent(in), target :: self + integer, intent(in), optional :: indent + end function asFormattedString + + end interface + + interface tScalar + module procedure tScalar_init__ + end interface tScalar + + interface assignment (=) + module procedure tScalar_assign__ + end interface assignment (=) + +contains + +subroutine types_init + call unitTest +end subroutine types_init + + +subroutine unitTest + + type(tScalar),target :: s1,s2 + + s1 = '1' + if(s1%asInt() /= 1) call IO_error(0,ext_msg='tScalar_asInt') + if(dNeq(s1%asFloat(),1.0_pReal)) call IO_error(0,ext_msg='tScalar_asFloat') + s1 = 'True' + if(.not. s1%asBool()) call IO_error(0,ext_msg='tScalar_asBool') + if(s1%asString() /= 'True') call IO_error(0,ext_msg='tScalar_asString') + + + block + type(tList), target :: l1, l2 + class(tNode), pointer :: n + + s1 = '2' + s2 = '3' + call l1%append(s1) + call l1%append(s2) + call l2%append(l1) + n => l1 + + if(any(l1%asInts() /= [2,3])) call IO_error(0,ext_msg='tList_asInts') + if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='tList_asFloats') + if(n%get_asInt(1) /= 2) call IO_error(0,ext_msg='byIndex_asInt') + if(dNeq(n%get_asFloat(2),3.0_pReal)) call IO_error(0,ext_msg='byIndex_asFloat') + if(any(l2%get_asInts(1) /= [2,3])) call IO_error(0,ext_msg='byIndex_asInts') + if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='byIndex_asFloats') + end block + + block + type(tList), target :: l1, l2 + class(tNode), pointer :: n + s1 = 'True' + s2 = 'False' + call l1%append(s1) + call l1%append(s2) + call l2%append(l1) + n=> l1 + + if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') + if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') + if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') + if(n%get_asString(1) /= 'True') call IO_error(0,ext_msg='byIndex_asString') + if(any(l2%get_asBools(1) .neqv. [.true., .false.])) call IO_error(0,ext_msg='byIndex_asBools') + if(any(l2%get_asStrings(1) /= ['True ','False'])) call IO_error(0,ext_msg='byIndex_asStrings') + end block + +end subroutine unitTest + + +!--------------------------------------------------------------------------------------------------- +!> @brief init from string +!--------------------------------------------------------------------------------------------------- +type(tScalar) pure function tScalar_init__(value) + + character(len=*), intent(in) :: value + + tScalar_init__%value =value + +end function tScalar_init__ + + +!--------------------------------------------------------------------------------------------------- +!> @brief set value from string +!--------------------------------------------------------------------------------------------------- +elemental pure subroutine tScalar_assign__(self,value) + + type(tScalar), intent(out) :: self + character(len=*), intent(in) :: value + + self%value = value + +end subroutine tScalar_assign__ + + +!-------------------------------------------------------------------------------------------------- +!> @brief Type guard, guarantee scalar +!-------------------------------------------------------------------------------------------------- +function tNode_asScalar(self) result(scalar) + + class(tNode), intent(in), target :: self + class(tScalar), pointer :: scalar + + select type(self) + class is(tScalar) + scalar => self + class default + call IO_error(0) + end select + +end function tNode_asScalar + + +!-------------------------------------------------------------------------------------------------- +!> @brief Type guard, guarantee list +!-------------------------------------------------------------------------------------------------- +function tNode_asList(self) result(list) + + class(tNode), intent(in), target :: self + class(tList), pointer :: list + + select type(self) + class is(tList) + list => self + class default + call IO_error(0) + end select + +end function tNode_asList + + +!-------------------------------------------------------------------------------------------------- +!> @brief Type guard, guarantee dict +!-------------------------------------------------------------------------------------------------- +function tNode_asDict(self) result(dict) + + class(tNode), intent(in), target :: self + class(tDict), pointer :: dict + + select type(self) + class is(tDict) + dict => self + class default + call IO_error(0) + end select + +end function tNode_asDict + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex(self,i) result(node) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + class(tNode), pointer :: node + + class(tList), pointer :: self_ + class(tItem), pointer :: item + integer :: j + + self_ => self%asList() + if(i < 1 .or. i > self_%length) call IO_error(0) + + j = 1 + item => self_%first + do while(j item%next + j = j + 1 + enddo + node => item%node + +end function tNode_get_byIndex + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to float +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asFloat(self,i) result(nodeAsFloat) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + real(pReal) :: nodeAsFloat + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(i) + scalar => node%asScalar() + nodeAsFloat = scalar%asFloat() + +end function tNode_get_byIndex_asFloat + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to int +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asInt(self,i) result(nodeAsInt) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + integer :: nodeAsInt + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(i) + scalar => node%asScalar() + nodeAsInt = scalar%asInt() + +end function tNode_get_byIndex_asInt + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to bool +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asBool(self,i) result(nodeAsBool) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + logical :: nodeAsBool + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(i) + scalar => node%asScalar() + nodeAsBool = scalar%asBool() + +end function tNode_get_byIndex_asBool + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to string +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asString(self,i) result(nodeAsString) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + character(len=:), allocatable :: nodeAsString + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(i) + scalar => node%asScalar() + nodeAsString = scalar%asString() + +end function tNode_get_byIndex_asString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to float array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asFloats(self,i) result(nodeAsFloats) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + real(pReal), dimension(:), allocatable :: nodeAsFloats + + class(tNode), pointer :: node + class(tList), pointer :: list + + node => self%get(i) + list => node%asList() + nodeAsFloats = list%asFloats() + +end function tNode_get_byIndex_asFloats + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to int array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asInts(self,i) result(nodeAsInts) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + integer, dimension(:), allocatable :: nodeAsInts + + class(tNode), pointer :: node + class(tList), pointer :: list + + node => self%get(i) + list => node%asList() + nodeAsInts = list%asInts() + +end function tNode_get_byIndex_asInts + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to bool array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asBools(self,i) result(nodeAsBools) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + logical, dimension(:), allocatable :: nodeAsBools + + class(tNode), pointer :: node + class(tList), pointer :: list + + node => self%get(i) + list => node%asList() + nodeAsBools = list%asBools() + +end function tNode_get_byIndex_asBools + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index and convert to string array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byIndex_asStrings(self,i) result(nodeAsStrings) + + class(tNode), intent(in), target :: self + integer, intent(in) :: i + character(len=:), allocatable, dimension(:) :: nodeAsStrings + + class(tNode), pointer :: node + type(tList), pointer :: list + + node => self%get(i) + list => node%asList() + nodeAsStrings = list%asStrings() + +end function tNode_get_byIndex_asStrings + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by index +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey(self,k) result(node) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + class(tNode), pointer :: node + + type(tDict), pointer :: self_ + type(tItem), pointer :: item + integer :: j + + self_ => self%asDict() + + j = 1 + item => self_%first + do while(j <= self_%length) + if (item%key == k) exit + item => item%next + j = j + 1 + enddo + if (.not. item%key == k) call IO_error(0) + node => item%node + +end function tNode_get_byKey + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to float +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asFloat(self,k) result(nodeAsFloat) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + real(pReal) :: nodeAsFloat + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(k) + scalar => node%asScalar() + nodeAsFloat = scalar%asFloat() + +end function tNode_get_byKey_asFloat + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to int +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asInt(self,k) result(nodeAsInt) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + integer :: nodeAsInt + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(k) + scalar => node%asScalar() + nodeAsInt = scalar%asInt() + +end function tNode_get_byKey_asInt + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to bool +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asBool(self,k) result(nodeAsBool) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + logical :: nodeAsBool + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(k) + scalar => node%asScalar() + nodeAsBool = scalar%asBool() + +end function tNode_get_byKey_asBool + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to string +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asString(self,k) result(nodeAsString) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + character(len=:), allocatable :: nodeAsString + + class(tNode), pointer :: node + type(tScalar), pointer :: scalar + + node => self%get(k) + scalar => node%asScalar() + nodeAsString = scalar%asString() + +end function tNode_get_byKey_asString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to float array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asFloats(self,k) result(nodeAsFloats) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + real(pReal), dimension(:), allocatable :: nodeAsFloats + + class(tNode), pointer :: node + type(tList), pointer :: list + + node => self%get(k) + list => node%asList() + nodeAsFloats = list%asFloats() + +end function tNode_get_byKey_asFloats + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to int array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asInts(self,k) result(nodeAsInts) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + integer, dimension(:), allocatable :: nodeAsInts + + class(tNode), pointer :: node + type(tList), pointer :: list + + node => self%get(k) + list => node%asList() + nodeAsInts = list%asInts() + +end function tNode_get_byKey_asInts + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to bool array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asBools(self,k) result(nodeAsBools) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + logical, dimension(:), allocatable :: nodeAsBools + + class(tNode), pointer :: node + type(tList), pointer :: list + + node => self%get(k) + list => node%asList() + nodeAsBools = list%asBools() + +end function tNode_get_byKey_asBools + + +!-------------------------------------------------------------------------------------------------- +!> @brief Access by key and convert to string array +!-------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asStrings(self,k) result(nodeAsStrings) + + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: k + character(len=:), allocatable, dimension(:) :: nodeAsStrings + + class(tNode), pointer :: node + type(tList), pointer :: list + + node => self%get(k) + list => node%asList() + nodeAsStrings = list%asStrings() + +end function tNode_get_byKey_asStrings + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return scalar as string +!-------------------------------------------------------------------------------------------------- +recursive function tScalar_asFormattedString(self,indent) + + character(len=:), allocatable :: tScalar_asFormattedString + class(tScalar), intent(in), target :: self + integer, intent(in), optional :: indent + + integer :: indent_ + + if(present(indent)) then + indent_ = indent + else + indent_ = 0 + endif + + tScalar_asFormattedString = repeat(' ',indent_)//trim(self%value)//IO_EOL + +end function tScalar_asFormattedString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return list as string (YAML block style) +!-------------------------------------------------------------------------------------------------- +recursive function tList_asFormattedString(self,indent) result(str) + + class(tList), intent(in), target :: self + integer, intent(in), optional :: indent + + class(tItem), pointer :: item + character(len=:), allocatable :: str + integer :: i,indent_ + + if(present(indent)) then + indent_ = indent + else + indent_ = 0 + endif + + item => self%first + do i = 1, self%length + str = str//repeat(' ',indent_)//'-'//IO_EOL//item%node%asFormattedString(indent_+2) + item => item%next + enddo + +end function tList_asFormattedString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return dictionary as string (YAML block style) +!-------------------------------------------------------------------------------------------------- +recursive function tDict_asFormattedString(self,indent) result(str) + + class(tDict), intent(in), target :: self + integer, intent(in), optional :: indent + + class(tItem), pointer :: item + character(len=:), allocatable :: str + integer :: i,indent_ + + if(present(indent)) then + indent_ = indent + else + indent_ = 0 + endif + + item => self%first + do i = 1, self%length + str = str//repeat(' ',indent_)//item%key//':'//IO_EOL//item%node%asFormattedString(indent_+2) + item => item%next + enddo + +end function tDict_asFormattedString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to float +!-------------------------------------------------------------------------------------------------- +function tScalar_asFloat(self) + + class(tScalar), intent(in), target :: self + real(pReal) :: tScalar_asFloat + + tScalar_asFloat = IO_stringAsFloat(self%value) + +end function tScalar_asFloat + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to int +!-------------------------------------------------------------------------------------------------- +function tScalar_asInt(self) + + class(tScalar), intent(in), target :: self + integer :: tScalar_asInt + + tScalar_asInt = IO_stringAsInt(self%value) + +end function tScalar_asInt + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to bool +!-------------------------------------------------------------------------------------------------- +function tScalar_asBool(self) + + class(tScalar), intent(in), target :: self + logical :: tScalar_asBool + + tScalar_asBool = IO_stringAsBool(self%value) + +end function tScalar_asBool + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to string +!-------------------------------------------------------------------------------------------------- +function tScalar_asString(self) + + class(tScalar), intent(in), target :: self + character(len=:), allocatable :: tScalar_asString + + tScalar_asString = self%value + +end function tScalar_asString + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to float array +!-------------------------------------------------------------------------------------------------- +function tList_asFloats(self) + + class(tList), intent(in), target :: self + real(pReal), dimension(:), allocatable :: tList_asFloats + + integer :: i + type(tItem), pointer :: item + type(tScalar), pointer :: scalar + + allocate(tList_asFloats(self%length)) + item => self%first + do i = 1, self%length + scalar => item%node%asScalar() + tList_asFloats(i) = scalar%asFloat() + item => item%next + enddo + +end function tList_asFloats + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to int array +!-------------------------------------------------------------------------------------------------- +function tList_asInts(self) + + class(tList), intent(in), target :: self + integer, dimension(:), allocatable :: tList_asInts + + integer :: i + type(tItem), pointer :: item + type(tScalar), pointer :: scalar + + allocate(tList_asInts(self%length)) + item => self%first + do i = 1, self%length + scalar => item%node%asScalar() + tList_asInts(i) = scalar%asInt() + item => item%next + enddo + +end function tList_asInts + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to bool array +!-------------------------------------------------------------------------------------------------- +function tList_asBools(self) + + class(tList), intent(in), target :: self + logical, dimension(:), allocatable :: tList_asBools + + integer :: i + type(tItem), pointer :: item + type(tScalar), pointer :: scalar + + allocate(tList_asBools(self%length)) + item => self%first + do i = 1, self%length + scalar => item%node%asScalar() + tList_asBools(i) = scalar%asBool() + item => item%next + enddo + +end function tList_asBools + + +!-------------------------------------------------------------------------------------------------- +!> @brief Convert to string array +!-------------------------------------------------------------------------------------------------- +function tList_asStrings(self) + + class(tList), intent(in), target :: self + character(len=:), allocatable, dimension(:) :: tList_asStrings + + integer :: i,len_max + type(tItem), pointer :: item + type(tScalar), pointer :: scalar + + len_max = 0 + allocate(character(len=pStringLen) :: tList_asStrings(self%length)) + item => self%first + do i = 1, self%length + scalar => item%node%asScalar() + tList_asStrings(i) = scalar%asString() + len_max = max(len_max, len_trim(tList_asStrings(i))) + item => item%next + enddo + + !ToDo: trim to len_max + +end function tList_asStrings + + +!-------------------------------------------------------------------------------------------------- +!> @brief Append element +!-------------------------------------------------------------------------------------------------- +subroutine tList_append(self,node) + + class(tList), intent(inout) :: self + class(tNode), intent(in) :: node + + type(tItem), pointer :: item + + if (.not. associated(self%first)) then + allocate(self%first) + item => self%first + else + item => self%first + do while (associated(item%next)) + item => item%next + end do + allocate(item%next) + item => item%next + end if + + allocate(item%node,source=node) ! ToDo: Discuss ownership (copy vs referencing) + self%length = self%length + 1 + +end subroutine tList_append + + +!-------------------------------------------------------------------------------------------------- +!> @brief Set the value of a key (either replace or add new) +!-------------------------------------------------------------------------------------------------- +subroutine tDict_set(self,key,node) + + class (tDict), intent(inout) :: self + character(len=*), intent(in) :: key + class(tNode), intent(in) :: node + + type(tItem), pointer :: item + + if (.not.associated(self%first)) then + allocate(self%first) + item => self%first + self%length = 1 + else + item => self%first + searchExisting: do while (associated(item%next)) + if (item%key == key) exit + item => item%next + end do searchExisting + if (.not. item%key == key) then + allocate(item%next) + item => item%next + self%length = self%length + 1 + end if + end if + + item%key = key + allocate(item%node,source=node) ! ToDo: Discuss ownership (copy vs referencing) + +end subroutine tDict_set + + +!-------------------------------------------------------------------------------------------------- +!> @brief empties dictionary and frees associated memory +!> @details called when variable goes out of scope. Triggers a chain reaction +!-------------------------------------------------------------------------------------------------- +recursive subroutine tDict_finalize(self) + + type (tDict),intent(inout) :: self + + type (tItem),pointer :: current, & + next + current => self%first + do while (associated(current)) + next => current%next + deallocate(current%node) + current => next + end do + nullify(self%first) + +end subroutine tDict_finalize + + +!-------------------------------------------------------------------------------------------------- +!> @brief empties lists and free associated memory +!> @details called when variable goes out of scope. +!-------------------------------------------------------------------------------------------------- +recursive subroutine tList_finalize(self) + + type (tList),intent(inout) :: self + + type (tItem),pointer :: current, & + next + current => self%first + do while (associated(current)) + next => current%next + deallocate(current%node) + current => next + end do + nullify(self%first) + +end subroutine tList_finalize + + +end module types diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index 64ad3e1d7..f13778f01 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -7,6 +7,7 @@ #include "numerics.f90" #include "debug.f90" #include "list.f90" +#include "YAML_types.f90" #include "future.f90" #include "config.f90" #include "LAPACK_interface.f90" From d61f302305782b208e3dca54859cba985a3c76bb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 22 Apr 2020 15:26:29 +0200 Subject: [PATCH 05/54] no need for separate file --- src/Lambert.f90 | 201 ------------------ src/commercialFEM_fileList.f90 | 1 - src/rotations.f90 | 370 +++++++++++++++++++++++---------- 3 files changed, 258 insertions(+), 314 deletions(-) delete mode 100644 src/Lambert.f90 diff --git a/src/Lambert.f90 b/src/Lambert.f90 deleted file mode 100644 index 932fe221b..000000000 --- a/src/Lambert.f90 +++ /dev/null @@ -1,201 +0,0 @@ -! ################################################################### -! 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 -! 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 -!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief Mapping homochoric <-> cubochoric -! -!> @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). -!-------------------------------------------------------------------------- -module Lambert - use prec - use math - - implicit none - private - - real(pReal), parameter :: & - 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 :: & - Lambert_CubeToBall, & - Lambert_BallToCube - -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 -!-------------------------------------------------------------------------- -pure function Lambert_CubeToBall(cube) result(ball) - - real(pReal), intent(in), dimension(3) :: cube - real(pReal), dimension(3) :: ball, LamXYZ, XYZ - real(pReal), dimension(2) :: T - real(pReal) :: c, s, q - real(pReal), parameter :: eps = 1.0e-8_pReal - integer, dimension(3,2) :: p - integer, 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(:,1)) * 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 / 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 - - ! reverse the coordinates back to order according to the original pyramid number - ball = LamXYZ(p(:,2)) - - endif center - -end function Lambert_CubeToBall - - -!-------------------------------------------------------------------------- -!> @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 Lambert_BallToCube(xyz) result(cube) - - 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, dimension(3,2) :: 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(:,1)) - - ! 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_pReal - 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_pReal,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_pReal,xyz3(3)) * rs / pref ] /sc - - ! reverse the coordinates back to order according to the original pyramid number - cube = xyz1(p(:,2)) - - endif center - -end function Lambert_BallToCube - - -!-------------------------------------------------------------------------- -!> @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) - - real(pReal),intent(in),dimension(3) :: xyz - integer, dimension(3,2) :: 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 = reshape([[1,2,3],[1,2,3]],[3,2]) - 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 = reshape([[2,3,1],[3,1,2]],[3,2]) - 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 = reshape([[3,1,2],[2,3,1]],[3,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 64ad3e1d7..ba614e253 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -12,7 +12,6 @@ #include "LAPACK_interface.f90" #include "math.f90" #include "quaternions.f90" -#include "Lambert.f90" #include "rotations.f90" #include "FEsolving.f90" #include "element.f90" diff --git a/src/rotations.f90 b/src/rotations.f90 index c20b9e905..98c529933 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -3,27 +3,27 @@ ! Modified 2017-2020, 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 +! 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 +! - 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 +! - 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 +! - 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 +! 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. ! ################################################################### @@ -31,7 +31,7 @@ !> @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 can be inialized from different +!> @details: rotation is internally stored as quaternion. It can be inialized from different !> representations and also returns itself in different representations. ! ! All methods and naming conventions based on Rowenhorst_etal2015 @@ -50,9 +50,8 @@ module rotations use prec use IO use math - use Lambert use quaternions - + implicit none private @@ -80,7 +79,19 @@ module rotations procedure, public :: misorientation procedure, public :: standardize end type rotation - + + real(pReal), parameter :: & + 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 :: & rotations_init, & eu2om @@ -106,16 +117,16 @@ pure function asQuaternion(self) class(rotation), intent(in) :: self real(pReal), dimension(4) :: asQuaternion - + asQuaternion = self%q%asArray() end function asQuaternion !--------------------------------------------------------------------------------------------------- pure function asEulers(self) - + class(rotation), intent(in) :: self real(pReal), dimension(3) :: asEulers - + asEulers = qu2eu(self%q%asArray()) end function asEulers @@ -124,16 +135,16 @@ pure function asAxisAngle(self) class(rotation), intent(in) :: self real(pReal), dimension(4) :: asAxisAngle - + asAxisAngle = qu2ax(self%q%asArray()) end function asAxisAngle !--------------------------------------------------------------------------------------------------- pure function asMatrix(self) - + class(rotation), intent(in) :: self real(pReal), dimension(3,3) :: asMatrix - + asMatrix = qu2om(self%q%asArray()) end function asMatrix @@ -142,20 +153,20 @@ pure function asRodrigues(self) class(rotation), intent(in) :: self real(pReal), dimension(4) :: asRodrigues - + asRodrigues = qu2ro(self%q%asArray()) - + end function asRodrigues !--------------------------------------------------------------------------------------------------- pure function asHomochoric(self) class(rotation), intent(in) :: self real(pReal), dimension(3) :: asHomochoric - + asHomochoric = qu2ho(self%q%asArray()) end function asHomochoric - + !--------------------------------------------------------------------------------------------------- ! Initialize rotation from different representations !--------------------------------------------------------------------------------------------------- @@ -207,7 +218,7 @@ subroutine fromAxisAngle(self,ax,degrees,P) else angle = merge(ax(4)*INRAD,ax(4),degrees) endif - + if (.not. present(P)) then axis = ax(1:3) else @@ -217,7 +228,7 @@ subroutine fromAxisAngle(self,ax,degrees,P) if(dNeq(norm2(axis),1.0_pReal) .or. angle < 0.0_pReal .or. angle > PI) & call IO_error(402,ext_msg='fromAxisAngle') - + self%q = ax2qu([axis,angle]) end subroutine fromAxisAngle @@ -240,10 +251,10 @@ end subroutine fromMatrix !> @brief: Rotate a rotation !--------------------------------------------------------------------------------------------------- pure elemental function rotRot__(self,R) result(rRot) - + type(rotation) :: rRot class(rotation), intent(in) :: self,R - + rRot = rotation(self%q*R%q) call rRot%standardize() @@ -251,12 +262,12 @@ end function rotRot__ !--------------------------------------------------------------------------------------------------- -!> @brief quaternion representation with positive q +!> @brief quaternion representation with positive q !--------------------------------------------------------------------------------------------------- pure elemental subroutine standardize(self) class(rotation), intent(inout) :: self - + if (real(self%q) < 0.0_pReal) self%q = self%q%homomorphed() end subroutine standardize @@ -267,22 +278,22 @@ end subroutine standardize !> @brief rotate a vector passively (default) or actively !--------------------------------------------------------------------------------------------------- pure function rotVector(self,v,active) result(vRot) - + real(pReal), dimension(3) :: vRot class(rotation), intent(in) :: self real(pReal), intent(in), dimension(3) :: v logical, intent(in), optional :: active - + real(pReal), dimension(3) :: v_normed type(quaternion) :: q logical :: passive - + if (present(active)) then passive = .not. active else passive = .true. endif - + if (dEq0(norm2(v))) then vRot = v else @@ -304,12 +315,12 @@ end function rotVector !> @details: rotation is based on rotation matrix !--------------------------------------------------------------------------------------------------- pure function rotTensor2(self,T,active) result(tRot) - + real(pReal), dimension(3,3) :: tRot class(rotation), intent(in) :: self real(pReal), intent(in), dimension(3,3) :: T logical, intent(in), optional :: active - + logical :: passive if (present(active)) then @@ -317,7 +328,7 @@ pure function rotTensor2(self,T,active) result(tRot) else passive = .true. endif - + if (passive) then tRot = matmul(matmul(self%asMatrix(),T),transpose(self%asMatrix())) else @@ -339,7 +350,7 @@ pure function rotTensor4(self,T,active) result(tRot) class(rotation), intent(in) :: self real(pReal), intent(in), dimension(3,3,3,3) :: T logical, intent(in), optional :: active - + real(pReal), dimension(3,3) :: R integer :: i,j,k,l,m,n,o,p @@ -370,7 +381,7 @@ pure function rotTensor4sym(self,T,active) result(tRot) class(rotation), intent(in) :: self real(pReal), intent(in), dimension(6,6) :: T logical, intent(in), optional :: active - + if (present(active)) then tRot = math_sym3333to66(rotTensor4(self,math_66toSym3333(T),active)) else @@ -384,10 +395,10 @@ end function rotTensor4sym !> @brief misorientation !--------------------------------------------------------------------------------------------------- pure elemental function misorientation(self,other) - + type(rotation) :: misorientation class(rotation), intent(in) :: self, other - + misorientation%q = other%q * conjg(self%q) end function misorientation @@ -401,7 +412,7 @@ pure function qu2om(qu) result(om) real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(3,3) :: om - + real(pReal) :: qq qq = qu(1)**2-sum(qu(2:4)**2) @@ -431,13 +442,13 @@ pure function qu2eu(qu) result(eu) real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(3) :: eu - + real(pReal) :: q12, q03, chi - + q03 = qu(1)**2+qu(4)**2 q12 = qu(2)**2+qu(3)**2 chi = sqrt(q03*q12) - + degenerated: if (dEq0(q12)) then eu = [atan2(-P*2.0_pReal*qu(1)*qu(4),qu(1)**2-qu(4)**2), 0.0_pReal, 0.0_pReal] elseif (dEq0(q03)) then @@ -460,7 +471,7 @@ pure function qu2ax(qu) result(ax) real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(4) :: ax - + real(pReal) :: omega, s if (dEq0(sum(qu(2:4)**2))) then @@ -481,13 +492,13 @@ end function qu2ax !> @brief convert unit quaternion to Rodrigues vector !--------------------------------------------------------------------------------------------------- pure function qu2ro(qu) result(ro) - + real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(4) :: ro - + real(pReal) :: s real(pReal), parameter :: thr = 1.0e-8_pReal - + if (abs(qu(1)) < thr) then ro = [qu(2), qu(3), qu(4), IEEE_value(1.0_pReal,IEEE_positive_inf)] else @@ -497,7 +508,7 @@ pure function qu2ro(qu) result(ro) else ro = [qu(2)/s,qu(3)/s,qu(4)/s, tan(acos(math_clip(qu(1),-1.0_pReal,1.0_pReal)))] endif - + end if end function qu2ro @@ -511,11 +522,11 @@ pure function qu2ho(qu) result(ho) real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(3) :: ho - + real(pReal) :: omega, f omega = 2.0 * acos(math_clip(qu(1),-1.0_pReal,1.0_pReal)) - + if (dEq0(omega)) then ho = [ 0.0_pReal, 0.0_pReal, 0.0_pReal ] else @@ -532,7 +543,7 @@ end function qu2ho !> @brief convert unit quaternion to cubochoric !--------------------------------------------------------------------------------------------------- pure function qu2cu(qu) result(cu) - + real(pReal), intent(in), dimension(4) :: qu real(pReal), dimension(3) :: cu @@ -565,18 +576,18 @@ pure function om2eu(om) result(eu) real(pReal), intent(in), dimension(3,3) :: om real(pReal), dimension(3) :: eu real(pReal) :: zeta - + if (abs(om(3,3)) < 1.0_pReal) then 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)] - else + else eu = [atan2(om(1,2),om(1,1)), 0.5_pReal*PI*(1.0_pReal-om(3,3)),0.0_pReal ] 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 @@ -588,19 +599,19 @@ function om2ax(om) result(ax) real(pReal), intent(in), dimension(3,3) :: om real(pReal), dimension(4) :: ax - + real(pReal) :: t real(pReal), dimension(3) :: Wr, Wi real(pReal), dimension((64+2)*3) :: work real(pReal), dimension(3,3) :: VR, devNull, om_ integer :: ierr, i - + om_ = om - + ! first get the rotation angle t = 0.5_pReal * (math_trace33(om) - 1.0_pReal) ax(4) = acos(math_clip(t,-1.0_pReal,1.0_pReal)) - + if (dEq0(ax(4))) then ax(1:3) = [ 0.0_pReal, 0.0_pReal, 1.0_pReal ] else @@ -674,7 +685,7 @@ pure function eu2qu(eu) result(qu) real(pReal) :: cPhi, sPhi ee = 0.5_pReal*eu - + cPhi = cos(ee(2)) sPhi = sin(ee(2)) @@ -692,15 +703,15 @@ end function eu2qu !> @brief Euler angles to orientation matrix !--------------------------------------------------------------------------------------------------- pure function eu2om(eu) result(om) - + real(pReal), intent(in), dimension(3) :: eu real(pReal), dimension(3,3) :: om - - real(pReal), dimension(3) :: c, s - + + 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) @@ -710,7 +721,7 @@ pure function eu2om(eu) result(om) 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 @@ -721,19 +732,19 @@ end function eu2om !> @brief convert euler to axis angle !--------------------------------------------------------------------------------------------------- pure function eu2ax(eu) result(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_pReal) sigma = 0.5_pReal*(eu(1)+eu(3)) delta = 0.5_pReal*(eu(1)-eu(3)) tau = sqrt(t**2+sin(sigma)**2) - + alpha = merge(PI, 2.0_pReal*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 @@ -741,7 +752,7 @@ pure function eu2ax(eu) result(ax) ax(4) = alpha if (alpha < 0.0_pReal) ax = -ax ! ensure alpha is positive end if - + end function eu2ax @@ -753,7 +764,7 @@ pure function eu2ro(eu) result(ro) real(pReal), intent(in), dimension(3) :: eu real(pReal), dimension(4) :: ro - + ro = eu2ax(eu) if (ro(4) >= PI) then ro(4) = IEEE_value(ro(4),IEEE_positive_inf) @@ -762,7 +773,7 @@ pure function eu2ro(eu) result(ro) else ro(4) = tan(ro(4)*0.5_pReal) end if - + end function eu2ro @@ -799,7 +810,7 @@ end function eu2cu !> @brief convert axis angle pair to quaternion !--------------------------------------------------------------------------------------------------- pure function ax2qu(ax) result(qu) - + real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(4) :: qu @@ -825,7 +836,7 @@ pure function ax2om(ax) result(om) real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(3,3) :: om - + real(pReal) :: q, c, s, omc c = cos(ax(4)) @@ -839,11 +850,11 @@ pure function ax2om(ax) result(om) 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) @@ -875,12 +886,12 @@ pure function ax2ro(ax) result(ro) real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(4) :: ro - + real(pReal), parameter :: thr = 1.0e-7_pReal - + if (dEq0(ax(4))) then ro = [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal ] - else + 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_pReal),abs(ax(4)-PI) < thr) @@ -897,9 +908,9 @@ pure function ax2ho(ax) result(ho) real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(3) :: ho - + real(pReal) :: f - + f = 0.75_pReal * ( ax(4) - sin(ax(4)) ) f = f**(1.0_pReal/3.0_pReal) ho = ax(1:3) * f @@ -929,7 +940,7 @@ pure function ro2qu(ro) result(qu) real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(4) :: qu - + qu = ax2qu(ro2ax(ro)) end function ro2qu @@ -957,7 +968,7 @@ pure function ro2eu(ro) result(eu) real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(3) :: eu - + eu = om2eu(ro2om(ro)) end function ro2eu @@ -971,14 +982,14 @@ pure function ro2ax(ro) result(ax) real(pReal), intent(in), dimension(4) :: ro real(pReal), dimension(4) :: ax - + real(pReal) :: ta, angle - + ta = ro(4) - + if (.not. IEEE_is_finite(ta)) then ax = [ ro(1), ro(2), ro(3), PI ] - elseif (dEq0(ta)) then + elseif (dEq0(ta)) then ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] else angle = 2.0_pReal*atan(ta) @@ -997,9 +1008,9 @@ pure function ro2ho(ro) result(ho) 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_pReal, 0.0_pReal, 0.0_pReal ] else @@ -1074,26 +1085,26 @@ pure function ho2ax(ho) result(ax) real(pReal), intent(in), dimension(3) :: ho real(pReal), dimension(4) :: ax - + integer :: 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, & + 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 @@ -1217,12 +1228,147 @@ pure function cu2ho(cu) result(ho) end function cu2ho +!-------------------------------------------------------------------------- +!> @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 +!-------------------------------------------------------------------------- +pure function Lambert_CubeToBall(cube) result(ball) + + real(pReal), intent(in), dimension(3) :: cube + real(pReal), dimension(3) :: ball, LamXYZ, XYZ + real(pReal), dimension(2) :: T + real(pReal) :: c, s, q + real(pReal), parameter :: eps = 1.0e-8_pReal + integer, dimension(3,2) :: p + integer, 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(:,1)) * 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 / 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 + + ! reverse the coordinates back to order according to the original pyramid number + ball = LamXYZ(p(:,2)) + + endif center + +end function Lambert_CubeToBall + + +!-------------------------------------------------------------------------- +!> @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 Lambert_BallToCube(xyz) result(cube) + + 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, dimension(3,2) :: 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(:,1)) + + ! 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_pReal + 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_pReal,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_pReal,xyz3(3)) * rs / pref ] /sc + + ! reverse the coordinates back to order according to the original pyramid number + cube = xyz1(p(:,2)) + + endif center + +end function Lambert_BallToCube + + +!-------------------------------------------------------------------------- +!> @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) + + real(pReal),intent(in),dimension(3) :: xyz + integer, dimension(3,2) :: 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 = reshape([[1,2,3],[1,2,3]],[3,2]) + 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 = reshape([[2,3,1],[3,1,2]],[3,2]) + 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 = reshape([[3,1,2],[2,3,1]],[3,2]) + else + GetPyramidOrder = -1 ! should be impossible, but might simplify debugging + end if + +end function GetPyramidOrder + !-------------------------------------------------------------------------------------------------- !> @brief check correctness of some rotations functions !-------------------------------------------------------------------------------------------------- subroutine unitTest - + type(rotation) :: R real(pReal), dimension(4) :: qu, ax, ro real(pReal), dimension(3) :: x, eu, ho, v3 @@ -1233,7 +1379,7 @@ subroutine unitTest integer :: i do i=1,10 - + msg = '' #if defined(__GFORTRAN__) && __GNUC__<9 @@ -1307,15 +1453,15 @@ subroutine unitTest #endif call R%fromMatrix(om) - + call random_number(v3) if(all(dNeq(R%rotVector(R%rotVector(v3),active=.true.),v3,1.0e-12_pReal))) & msg = trim(msg)//'rotVector,' - + call random_number(t33) if(all(dNeq(R%rotTensor2(R%rotTensor2(t33),active=.true.),t33,1.0e-12_pReal))) & msg = trim(msg)//'rotTensor2,' - + call random_number(t3333) if(all(dNeq(R%rotTensor4(R%rotTensor4(t3333),active=.true.),t3333,1.0e-12_pReal))) & msg = trim(msg)//'rotTensor4,' From 6a0a8f1d275e88a5788045b85600f74f06f96794 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 22 Apr 2020 15:51:05 +0200 Subject: [PATCH 06/54] Fortran syntax check showed an error --- src/YAML_types.f90 | 54 ++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 165a34033..049029203 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -33,25 +33,43 @@ module types asList => tNode_asList procedure :: & asDict => tNode_asDict + procedure :: & + tNode_get_byIndex => tNode_get_byIndex procedure :: & - tNode_get_byIndex, & - tNode_get_byIndex_asFloat, & - tNode_get_byIndex_asFloats, & - tNode_get_byIndex_asInt, & - tNode_get_byIndex_asInts, & - tNode_get_byIndex_asBool, & - tNode_get_byIndex_asBools, & - tNode_get_byIndex_asString, & - tNode_get_byIndex_asStrings, & - tNode_get_byKey, & - tNode_get_byKey_asFloat, & - tNode_get_byKey_asFloats, & - tNode_get_byKey_asInt, & - tNode_get_byKey_asInts, & - tNode_get_byKey_asBool, & - tNode_get_byKey_asBools, & - tNode_get_byKey_asString, & - tNode_get_byKey_asStrings + tNode_get_byIndex_asFloat => tNode_get_byIndex_asFloat + procedure :: & + tNode_get_byIndex_asFloats => tNode_get_byIndex_asFloats + procedure :: & + tNode_get_byIndex_asInt => tNode_get_byIndex_asInt + procedure :: & + tNode_get_byIndex_asInts => tNode_get_byIndex_asInts + procedure :: & + tNode_get_byIndex_asBool => tNode_get_byIndex_asBool + procedure :: & + tNode_get_byIndex_asBools => tNode_get_byIndex_asBools + procedure :: & + tNode_get_byIndex_asString => tNode_get_byIndex_asString + procedure :: & + tNode_get_byIndex_asStrings => tNode_get_byIndex_asStrings + procedure :: & + tNode_get_byKey => tNode_get_byKey + procedure :: & + tNode_get_byKey_asFloat => tNode_get_byKey_asFloat + procedure :: & + tNode_get_byKey_asFloats => tNode_get_byKey_asFloats + procedure :: & + tNode_get_byKey_asInt => tNode_get_byKey_asInt + procedure :: & + tNode_get_byKey_asInts => tNode_get_byKey_asInts + procedure :: & + tNode_get_byKey_asBool => tNode_get_byKey_asBool + procedure :: & + tNode_get_byKey_asBools => tNode_get_byKey_asBools + procedure :: & + tNode_get_byKey_asString => tNode_get_byKey_asString + procedure :: & + tNode_get_byKey_asStrings => tNode_get_byKey_asStrings + generic :: & get => tNode_get_byIndex, & tNode_get_byKey From 11c4ff7787f2d980fd527f3d8f804a8df27e3ddc Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Wed, 22 Apr 2020 16:49:31 +0200 Subject: [PATCH 07/54] finalization error --- src/YAML_types.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 049029203..2edff3a58 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -984,7 +984,7 @@ recursive subroutine tList_finalize(self) current => self%first do while (associated(current)) next => current%next - deallocate(current%node) + if(allocated(current%node)) deallocate(current%node) current => next end do nullify(self%first) From 7fe2a52b65eb8e22aeadb731a95818504e6c1f9d Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Thu, 23 Apr 2020 17:10:33 +0200 Subject: [PATCH 08/54] better logic for finalization --- src/YAML_types.f90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 2edff3a58..e951c2c83 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -214,7 +214,7 @@ subroutine unitTest call l1%append(s2) call l2%append(l1) n=> l1 - + if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') @@ -960,13 +960,13 @@ recursive subroutine tDict_finalize(self) type (tItem),pointer :: current, & next + current => self%first do while (associated(current)) next => current%next - deallocate(current%node) + deallocate(current) current => next end do - nullify(self%first) end subroutine tDict_finalize @@ -981,13 +981,13 @@ recursive subroutine tList_finalize(self) type (tItem),pointer :: current, & next + current => self%first do while (associated(current)) next => current%next - if(allocated(current%node)) deallocate(current%node) + deallocate(current) current => next end do - nullify(self%first) end subroutine tList_finalize From ca6aa4bcd1ba6036aa0ac7d40c481085fe8c0046 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Fri, 24 Apr 2020 16:50:42 +0200 Subject: [PATCH 09/54] child type would inherit procedures from parent type --- src/YAML_types.f90 | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index e951c2c83..9dba4fd37 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -138,7 +138,6 @@ module types contains procedure :: asFormattedString => tDict_asFormattedString procedure :: set => tDict_set - final :: tDict_finalize end type tDict @@ -951,28 +950,7 @@ end subroutine tDict_set !-------------------------------------------------------------------------------------------------- -!> @brief empties dictionary and frees associated memory -!> @details called when variable goes out of scope. Triggers a chain reaction -!-------------------------------------------------------------------------------------------------- -recursive subroutine tDict_finalize(self) - - type (tDict),intent(inout) :: self - - type (tItem),pointer :: current, & - next - - current => self%first - do while (associated(current)) - next => current%next - deallocate(current) - current => next - end do - -end subroutine tDict_finalize - - -!-------------------------------------------------------------------------------------------------- -!> @brief empties lists and free associated memory +!> @brief empties lists and dicts and free associated memory !> @details called when variable goes out of scope. !-------------------------------------------------------------------------------------------------- recursive subroutine tList_finalize(self) From 9671a632b55110992eb6878a61c2488b05abce15 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 26 Apr 2020 14:58:07 +0200 Subject: [PATCH 10/54] compare floats with tolerances --- src/rotations.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index 98c529933..8ff5aca4e 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -527,7 +527,7 @@ pure function qu2ho(qu) result(ho) omega = 2.0 * acos(math_clip(qu(1),-1.0_pReal,1.0_pReal)) - if (dEq0(omega)) then + if (dEq0(omega,tol=1.e-5_pReal)) then ho = [ 0.0_pReal, 0.0_pReal, 0.0_pReal ] else ho = qu(2:4) @@ -1298,7 +1298,7 @@ pure function Lambert_BallToCube(xyz) result(cube) integer, dimension(3,2) :: p rs = norm2(xyz) - if (rs > R1) then + if (rs > R1+1.e-6_pReal) then cube = IEEE_value(cube,IEEE_positive_inf) return endif From 2d14790863bb3ebbef8aee5ebd17cbf656543642 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 27 Apr 2020 05:08:47 +0200 Subject: [PATCH 11/54] the result of a differential operator operating on a constant field is 0 --- python/tests/test_grid_filters.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index eb359006a..35f28bb0d 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -101,6 +101,7 @@ class TestGridFilters: with pytest.raises(ValueError): function(uneven) + @pytest.mark.parametrize('mode',[True,False]) @pytest.mark.parametrize('function',[grid_filters.node_coord0_gridSizeOrigin, grid_filters.cell_coord0_gridSizeOrigin]) @@ -120,3 +121,20 @@ class TestGridFilters: grid = np.random.randint(8,32,(3)) F = np.broadcast_to(np.eye(3), tuple(grid)+(3,3)) assert all(grid_filters.regrid(size,F,grid) == np.arange(grid.prod())) + + + @pytest.mark.parametrize('differential_operator',[grid_filters.curl, + grid_filters.divergence, + grid_filters.gradient]) + def test_differential_operator_constant(self,differential_operator): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + shapes = { + grid_filters.curl: [(3,),(3,3)], + grid_filters.divergence:[(3,),(3,3)], + grid_filters.gradient: [(1,),(3,)] + } + for shape in shapes[differential_operator]: + field = np.ones(tuple(grid)+shape)*np.random.random()*1.0e5 + assert np.allclose(differential_operator(size,field),0.0) + From 9273c887824fa940f3be541958e7f933247b9a26 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 27 Apr 2020 06:10:48 +0200 Subject: [PATCH 12/54] [skip ci] WIP: migrating from PRIVATE repo --- python/tests/test_grid_filters.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 35f28bb0d..84d2ef771 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -138,3 +138,33 @@ class TestGridFilters: field = np.ones(tuple(grid)+shape)*np.random.random()*1.0e5 assert np.allclose(differential_operator(size,field),0.0) + + @pytest.mark.parametrize('field_def,curl_def', + [(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0' ], + ['0.0' , '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] + ) + ]) + def test_curl(self,field_def,curl_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + curl = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in curl_def], axis=-1) + curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) + + assert np.allclose(curl,grid_filters.curl(size,field)) From f3be26ffa251330d2dbd10aa2f54d7ff6b1dd247 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 28 Apr 2020 10:05:36 +0200 Subject: [PATCH 13/54] long error and warning functions at the end of public methods --- src/IO.f90 | 170 ++++++++++++++++++++++++++--------------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/src/IO.f90 b/src/IO.f90 index 11ce664f8..1bd2df833 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -29,13 +29,13 @@ module IO IO_getTag, & IO_stringPos, & IO_stringValue, & - IO_floatValue, & IO_intValue, & + IO_floatValue, & + IO_lc, & + IO_rmComment, & IO_stringAsInt, & IO_stringAsFloat, & IO_stringAsBool, & - IO_rmComment, & - IO_lc, & IO_error, & IO_warning @@ -298,6 +298,88 @@ pure function IO_lc(string) end function IO_lc +!-------------------------------------------------------------------------------------------------- +! @brief Remove comments (characters beyond '#') and trailing space +! ToDo: Discuss name (the trim aspect is not clear) +!-------------------------------------------------------------------------------------------------- +function IO_rmComment(line) + + character(len=*), intent(in) :: line + character(len=:), allocatable :: IO_rmComment + integer :: split + + split = index(line,IO_COMMENT) + + if (split == 0) then + IO_rmComment = trim(line) + else + IO_rmComment = trim(line(:split-1)) + endif + +end function IO_rmComment + + +!-------------------------------------------------------------------------------------------------- +!> @brief return verified integer value in given string +!-------------------------------------------------------------------------------------------------- +integer function IO_stringAsInt(string) + + character(len=*), intent(in) :: string !< string for conversion to int value + + integer :: readStatus + character(len=*), parameter :: VALIDCHARS = '0123456789+- ' + + valid: if (verify(string,VALIDCHARS) == 0) then + read(string,*,iostat=readStatus) IO_stringAsInt + if (readStatus /= 0) call IO_error(111,ext_msg=string) + else valid + IO_stringAsInt = 0 + call IO_error(111,ext_msg=string) + endif valid + +end function IO_stringAsInt + + +!-------------------------------------------------------------------------------------------------- +!> @brief return verified float value in given string +!-------------------------------------------------------------------------------------------------- +real(pReal) function IO_stringAsFloat(string) + + character(len=*), intent(in) :: string !< string for conversion to float value + + integer :: readStatus + character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- ' + + valid: if (verify(string,VALIDCHARS) == 0) then + read(string,*,iostat=readStatus) IO_stringAsFloat + if (readStatus /= 0) call IO_error(112,ext_msg=string) + else valid + IO_stringAsFloat = 0.0_pReal + call IO_error(112,ext_msg=string) + endif valid + +end function IO_stringAsFloat + + +!-------------------------------------------------------------------------------------------------- +!> @brief return verified logical value in given string +!-------------------------------------------------------------------------------------------------- +logical function IO_stringAsBool(string) + + character(len=*), intent(in) :: string !< string for conversion to int value + + if (trim(adjustl(string)) == 'True') then + IO_stringAsBool = .true. + elseif (trim(adjustl(string)) == 'False') then + IO_stringAsBool = .false. + else + IO_stringAsBool = .false. + call IO_error(113,ext_msg=string) + endif + +end function IO_stringAsBool + + !-------------------------------------------------------------------------------------------------- !> @brief write error statements to standard out and terminate the Marc/spectral run with exit #9xxx !-------------------------------------------------------------------------------------------------- @@ -611,88 +693,6 @@ subroutine IO_warning(warning_ID,el,ip,g,ext_msg) end subroutine IO_warning -!-------------------------------------------------------------------------------------------------- -!> @brief return verified integer value in given string -!-------------------------------------------------------------------------------------------------- -integer function IO_stringAsInt(string) - - character(len=*), intent(in) :: string !< string for conversion to int value - - integer :: readStatus - character(len=*), parameter :: VALIDCHARS = '0123456789+- ' - - valid: if (verify(string,VALIDCHARS) == 0) then - read(string,*,iostat=readStatus) IO_stringAsInt - if (readStatus /= 0) call IO_error(111,ext_msg=string) - else valid - IO_stringAsInt = 0 - call IO_error(111,ext_msg=string) - endif valid - -end function IO_stringAsInt - - -!-------------------------------------------------------------------------------------------------- -!> @brief return verified float value in given string -!-------------------------------------------------------------------------------------------------- -real(pReal) function IO_stringAsFloat(string) - - character(len=*), intent(in) :: string !< string for conversion to float value - - integer :: readStatus - character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- ' - - valid: if (verify(string,VALIDCHARS) == 0) then - read(string,*,iostat=readStatus) IO_stringAsFloat - if (readStatus /= 0) call IO_error(112,ext_msg=string) - else valid - IO_stringAsFloat = 0.0_pReal - call IO_error(112,ext_msg=string) - endif valid - -end function IO_stringAsFloat - - -!-------------------------------------------------------------------------------------------------- -!> @brief return verified logical value in given string -!-------------------------------------------------------------------------------------------------- -logical function IO_stringAsBool(string) - - character(len=*), intent(in) :: string !< string for conversion to int value - - if (trim(adjustl(string)) == 'True') then - IO_stringAsBool = .true. - elseif (trim(adjustl(string)) == 'False') then - IO_stringAsBool = .false. - else - IO_stringAsBool = .false. - call IO_error(113,ext_msg=string) - endif - -end function IO_stringAsBool - - -!-------------------------------------------------------------------------------------------------- -! @brief Remove comments (characters beyond '#') and trailing space -! ToDo: Discuss name (the trim aspect is not clear) -!-------------------------------------------------------------------------------------------------- -function IO_rmComment(line) - - character(len=*), intent(in) :: line - character(len=:), allocatable :: IO_rmComment - integer :: split - - split = index(line,IO_COMMENT) - - if (split == 0) then - IO_rmComment = trim(line) - else - IO_rmComment = trim(line(:split-1)) - endif - -end function IO_rmComment - - !-------------------------------------------------------------------------------------------------- !> @brief check correctness of some IO functions !-------------------------------------------------------------------------------------------------- From 20b604a334fee662a5905927440adaa7551f39af Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 28 Apr 2020 10:29:13 +0200 Subject: [PATCH 14/54] finalize does not work for gfortran --- src/CPFEM.f90 | 4 ++-- src/CPFEM2.f90 | 4 ++-- src/YAML_types.f90 | 49 +++++++++++++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index f26d4d064..83ecf65a4 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -10,7 +10,7 @@ module CPFEM use FEsolving use math use rotations - use types + use YAML_types use discretization_marc use material use config @@ -84,7 +84,7 @@ subroutine CPFEM_initAll(el,ip) call config_init call math_init call rotations_init - call types_init + call YAML_types_init call HDF5_utilities_init call results_init call discretization_marc_init(ip, el) diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 2893b4759..9f61e4ebd 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -11,7 +11,7 @@ module CPFEM2 use FEsolving use math use rotations - use types + use YAML_types use material use lattice use IO @@ -51,7 +51,7 @@ subroutine CPFEM_initAll call config_init call math_init call rotations_init - call types_init + call YAML_types_init call lattice_init call HDF5_utilities_init call results_init diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 9dba4fd37..26f17430a 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -8,7 +8,7 @@ !! functions exist to convert this scalar type to its respective primitive data type. !-------------------------------------------------------------------------------------------------- -module types +module YAML_types use IO use prec @@ -17,11 +17,12 @@ module types private - public tNode - public tScalar - public tDict - public tList - public types_init + public :: & + tNode, & + tScalar, & + tDict, & + tList, & + YAML_types_init type, abstract :: tNode integer :: length = 0 @@ -69,7 +70,7 @@ module types tNode_get_byKey_asString => tNode_get_byKey_asString procedure :: & tNode_get_byKey_asStrings => tNode_get_byKey_asStrings - + generic :: & get => tNode_get_byIndex, & tNode_get_byKey @@ -102,7 +103,7 @@ module types type, extends(tNode) :: tScalar - character(len=:), allocatable, private :: value + character(len=:), allocatable, private :: value contains procedure :: asFormattedString => tScalar_asFormattedString @@ -117,7 +118,7 @@ module types end type tScalar type, extends(tNode) :: tList - + class(tItem), pointer :: first => null() contains @@ -131,7 +132,9 @@ module types asBools => tList_asBools procedure :: & asStrings => tList_asStrings +#ifndef __GFORTRAN__ final :: tList_finalize +#endif end type tList type, extends(tList) :: tDict @@ -168,14 +171,24 @@ module types contains -subroutine types_init +!-------------------------------------------------------------------------------------------------- +!> @brief do sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine YAML_types_init + + write(6,'(/,a)') ' <<<+- YAML_types init -+>>>' + call unitTest -end subroutine types_init + +end subroutine YAML_types_init +!-------------------------------------------------------------------------------------------------- +!> @brief check correctness of some type bound procedures +!-------------------------------------------------------------------------------------------------- subroutine unitTest - type(tScalar),target :: s1,s2 + type(tScalar),target :: s1,s2 s1 = '1' if(s1%asInt() /= 1) call IO_error(0,ext_msg='tScalar_asInt') @@ -213,7 +226,7 @@ subroutine unitTest call l1%append(s2) call l2%append(l1) n=> l1 - + if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') @@ -598,7 +611,7 @@ function tNode_get_byKey_asFloats(self,k) result(nodeAsFloats) class(tNode), pointer :: node type(tList), pointer :: list - + node => self%get(k) list => node%asList() nodeAsFloats = list%asFloats() @@ -926,7 +939,7 @@ subroutine tDict_set(self,key,node) type(tItem), pointer :: item - if (.not.associated(self%first)) then + if (.not. associated(self%first)) then allocate(self%first) item => self%first self%length = 1 @@ -944,7 +957,7 @@ subroutine tDict_set(self,key,node) end if item%key = key - allocate(item%node,source=node) ! ToDo: Discuss ownership (copy vs referencing) + allocate(item%node,source=node) end subroutine tDict_set @@ -959,7 +972,7 @@ recursive subroutine tList_finalize(self) type (tItem),pointer :: current, & next - + current => self%first do while (associated(current)) next => current%next @@ -970,4 +983,4 @@ recursive subroutine tList_finalize(self) end subroutine tList_finalize -end module types +end module YAML_types From ce9bdc50a4842edc4b1b76f6377f053e90c0cc9f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 29 Apr 2020 14:42:21 +0200 Subject: [PATCH 15/54] common variable names --- python/damask/_rotation.py | 36 +++++++++++++++++----------------- src/rotations.f90 | 40 +++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 723664e18..42b32552b 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1057,15 +1057,15 @@ class Rotation: """ if len(ho.shape) == 1: - ball_ = ho/np.linalg.norm(ho)*_R1 if np.isclose(np.linalg.norm(ho),_R1,atol=1e-6) \ + ho_ = ho/np.linalg.norm(ho)*_R1 if np.isclose(np.linalg.norm(ho),_R1,atol=1e-6) \ else ho - rs = np.linalg.norm(ball_) + rs = np.linalg.norm(ho_) - if np.allclose(ball_,0.0,rtol=0.0,atol=1.0e-16): - cube = np.zeros(3) + if np.allclose(ho_,0.0,rtol=0.0,atol=1.0e-16): + cu = np.zeros(3) else: - p = _get_order(ball_) - xyz3 = ball_[p[0]] + p = _get_order(ho_) + xyz3 = ho_[p[0]] # inverse M_3 xyz2 = xyz3[0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[2])) ) @@ -1085,11 +1085,11 @@ class Rotation: 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 + cu = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /_sc # reverse the coordinates back to the regular order according to the original pyramid number - cube = cube[p[1]] + cu = cu[p[1]] - return cube + return cu else: raise NotImplementedError @@ -1133,20 +1133,20 @@ class Rotation: """ if len(cu.shape) == 1: - cube_ = np.clip(cu,None,np.pi**(2./3.) * 0.5) if np.isclose(np.abs(np.max(cu)),np.pi**(2./3.) * 0.5,atol=1e-6) \ + cu_ = np.clip(cu,None,np.pi**(2./3.) * 0.5) if np.isclose(np.abs(np.max(cu)),np.pi**(2./3.) * 0.5,atol=1e-6) \ else cu # 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-16): - ball = np.zeros(3) + if np.allclose(cu_,0.0,rtol=0.0,atol=1.0e-16): + ho = np.zeros(3) else: # get pyramide and scale by grid parameter ratio - p = _get_order(cube_) - XYZ = cube_[p[0]] * _sc + p = _get_order(cu_) + XYZ = cu_[p[0]] * _sc # intercept all the points along the z-axis if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): - ball = np.array([0.0, 0.0, np.sqrt(6.0/np.pi) * XYZ[2]]) + ho = 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]] @@ -1161,12 +1161,12 @@ class Rotation: 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 ]) + ho = 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[1]] + ho = ho[p[1]] - return ball + return ho else: raise NotImplementedError diff --git a/src/rotations.f90 b/src/rotations.f90 index 8ff5aca4e..f3110b7d4 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -1233,28 +1233,28 @@ end function cu2ho !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief map from 3D cubic grid to 3D ball !-------------------------------------------------------------------------- -pure function Lambert_CubeToBall(cube) result(ball) +pure function Lambert_CubeToBall(cu) result(ho) - real(pReal), intent(in), dimension(3) :: cube - real(pReal), dimension(3) :: ball, LamXYZ, XYZ + real(pReal), intent(in), dimension(3) :: cu + real(pReal), dimension(3) :: ho, LamXYZ, XYZ real(pReal), dimension(2) :: T real(pReal) :: c, s, q real(pReal), parameter :: eps = 1.0e-8_pReal integer, dimension(3,2) :: p integer, dimension(2) :: order - if (maxval(abs(cube)) > AP/2.0+eps) then - ball = IEEE_value(cube,IEEE_positive_inf) + if (maxval(abs(cu)) > AP/2.0+eps) then + ho = IEEE_value(cu,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 + center: if (all(dEq0(cu))) then + ho = 0.0_pReal else center ! get pyramide and scale by grid parameter ratio - p = GetPyramidOrder(cube) - XYZ = cube(p(:,1)) * sc + p = GetPyramidOrder(cu) + XYZ = cu(p(:,1)) * sc ! intercept all the points along the z-axis special: if (all(dEq0(XYZ(1:2)))) then @@ -1277,7 +1277,7 @@ pure function Lambert_CubeToBall(cube) result(ball) endif special ! reverse the coordinates back to order according to the original pyramid number - ball = LamXYZ(p(:,2)) + ho = LamXYZ(p(:,2)) endif center @@ -1289,25 +1289,25 @@ end function Lambert_CubeToBall !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief map from 3D ball to 3D cubic grid !-------------------------------------------------------------------------- -pure function Lambert_BallToCube(xyz) result(cube) +pure function Lambert_BallToCube(ho) result(cu) - real(pReal), intent(in), dimension(3) :: xyz - real(pReal), dimension(3) :: cube, xyz1, xyz3 + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(3) :: cu, xyz1, xyz3 real(pReal), dimension(2) :: Tinv, xyz2 real(pReal) :: rs, qxy, q2, sq2, q, tt integer, dimension(3,2) :: p - rs = norm2(xyz) + rs = norm2(ho) if (rs > R1+1.e-6_pReal) then - cube = IEEE_value(cube,IEEE_positive_inf) + cu = IEEE_value(cu,IEEE_positive_inf) return endif - center: if (all(dEq0(xyz))) then - cube = 0.0_pReal + center: if (all(dEq0(ho))) then + cu = 0.0_pReal else center - p = GetPyramidOrder(xyz) - xyz3 = xyz(p(:,1)) + p = GetPyramidOrder(ho) + xyz3 = ho(p(:,1)) ! inverse M_3 xyz2 = xyz3(1:2) * sqrt( 2.0*rs/(rs+abs(xyz3(3))) ) @@ -1331,7 +1331,7 @@ pure function Lambert_BallToCube(xyz) result(cube) xyz1 = [ Tinv(1), Tinv(2), sign(1.0_pReal,xyz3(3)) * rs / pref ] /sc ! reverse the coordinates back to order according to the original pyramid number - cube = xyz1(p(:,2)) + cu = xyz1(p(:,2)) endif center From d0dcfedb47d97ef785f8c3ebf38955757d616976 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 29 Apr 2020 14:52:18 +0200 Subject: [PATCH 16/54] no extra function needed --- src/rotations.f90 | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index f3110b7d4..feb7e54db 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -927,7 +927,7 @@ function ax2cu(ax) result(cu) real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(3) :: cu - cu = ho2cu(ax2ho(ax)) + cu = ho2cu(ax2ho(ax)) end function ax2cu @@ -1131,20 +1131,6 @@ pure function ho2ro(ho) result(ro) end function ho2ro -!--------------------------------------------------------------------------------------------------- -!> @author Marc De Graef, Carnegie Mellon University -!> @brief convert homochoric to cubochoric -!--------------------------------------------------------------------------------------------------- -pure function ho2cu(ho) result(cu) - - real(pReal), intent(in), dimension(3) :: ho - real(pReal), dimension(3) :: cu - - cu = Lambert_BallToCube(ho) - -end function ho2cu - - !--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief convert cubochoric to unit quaternion @@ -1215,25 +1201,12 @@ pure function cu2ro(cu) result(ro) end function cu2ro -!--------------------------------------------------------------------------------------------------- -!> @author Marc De Graef, Carnegie Mellon University -!> @brief convert cubochoric to homochoric -!--------------------------------------------------------------------------------------------------- -pure function cu2ho(cu) result(ho) - - real(pReal), intent(in), dimension(3) :: cu - real(pReal), dimension(3) :: ho - - ho = Lambert_CubeToBall(cu) - -end function cu2ho - !-------------------------------------------------------------------------- !> @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 !-------------------------------------------------------------------------- -pure function Lambert_CubeToBall(cu) result(ho) +pure function cu2ho(cu) result(ho) real(pReal), intent(in), dimension(3) :: cu real(pReal), dimension(3) :: ho, LamXYZ, XYZ @@ -1281,15 +1254,15 @@ pure function Lambert_CubeToBall(cu) result(ho) endif center -end function Lambert_CubeToBall +end function cu2ho !-------------------------------------------------------------------------- !> @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 +!> @brief convert homochoric to cubochoric !-------------------------------------------------------------------------- -pure function Lambert_BallToCube(ho) result(cu) +pure function ho2cu(ho) result(cu) real(pReal), intent(in), dimension(3) :: ho real(pReal), dimension(3) :: cu, xyz1, xyz3 @@ -1335,7 +1308,7 @@ pure function Lambert_BallToCube(ho) result(cu) endif center -end function Lambert_BallToCube +end function ho2cu !-------------------------------------------------------------------------- From ad312201ddf5cefcd4367261561621febfee5946 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 29 Apr 2020 14:53:27 +0200 Subject: [PATCH 17/54] keep order --- src/rotations.f90 | 108 +++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/rotations.f90 b/src/rotations.f90 index feb7e54db..fea642170 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -1131,6 +1131,60 @@ pure function ho2ro(ho) result(ro) end function ho2ro +!-------------------------------------------------------------------------- +!> @author Marc De Graef, Carnegie Mellon University +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief convert homochoric to cubochoric +!-------------------------------------------------------------------------- +pure function ho2cu(ho) result(cu) + + real(pReal), intent(in), dimension(3) :: ho + real(pReal), dimension(3) :: cu, xyz1, xyz3 + real(pReal), dimension(2) :: Tinv, xyz2 + real(pReal) :: rs, qxy, q2, sq2, q, tt + integer, dimension(3,2) :: p + + rs = norm2(ho) + if (rs > R1+1.e-6_pReal) then + cu = IEEE_value(cu,IEEE_positive_inf) + return + endif + + center: if (all(dEq0(ho))) then + cu = 0.0_pReal + else center + p = GetPyramidOrder(ho) + xyz3 = ho(p(:,1)) + + ! 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_pReal + 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_pReal,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_pReal,xyz3(3)) * rs / pref ] /sc + + ! reverse the coordinates back to order according to the original pyramid number + cu = xyz1(p(:,2)) + + endif center + +end function ho2cu + + !--------------------------------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @brief convert cubochoric to unit quaternion @@ -1257,60 +1311,6 @@ pure function cu2ho(cu) result(ho) end function cu2ho -!-------------------------------------------------------------------------- -!> @author Marc De Graef, Carnegie Mellon University -!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief convert homochoric to cubochoric -!-------------------------------------------------------------------------- -pure function ho2cu(ho) result(cu) - - real(pReal), intent(in), dimension(3) :: ho - real(pReal), dimension(3) :: cu, xyz1, xyz3 - real(pReal), dimension(2) :: Tinv, xyz2 - real(pReal) :: rs, qxy, q2, sq2, q, tt - integer, dimension(3,2) :: p - - rs = norm2(ho) - if (rs > R1+1.e-6_pReal) then - cu = IEEE_value(cu,IEEE_positive_inf) - return - endif - - center: if (all(dEq0(ho))) then - cu = 0.0_pReal - else center - p = GetPyramidOrder(ho) - xyz3 = ho(p(:,1)) - - ! 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_pReal - 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_pReal,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_pReal,xyz3(3)) * rs / pref ] /sc - - ! reverse the coordinates back to order according to the original pyramid number - cu = xyz1(p(:,2)) - - endif center - -end function ho2cu - - !-------------------------------------------------------------------------- !> @author Marc De Graef, Carnegie Mellon University !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH From 10710bc4460fe4286594c364d72adbac6375830f Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Thu, 30 Apr 2020 21:29:59 +0200 Subject: [PATCH 18/54] using pointers makes finalize general for GNU and Intel --- src/YAML_types.f90 | 253 ++++++++++++++++++++++++++++----------------- 1 file changed, 159 insertions(+), 94 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 26f17430a..7a53bdbd3 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -70,6 +70,8 @@ module YAML_types tNode_get_byKey_asString => tNode_get_byKey_asString procedure :: & tNode_get_byKey_asStrings => tNode_get_byKey_asStrings + procedure :: & + getIndex => tNode_get_byKey_asIndex generic :: & get => tNode_get_byIndex, & @@ -132,9 +134,7 @@ module YAML_types asBools => tList_asBools procedure :: & asStrings => tList_asStrings -#ifndef __GFORTRAN__ final :: tList_finalize -#endif end type tList type, extends(tList) :: tDict @@ -146,18 +146,20 @@ module YAML_types type :: tItem character(len=:), allocatable :: key - class(tNode), allocatable :: node + class(tNode), pointer :: node => null() class(tItem), pointer :: next => null() + + contains + final :: tItem_finalize end type tItem abstract interface - recursive function asFormattedString(self,indent) + recursive subroutine asFormattedString(self,indent) import tNode - character(len=:), allocatable :: asFormattedString class(tNode), intent(in), target :: self integer, intent(in), optional :: indent - end function asFormattedString + end subroutine asFormattedString end interface @@ -188,52 +190,76 @@ end subroutine YAML_types_init !-------------------------------------------------------------------------------------------------- subroutine unitTest - type(tScalar),target :: s1,s2 - - s1 = '1' - if(s1%asInt() /= 1) call IO_error(0,ext_msg='tScalar_asInt') - if(dNeq(s1%asFloat(),1.0_pReal)) call IO_error(0,ext_msg='tScalar_asFloat') - s1 = 'True' - if(.not. s1%asBool()) call IO_error(0,ext_msg='tScalar_asBool') - if(s1%asString() /= 'True') call IO_error(0,ext_msg='tScalar_asString') - + class(tNode), pointer :: s1,s2 + allocate(tScalar::s1) + allocate(tScalar::s2) + select type(s1) + class is(tScalar) + s1 = '1' + if(s1%asInt() /= 1) call IO_error(0,ext_msg='tScalar_asInt') + if(dNeq(s1%asFloat(),1.0_pReal)) call IO_error(0,ext_msg='tScalar_asFloat') + s1 = 'True' + if(.not. s1%asBool()) call IO_error(0,ext_msg='tScalar_asBool') + if(s1%asString() /= 'True') call IO_error(0,ext_msg='tScalar_asString') + end select block - type(tList), target :: l1, l2 - class(tNode), pointer :: n + class(tNode), pointer :: l1, l2, n + character(len=1) :: test = '2' + select type(s1) + class is(tScalar) + s1 = test + endselect + + select type(s2) + class is(tScalar) + s2 = '3' + endselect - s1 = '2' - s2 = '3' - call l1%append(s1) - call l1%append(s2) - call l2%append(l1) - n => l1 + allocate(tList::l1) + select type(l1) + class is(tList) + call l1%append(s1) + call l1%append(s2) + n => l1 + if(any(l1%asInts() /= [2,3])) call IO_error(0,ext_msg='tList_asInts') + if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='tList_asFloats') + if(n%get_asInt(1) /= 2) call IO_error(0,ext_msg='byIndex_asInt') + if(dNeq(n%get_asFloat(2),3.0_pReal)) call IO_error(0,ext_msg='byIndex_asFloat') + endselect + + allocate(tList::l2) + select type(l2) + class is(tList) + call l2%append(l1) + if(any(l2%get_asInts(1) /= [2,3])) call IO_error(0,ext_msg='byIndex_asInts') + if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='byIndex_asFloats') + n => l2 + end select + deallocate(n) + end block - if(any(l1%asInts() /= [2,3])) call IO_error(0,ext_msg='tList_asInts') - if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='tList_asFloats') - if(n%get_asInt(1) /= 2) call IO_error(0,ext_msg='byIndex_asInt') - if(dNeq(n%get_asFloat(2),3.0_pReal)) call IO_error(0,ext_msg='byIndex_asFloat') - if(any(l2%get_asInts(1) /= [2,3])) call IO_error(0,ext_msg='byIndex_asInts') - if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='byIndex_asFloats') - end block - - block - type(tList), target :: l1, l2 - class(tNode), pointer :: n - s1 = 'True' - s2 = 'False' - call l1%append(s1) - call l1%append(s2) - call l2%append(l1) - n=> l1 - - if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') - if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') - if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') - if(n%get_asString(1) /= 'True') call IO_error(0,ext_msg='byIndex_asString') - if(any(l2%get_asBools(1) .neqv. [.true., .false.])) call IO_error(0,ext_msg='byIndex_asBools') - if(any(l2%get_asStrings(1) /= ['True ','False'])) call IO_error(0,ext_msg='byIndex_asStrings') - end block + block + type(tList), target :: l1 + type(tScalar),pointer :: s3,s4 + class(tNode), pointer :: n + + allocate(tScalar::s1) + allocate(tScalar::s2) + s3 => s1%asScalar() + s4 => s2%asScalar() + s3 = 'True' + s4 = 'False' + + call l1%append(s1) + call l1%append(s2) + n => l1 + + if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') + if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') + if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') + if(n%get_asString(1) /= 'True') call IO_error(0,ext_msg='byIndex_asString') + end block end subroutine unitTest @@ -676,14 +702,40 @@ function tNode_get_byKey_asStrings(self,k) result(nodeAsStrings) end function tNode_get_byKey_asStrings -!-------------------------------------------------------------------------------------------------- -!> @brief Return scalar as string -!-------------------------------------------------------------------------------------------------- -recursive function tScalar_asFormattedString(self,indent) +!------------------------------------------------------------------------------------------------------- +!> @brief Returns the index of a key in a dictionary +!------------------------------------------------------------------------------------------------------- +function tNode_get_byKey_asIndex(self,key) result(keyIndex) - character(len=:), allocatable :: tScalar_asFormattedString - class(tScalar), intent(in), target :: self - integer, intent(in), optional :: indent + class(tNode), intent(in), target :: self + character(len=*), intent(in) :: key + + integer :: keyIndex + integer :: i + type(tDict), pointer :: dict + type(tItem), pointer :: item + + dict => self%asDict() + item => dict%first + do i = 1, dict%length + if(key == item%key) then + keyIndex = i + exit + else + item => item%next + endif + enddo + +end function tNode_get_byKey_asIndex + + +!-------------------------------------------------------------------------------------------------- +!> @brief Prints scalar as string +!-------------------------------------------------------------------------------------------------- +recursive subroutine tScalar_asFormattedString(self,indent) + + class (tScalar), intent(in), target :: self + integer, intent(in), optional :: indent integer :: indent_ @@ -693,22 +745,21 @@ recursive function tScalar_asFormattedString(self,indent) indent_ = 0 endif - tScalar_asFormattedString = repeat(' ',indent_)//trim(self%value)//IO_EOL + write (6,'(a)') trim(self%value) -end function tScalar_asFormattedString +end subroutine tScalar_asFormattedString !-------------------------------------------------------------------------------------------------- -!> @brief Return list as string (YAML block style) +!> @brief Prints list as string (YAML block style) !-------------------------------------------------------------------------------------------------- -recursive function tList_asFormattedString(self,indent) result(str) +recursive subroutine tList_asFormattedString(self,indent) - class(tList), intent(in), target :: self - integer, intent(in), optional :: indent + class (tList),intent(in),target :: self + integer, intent(in),optional :: indent - class(tItem), pointer :: item - character(len=:), allocatable :: str - integer :: i,indent_ + type (tItem), pointer :: item + integer :: i, indent_ if(present(indent)) then indent_ = indent @@ -718,24 +769,25 @@ recursive function tList_asFormattedString(self,indent) result(str) item => self%first do i = 1, self%length - str = str//repeat(' ',indent_)//'-'//IO_EOL//item%node%asFormattedString(indent_+2) + if( i /= 1) write (6,'(a)',advance='NO') repeat(' ',indent_) + write (6,'(a)',advance='NO') '- ' + call item%node%asFormattedString(indent_+2) item => item%next - enddo + end do -end function tList_asFormattedString +end subroutine tList_asFormattedString !-------------------------------------------------------------------------------------------------- -!> @brief Return dictionary as string (YAML block style) +!> @brief Prints dictionary as string (YAML block style) !-------------------------------------------------------------------------------------------------- -recursive function tDict_asFormattedString(self,indent) result(str) +recursive subroutine tDict_asFormattedString(self,indent) - class(tDict), intent(in), target :: self - integer, intent(in), optional :: indent - - class(tItem), pointer :: item - character(len=:), allocatable :: str - integer :: i,indent_ + class (tDict),intent(in),target :: self + integer, intent(in),optional :: indent + + type (tItem),pointer :: item + integer :: i, indent_ if(present(indent)) then indent_ = indent @@ -745,11 +797,20 @@ recursive function tDict_asFormattedString(self,indent) result(str) item => self%first do i = 1, self%length - str = str//repeat(' ',indent_)//item%key//':'//IO_EOL//item%node%asFormattedString(indent_+2) + if( i /= 1) write (6,'(a)',advance='NO') repeat(' ',indent_) + select type (node_ => item%node) + class is (tScalar) + write (6,'(a)',advance='NO') trim(item%key)//': ' + call node_%asFormattedString(indent_+len_trim(item%key)+2) + class default + write (6,'(a)') trim(item%key)//':' + write (6,'(a)',advance='NO') repeat(' ',indent_+2) + call node_%asFormattedString(indent_+2) + end select item => item%next - enddo + end do -end function tDict_asFormattedString +end subroutine tDict_asFormattedString !-------------------------------------------------------------------------------------------------- @@ -905,8 +966,8 @@ end function tList_asStrings !-------------------------------------------------------------------------------------------------- subroutine tList_append(self,node) - class(tList), intent(inout) :: self - class(tNode), intent(in) :: node + class(tList), intent(inout) :: self + class(tNode), intent(in), target :: node type(tItem), pointer :: item @@ -922,7 +983,7 @@ subroutine tList_append(self,node) item => item%next end if - allocate(item%node,source=node) ! ToDo: Discuss ownership (copy vs referencing) + item%node => node self%length = self%length + 1 end subroutine tList_append @@ -933,9 +994,9 @@ end subroutine tList_append !-------------------------------------------------------------------------------------------------- subroutine tDict_set(self,key,node) - class (tDict), intent(inout) :: self - character(len=*), intent(in) :: key - class(tNode), intent(in) :: node + class (tDict), intent(inout) :: self + character(len=*), intent(in) :: key + class(tNode), intent(in), target :: node type(tItem), pointer :: item @@ -957,7 +1018,7 @@ subroutine tDict_set(self,key,node) end if item%key = key - allocate(item%node,source=node) + item%node => node end subroutine tDict_set @@ -970,17 +1031,21 @@ recursive subroutine tList_finalize(self) type (tList),intent(inout) :: self - type (tItem),pointer :: current, & - next - - current => self%first - do while (associated(current)) - next => current%next - deallocate(current) - current => next - end do + deallocate(self%first) end subroutine tList_finalize +!-------------------------------------------------------------------------------------------------- +!> @brief empties nodes and frees associated memory +!-------------------------------------------------------------------------------------------------- +recursive subroutine tItem_finalize(self) + + type(tItem),intent(inout) :: self + + deallocate(self%node) + if(associated(self%next)) deallocate(self%next) + +end subroutine tItem_finalize + end module YAML_types From 815608ac4213287f6e00a84f87a3f467f741989b Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Thu, 30 Apr 2020 21:34:11 +0200 Subject: [PATCH 19/54] polishing --- src/YAML_types.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 7a53bdbd3..02b2d5fdb 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -205,10 +205,9 @@ subroutine unitTest block class(tNode), pointer :: l1, l2, n - character(len=1) :: test = '2' select type(s1) class is(tScalar) - s1 = test + s1 = '2' endselect select type(s2) From 2df78e4e2f4b8a018262a9d61a118496c612c597 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 29 Apr 2020 17:52:09 +0200 Subject: [PATCH 20/54] vecorized pyramid function for lambert projection --- python/damask/_rotation.py | 65 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 42b32552b..876e59747 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1064,8 +1064,7 @@ class Rotation: if np.allclose(ho_,0.0,rtol=0.0,atol=1.0e-16): cu = np.zeros(3) else: - p = _get_order(ho_) - xyz3 = ho_[p[0]] + xyz3 = ho_[Rotation._get_order(ho_,'forward')] # inverse M_3 xyz2 = xyz3[0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[2])) ) @@ -1087,7 +1086,7 @@ class Rotation: # inverse M_1 cu = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /_sc # reverse the coordinates back to the regular order according to the original pyramid number - cu = cu[p[1]] + cu = cu[Rotation._get_order(ho_,'backward')] return cu else: @@ -1141,8 +1140,7 @@ class Rotation: ho = np.zeros(3) else: # get pyramide and scale by grid parameter ratio - p = _get_order(cu_) - XYZ = cu_[p[0]] * _sc + XYZ = cu_[Rotation._get_order(cu_,'forward')] * _sc # intercept all the points along the z-axis if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): @@ -1164,37 +1162,46 @@ class Rotation: ho = 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 - ho = ho[p[1]] + ho = ho[Rotation._get_order(cu_,'backward')] return ho else: raise NotImplementedError -def _get_order(xyz): - """ - Get order of the coordinates. + @staticmethod + def _get_order(xyz,direction=None): + """ + Get order of the coordinates. - Depending on the pyramid in which the point is located, the order need to be adjusted. + Depending on the pyramid in which the point is located, the order need to be adjusted. - Parameters - ---------- - xyz : numpy.ndarray - coordinates of a point on a uniform refinable grid on a ball or - in a uniform refinable cubical grid. + Parameters + ---------- + xyz : numpy.ndarray + coordinates of a point on a uniform refinable grid on a ball or + in a uniform refinable cubical grid. - References - ---------- - D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 - https://doi.org/10.1088/0965-0393/22/7/075013 + References + ---------- + D. Roşca et al., Modelling and Simulation in Materials Science and Engineering 22:075013, 2014 + https://doi.org/10.1088/0965-0393/22/7/075013 - """ - 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],[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],[2,0,1]] - 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],[1,2,0]] + """ + order = {'forward':np.array([[0,1,2],[1,2,0],[2,0,1]]), + 'backward':np.array([[0,1,2],[2,0,1],[1,2,0]])} + if len(xyz.shape) == 1: + if np.maximum(abs(xyz[0]),abs(xyz[1])) <= xyz[2] or \ + np.maximum(abs(xyz[0]),abs(xyz[1])) <=-xyz[2]: + p = 0 + elif np.maximum(abs(xyz[1]),abs(xyz[2])) <= xyz[0] or \ + np.maximum(abs(xyz[1]),abs(xyz[2])) <=-xyz[0]: + p = 1 + elif np.maximum(abs(xyz[2]),abs(xyz[0])) <= xyz[1] or \ + np.maximum(abs(xyz[2]),abs(xyz[0])) <=-xyz[1]: + p = 2 + else: + p = np.where(np.maximum(np.abs(xyz[...,0]),np.abs(xyz[...,1])) <= np.abs(xyz[...,2]),0, + np.where(np.maximum(np.abs(xyz[...,1]),np.abs(xyz[...,2])) <= np.abs(xyz[...,0]),2,3)) + + return order[direction][p] From 47f85402c492fe5c3cae3b5091f74195c2dca9dc Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Sat, 2 May 2020 23:03:11 +0200 Subject: [PATCH 21/54] using function makes it more readable --- src/YAML_types.f90 | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 02b2d5fdb..f1af2f9cb 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -155,11 +155,12 @@ module YAML_types abstract interface - recursive subroutine asFormattedString(self,indent) + recursive function asFormattedString(self,indent) import tNode + character(len=:), allocatable :: asFormattedString class(tNode), intent(in), target :: self integer, intent(in), optional :: indent - end subroutine asFormattedString + end function asFormattedString end interface @@ -731,8 +732,9 @@ end function tNode_get_byKey_asIndex !-------------------------------------------------------------------------------------------------- !> @brief Prints scalar as string !-------------------------------------------------------------------------------------------------- -recursive subroutine tScalar_asFormattedString(self,indent) +recursive function tScalar_asFormattedString(self,indent) + character(len=:), allocatable :: tScalar_asFormattedString class (tScalar), intent(in), target :: self integer, intent(in), optional :: indent @@ -744,20 +746,21 @@ recursive subroutine tScalar_asFormattedString(self,indent) indent_ = 0 endif - write (6,'(a)') trim(self%value) + tScalar_asFormattedString = trim(self%value)//IO_EOL -end subroutine tScalar_asFormattedString +end function tScalar_asFormattedString !-------------------------------------------------------------------------------------------------- !> @brief Prints list as string (YAML block style) !-------------------------------------------------------------------------------------------------- -recursive subroutine tList_asFormattedString(self,indent) +recursive function tList_asFormattedString(self,indent) result(str) class (tList),intent(in),target :: self integer, intent(in),optional :: indent type (tItem), pointer :: item + character(len=:), allocatable :: str integer :: i, indent_ if(present(indent)) then @@ -768,24 +771,24 @@ recursive subroutine tList_asFormattedString(self,indent) item => self%first do i = 1, self%length - if( i /= 1) write (6,'(a)',advance='NO') repeat(' ',indent_) - write (6,'(a)',advance='NO') '- ' - call item%node%asFormattedString(indent_+2) + if(i /= 1) str = str//repeat(' ',indent_) + str = str//'- '//item%node%asFormattedString(indent_+2) item => item%next end do -end subroutine tList_asFormattedString +end function tList_asFormattedString !-------------------------------------------------------------------------------------------------- !> @brief Prints dictionary as string (YAML block style) !-------------------------------------------------------------------------------------------------- -recursive subroutine tDict_asFormattedString(self,indent) +recursive function tDict_asFormattedString(self,indent) result(str) class (tDict),intent(in),target :: self integer, intent(in),optional :: indent type (tItem),pointer :: item + character(len=:), allocatable :: str integer :: i, indent_ if(present(indent)) then @@ -796,20 +799,17 @@ recursive subroutine tDict_asFormattedString(self,indent) item => self%first do i = 1, self%length - if( i /= 1) write (6,'(a)',advance='NO') repeat(' ',indent_) - select type (node_ => item%node) - class is (tScalar) - write (6,'(a)',advance='NO') trim(item%key)//': ' - call node_%asFormattedString(indent_+len_trim(item%key)+2) + if(i /= 1) str = str//repeat(' ',indent_) + select type(node_1 =>item%node) + class is(tScalar) + str = str//trim(item%key)//': '//item%node%asFormattedString(indent_+len_trim(item%key)+2) class default - write (6,'(a)') trim(item%key)//':' - write (6,'(a)',advance='NO') repeat(' ',indent_+2) - call node_%asFormattedString(indent_+2) - end select + str = str//trim(item%key)//':'//IO_EOL//repeat(' ',indent_+2)//item%node%asFormattedString(indent_+2) + endselect item => item%next end do -end subroutine tDict_asFormattedString +end function tDict_asFormattedString !-------------------------------------------------------------------------------------------------- From 00deddac44df1657bd5b5c312273535cce5ee278 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Sat, 2 May 2020 23:17:53 +0200 Subject: [PATCH 22/54] initialization needed --- src/YAML_types.f90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index f1af2f9cb..314c099f8 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -762,7 +762,8 @@ recursive function tList_asFormattedString(self,indent) result(str) type (tItem), pointer :: item character(len=:), allocatable :: str integer :: i, indent_ - + + str = '' if(present(indent)) then indent_ = indent else @@ -791,6 +792,7 @@ recursive function tDict_asFormattedString(self,indent) result(str) character(len=:), allocatable :: str integer :: i, indent_ + str = '' if(present(indent)) then indent_ = indent else From c241eaec15dec1706acebe5fbde6dbee258c68b3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 07:23:46 +0200 Subject: [PATCH 23/54] rely on correct input data --- python/damask/_rotation.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 83c790d74..6fe546fd9 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1061,14 +1061,12 @@ class Rotation: """ if len(ho.shape) == 1: - ho_ = ho/np.linalg.norm(ho)*_R1 if np.isclose(np.linalg.norm(ho),_R1,atol=1e-6) \ - else ho - rs = np.linalg.norm(ho_) + rs = np.linalg.norm(ho) - if np.allclose(ho_,0.0,rtol=0.0,atol=1.0e-16): + if np.allclose(ho,0.0,rtol=0.0,atol=1.0e-16): cu = np.zeros(3) else: - xyz3 = ho_[Rotation._get_order(ho_,'forward')] + xyz3 = ho[Rotation._get_order(ho,'forward')] # inverse M_3 xyz2 = xyz3[0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[2])) ) @@ -1090,7 +1088,7 @@ class Rotation: # inverse M_1 cu = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /_sc # reverse the coordinates back to the regular order according to the original pyramid number - cu = cu[Rotation._get_order(ho_,'backward')] + cu = cu[Rotation._get_order(ho,'backward')] return cu else: @@ -1135,16 +1133,12 @@ class Rotation: """ if len(cu.shape) == 1: - - cu_ = np.clip(cu,None,np.pi**(2./3.) * 0.5) if np.isclose(np.abs(np.max(cu)),np.pi**(2./3.) * 0.5,atol=1e-6) \ - else cu - # transform to the sphere grid via the curved square, and intercept the zero point - if np.allclose(cu_,0.0,rtol=0.0,atol=1.0e-16): + if np.allclose(cu,0.0,rtol=0.0,atol=1.0e-16): ho = np.zeros(3) else: # get pyramide and scale by grid parameter ratio - XYZ = cu_[Rotation._get_order(cu_,'forward')] * _sc + XYZ = cu[Rotation._get_order(cu,'forward')] * _sc # intercept all the points along the z-axis if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): @@ -1166,7 +1160,7 @@ class Rotation: ho = 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 - ho = ho[Rotation._get_order(cu_,'backward')] + ho = ho[Rotation._get_order(cu,'backward')] return ho else: From 5d4b554b007be36eb383a1e39ac911f2de4a9fc0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 07:30:09 +0200 Subject: [PATCH 24/54] WIP: vectorizing --- python/damask/_rotation.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 6fe546fd9..f97e356fc 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1092,6 +1092,13 @@ class Rotation: return cu 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) raise NotImplementedError('Support for multiple rotations missing') @@ -1164,6 +1171,19 @@ class Rotation: return ho else: + # get pyramide and scale by grid parameter ratio + XYZ = cu[Rotation._get_order(cu,'forward')] * _sc + order = np.where(np.abs(XYZ[...,1]) <= np.abs(XYZ[...,0]), + np.broadcast_to([1,0],XYZ.shape[:-1]+(2,)), + np.broadcast_to([0,1],XYZ.shape[:-1]+(2,))) + 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.block([ (np.sqrt(2.0)*c - 1.0), np.sqrt(2.0) * s]) * q + 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 ) raise NotImplementedError('Support for multiple rotations missing') @staticmethod From 8995faae8ba0c0a4277ca1d2dc67cb018ca998e9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 10:49:36 +0200 Subject: [PATCH 25/54] WIP: part of dotState should be in deltaState --- src/constitutive_plastic_nonlocal.f90 | 404 ++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 77f1556f6..153e12dd1 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1344,6 +1344,410 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & end subroutine plastic_nonlocal_dotState +!--------------------------------------------------------------------------------------------------- +!> @brief calculates the rate of change of microstructure +!--------------------------------------------------------------------------------------------------- +subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & + instance,of,ip,el) + + real(pReal), dimension(3,3), intent(in) :: & + Mp !< MandelStress + real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & + F, & !< elastic deformation gradient + Fp !< plastic deformation gradient + real(pReal), intent(in) :: & + Temperature, & !< temperature + timestep !< substepped crystallite time increment + integer, intent(in) :: & + instance, & + of, & + ip, & !< current integration point + el !< current element number + + integer :: & + ph, & + neighbor_instance, & !< instance of my neighbor's plasticity + ns, & !< short notation for the total number of active slip systems + c, & !< character of dislocation + n, & !< index of my current neighbor + neighbor_el, & !< element number of my neighbor + neighbor_ip, & !< integration point of my neighbor + neighbor_n, & !< neighbor index pointing to me when looking from my neighbor + opposite_neighbor, & !< index of my opposite neighbor + opposite_ip, & !< ip of my opposite neighbor + opposite_el, & !< element index of my opposite neighbor + opposite_n, & !< neighbor index pointing to me when looking from my opposite neighbor + t, & !< type of dislocation + no,& !< neighbor offset shortcut + np,& !< neighbor phase shortcut + topp, & !< type of dislocation with opposite sign to t + s !< index of my current slip system + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & + rho, & + rho0, & !< dislocation density at beginning of time step + rhoDot, & !< density evolution + rhoDotMultiplication, & !< density evolution by multiplication + rhoDotFlux, & !< density evolution by flux + rhoDotSingle2DipoleGlide, & !< density evolution by dipole formation (by glide) + rhoDotAthermalAnnihilation, & !< density evolution by athermal annihilation + rhoDotThermalAnnihilation !< density evolution by thermal annihilation + real(pReal), dimension(param(instance)%sum_N_sl,8) :: & + rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) + neighbor_rhoSgl0, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) + my_rhoSgl0 !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) + real(pReal), dimension(param(instance)%sum_N_sl,4) :: & + v, & !< current dislocation glide velocity + v0, & + neighbor_v0, & !< dislocation glide velocity of enighboring ip + gdot !< shear rates + real(pReal), dimension(param(instance)%sum_N_sl) :: & + tau, & !< current resolved shear stress + vClimb !< climb velocity of edge dipoles + real(pReal), dimension(param(instance)%sum_N_sl,2) :: & + rhoDip, & !< current 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,param(instance)%sum_N_sl,4) :: & + m !< direction of dislocation motion + real(pReal), dimension(3,3) :: & + my_F, & !< my total deformation gradient + neighbor_F, & !< total deformation gradient of my neighbor + my_Fe, & !< my elastic deformation gradient + neighbor_Fe, & !< elastic deformation gradient of my neighbor + Favg !< average total deformation gradient of me and my neighbor + real(pReal), dimension(3) :: & + normal_neighbor2me, & !< interface normal pointing from my neighbor to me in neighbor's lattice configuration + normal_neighbor2me_defConf, & !< interface normal pointing from my neighbor to me in shared deformed configuration + normal_me2neighbor, & !< interface normal pointing from me to my neighbor in my lattice configuration + normal_me2neighbor_defConf !< interface normal pointing from me to my neighbor in shared deformed configuration + 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 + + ph = material_phaseAt(1,el) + if (timestep <= 0.0_pReal) then + plasticState(ph)%dotState = 0.0_pReal + return + endif + + associate(prm => param(instance), & + dst => microstructure(instance), & + dot => dotState(instance), & + stt => state(instance)) + ns = prm%sum_N_sl + + tau = 0.0_pReal + gdot = 0.0_pReal + + rho = getRho(instance,of,ip,el) + rhoSgl = rho(:,sgl) + rhoDip = rho(:,dip) + rho0 = getRho0(instance,of,ip,el) + my_rhoSgl0 = rho0(:,sgl) + + forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) + gdot = rhoSgl(:,1:4) * v * spread(prm%burgers,2,4) + +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0 & + .and. ((debug_e == el .and. debug_i == ip)& + .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> rho / 1/m^2', rhoSgl, rhoDip + write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> gdot / 1/s',gdot + endif +#endif + + !**************************************************************************** + !*** limits for stable dipole height + do s = 1,ns + tau(s) = math_tensordot(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 + dUpper(:,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) + dUpper(:,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) + + where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & + dUpper(:,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(:,1)) + where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & + dUpper(:,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(:,2)) + + dUpper = max(dUpper,dLower) + + !**************************************************************************** + !*** dislocation multiplication + rhoDotMultiplication = 0.0_pReal + isBCC: if (lattice_structure(ph) == LATTICE_bcc_ID) then + 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(stt%rho_forest(s,of)) / 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(stt%rho_forest(s,of)) / 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 isBCC + rhoDotMultiplication(:,1:4) = spread( & + (sum(abs(gdot(:,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(:,3:4)),2)) & + * sqrt(stt%rho_forest(:,of)) / prm%lambda0 / prm%burgers, 2, 4) + endif isBCC + + forall (s = 1:ns, t = 1:4) v0(s,t) = plasticState(ph)%state0(iV(s,t,instance),of) + + !**************************************************************************** + !*** calculate dislocation fluxes (only for nonlocal plasticity) + rhoDotFlux = 0.0_pReal + if (.not. phase_localPlasticity(material_phaseAt(1,el))) then + + !*** check CFL (Courant-Friedrichs-Lewy) condition for flux + if (any( abs(gdot) > 0.0_pReal & ! any active slip system ... + .and. prm%CFLfactor * abs(v0) * timestep & + > IPvolume(ip,el) / maxval(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) 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(v0), abs(gdot) > 0.0_pReal & + .and. prm%CFLfactor * abs(v0) * timestep & + > IPvolume(ip,el) / maxval(IParea(:,ip,el))), & + ' at a timestep of ',timestep + write(6,'(a)') '<< CONST >> enforcing cutback !!!' + endif +#endif + plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! -> return NaN and, hence, enforce cutback + return + endif + + + !*** be aware of the definition of slip_transverse = slip_direction x slip_normal !!! + !*** opposite sign to our t vector in the (s,t,n) triplet !!! + + m(1:3,:,1) = prm%slip_direction + m(1:3,:,2) = -prm%slip_direction + m(1:3,:,3) = -prm%slip_transverse + m(1:3,:,4) = prm%slip_transverse + + my_F = F(1:3,1:3,1,ip,el) + my_Fe = matmul(my_F, math_inv33(Fp(1:3,1:3,1,ip,el))) + + neighbors: do n = 1,nIPneighbors + + neighbor_el = IPneighborhood(1,n,ip,el) + neighbor_ip = IPneighborhood(2,n,ip,el) + neighbor_n = IPneighborhood(3,n,ip,el) + np = material_phaseAt(1,neighbor_el) + no = material_phasememberAt(1,neighbor_ip,neighbor_el) + + opposite_neighbor = n + mod(n,2) - mod(n+1,2) + opposite_el = IPneighborhood(1,opposite_neighbor,ip,el) + opposite_ip = IPneighborhood(2,opposite_neighbor,ip,el) + opposite_n = IPneighborhood(3,opposite_neighbor,ip,el) + + if (neighbor_n > 0) then ! if neighbor exists, average deformation gradient + neighbor_instance = phase_plasticityInstance(material_phaseAt(1,neighbor_el)) + neighbor_F = F(1:3,1:3,1,neighbor_ip,neighbor_el) + neighbor_Fe = matmul(neighbor_F, math_inv33(Fp(1:3,1:3,1,neighbor_ip,neighbor_el))) + Favg = 0.5_pReal * (my_F + neighbor_F) + else ! if no neighbor, take my value as average + Favg = my_F + endif + + neighbor_v0 = 0.0_pReal ! needed for check of sign change in flux density below + + !* FLUX FROM MY NEIGHBOR TO ME + !* This is only considered, if I have a neighbor of nonlocal plasticity + !* (also nonlocal constitutive law with local properties) that is at least a little bit + !* compatible. + !* If it's not at all compatible, no flux is arriving, because everything is dammed in front of + !* my neighbor's interface. + !* The entering flux from my neighbor will be distributed on my slip systems according to the + !* compatibility + if (neighbor_n > 0) then + if (phase_plasticity(material_phaseAt(1,neighbor_el)) == PLASTICITY_NONLOCAL_ID .and. & + any(compatibility(:,:,:,n,ip,el) > 0.0_pReal)) then + + forall (s = 1:ns, t = 1:4) + neighbor_v0(s,t) = plasticState(np)%state0(iV (s,t,neighbor_instance),no) + neighbor_rhoSgl0(s,t) = max(plasticState(np)%state0(iRhoU(s,t,neighbor_instance),no),0.0_pReal) + endforall + + where (neighbor_rhoSgl0 * IPvolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & + .or. neighbor_rhoSgl0 < prm%significantRho) & + neighbor_rhoSgl0 = 0.0_pReal + normal_neighbor2me_defConf = math_det33(Favg) * matmul(math_inv33(transpose(Favg)), & + IPareaNormal(1:3,neighbor_n,neighbor_ip,neighbor_el)) ! normal of the interface in (average) deformed configuration (pointing neighbor => me) + normal_neighbor2me = matmul(transpose(neighbor_Fe), normal_neighbor2me_defConf) & + / math_det33(neighbor_Fe) ! interface normal in the lattice configuration of my neighbor + area = IParea(neighbor_n,neighbor_ip,neighbor_el) * norm2(normal_neighbor2me) + normal_neighbor2me = normal_neighbor2me / norm2(normal_neighbor2me) ! normalize the surface normal to unit length + do s = 1,ns + do t = 1,4 + c = (t + 1) / 2 + topp = t + mod(t,2) - mod(t+1,2) + if (neighbor_v0(s,t) * math_inner(m(1:3,s,t), normal_neighbor2me) > 0.0_pReal & ! flux from my neighbor to me == entering flux for me + .and. v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal ) then ! ... only if no sign change in flux density + lineLength = neighbor_rhoSgl0(s,t) * neighbor_v0(s,t) & + * math_inner(m(1:3,s,t), normal_neighbor2me) * area ! positive line length that wants to enter through this interface + where (compatibility(c,:,s,n,ip,el) > 0.0_pReal) & + rhoDotFlux(:,t) = rhoDotFlux(1:ns,t) & + + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to equally signed mobile dislocation type + where (compatibility(c,:,s,n,ip,el) < 0.0_pReal) & + rhoDotFlux(:,topp) = rhoDotFlux(:,topp) & + + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to opposite signed mobile dislocation type + + endif + enddo + enddo + endif; endif + + + !* 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 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 + !* In case of reduced transmissivity, part of the leaving flux is stored as dead dislocation density. + !* That means for an interface of zero transmissivity the leaving flux is fully converted to dead dislocations. + if (opposite_n > 0) then + if (phase_plasticity(material_phaseAt(1,opposite_el)) == PLASTICITY_NONLOCAL_ID) then + + normal_me2neighbor_defConf = math_det33(Favg) & + * matmul(math_inv33(transpose(Favg)),IPareaNormal(1:3,n,ip,el)) ! normal of the interface in (average) deformed configuration (pointing me => neighbor) + normal_me2neighbor = matmul(transpose(my_Fe), normal_me2neighbor_defConf) & + / math_det33(my_Fe) ! interface normal in my lattice configuration + area = IParea(n,ip,el) * norm2(normal_me2neighbor) + normal_me2neighbor = normal_me2neighbor / norm2(normal_me2neighbor) ! normalize the surface normal to unit length + do s = 1,ns + do t = 1,4 + c = (t + 1) / 2 + if (v0(s,t) * math_inner(m(1:3,s,t), normal_me2neighbor) > 0.0_pReal ) then ! flux from me to my neighbor == leaving flux for me (might also be a pure flux from my mobile density to dead density if interface not at all transmissive) + if (v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal) then ! no sign change in flux density + transmissivity = sum(compatibility(c,:,s,n,ip,el)**2.0_pReal) ! overall transmissivity from this slip system to my neighbor + else ! sign change in flux density means sign change in stress which does not allow for dislocations to arive at the neighbor + transmissivity = 0.0_pReal + endif + lineLength = my_rhoSgl0(s,t) * v0(s,t) & + * math_inner(m(1:3,s,t), normal_me2neighbor) * area ! positive line length of mobiles that wants to leave through this interface + rhoDotFlux(s,t) = rhoDotFlux(s,t) - lineLength / IPvolume(ip,el) ! subtract dislocation flux from current type + rhoDotFlux(s,t+4) = rhoDotFlux(s,t+4) & + + lineLength / IPvolume(ip,el) * (1.0_pReal - transmissivity) & + * sign(1.0_pReal, v0(s,t)) ! dislocation flux that is not able to leave through interface (because of low transmissivity) will remain as immobile single density at the material point + endif + enddo + enddo + endif; endif + + enddo neighbors + endif + + + + !**************************************************************************** + !*** calculate dipole formation and annihilation + + !*** formation by glide + do c = 1,2 + rhoDotSingle2DipoleGlide(:,2*c-1) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile + + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile + + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) ! positive mobile --> negative immobile + + rhoDotSingle2DipoleGlide(:,2*c) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile + + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile + + abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c))) ! negative mobile --> positive immobile + + rhoDotSingle2DipoleGlide(:,2*c+3) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * rhoSgl(:,2*c+3) * abs(gdot(:,2*c)) ! negative mobile --> positive immobile + + rhoDotSingle2DipoleGlide(:,2*c+4) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * rhoSgl(:,2*c+4) * abs(gdot(:,2*c-1)) ! positive mobile --> negative immobile + + rhoDotSingle2DipoleGlide(:,c+8) = abs(rhoDotSingle2DipoleGlide(:,2*c+3)) & + + abs(rhoDotSingle2DipoleGlide(:,2*c+4)) & + - rhoDotSingle2DipoleGlide(:,2*c-1) & + - rhoDotSingle2DipoleGlide(:,2*c) + enddo + + + !*** athermal annihilation + rhoDotAthermalAnnihilation = 0.0_pReal + forall (c=1:2) & + rhoDotAthermalAnnihilation(:,c+8) = -2.0_pReal * dLower(:,c) / prm%burgers & + * ( 2.0_pReal * (rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) + rhoSgl(:,2*c) * abs(gdot(:,2*c-1))) & ! was single hitting single + + 2.0_pReal * (abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c)) + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) & ! was single hitting immobile single or was immobile single hit by single + + rhoDip(:,c) * (abs(gdot(:,2*c-1)) + abs(gdot(:,2*c)))) ! single knocks dipole constituent + + ! annihilated screw dipoles leave edge jogs behind on the colinear system + if (lattice_structure(ph) == LATTICE_fcc_ID) & + forall (s = 1:ns, prm%colinearSystem(s) > 0) & + rhoDotAthermalAnnihilation(prm%colinearSystem(s),1:2) = - rhoDotAthermalAnnihilation(s,10) & + * 0.25_pReal * sqrt(stt%rho_forest(s,of)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor + + + !*** thermally activated annihilation of edge dipoles by climb + rhoDotThermalAnnihilation = 0.0_pReal + selfDiffusion = prm%Dsd0 * exp(-prm%selfDiffusionEnergy / (kB * Temperature)) + vClimb = prm%atomicVolume * selfDiffusion * prm%mu & + / ( kB * Temperature * PI * (1.0_pReal-prm%nu) * (dUpper(:,1) + dLower(:,1))) + forall (s = 1: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)), & + - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & + - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have + + rhoDot = rhoDotFlux & + + rhoDotMultiplication & + + rhoDotSingle2DipoleGlide & + + rhoDotAthermalAnnihilation & + + rhoDotThermalAnnihilation + +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & + .and. ((debug_e == el .and. debug_i == ip)& + .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then + write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & + rhoDotMultiplication(:,1:4) * timestep + write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation flux', & + rhoDotFlux(:,1:8) * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> dipole formation by glide', & + rhoDotSingle2DipoleGlide * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> athermal dipole annihilation', & + rhoDotAthermalAnnihilation * timestep + write(6,'(a,/,2(12x,12(e12.5,1x),/))') '<< CONST >> thermally activated dipole annihilation', & + rhoDotThermalAnnihilation(:,9:10) * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> total density change', & + rhoDot * timestep + write(6,'(a,/,10(12x,12(f12.5,1x),/))') '<< CONST >> relative density change', & + rhoDot(:,1:8) * timestep / (abs(stt%rho(:,sgl))+1.0e-10), & + rhoDot(:,9:10) * timestep / (stt%rho(:,dip)+1.0e-10) + write(6,*) + endif +#endif + + + if ( any(rho(:,mob) + rhoDot(:,1:4) * timestep < -prm%atol_rho) & + .or. any(rho(:,dip) + rhoDot(:,9:10) * timestep < -prm%atol_rho)) then +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then + write(6,'(a,i5,a,i2)') '<< CONST >> evolution rate leads to negative density at el ',el,' ip ',ip + write(6,'(a)') '<< CONST >> enforcing cutback !!!' + endif +#endif + plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) + else + dot%rho(:,of) = pack(rhoDot,.true.) + dot%gamma(:,of) = sum(gdot,2) + endif + + end associate + +end subroutine plastic_nonlocal_dotState2 + + !-------------------------------------------------------------------------------------------------- !> @brief Compatibility update !> @detail Compatibility is defined as normalized product of signed cosine of the angle between the slip From 6f627892bc9871b73d0ce66c19bdb4cb1365cad7 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 10:54:57 +0200 Subject: [PATCH 26/54] not needed --- src/constitutive_plastic_nonlocal.f90 | 170 +------------------------- 1 file changed, 4 insertions(+), 166 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 153e12dd1..e80f2ceab 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1347,16 +1347,13 @@ end subroutine plastic_nonlocal_dotState !--------------------------------------------------------------------------------------------------- !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & - instance,of,ip,el) +subroutine plastic_nonlocal_dotState2(F, Fp,timestep, & + instance,of,ip,el) - real(pReal), dimension(3,3), intent(in) :: & - Mp !< MandelStress real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & F, & !< elastic deformation gradient Fp !< plastic deformation gradient real(pReal), intent(in) :: & - Temperature, & !< temperature timestep !< substepped crystallite time increment integer, intent(in) :: & instance, & @@ -1385,12 +1382,7 @@ subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & real(pReal), dimension(param(instance)%sum_N_sl,10) :: & rho, & rho0, & !< dislocation density at beginning of time step - rhoDot, & !< density evolution - rhoDotMultiplication, & !< density evolution by multiplication - rhoDotFlux, & !< density evolution by flux - rhoDotSingle2DipoleGlide, & !< density evolution by dipole formation (by glide) - rhoDotAthermalAnnihilation, & !< density evolution by athermal annihilation - rhoDotThermalAnnihilation !< density evolution by thermal annihilation + rhoDotFlux !< density evolution by flux real(pReal), dimension(param(instance)%sum_N_sl,8) :: & rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) neighbor_rhoSgl0, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) @@ -1400,13 +1392,6 @@ subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & v0, & neighbor_v0, & !< dislocation glide velocity of enighboring ip gdot !< shear rates - real(pReal), dimension(param(instance)%sum_N_sl) :: & - tau, & !< current resolved shear stress - vClimb !< climb velocity of edge dipoles - real(pReal), dimension(param(instance)%sum_N_sl,2) :: & - rhoDip, & !< current 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,param(instance)%sum_N_sl,4) :: & m !< direction of dislocation motion real(pReal), dimension(3,3) :: & @@ -1423,8 +1408,7 @@ subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & 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 + lineLength !< dislocation line length leaving the current interface ph = material_phaseAt(1,el) if (timestep <= 0.0_pReal) then @@ -1438,63 +1422,16 @@ subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & stt => state(instance)) ns = prm%sum_N_sl - tau = 0.0_pReal gdot = 0.0_pReal rho = getRho(instance,of,ip,el) rhoSgl = rho(:,sgl) - rhoDip = rho(:,dip) rho0 = getRho0(instance,of,ip,el) my_rhoSgl0 = rho0(:,sgl) forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) gdot = rhoSgl(:,1:4) * v * spread(prm%burgers,2,4) -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> rho / 1/m^2', rhoSgl, rhoDip - write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> gdot / 1/s',gdot - endif -#endif - - !**************************************************************************** - !*** limits for stable dipole height - do s = 1,ns - tau(s) = math_tensordot(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 - dUpper(:,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) - dUpper(:,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) - - where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & - dUpper(:,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(:,1)) - where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & - dUpper(:,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(:,2)) - - dUpper = max(dUpper,dLower) - - !**************************************************************************** - !*** dislocation multiplication - rhoDotMultiplication = 0.0_pReal - isBCC: if (lattice_structure(ph) == LATTICE_bcc_ID) then - 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(stt%rho_forest(s,of)) / 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(stt%rho_forest(s,of)) / 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 isBCC - rhoDotMultiplication(:,1:4) = spread( & - (sum(abs(gdot(:,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(:,3:4)),2)) & - * sqrt(stt%rho_forest(:,of)) / prm%lambda0 / prm%burgers, 2, 4) - endif isBCC forall (s = 1:ns, t = 1:4) v0(s,t) = plasticState(ph)%state0(iV(s,t,instance),of) @@ -1644,105 +1581,6 @@ subroutine plastic_nonlocal_dotState2(Mp, F, Fp, Temperature,timestep, & enddo neighbors endif - - - !**************************************************************************** - !*** calculate dipole formation and annihilation - - !*** formation by glide - do c = 1,2 - rhoDotSingle2DipoleGlide(:,2*c-1) = -2.0_pReal * dUpper(:,c) / prm%burgers & - * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile - + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile - + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) ! positive mobile --> negative immobile - - rhoDotSingle2DipoleGlide(:,2*c) = -2.0_pReal * dUpper(:,c) / prm%burgers & - * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile - + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile - + abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c))) ! negative mobile --> positive immobile - - rhoDotSingle2DipoleGlide(:,2*c+3) = -2.0_pReal * dUpper(:,c) / prm%burgers & - * rhoSgl(:,2*c+3) * abs(gdot(:,2*c)) ! negative mobile --> positive immobile - - rhoDotSingle2DipoleGlide(:,2*c+4) = -2.0_pReal * dUpper(:,c) / prm%burgers & - * rhoSgl(:,2*c+4) * abs(gdot(:,2*c-1)) ! positive mobile --> negative immobile - - rhoDotSingle2DipoleGlide(:,c+8) = abs(rhoDotSingle2DipoleGlide(:,2*c+3)) & - + abs(rhoDotSingle2DipoleGlide(:,2*c+4)) & - - rhoDotSingle2DipoleGlide(:,2*c-1) & - - rhoDotSingle2DipoleGlide(:,2*c) - enddo - - - !*** athermal annihilation - rhoDotAthermalAnnihilation = 0.0_pReal - forall (c=1:2) & - rhoDotAthermalAnnihilation(:,c+8) = -2.0_pReal * dLower(:,c) / prm%burgers & - * ( 2.0_pReal * (rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) + rhoSgl(:,2*c) * abs(gdot(:,2*c-1))) & ! was single hitting single - + 2.0_pReal * (abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c)) + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) & ! was single hitting immobile single or was immobile single hit by single - + rhoDip(:,c) * (abs(gdot(:,2*c-1)) + abs(gdot(:,2*c)))) ! single knocks dipole constituent - - ! annihilated screw dipoles leave edge jogs behind on the colinear system - if (lattice_structure(ph) == LATTICE_fcc_ID) & - forall (s = 1:ns, prm%colinearSystem(s) > 0) & - rhoDotAthermalAnnihilation(prm%colinearSystem(s),1:2) = - rhoDotAthermalAnnihilation(s,10) & - * 0.25_pReal * sqrt(stt%rho_forest(s,of)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor - - - !*** thermally activated annihilation of edge dipoles by climb - rhoDotThermalAnnihilation = 0.0_pReal - selfDiffusion = prm%Dsd0 * exp(-prm%selfDiffusionEnergy / (kB * Temperature)) - vClimb = prm%atomicVolume * selfDiffusion * prm%mu & - / ( kB * Temperature * PI * (1.0_pReal-prm%nu) * (dUpper(:,1) + dLower(:,1))) - forall (s = 1: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)), & - - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & - - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have - - rhoDot = rhoDotFlux & - + rhoDotMultiplication & - + rhoDotSingle2DipoleGlide & - + rhoDotAthermalAnnihilation & - + rhoDotThermalAnnihilation - -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & - rhoDotMultiplication(:,1:4) * timestep - write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation flux', & - rhoDotFlux(:,1:8) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> dipole formation by glide', & - rhoDotSingle2DipoleGlide * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> athermal dipole annihilation', & - rhoDotAthermalAnnihilation * timestep - write(6,'(a,/,2(12x,12(e12.5,1x),/))') '<< CONST >> thermally activated dipole annihilation', & - rhoDotThermalAnnihilation(:,9:10) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> total density change', & - rhoDot * timestep - write(6,'(a,/,10(12x,12(f12.5,1x),/))') '<< CONST >> relative density change', & - rhoDot(:,1:8) * timestep / (abs(stt%rho(:,sgl))+1.0e-10), & - rhoDot(:,9:10) * timestep / (stt%rho(:,dip)+1.0e-10) - write(6,*) - endif -#endif - - - if ( any(rho(:,mob) + rhoDot(:,1:4) * timestep < -prm%atol_rho) & - .or. any(rho(:,dip) + rhoDot(:,9:10) * timestep < -prm%atol_rho)) then -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then - write(6,'(a,i5,a,i2)') '<< CONST >> evolution rate leads to negative density at el ',el,' ip ',ip - write(6,'(a)') '<< CONST >> enforcing cutback !!!' - endif -#endif - plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) - else - dot%rho(:,of) = pack(rhoDot,.true.) - dot%gamma(:,of) = sum(gdot,2) - endif - end associate end subroutine plastic_nonlocal_dotState2 From 53de95798a38e3b85f90b4168a38c74b2671b320 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 11:49:16 +0200 Subject: [PATCH 27/54] separated local and nonlocal part of dotState --- src/constitutive_plastic_nonlocal.f90 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index e80f2ceab..928800e1d 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1295,7 +1295,7 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have - rhoDot = rhoDotFlux & + rhoDot = plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) & + rhoDotMultiplication & + rhoDotSingle2DipoleGlide & + rhoDotAthermalAnnihilation & @@ -1347,8 +1347,7 @@ end subroutine plastic_nonlocal_dotState !--------------------------------------------------------------------------------------------------- !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_dotState2(F, Fp,timestep, & - instance,of,ip,el) +function plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) result(rhoDotFlux) real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & F, & !< elastic deformation gradient @@ -1583,7 +1582,7 @@ subroutine plastic_nonlocal_dotState2(F, Fp,timestep, & end associate -end subroutine plastic_nonlocal_dotState2 +end function plastic_nonlocal_dotState2 !-------------------------------------------------------------------------------------------------- From 2a1badb548ccd5979461ab17344ceeec0a4a7976 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 12:04:57 +0200 Subject: [PATCH 28/54] not needed --- src/constitutive_plastic_nonlocal.f90 | 180 +------------------------- 1 file changed, 1 insertion(+), 179 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 928800e1d..08d14a5ce 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -962,39 +962,24 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & integer :: & ph, & - neighbor_instance, & !< instance of my neighbor's plasticity ns, & !< short notation for the total number of active slip systems c, & !< character of dislocation - n, & !< index of my current neighbor - neighbor_el, & !< element number of my neighbor - neighbor_ip, & !< integration point of my neighbor - neighbor_n, & !< neighbor index pointing to me when looking from my neighbor - opposite_neighbor, & !< index of my opposite neighbor - opposite_ip, & !< ip of my opposite neighbor - opposite_el, & !< element index of my opposite neighbor - opposite_n, & !< neighbor index pointing to me when looking from my opposite neighbor t, & !< type of dislocation - no,& !< neighbor offset shortcut - np,& !< neighbor phase shortcut - topp, & !< type of dislocation with opposite sign to t s !< index of my current slip system real(pReal), dimension(param(instance)%sum_N_sl,10) :: & rho, & rho0, & !< dislocation density at beginning of time step rhoDot, & !< density evolution rhoDotMultiplication, & !< density evolution by multiplication - rhoDotFlux, & !< density evolution by flux rhoDotSingle2DipoleGlide, & !< density evolution by dipole formation (by glide) rhoDotAthermalAnnihilation, & !< density evolution by athermal annihilation rhoDotThermalAnnihilation !< density evolution by thermal annihilation real(pReal), dimension(param(instance)%sum_N_sl,8) :: & rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) - neighbor_rhoSgl0, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) my_rhoSgl0 !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) real(pReal), dimension(param(instance)%sum_N_sl,4) :: & v, & !< current dislocation glide velocity v0, & - neighbor_v0, & !< dislocation glide velocity of enighboring ip gdot !< shear rates real(pReal), dimension(param(instance)%sum_N_sl) :: & tau, & !< current resolved shear stress @@ -1003,23 +988,7 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & rhoDip, & !< current 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,param(instance)%sum_N_sl,4) :: & - m !< direction of dislocation motion - real(pReal), dimension(3,3) :: & - my_F, & !< my total deformation gradient - neighbor_F, & !< total deformation gradient of my neighbor - my_Fe, & !< my elastic deformation gradient - neighbor_Fe, & !< elastic deformation gradient of my neighbor - Favg !< average total deformation gradient of me and my neighbor - real(pReal), dimension(3) :: & - normal_neighbor2me, & !< interface normal pointing from my neighbor to me in neighbor's lattice configuration - normal_neighbor2me_defConf, & !< interface normal pointing from my neighbor to me in shared deformed configuration - normal_me2neighbor, & !< interface normal pointing from me to my neighbor in my lattice configuration - normal_me2neighbor_defConf !< interface normal pointing from me to my neighbor in shared deformed configuration 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 ph = material_phaseAt(1,el) @@ -1094,153 +1063,6 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & forall (s = 1:ns, t = 1:4) v0(s,t) = plasticState(ph)%state0(iV(s,t,instance),of) - !**************************************************************************** - !*** calculate dislocation fluxes (only for nonlocal plasticity) - rhoDotFlux = 0.0_pReal - if (.not. phase_localPlasticity(material_phaseAt(1,el))) then - - !*** check CFL (Courant-Friedrichs-Lewy) condition for flux - if (any( abs(gdot) > 0.0_pReal & ! any active slip system ... - .and. prm%CFLfactor * abs(v0) * timestep & - > IPvolume(ip,el) / maxval(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) 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(v0), abs(gdot) > 0.0_pReal & - .and. prm%CFLfactor * abs(v0) * timestep & - > IPvolume(ip,el) / maxval(IParea(:,ip,el))), & - ' at a timestep of ',timestep - write(6,'(a)') '<< CONST >> enforcing cutback !!!' - endif -#endif - plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! -> return NaN and, hence, enforce cutback - return - endif - - - !*** be aware of the definition of slip_transverse = slip_direction x slip_normal !!! - !*** opposite sign to our t vector in the (s,t,n) triplet !!! - - m(1:3,:,1) = prm%slip_direction - m(1:3,:,2) = -prm%slip_direction - m(1:3,:,3) = -prm%slip_transverse - m(1:3,:,4) = prm%slip_transverse - - my_F = F(1:3,1:3,1,ip,el) - my_Fe = matmul(my_F, math_inv33(Fp(1:3,1:3,1,ip,el))) - - neighbors: do n = 1,nIPneighbors - - neighbor_el = IPneighborhood(1,n,ip,el) - neighbor_ip = IPneighborhood(2,n,ip,el) - neighbor_n = IPneighborhood(3,n,ip,el) - np = material_phaseAt(1,neighbor_el) - no = material_phasememberAt(1,neighbor_ip,neighbor_el) - - opposite_neighbor = n + mod(n,2) - mod(n+1,2) - opposite_el = IPneighborhood(1,opposite_neighbor,ip,el) - opposite_ip = IPneighborhood(2,opposite_neighbor,ip,el) - opposite_n = IPneighborhood(3,opposite_neighbor,ip,el) - - if (neighbor_n > 0) then ! if neighbor exists, average deformation gradient - neighbor_instance = phase_plasticityInstance(material_phaseAt(1,neighbor_el)) - neighbor_F = F(1:3,1:3,1,neighbor_ip,neighbor_el) - neighbor_Fe = matmul(neighbor_F, math_inv33(Fp(1:3,1:3,1,neighbor_ip,neighbor_el))) - Favg = 0.5_pReal * (my_F + neighbor_F) - else ! if no neighbor, take my value as average - Favg = my_F - endif - - neighbor_v0 = 0.0_pReal ! needed for check of sign change in flux density below - - !* FLUX FROM MY NEIGHBOR TO ME - !* This is only considered, if I have a neighbor of nonlocal plasticity - !* (also nonlocal constitutive law with local properties) that is at least a little bit - !* compatible. - !* If it's not at all compatible, no flux is arriving, because everything is dammed in front of - !* my neighbor's interface. - !* The entering flux from my neighbor will be distributed on my slip systems according to the - !* compatibility - if (neighbor_n > 0) then - if (phase_plasticity(material_phaseAt(1,neighbor_el)) == PLASTICITY_NONLOCAL_ID .and. & - any(compatibility(:,:,:,n,ip,el) > 0.0_pReal)) then - - forall (s = 1:ns, t = 1:4) - neighbor_v0(s,t) = plasticState(np)%state0(iV (s,t,neighbor_instance),no) - neighbor_rhoSgl0(s,t) = max(plasticState(np)%state0(iRhoU(s,t,neighbor_instance),no),0.0_pReal) - endforall - - where (neighbor_rhoSgl0 * IPvolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & - .or. neighbor_rhoSgl0 < prm%significantRho) & - neighbor_rhoSgl0 = 0.0_pReal - normal_neighbor2me_defConf = math_det33(Favg) * matmul(math_inv33(transpose(Favg)), & - IPareaNormal(1:3,neighbor_n,neighbor_ip,neighbor_el)) ! normal of the interface in (average) deformed configuration (pointing neighbor => me) - normal_neighbor2me = matmul(transpose(neighbor_Fe), normal_neighbor2me_defConf) & - / math_det33(neighbor_Fe) ! interface normal in the lattice configuration of my neighbor - area = IParea(neighbor_n,neighbor_ip,neighbor_el) * norm2(normal_neighbor2me) - normal_neighbor2me = normal_neighbor2me / norm2(normal_neighbor2me) ! normalize the surface normal to unit length - do s = 1,ns - do t = 1,4 - c = (t + 1) / 2 - topp = t + mod(t,2) - mod(t+1,2) - if (neighbor_v0(s,t) * math_inner(m(1:3,s,t), normal_neighbor2me) > 0.0_pReal & ! flux from my neighbor to me == entering flux for me - .and. v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal ) then ! ... only if no sign change in flux density - lineLength = neighbor_rhoSgl0(s,t) * neighbor_v0(s,t) & - * math_inner(m(1:3,s,t), normal_neighbor2me) * area ! positive line length that wants to enter through this interface - where (compatibility(c,:,s,n,ip,el) > 0.0_pReal) & - rhoDotFlux(:,t) = rhoDotFlux(1:ns,t) & - + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to equally signed mobile dislocation type - where (compatibility(c,:,s,n,ip,el) < 0.0_pReal) & - rhoDotFlux(:,topp) = rhoDotFlux(:,topp) & - + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to opposite signed mobile dislocation type - - endif - enddo - enddo - endif; endif - - - !* 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 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 - !* In case of reduced transmissivity, part of the leaving flux is stored as dead dislocation density. - !* That means for an interface of zero transmissivity the leaving flux is fully converted to dead dislocations. - if (opposite_n > 0) then - if (phase_plasticity(material_phaseAt(1,opposite_el)) == PLASTICITY_NONLOCAL_ID) then - - normal_me2neighbor_defConf = math_det33(Favg) & - * matmul(math_inv33(transpose(Favg)),IPareaNormal(1:3,n,ip,el)) ! normal of the interface in (average) deformed configuration (pointing me => neighbor) - normal_me2neighbor = matmul(transpose(my_Fe), normal_me2neighbor_defConf) & - / math_det33(my_Fe) ! interface normal in my lattice configuration - area = IParea(n,ip,el) * norm2(normal_me2neighbor) - normal_me2neighbor = normal_me2neighbor / norm2(normal_me2neighbor) ! normalize the surface normal to unit length - do s = 1,ns - do t = 1,4 - c = (t + 1) / 2 - if (v0(s,t) * math_inner(m(1:3,s,t), normal_me2neighbor) > 0.0_pReal ) then ! flux from me to my neighbor == leaving flux for me (might also be a pure flux from my mobile density to dead density if interface not at all transmissive) - if (v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal) then ! no sign change in flux density - transmissivity = sum(compatibility(c,:,s,n,ip,el)**2.0_pReal) ! overall transmissivity from this slip system to my neighbor - else ! sign change in flux density means sign change in stress which does not allow for dislocations to arive at the neighbor - transmissivity = 0.0_pReal - endif - lineLength = my_rhoSgl0(s,t) * v0(s,t) & - * math_inner(m(1:3,s,t), normal_me2neighbor) * area ! positive line length of mobiles that wants to leave through this interface - rhoDotFlux(s,t) = rhoDotFlux(s,t) - lineLength / IPvolume(ip,el) ! subtract dislocation flux from current type - rhoDotFlux(s,t+4) = rhoDotFlux(s,t+4) & - + lineLength / IPvolume(ip,el) * (1.0_pReal - transmissivity) & - * sign(1.0_pReal, v0(s,t)) ! dislocation flux that is not able to leave through interface (because of low transmissivity) will remain as immobile single density at the material point - endif - enddo - enddo - endif; endif - - enddo neighbors - endif - - !**************************************************************************** !*** calculate dipole formation and annihilation @@ -1454,7 +1276,7 @@ function plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) result(rh write(6,'(a)') '<< CONST >> enforcing cutback !!!' endif #endif - plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! -> return NaN and, hence, enforce cutback + rhoDotFlux = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! enforce cutback return endif From 520a484df2d81fd3c24e443809c4453082afe67c Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 13:09:49 +0200 Subject: [PATCH 29/54] reasonable name --- src/constitutive_plastic_nonlocal.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 08d14a5ce..f1994444e 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1117,7 +1117,7 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have - rhoDot = plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) & + rhoDot = rhoDotFlux(F,Fp,timestep, instance,of,ip,el) & + rhoDotMultiplication & + rhoDotSingle2DipoleGlide & + rhoDotAthermalAnnihilation & @@ -1169,7 +1169,7 @@ end subroutine plastic_nonlocal_dotState !--------------------------------------------------------------------------------------------------- !> @brief calculates the rate of change of microstructure !--------------------------------------------------------------------------------------------------- -function plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) result(rhoDotFlux) +function rhoDotFlux(F,Fp,timestep, instance,of,ip,el) real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & F, & !< elastic deformation gradient @@ -1404,7 +1404,7 @@ function plastic_nonlocal_dotState2(F,Fp,timestep, instance,of,ip,el) result(rh end associate -end function plastic_nonlocal_dotState2 +end function rhoDotFlux !-------------------------------------------------------------------------------------------------- From 7d1e0850ab217794cca8607942d58eb345f60412 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 17:04:03 +0200 Subject: [PATCH 30/54] test + resulting bug fix --- python/damask/_rotation.py | 2 +- python/tests/test_Rotation.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index f97e356fc..878face97 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1219,6 +1219,6 @@ class Rotation: p = 2 else: p = np.where(np.maximum(np.abs(xyz[...,0]),np.abs(xyz[...,1])) <= np.abs(xyz[...,2]),0, - np.where(np.maximum(np.abs(xyz[...,1]),np.abs(xyz[...,2])) <= np.abs(xyz[...,0]),2,3)) + np.where(np.maximum(np.abs(xyz[...,1]),np.abs(xyz[...,2])) <= np.abs(xyz[...,0]),1,2)) return order[direction][p] diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index 302e895ee..a46cf1a23 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -264,3 +264,18 @@ class TestRotation: for h,c in zip(ho,co): print(h,c) assert np.allclose(conversion(h),c) + + + @pytest.mark.parametrize('direction',['forward', + 'backward']) + def test_pyramid_vectorization(self,direction): + p = np.random.rand(n,3) + o = Rotation._get_order(p,direction) + for i,o_i in enumerate(o): + assert np.allclose(o_i,Rotation._get_order(p[i],direction)) + + def test_pyramid_invariant(self): + a = np.random.rand(n,3) + f = damask.Rotation._get_order(a,'forward') + b = damask.Rotation._get_order(a,'backward') + assert np.all(np.take_along_axis(np.take_along_axis(a,f,-1),b,-1) == a) From 76d37b5bcd7eba064f9f1f19d36eb9fea37fd9c3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 20:38:25 +0200 Subject: [PATCH 31/54] flux debug would need temporary variable --- src/constitutive_plastic_nonlocal.f90 | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index f1994444e..cc5655e78 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1123,29 +1123,6 @@ module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & + rhoDotAthermalAnnihilation & + rhoDotThermalAnnihilation -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & - rhoDotMultiplication(:,1:4) * timestep - write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation flux', & - rhoDotFlux(:,1:8) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> dipole formation by glide', & - rhoDotSingle2DipoleGlide * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> athermal dipole annihilation', & - rhoDotAthermalAnnihilation * timestep - write(6,'(a,/,2(12x,12(e12.5,1x),/))') '<< CONST >> thermally activated dipole annihilation', & - rhoDotThermalAnnihilation(:,9:10) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> total density change', & - rhoDot * timestep - write(6,'(a,/,10(12x,12(f12.5,1x),/))') '<< CONST >> relative density change', & - rhoDot(:,1:8) * timestep / (abs(stt%rho(:,sgl))+1.0e-10), & - rhoDot(:,9:10) * timestep / (stt%rho(:,dip)+1.0e-10) - write(6,*) - endif -#endif - if ( any(rho(:,mob) + rhoDot(:,1:4) * timestep < -prm%atol_rho) & .or. any(rho(:,dip) + rhoDot(:,9:10) * timestep < -prm%atol_rho)) then From 5f3f87cd68b26081b10ad8a96c655b3a56348830 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 3 May 2020 18:51:30 +0200 Subject: [PATCH 32/54] vectorizing cubochoric conversions --- python/damask/_rotation.py | 104 ++++++++++++++++++++++------------ python/tests/test_Rotation.py | 91 +++++++++++++++++------------ 2 files changed, 124 insertions(+), 71 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 878face97..a13a9af0b 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -241,7 +241,7 @@ class Rotation: """Homochoric vector: (h_1, h_2, h_3).""" return Rotation.qu2ho(self.quaternion) - def asCubochoric(self): + def as_cubochoric(self): """Cubochoric vector: (c_1, c_2, c_3).""" return Rotation.qu2cu(self.quaternion) @@ -265,6 +265,7 @@ class Rotation: asMatrix = as_matrix asRodrigues = as_Rodrigues asHomochoric = as_homochoric + asCubochoric = as_cubochoric ################################################################################################ # Static constructors. The input data needs to follow the conventions, options allow to @@ -386,7 +387,7 @@ class Rotation: return Rotation(Rotation.ho2qu(ho)) @staticmethod - def fromCubochoric(cubochoric, + def from_cubochoric(cubochoric, P = -1): cu = np.array(cubochoric,dtype=float) @@ -461,6 +462,7 @@ class Rotation: fromMatrix = from_matrix fromRodrigues = from_Rodrigues fromHomochoric = from_homochoric + fromCubochoric = from_cubochoric fromRandom = from_random #################################################################################################### @@ -1066,7 +1068,7 @@ class Rotation: if np.allclose(ho,0.0,rtol=0.0,atol=1.0e-16): cu = np.zeros(3) else: - xyz3 = ho[Rotation._get_order(ho,'forward')] + xyz3 = ho[Rotation._get_pyramid_order(ho,'forward')] # inverse M_3 xyz2 = xyz3[0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[2])) ) @@ -1087,20 +1089,35 @@ class Rotation: # inverse M_1 cu = np.array([ Tinv[0], Tinv[1], (-1.0 if xyz3[2] < 0.0 else 1.0) * rs / np.sqrt(6.0/np.pi) ]) /_sc - # reverse the coordinates back to the regular order according to the original pyramid number - cu = cu[Rotation._get_order(ho,'backward')] - - return cu + cu = cu[Rotation._get_pyramid_order(ho,'backward')] 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) - raise NotImplementedError('Support for multiple rotations missing') + rs = np.linalg.norm(ho,axis=-1,keepdims=True) + xyz3 = np.take_along_axis(ho,Rotation._get_pyramid_order(ho,'forward'),-1) + + with np.errstate(invalid='ignore',divide='ignore'): + # inverse M_3 + xyz2 = xyz3[...,0:2] * np.sqrt( 2.0*rs/(rs+np.abs(xyz3[...,2:3])) ) + qxy = np.sum(xyz2**2,axis=-1,keepdims=True) + + q2 = qxy + np.max(np.abs(xyz2),axis=-1,keepdims=True)**2 + sq2 = np.sqrt(q2) + q = (_beta/np.sqrt(2.0)/_R1) * np.sqrt(q2*qxy/(q2-np.max(np.abs(xyz2),axis=-1,keepdims=True)*sq2)) + tt = np.clip((np.min(np.abs(xyz2),axis=-1,keepdims=True)**2\ + +np.max(np.abs(xyz2),axis=-1,keepdims=True)*sq2)/np.sqrt(2.0)/qxy,-1.0,1.0) + T_inv = np.where(np.abs(xyz2[...,1:2]) <= np.abs(xyz2[...,0:1]), + np.block([np.ones_like(tt),np.arccos(tt)/np.pi*12.0]), + np.block([np.arccos(tt)/np.pi*12.0,np.ones_like(tt)]))*q + T_inv[xyz2<0.0] *= -1.0 + T_inv[np.broadcast_to(np.isclose(qxy,0.0,rtol=0.0,atol=1.0e-12),T_inv.shape)] = 0.0 + cu = np.block([T_inv, np.where(xyz3[...,2:3]<0.0,-np.ones_like(xyz3[...,2:3]),np.ones_like(xyz3[...,2:3])) \ + * rs/np.sqrt(6.0/np.pi), + ])/ _sc + + cu[np.isclose(np.sum(np.abs(ho),axis=-1),0.0,rtol=0.0,atol=1.0e-16)] = 0.0 + cu = np.take_along_axis(cu,Rotation._get_pyramid_order(ho,'backward'),-1) + + return cu #---------- Cubochoric ---------- @staticmethod @@ -1145,7 +1162,7 @@ class Rotation: ho = np.zeros(3) else: # get pyramide and scale by grid parameter ratio - XYZ = cu[Rotation._get_order(cu,'forward')] * _sc + XYZ = cu[Rotation._get_pyramid_order(cu,'forward')] * _sc # intercept all the points along the z-axis if np.allclose(XYZ[0:2],0.0,rtol=0.0,atol=1.0e-16): @@ -1163,31 +1180,46 @@ class Rotation: 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 ) ho = 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 - ho = ho[Rotation._get_order(cu,'backward')] - - return ho + ho = ho[Rotation._get_pyramid_order(cu,'backward')] else: - # get pyramide and scale by grid parameter ratio - XYZ = cu[Rotation._get_order(cu,'forward')] * _sc - order = np.where(np.abs(XYZ[...,1]) <= np.abs(XYZ[...,0]), - np.broadcast_to([1,0],XYZ.shape[:-1]+(2,)), - np.broadcast_to([0,1],XYZ.shape[:-1]+(2,))) - 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.block([ (np.sqrt(2.0)*c - 1.0), np.sqrt(2.0) * s]) * q - 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 ) - raise NotImplementedError('Support for multiple rotations missing') + with np.errstate(invalid='ignore',divide='ignore'): + # get pyramide and scale by grid parameter ratio + XYZ = np.take_along_axis(cu,Rotation._get_pyramid_order(cu,'forward'),-1) * _sc + order = np.abs(XYZ[...,1:2]) <= np.abs(XYZ[...,0:1]) + q = np.pi/12.0 * np.where(order,XYZ[...,1:2],XYZ[...,0:1]) \ + / np.where(order,XYZ[...,0:1],XYZ[...,1:2]) + c = np.cos(q) + s = np.sin(q) + q = _R1*2.0**0.25/_beta/ np.sqrt(np.sqrt(2.0)-c) \ + * np.where(order,XYZ[...,0:1],XYZ[...,1:2]) + + T = np.block([ (np.sqrt(2.0)*c - 1.0), np.sqrt(2.0) * s]) * q + + # transform to sphere grid (inverse Lambert) + c = np.sum(T**2,axis=-1,keepdims=True) + s = c * np.pi/24.0 /XYZ[...,2:3]**2 + c = c * np.sqrt(np.pi/24.0)/XYZ[...,2:3] + q = np.sqrt( 1.0 - s) + + ho = np.where(np.isclose(np.sum(np.abs(XYZ[...,0:2]),axis=-1,keepdims=True),0.0,rtol=0.0,atol=1.0e-16), + np.block([np.zeros_like(XYZ[...,0:2]),np.sqrt(6.0/np.pi) *XYZ[...,2:3]]), + np.block([np.where(order,T[...,0:1],T[...,1:2])*q, + np.where(order,T[...,1:2],T[...,0:1])*q, + np.sqrt(6.0/np.pi) * XYZ[...,2:3] - c]) + ) + + ho[np.isclose(np.sum(np.abs(cu),axis=-1),0.0,rtol=0.0,atol=1.0e-16)] = 0.0 + ho = np.take_along_axis(ho,Rotation._get_pyramid_order(cu,'backward'),-1) + + return ho + @staticmethod - def _get_order(xyz,direction=None): + def _get_pyramid_order(xyz,direction=None): """ Get order of the coordinates. @@ -1206,7 +1238,7 @@ class Rotation: """ order = {'forward':np.array([[0,1,2],[1,2,0],[2,0,1]]), - 'backward':np.array([[0,1,2],[2,0,1],[1,2,0]])} + 'backward':np.array([[0,1,2],[2,0,1],[1,2,0]])} if len(xyz.shape) == 1: if np.maximum(abs(xyz[0]),abs(xyz[1])) <= xyz[2] or \ np.maximum(abs(xyz[0]),abs(xyz[1])) <=-xyz[2]: diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index a46cf1a23..b7442035f 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -78,9 +78,9 @@ def default(): specials_scatter /= np.linalg.norm(specials_scatter,axis=1).reshape(-1,1) specials_scatter[specials_scatter[:,0]<0]*=-1 - return [Rotation.fromQuaternion(s) for s in specials] + \ - [Rotation.fromQuaternion(s) for s in specials_scatter] + \ - [Rotation.fromRandom() for _ in range(n-len(specials)-len(specials_scatter))] + return [Rotation.from_quaternion(s) for s in specials] + \ + [Rotation.from_quaternion(s) for s in specials_scatter] + \ + [Rotation.from_random() for _ in range(n-len(specials)-len(specials_scatter))] @pytest.fixture def reference_dir(reference_dir_base): @@ -92,41 +92,41 @@ class TestRotation: def test_Eulers(self,default): for rot in default: - m = rot.asQuaternion() - o = Rotation.fromEulers(rot.asEulers()).asQuaternion() + m = rot.as_quaternion() + o = Rotation.from_Eulers(rot.as_Eulers()).as_quaternion() ok = np.allclose(m,o,atol=atol) - if np.isclose(rot.asQuaternion()[0],0.0,atol=atol): + if np.isclose(rot.as_quaternion()[0],0.0,atol=atol): ok = ok or np.allclose(m*-1.,o,atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and np.isclose(np.linalg.norm(o),1.0) def test_AxisAngle(self,default): for rot in default: - m = rot.asEulers() - o = Rotation.fromAxisAngle(rot.asAxisAngle()).asEulers() + m = rot.as_Eulers() + o = Rotation.from_axis_angle(rot.as_axis_angle()).as_Eulers() u = np.array([np.pi*2,np.pi,np.pi*2]) ok = np.allclose(m,o,atol=atol) ok = ok or np.allclose(np.where(np.isclose(m,u),m-u,m),np.where(np.isclose(o,u),o-u,o),atol=atol) if np.isclose(m[1],0.0,atol=atol) or np.isclose(m[1],np.pi,atol=atol): sum_phi = np.unwrap([m[0]+m[2],o[0]+o[2]]) ok = ok or np.isclose(sum_phi[0],sum_phi[1],atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and (np.zeros(3)-1.e-9 <= o).all() and (o <= np.array([np.pi*2.,np.pi,np.pi*2.])+1.e-9).all() def test_Matrix(self,default): for rot in default: - m = rot.asAxisAngle() - o = Rotation.fromAxisAngle(rot.asAxisAngle()).asAxisAngle() + m = rot.as_axis_angle() + o = Rotation.from_axis_angle(rot.as_axis_angle()).as_axis_angle() ok = np.allclose(m,o,atol=atol) if np.isclose(m[3],np.pi,atol=atol): ok = ok or np.allclose(m*np.array([-1.,-1.,-1.,1.]),o,atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) and o[3]<=np.pi++1.e-9 def test_Rodrigues(self,default): for rot in default: - m = rot.asMatrix() - o = Rotation.fromRodrigues(rot.asRodrigues()).asMatrix() + m = rot.as_matrix() + o = Rotation.from_Rodrigues(rot.as_Rodrigues()).as_matrix() ok = np.allclose(m,o,atol=atol) print(m,o) assert ok and np.isclose(np.linalg.det(o),1.0) @@ -134,27 +134,27 @@ class TestRotation: def test_Homochoric(self,default): cutoff = np.tan(np.pi*.5*(1.-1e-4)) for rot in default: - m = rot.asRodrigues() - o = Rotation.fromHomochoric(rot.asHomochoric()).asRodrigues() + m = rot.as_Rodrigues() + o = Rotation.from_homochoric(rot.as_homochoric()).as_Rodrigues() ok = np.allclose(np.clip(m,None,cutoff),np.clip(o,None,cutoff),atol=atol) ok = ok or np.isclose(m[3],0.0,atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) def test_Cubochoric(self,default): for rot in default: - m = rot.asHomochoric() - o = Rotation.fromCubochoric(rot.asCubochoric()).asHomochoric() + m = rot.as_homochoric() + o = Rotation.from_cubochoric(rot.as_cubochoric()).as_homochoric() ok = np.allclose(m,o,atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and np.linalg.norm(o) < (3.*np.pi/4.)**(1./3.) + 1.e-9 def test_Quaternion(self,default): for rot in default: - m = rot.asCubochoric() - o = Rotation.fromQuaternion(rot.asQuaternion()).asCubochoric() + m = rot.as_cubochoric() + o = Rotation.from_quaternion(rot.as_quaternion()).as_cubochoric() ok = np.allclose(m,o,atol=atol) - print(m,o,rot.asQuaternion()) + print(m,o,rot.as_quaternion()) assert ok and o.max() < np.pi**(2./3.)*0.5+1.e-9 @pytest.mark.parametrize('function',[Rotation.from_quaternion, @@ -185,9 +185,11 @@ class TestRotation: Rotation.qu2eu, Rotation.qu2ax, Rotation.qu2ro, - Rotation.qu2ho]) + Rotation.qu2ho, + Rotation.qu2cu + ]) def test_quaternion_vectorization(self,default,conversion): - qu = np.array([rot.asQuaternion() for rot in default]) + qu = np.array([rot.as_quaternion() for rot in default]) conversion(qu.reshape(qu.shape[0]//2,-1,4)) co = conversion(qu) for q,c in zip(qu,co): @@ -199,9 +201,10 @@ class TestRotation: Rotation.om2ax, Rotation.om2ro, Rotation.om2ho, + Rotation.om2cu ]) def test_matrix_vectorization(self,default,conversion): - om = np.array([rot.asMatrix() for rot in default]) + om = np.array([rot.as_matrix() for rot in default]) conversion(om.reshape(om.shape[0]//2,-1,3,3)) co = conversion(om) for o,c in zip(om,co): @@ -213,9 +216,10 @@ class TestRotation: Rotation.eu2ax, Rotation.eu2ro, Rotation.eu2ho, + Rotation.eu2cu ]) def test_Euler_vectorization(self,default,conversion): - eu = np.array([rot.asEulers() for rot in default]) + eu = np.array([rot.as_Eulers() for rot in default]) conversion(eu.reshape(eu.shape[0]//2,-1,3)) co = conversion(eu) for e,c in zip(eu,co): @@ -227,9 +231,10 @@ class TestRotation: Rotation.ax2eu, Rotation.ax2ro, Rotation.ax2ho, + Rotation.ax2cu ]) def test_axisAngle_vectorization(self,default,conversion): - ax = np.array([rot.asAxisAngle() for rot in default]) + ax = np.array([rot.as_axis_angle() for rot in default]) conversion(ax.reshape(ax.shape[0]//2,-1,4)) co = conversion(ax) for a,c in zip(ax,co): @@ -242,9 +247,10 @@ class TestRotation: Rotation.ro2eu, Rotation.ro2ax, Rotation.ro2ho, + Rotation.ro2cu ]) def test_Rodrigues_vectorization(self,default,conversion): - ro = np.array([rot.asRodrigues() for rot in default]) + ro = np.array([rot.as_Rodrigues() for rot in default]) conversion(ro.reshape(ro.shape[0]//2,-1,4)) co = conversion(ro) for r,c in zip(ro,co): @@ -256,26 +262,41 @@ class TestRotation: Rotation.ho2eu, Rotation.ho2ax, Rotation.ho2ro, + Rotation.ho2cu ]) def test_homochoric_vectorization(self,default,conversion): - ho = np.array([rot.asHomochoric() for rot in default]) + ho = np.array([rot.as_homochoric() for rot in default]) conversion(ho.reshape(ho.shape[0]//2,-1,3)) co = conversion(ho) for h,c in zip(ho,co): print(h,c) assert np.allclose(conversion(h),c) + @pytest.mark.parametrize('conversion',[Rotation.cu2qu, + Rotation.cu2om, + Rotation.cu2eu, + Rotation.cu2ax, + Rotation.cu2ro, + Rotation.cu2ho + ]) + def test_cubochoric_vectorization(self,default,conversion): + cu = np.array([rot.as_cubochoric() for rot in default]) + conversion(cu.reshape(cu.shape[0]//2,-1,3)) + co = conversion(cu) + for u,c in zip(cu,co): + print(u,c) + assert np.allclose(conversion(u),c) @pytest.mark.parametrize('direction',['forward', 'backward']) def test_pyramid_vectorization(self,direction): p = np.random.rand(n,3) - o = Rotation._get_order(p,direction) + o = Rotation._get_pyramid_order(p,direction) for i,o_i in enumerate(o): - assert np.allclose(o_i,Rotation._get_order(p[i],direction)) + assert np.all(o_i==Rotation._get_pyramid_order(p[i],direction)) def test_pyramid_invariant(self): a = np.random.rand(n,3) - f = damask.Rotation._get_order(a,'forward') - b = damask.Rotation._get_order(a,'backward') + f = Rotation._get_pyramid_order(a,'forward') + b = Rotation._get_pyramid_order(a,'backward') assert np.all(np.take_along_axis(np.take_along_axis(a,f,-1),b,-1) == a) From 0650f46ab1540c3e995df1d188a75a95c8b5ae69 Mon Sep 17 00:00:00 2001 From: Vitesh Shah Date: Mon, 4 May 2020 16:57:08 +0200 Subject: [PATCH 33/54] Tests for gradient --- python/tests/test_grid_filters.py | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 84d2ef771..2ee062ee5 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -168,3 +168,63 @@ class TestGridFilters: curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) assert np.allclose(curl,grid_filters.curl(size,field)) + + grad_test_data = [(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), + + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['0.0', '0.0', '0.0', + '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0' ]), + + (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + + (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', + '0.0', '0.0', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + + (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]) + ] + +# @pytest.mark.parametrize('field_def,grad_def', +# [(['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], +# ['0.0', '0.0', '0.0', +# '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', +# '0.0', '0.0', '0.0' ]) +# ]) + @pytest.mark.parametrize('field_def,grad_def',grad_test_data) + + def test_grad(self,field_def,grad_def): +# size = np.random.random(3)+1.0 +# grid = np.random.randint(8,32,(3)) + size = np.array([1.0,1.0,1.0]) + grid = np.array([2,5,3]) + + nodes = grid_filters.cell_coord0(grid,size) +# print('y nodes are',nodes[...,1]) +# print('inner bracket is',np.pi*2*nodes[...,1]/size[1]) + my_locals = locals() # needed for list comprehension + + print('field length is',len(field_def)) + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + print('field initial shape is',field.shape) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + print('field is',field.shape) + grad = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in grad_def], axis=-1) + grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) + print('gradient is',grad.shape) + print('code gradient is',grid_filters.gradient(size,field)) + assert np.allclose(grad,grid_filters.gradient(size,field)) + From 307debebd45e2fbad925c297bd2b3d03f2fba8ef Mon Sep 17 00:00:00 2001 From: Vitesh Shah Date: Tue, 5 May 2020 10:14:27 +0200 Subject: [PATCH 34/54] Correct shapes for gradient calculations --- python/tests/test_grid_filters.py | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 2ee062ee5..8170ba7af 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -189,42 +189,32 @@ class TestGridFilters: '0.0', '0.0', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ + 'np.sin(np.pi*2*nodes[...,2]/size[2])'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]) + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), + + (['8.0' ], + ['0.0', '0.0', '0.0' ]) ] -# @pytest.mark.parametrize('field_def,grad_def', -# [(['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], -# ['0.0', '0.0', '0.0', -# '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', -# '0.0', '0.0', '0.0' ]) -# ]) @pytest.mark.parametrize('field_def,grad_def',grad_test_data) def test_grad(self,field_def,grad_def): -# size = np.random.random(3)+1.0 -# grid = np.random.randint(8,32,(3)) - size = np.array([1.0,1.0,1.0]) - grid = np.array([2,5,3]) + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) nodes = grid_filters.cell_coord0(grid,size) -# print('y nodes are',nodes[...,1]) -# print('inner bracket is',np.pi*2*nodes[...,1]/size[1]) my_locals = locals() # needed for list comprehension - print('field length is',len(field_def)) field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) - print('field initial shape is',field.shape) - field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) - print('field is',field.shape) + field = field.reshape(tuple(grid) + ((3,) if len(field_def)==3 else (1,))) grad = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in grad_def], axis=-1) grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) - print('gradient is',grad.shape) - print('code gradient is',grid_filters.gradient(size,field)) + assert np.allclose(grad,grid_filters.gradient(size,field)) From 4dcec8b309d11a61d2c8fef77c75050b2ebef0ad Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 5 May 2020 11:18:58 +0200 Subject: [PATCH 35/54] not needed --- src/constitutive_plastic_nonlocal.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index cc5655e78..fefb668eb 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1209,10 +1209,6 @@ function rhoDotFlux(F,Fp,timestep, instance,of,ip,el) lineLength !< dislocation line length leaving the current interface ph = material_phaseAt(1,el) - if (timestep <= 0.0_pReal) then - plasticState(ph)%dotState = 0.0_pReal - return - endif associate(prm => param(instance), & dst => microstructure(instance), & From a5b78dc30af2211b1188407b3b1e277f1c0a0855 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 5 May 2020 11:20:16 +0200 Subject: [PATCH 36/54] potential glitch --- src/constitutive_plastic_nonlocal.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index fefb668eb..65fea24b2 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -1223,7 +1223,7 @@ function rhoDotFlux(F,Fp,timestep, instance,of,ip,el) rho0 = getRho0(instance,of,ip,el) my_rhoSgl0 = rho0(:,sgl) - forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) + forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) !ToDo: MD: I think we should use state0 here gdot = rhoSgl(:,1:4) * v * spread(prm%burgers,2,4) From bd518b28067b75c57d3bb13dbfc6e24327fb4708 Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 12:44:56 +0200 Subject: [PATCH 37/54] test_curl done --- python/tests/test_curl.py | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 python/tests/test_curl.py diff --git a/python/tests/test_curl.py b/python/tests/test_curl.py new file mode 100644 index 000000000..52e12d223 --- /dev/null +++ b/python/tests/test_curl.py @@ -0,0 +1,63 @@ +import pytest +import numpy as np +from damask import grid_filters + + +class TestGridFilters: + + + @pytest.mark.parametrize('field_def,curl_def', + [(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0' ], + ['0.0' , '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] + ), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['5.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], + ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], + ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ + '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ + '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])'] + ), + (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], + ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ + '0.0',\ + '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'] + ) + ]) + def test_curl(self,field_def,curl_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + curl = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in curl_def], axis=-1) + curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) + + assert np.allclose(curl,grid_filters.curl(size,field)) + + \ No newline at end of file From 8b4baecdee110da3e54efa6cb40505d437004e83 Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 12:54:24 +0200 Subject: [PATCH 38/54] better looking test fields --- python/tests/test_curl.py | 81 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/python/tests/test_curl.py b/python/tests/test_curl.py index 52e12d223..c3bcc2682 100644 --- a/python/tests/test_curl.py +++ b/python/tests/test_curl.py @@ -6,46 +6,47 @@ from damask import grid_filters class TestGridFilters: - @pytest.mark.parametrize('field_def,curl_def', - [(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0' ], - ['0.0' , '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] - ), - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', - 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', - 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['5.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], - ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], - ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ - '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ - '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])'] - ), - (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], - ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ - '0.0',\ - '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'] - ) - ]) + curl_test_data =[(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0' ], + ['0.0' , '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] + ), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['5.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], + ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'] + ), + (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], + ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ + '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ + '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])'] + ), + (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], + ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ + '0.0',\ + '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'])] + + + @pytest.mark.parametrize('field_def,curl_def',curl_test_data) + def test_curl(self,field_def,curl_def): size = np.random.random(3)+1.0 grid = np.random.randint(8,32,(3)) From d4091a21a8becd0e6d5adf1907ef493bdea730ad Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 13:05:53 +0200 Subject: [PATCH 39/54] grad test done --- python/tests/test_grad.py | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 python/tests/test_grad.py diff --git a/python/tests/test_grad.py b/python/tests/test_grad.py new file mode 100644 index 000000000..d02c57cdc --- /dev/null +++ b/python/tests/test_grad.py @@ -0,0 +1,49 @@ +import pytest +import numpy as np +from damask import grid_filters + + +class TestGridFilters: + + grad_test_data = [(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['0.0', '0.0', '0.0', + '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0' ]), + (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', + '0.0', '0.0', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ + 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), + (['8.0' ], + ['0.0', '0.0', '0.0' ])] + + @pytest.mark.parametrize('field_def,grad_def',grad_test_data) + + def test_grad(self,field_def,grad_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,) if len(field_def)==3 else (1,))) + grad = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in grad_def], axis=-1) + grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) + + assert np.allclose(grad,grid_filters.gradient(size,field)) + \ No newline at end of file From a122a307b9d714eccb2259a78cc7a20a2694571d Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 14:14:18 +0200 Subject: [PATCH 40/54] div test done --- python/tests/test_div.py | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 python/tests/test_div.py diff --git a/python/tests/test_div.py b/python/tests/test_div.py new file mode 100644 index 000000000..f703c5371 --- /dev/null +++ b/python/tests/test_div.py @@ -0,0 +1,63 @@ +import pytest +import numpy as np +from damask import grid_filters + + +class TestGridFilters: + + + div_test_data =[(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', + '0.0' , '0.0', '0.0', + '0.0' , '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]' ,'0.0', '0.0'] + ), + (['0.0', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0'], + ['0.0', '-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0'] + ), + (['1.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], + ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] + ), + ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]'] + ), + (['400.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,0]/size[0])', 'np.sin(np.pi*2*nodes[...,1]/size[1])', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '10.0', '6.0' ], + ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ] + ), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',] + ), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'] + ) + + + ] + + + @pytest.mark.parametrize('field_def,div_def',div_test_data) + + def test_div(self,field_def,div_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + div = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in div_def], axis=-1) + if len(div_def)==3: + div = div.reshape(tuple(grid) + ((3,))) + else: + div=div.reshape(tuple(grid)) + + assert np.allclose(div,grid_filters.divergence(size,field)) + \ No newline at end of file From 26f55781aedede7f2acc6ef1715938b0b1bcfb7c Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 14:26:15 +0200 Subject: [PATCH 41/54] merge test into gridFilters --- python/tests/test_div.py | 63 ---------- python/tests/test_grad.py | 49 -------- python/tests/test_grid_filters.py | 188 ++++++++++++++++++++---------- 3 files changed, 126 insertions(+), 174 deletions(-) delete mode 100644 python/tests/test_div.py delete mode 100644 python/tests/test_grad.py diff --git a/python/tests/test_div.py b/python/tests/test_div.py deleted file mode 100644 index f703c5371..000000000 --- a/python/tests/test_div.py +++ /dev/null @@ -1,63 +0,0 @@ -import pytest -import numpy as np -from damask import grid_filters - - -class TestGridFilters: - - - div_test_data =[(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', - '0.0' , '0.0', '0.0', - '0.0' , '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]' ,'0.0', '0.0'] - ), - (['0.0', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0'], - ['0.0', '-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0'] - ), - (['1.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], - ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] - ), - ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]'] - ), - (['400.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,0]/size[0])', 'np.sin(np.pi*2*nodes[...,1]/size[1])', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '10.0', '6.0' ], - ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ] - ), - (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',] - ), - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], - ['-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'] - ) - - - ] - - - @pytest.mark.parametrize('field_def,div_def',div_test_data) - - def test_div(self,field_def,div_def): - size = np.random.random(3)+1.0 - grid = np.random.randint(8,32,(3)) - - nodes = grid_filters.cell_coord0(grid,size) - my_locals = locals() # needed for list comprehension - - field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) - field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) - div = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in div_def], axis=-1) - if len(div_def)==3: - div = div.reshape(tuple(grid) + ((3,))) - else: - div=div.reshape(tuple(grid)) - - assert np.allclose(div,grid_filters.divergence(size,field)) - \ No newline at end of file diff --git a/python/tests/test_grad.py b/python/tests/test_grad.py deleted file mode 100644 index d02c57cdc..000000000 --- a/python/tests/test_grad.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -import numpy as np -from damask import grid_filters - - -class TestGridFilters: - - grad_test_data = [(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0']), - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], - ['0.0', '0.0', '0.0', - '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0' ]), - (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), - (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', - '0.0', '0.0', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ - 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), - (['8.0' ], - ['0.0', '0.0', '0.0' ])] - - @pytest.mark.parametrize('field_def,grad_def',grad_test_data) - - def test_grad(self,field_def,grad_def): - size = np.random.random(3)+1.0 - grid = np.random.randint(8,32,(3)) - - nodes = grid_filters.cell_coord0(grid,size) - my_locals = locals() # needed for list comprehension - - field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) - field = field.reshape(tuple(grid) + ((3,) if len(field_def)==3 else (1,))) - grad = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in grad_def], axis=-1) - grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) - - assert np.allclose(grad,grid_filters.gradient(size,field)) - \ No newline at end of file diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 8170ba7af..6a30481c9 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -139,68 +139,32 @@ class TestGridFilters: assert np.allclose(differential_operator(size,field),0.0) - @pytest.mark.parametrize('field_def,curl_def', - [(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0' ], - ['0.0' , '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] - ) - ]) - def test_curl(self,field_def,curl_def): - size = np.random.random(3)+1.0 - grid = np.random.randint(8,32,(3)) - - nodes = grid_filters.cell_coord0(grid,size) - my_locals = locals() # needed for list comprehension - - field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) - field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) - curl = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in curl_def], axis=-1) - curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) - - assert np.allclose(curl,grid_filters.curl(size,field)) - - grad_test_data = [(['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0']), - - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], - ['0.0', '0.0', '0.0', - '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0' ]), - - (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), - - (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', - '0.0', '0.0', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ - 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - - (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), - - (['8.0' ], - ['0.0', '0.0', '0.0' ]) - ] + grad_test_data = [ + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['0.0', '0.0', '0.0', + '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0' ]), + (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', + '0.0', '0.0', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ + 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), + (['8.0' ], + ['0.0', '0.0', '0.0' ])] @pytest.mark.parametrize('field_def,grad_def',grad_test_data) @@ -218,3 +182,103 @@ class TestGridFilters: assert np.allclose(grad,grid_filters.gradient(size,field)) + + curl_test_data =[ + (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0' ], + ['0.0' , '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', + '0.0', '0.0', '0.0']), + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), + (['5.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], + ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), + (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], + ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ + '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ + '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])']), + (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], + ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ + '0.0',\ + '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'])] + + @pytest.mark.parametrize('field_def,curl_def',curl_test_data) + + def test_curl(self,field_def,curl_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + curl = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in curl_def], axis=-1) + curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) + + assert np.allclose(curl,grid_filters.curl(size,field)) + + + div_test_data =[ + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', + '0.0' , '0.0', '0.0', + '0.0' , '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]' ,'0.0', '0.0']), + (['0.0', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0'], + ['0.0', '-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0']), + (['1.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], + ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] + ), + ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['400.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,0]/size[0])', 'np.sin(np.pi*2*nodes[...,1]/size[1])', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '10.0', '6.0' ], + ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ]), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',]), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]']) + ] + + @pytest.mark.parametrize('field_def,div_def',div_test_data) + + def test_div(self,field_def,div_def): + size = np.random.random(3)+1.0 + grid = np.random.randint(8,32,(3)) + + nodes = grid_filters.cell_coord0(grid,size) + my_locals = locals() # needed for list comprehension + + field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) + field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) + div = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in div_def], axis=-1) + if len(div_def)==3: + div = div.reshape(tuple(grid) + ((3,))) + else: + div=div.reshape(tuple(grid)) + + assert np.allclose(div,grid_filters.divergence(size,field)) + + From d977f2ad254736f36b91e3b05228d9af339ed088 Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 14:26:54 +0200 Subject: [PATCH 42/54] already merged --- python/tests/test_curl.py | 64 --------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 python/tests/test_curl.py diff --git a/python/tests/test_curl.py b/python/tests/test_curl.py deleted file mode 100644 index c3bcc2682..000000000 --- a/python/tests/test_curl.py +++ /dev/null @@ -1,64 +0,0 @@ -import pytest -import numpy as np -from damask import grid_filters - - -class TestGridFilters: - - - curl_test_data =[(['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0' ], - ['0.0' , '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0'] - ), - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', - 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', - 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['5.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], - ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0'] - ), - (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], - ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ - '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ - '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])'] - ), - (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], - ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ - '0.0',\ - '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'])] - - - @pytest.mark.parametrize('field_def,curl_def',curl_test_data) - - def test_curl(self,field_def,curl_def): - size = np.random.random(3)+1.0 - grid = np.random.randint(8,32,(3)) - - nodes = grid_filters.cell_coord0(grid,size) - my_locals = locals() # needed for list comprehension - - field = np.stack([np.broadcast_to(eval(f,globals(),my_locals),grid) for f in field_def],axis=-1) - field = field.reshape(tuple(grid) + ((3,3) if len(field_def)==9 else (3,))) - curl = np.stack([np.broadcast_to(eval(c,globals(),my_locals),grid) for c in curl_def], axis=-1) - curl = curl.reshape(tuple(grid) + ((3,3) if len(curl_def)==9 else (3,))) - - assert np.allclose(curl,grid_filters.curl(size,field)) - - \ No newline at end of file From fcd0028b83ef5428032abfdcbe91ee6dcd8a5ae3 Mon Sep 17 00:00:00 2001 From: "f.basile" Date: Wed, 6 May 2020 14:33:04 +0200 Subject: [PATCH 43/54] avoid line length limit (maximum line length 182 > 132 --- python/tests/test_grid_filters.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 6a30481c9..3d06ee01c 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -181,7 +181,10 @@ class TestGridFilters: grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) assert np.allclose(grad,grid_filters.gradient(size,field)) - + + + + curl_test_data =[ (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', @@ -208,7 +211,9 @@ class TestGridFilters: ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']), - (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], + (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', \ + '8*np.sin(np.pi*2*nodes[...,0]/size[0])', \ + '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])']), @@ -251,11 +256,17 @@ class TestGridFilters: ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', \ + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), (['400.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,0]/size[0])', 'np.sin(np.pi*2*nodes[...,1]/size[1])', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + 'np.sin(np.pi*2*nodes[...,0]/size[0])', \ + 'np.sin(np.pi*2*nodes[...,1]/size[1])', \ + 'np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '10.0', '6.0' ], - ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ]), + ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'\ + '+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'\ + '+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ]), (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',]), (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], From 58537c478d3edc95f26d392b7ae3cfb77ecdce00 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 6 May 2020 16:01:35 +0200 Subject: [PATCH 44/54] [skip ci] updated version information after successful test of v2.0.3-2412-g0d03c469 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6f8955f5c..f955915ff 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-2402-gb88f5ec0 +v2.0.3-2412-g0d03c469 From 0c70f1a54f1ffe2fb90e76cdd6bc4864bf6e9624 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Thu, 7 May 2020 21:13:25 +0200 Subject: [PATCH 45/54] polishing --- src/YAML_types.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index 314c099f8..aa09364df 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -638,7 +638,7 @@ function tNode_get_byKey_asFloats(self,k) result(nodeAsFloats) class(tNode), pointer :: node type(tList), pointer :: list - node => self%get(k) + node => self%get(k) list => node%asList() nodeAsFloats = list%asFloats() @@ -657,7 +657,7 @@ function tNode_get_byKey_asInts(self,k) result(nodeAsInts) class(tNode), pointer :: node type(tList), pointer :: list - node => self%get(k) + node => self%get(k) list => node%asList() nodeAsInts = list%asInts() @@ -676,7 +676,7 @@ function tNode_get_byKey_asBools(self,k) result(nodeAsBools) class(tNode), pointer :: node type(tList), pointer :: list - node => self%get(k) + node => self%get(k) list => node%asList() nodeAsBools = list%asBools() @@ -695,7 +695,7 @@ function tNode_get_byKey_asStrings(self,k) result(nodeAsStrings) class(tNode), pointer :: node type(tList), pointer :: list - node => self%get(k) + node => self%get(k) list => node%asList() nodeAsStrings = list%asStrings() From 1610a6e12a7e227fad70d8c2c9ebfdb94e83d3f2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 7 May 2020 23:10:27 +0200 Subject: [PATCH 46/54] editorial changes --- src/YAML_types.f90 | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index aa09364df..dc7c09815 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -1,11 +1,10 @@ !-------------------------------------------------------------------------------------------------- -!> @brief yaml_types +!> @author Sharan Roongta, Max-Planck-Institut für Eisenforschung GmbH +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Data types to create a scalar, a list, and a dictionary/hash !> @details module describes the various functions to store and get the yaml data. -!! tNode is the fundamental derived data type. It can be of tScalar, & -!! tList or tDict. -!! Every 'value' in a key: value pair is of tNode and is a pointer. -!! If 'value' is of tScalar, it can either be a string, real, integer or logical, & -!! functions exist to convert this scalar type to its respective primitive data type. +!! A node is the base class for scalar, list and dictionary, list items and dictionary entries point +!! to a node. !-------------------------------------------------------------------------------------------------- module YAML_types @@ -70,7 +69,7 @@ module YAML_types tNode_get_byKey_asString => tNode_get_byKey_asString procedure :: & tNode_get_byKey_asStrings => tNode_get_byKey_asStrings - procedure :: & + procedure :: & getIndex => tNode_get_byKey_asIndex generic :: & @@ -148,7 +147,7 @@ module YAML_types character(len=:), allocatable :: key class(tNode), pointer :: node => null() class(tItem), pointer :: next => null() - + contains final :: tItem_finalize end type tItem @@ -195,7 +194,7 @@ subroutine unitTest allocate(tScalar::s1) allocate(tScalar::s2) select type(s1) - class is(tScalar) + class is(tScalar) s1 = '1' if(s1%asInt() /= 1) call IO_error(0,ext_msg='tScalar_asInt') if(dNeq(s1%asFloat(),1.0_pReal)) call IO_error(0,ext_msg='tScalar_asFloat') @@ -210,7 +209,7 @@ subroutine unitTest class is(tScalar) s1 = '2' endselect - + select type(s2) class is(tScalar) s2 = '3' @@ -222,44 +221,44 @@ subroutine unitTest call l1%append(s1) call l1%append(s2) n => l1 - if(any(l1%asInts() /= [2,3])) call IO_error(0,ext_msg='tList_asInts') - if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='tList_asFloats') - if(n%get_asInt(1) /= 2) call IO_error(0,ext_msg='byIndex_asInt') - if(dNeq(n%get_asFloat(2),3.0_pReal)) call IO_error(0,ext_msg='byIndex_asFloat') + if(any(l1%asInts() /= [2,3])) call IO_error(0,ext_msg='tList_asInts') + if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='tList_asFloats') + if(n%get_asInt(1) /= 2) call IO_error(0,ext_msg='byIndex_asInt') + if(dNeq(n%get_asFloat(2),3.0_pReal)) call IO_error(0,ext_msg='byIndex_asFloat') endselect - + allocate(tList::l2) select type(l2) class is(tList) call l2%append(l1) - if(any(l2%get_asInts(1) /= [2,3])) call IO_error(0,ext_msg='byIndex_asInts') - if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='byIndex_asFloats') + if(any(l2%get_asInts(1) /= [2,3])) call IO_error(0,ext_msg='byIndex_asInts') + if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) call IO_error(0,ext_msg='byIndex_asFloats') n => l2 end select deallocate(n) - end block + end block - block + block type(tList), target :: l1 type(tScalar),pointer :: s3,s4 class(tNode), pointer :: n - + allocate(tScalar::s1) allocate(tScalar::s2) s3 => s1%asScalar() s4 => s2%asScalar() s3 = 'True' s4 = 'False' - + call l1%append(s1) call l1%append(s2) n => l1 - - if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') - if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') - if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') - if(n%get_asString(1) /= 'True') call IO_error(0,ext_msg='byIndex_asString') - end block + + if(any(l1%asBools() .neqv. [.true., .false.])) call IO_error(0,ext_msg='tList_asBools') + if(any(l1%asStrings() /= ['True ','False'])) call IO_error(0,ext_msg='tList_asStrings') + if(n%get_asBool(2)) call IO_error(0,ext_msg='byIndex_asBool') + if(n%get_asString(1) /= 'True') call IO_error(0,ext_msg='byIndex_asString') + end block end subroutine unitTest @@ -531,7 +530,7 @@ function tNode_get_byKey(self,k) result(node) character(len=*), intent(in) :: k class(tNode), pointer :: node - type(tDict), pointer :: self_ + type(tDict), pointer :: self_ type(tItem), pointer :: item integer :: j @@ -702,9 +701,9 @@ function tNode_get_byKey_asStrings(self,k) result(nodeAsStrings) end function tNode_get_byKey_asStrings -!------------------------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------------------- !> @brief Returns the index of a key in a dictionary -!------------------------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------------------- function tNode_get_byKey_asIndex(self,key) result(keyIndex) class(tNode), intent(in), target :: self @@ -717,6 +716,7 @@ function tNode_get_byKey_asIndex(self,key) result(keyIndex) dict => self%asDict() item => dict%first + keyIndex = -1 do i = 1, dict%length if(key == item%key) then keyIndex = i @@ -730,7 +730,7 @@ end function tNode_get_byKey_asIndex !-------------------------------------------------------------------------------------------------- -!> @brief Prints scalar as string +!> @brief Scalar as string (YAML block style) !-------------------------------------------------------------------------------------------------- recursive function tScalar_asFormattedString(self,indent) @@ -752,7 +752,7 @@ end function tScalar_asFormattedString !-------------------------------------------------------------------------------------------------- -!> @brief Prints list as string (YAML block style) +!> @brief List as string (YAML block style) !-------------------------------------------------------------------------------------------------- recursive function tList_asFormattedString(self,indent) result(str) @@ -762,7 +762,7 @@ recursive function tList_asFormattedString(self,indent) result(str) type (tItem), pointer :: item character(len=:), allocatable :: str integer :: i, indent_ - + str = '' if(present(indent)) then indent_ = indent @@ -781,15 +781,15 @@ end function tList_asFormattedString !-------------------------------------------------------------------------------------------------- -!> @brief Prints dictionary as string (YAML block style) +!> @brief Dictionary as string (YAML block style) !-------------------------------------------------------------------------------------------------- recursive function tDict_asFormattedString(self,indent) result(str) class (tDict),intent(in),target :: self integer, intent(in),optional :: indent - + type (tItem),pointer :: item - character(len=:), allocatable :: str + character(len=:), allocatable :: str integer :: i, indent_ str = '' @@ -801,7 +801,7 @@ recursive function tDict_asFormattedString(self,indent) result(str) item => self%first do i = 1, self%length - if(i /= 1) str = str//repeat(' ',indent_) + if(i /= 1) str = str//repeat(' ',indent_) select type(node_1 =>item%node) class is(tScalar) str = str//trim(item%key)//': '//item%node%asFormattedString(indent_+len_trim(item%key)+2) @@ -1043,7 +1043,7 @@ end subroutine tList_finalize recursive subroutine tItem_finalize(self) type(tItem),intent(inout) :: self - + deallocate(self%node) if(associated(self%next)) deallocate(self%next) From c8701a46657f1d8bee9c096bc44a4b05b04a21bb Mon Sep 17 00:00:00 2001 From: Vitesh Shah Date: Fri, 8 May 2020 12:15:10 +0200 Subject: [PATCH 47/54] Cleanup/better readability --- python/tests/test_grid_filters.py | 83 +++++++++++++++++++------------ 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 3d06ee01c..3dbc665c0 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -144,25 +144,31 @@ class TestGridFilters: ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']), - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], - ['0.0', '0.0', '0.0', - '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0' ]), - (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['0.0', '0.0', '0.0', + '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0' ]), + + (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ - 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + 'np.sin(np.pi*2*nodes[...,2]/size[2])'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), + (['8.0' ], ['0.0', '0.0', '0.0' ])] @@ -187,36 +193,41 @@ class TestGridFilters: curl_test_data =[ - (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0' ], + (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'], ['0.0' , '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', '0.0', '0.0', '0.0']), - (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])', 'np.sin(np.pi*2*nodes[...,0]/size[0])','np.cos(np.pi*2*nodes[...,1]/size[1])','np.sin(np.pi*2*nodes[...,2]/size[2])'], ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']), + (['5.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,1]/size[1])'], ['0.0', '0.0', '-2*np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']), + (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', \ '8*np.sin(np.pi*2*nodes[...,0]/size[0])', \ '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ - '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ - '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])']), + '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ + '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])']), + (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ '0.0',\ @@ -240,35 +251,41 @@ class TestGridFilters: div_test_data =[ - (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', - '0.0' , '0.0', '0.0', - '0.0' , '0.0', '0.0'], + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', + '0.0' , '0.0', '0.0', + '0.0' , '0.0', '0.0'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]' ,'0.0', '0.0']), - (['0.0', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0'], + + (['0.0', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0'], ['0.0', '-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0']), - (['1.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], - ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] + + (['1.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], + ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] ), - ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + + ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', \ 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['400.0', '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,0]/size[0])', \ 'np.sin(np.pi*2*nodes[...,1]/size[1])', \ 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '10.0', '6.0' ], + '0.0', '10.0', '6.0'], ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'\ - '+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'\ - '+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]','0.0' ]), + '+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'\ + '+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0' ]), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',]), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], ['-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]']) ] From 6928a8290fbab2506b53fffed673484f037fbf55 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 10 May 2020 13:02:26 +0200 Subject: [PATCH 48/54] less whitespace, alingment only within one vector/tensor --- python/tests/test_grid_filters.py | 154 ++++++++++++++---------------- 1 file changed, 74 insertions(+), 80 deletions(-) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index 3dbc665c0..ab60c0446 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -140,44 +140,45 @@ class TestGridFilters: grad_test_data = [ - (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0']), - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], - ['0.0', '0.0', '0.0', - '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0' ]), + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + ['0.0', '0.0', '0.0', + '0.0', '-np.pi*2/size[1]*np.sin(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0' ]), - (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), + (['1.0', '0.0', '2.0*np.cos(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])']), - (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', - '0.0', '0.0', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.cos(np.pi*2*nodes[...,2]/size[2])', '3.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['0.0', '0.0', '-np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', + '0.0', '0.0', '0.0', + '0.0', '0.0', ' np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['np.sin(np.pi*2*nodes[...,0]/size[0])','np.sin(np.pi*2*nodes[...,1]/size[1])',\ - 'np.sin(np.pi*2*nodes[...,2]/size[2])'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', - '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', + 'np.sin(np.pi*2*nodes[...,1]/size[1])', + 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', + '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['np.sin(np.pi*2*nodes[...,0]/size[0])' ], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0' ]), + (['np.sin(np.pi*2*nodes[...,0]/size[0])'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]', '0.0', '0.0']), - (['8.0' ], - ['0.0', '0.0', '0.0' ])] + (['8.0'], + ['0.0', '0.0', '0.0' ]) + ] @pytest.mark.parametrize('field_def,grad_def',grad_test_data) - def test_grad(self,field_def,grad_def): size = np.random.random(3)+1.0 grid = np.random.randint(8,32,(3)) - + nodes = grid_filters.cell_coord0(grid,size) my_locals = locals() # needed for list comprehension @@ -187,22 +188,19 @@ class TestGridFilters: grad = grad.reshape(tuple(grid) + ((3,3) if len(grad_def)==9 else (3,))) assert np.allclose(grad,grid_filters.gradient(size,field)) - - - - - - curl_test_data =[ - (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '0.0'], + + + curl_test_data = [ + (['np.sin(np.pi*2*nodes[...,2]/size[2])', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '0.0'], ['0.0' , '0.0', '0.0', 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0', '0.0', '0.0', '0.0', '0.0']), - (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', - '0.0', '0.0', '0.0', - 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + (['np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', '0.0', + '0.0', '0.0', '0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0', '0.0']), @@ -221,20 +219,22 @@ class TestGridFilters: '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']), - (['4*np.sin(np.pi*2*nodes[...,2]/size[2])', \ - '8*np.sin(np.pi*2*nodes[...,0]/size[0])', \ + ([ '4*np.sin(np.pi*2*nodes[...,2]/size[2])', + '8*np.sin(np.pi*2*nodes[...,0]/size[0])', '16*np.sin(np.pi*2*nodes[...,1]/size[1])'], - ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', \ - '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', \ + ['16*np.pi*2/size[1]*np.cos(np.pi*2*nodes[...,1]/size[1])', + '4*np.pi*2/size[2]*np.cos(np.pi*2*nodes[...,2]/size[2])', '8*np.pi*2/size[0]*np.cos(np.pi*2*nodes[...,0]/size[0])']), - (['0.0', 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', '0.0'], - ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ - '0.0',\ - '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'])] + (['0.0', + 'np.cos(np.pi*2*nodes[...,0]/size[0])+5*np.cos(np.pi*2*nodes[...,2]/size[2])', + '0.0'], + ['5*np.sin(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', + '0.0', + '-np.sin(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]']) + ] - @pytest.mark.parametrize('field_def,curl_def',curl_test_data) - + @pytest.mark.parametrize('field_def,curl_def',curl_test_data) def test_curl(self,field_def,curl_def): size = np.random.random(3)+1.0 grid = np.random.randint(8,32,(3)) @@ -251,47 +251,43 @@ class TestGridFilters: div_test_data =[ - (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', - '0.0' , '0.0', '0.0', - '0.0' , '0.0', '0.0'], - ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]' ,'0.0', '0.0']), + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0', + '0.0' , '0.0', '0.0', + '0.0' , '0.0', '0.0'], + ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]','0.0', '0.0']), - (['0.0', '0.0', '0.0', - '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', - '0.0', '0.0', '0.0'], + (['0.0', '0.0', '0.0', + '0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0', + '0.0', '0.0', '0.0'], ['0.0', '-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]', '0.0']), - (['1.0', '0.0', '0.0', - '0.0', '0.0', '0.0', - '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], - ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] + (['1.0', '0.0', '0.0', + '0.0', '0.0', '0.0', + '0.0', '0.0', '2*np.cos(np.pi*2*nodes[...,2]/size[2])' ], + ['0.0', '0.0', '-2.0*np.pi*2/size[2]*np.sin(np.pi*2*nodes[...,2]/size[2])'] ), - ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], + ([ '23.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '100.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '0.0', 'np.sin(np.pi*2*nodes[...,2]/size[2])'], ['np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]',\ - 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', \ - 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', \ + 'np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]']), - (['400.0', '0.0', '0.0', - 'np.sin(np.pi*2*nodes[...,0]/size[0])', \ - 'np.sin(np.pi*2*nodes[...,1]/size[1])', \ - 'np.sin(np.pi*2*nodes[...,2]/size[2])', - '0.0', '10.0', '6.0'], - ['0.0','np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]'\ - '+np.cos(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]'\ - '+np.cos(np.pi*2*nodes[...,2]/size[2])*np.pi*2/size[2]', '0.0' ]), + (['400.0', '0.0', '0.0', + 'np.sin(np.pi*2*nodes[...,0]/size[0])', 'np.sin(np.pi*2*nodes[...,1]/size[1])', 'np.sin(np.pi*2*nodes[...,2]/size[2])', + '0.0', '10.0', '6.0'], + ['0.0','np.sum(np.cos(np.pi*2*nodes/size)*np.pi*2/size,axis=-1)', '0.0' ]), - (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], + (['np.sin(np.pi*2*nodes[...,0]/size[0])', '0.0', '0.0'], ['np.cos(np.pi*2*nodes[...,0]/size[0])*np.pi*2/size[0]',]), - (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], + (['0.0', 'np.cos(np.pi*2*nodes[...,1]/size[1])', '0.0' ], ['-np.sin(np.pi*2*nodes[...,1]/size[1])*np.pi*2/size[1]']) ] - - @pytest.mark.parametrize('field_def,div_def',div_test_data) - + + @pytest.mark.parametrize('field_def,div_def',div_test_data) + def test_div(self,field_def,div_def): size = np.random.random(3)+1.0 grid = np.random.randint(8,32,(3)) @@ -308,5 +304,3 @@ class TestGridFilters: div=div.reshape(tuple(grid)) assert np.allclose(div,grid_filters.divergence(size,field)) - - From 04e7838eb751ddab7b1d87cf0a6f5b8d7d020dd0 Mon Sep 17 00:00:00 2001 From: Test User Date: Sun, 10 May 2020 15:34:31 +0200 Subject: [PATCH 49/54] [skip ci] updated version information after successful test of v2.0.3-2428-g7b89d748 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index f955915ff..2b197ce0e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-2412-g0d03c469 +v2.0.3-2428-g7b89d748 From 5a94218d234efcf4799e459eceb08a672ebd3373 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 11 May 2020 08:02:34 +0200 Subject: [PATCH 50/54] fixes error: [0]PETSC ERROR: Object is in wrong state [0]PETSC ERROR: Cannot set coordinates until after DMDA has been setup --- src/grid/grid_mech_FEM.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/grid/grid_mech_FEM.f90 b/src/grid/grid_mech_FEM.f90 index 9cdf2f5b5..c8bef7ff2 100644 --- a/src/grid/grid_mech_FEM.f90 +++ b/src/grid/grid_mech_FEM.f90 @@ -132,11 +132,11 @@ subroutine grid_mech_FEM_init [grid(1)],[grid(2)],localK, & mech_grid,ierr) CHKERRQ(ierr) - call DMDASetUniformCoordinates(mech_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),ierr) - CHKERRQ(ierr) call SNESSetDM(mech_snes,mech_grid,ierr); CHKERRQ(ierr) call DMsetFromOptions(mech_grid,ierr); CHKERRQ(ierr) call DMsetUp(mech_grid,ierr); CHKERRQ(ierr) + call DMDASetUniformCoordinates(mech_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),ierr) + CHKERRQ(ierr) call DMCreateGlobalVector(mech_grid,solution_current,ierr); CHKERRQ(ierr) call DMCreateGlobalVector(mech_grid,solution_lastInc,ierr); CHKERRQ(ierr) call DMCreateGlobalVector(mech_grid,solution_rate ,ierr); CHKERRQ(ierr) From 620154a1a8ab08e0bc42cf515c0a72f006a7da08 Mon Sep 17 00:00:00 2001 From: Sharan Roongta Date: Mon, 11 May 2020 14:00:19 +0200 Subject: [PATCH 51/54] not needed --- src/YAML_types.f90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/YAML_types.f90 b/src/YAML_types.f90 index dc7c09815..07541bc1a 100644 --- a/src/YAML_types.f90 +++ b/src/YAML_types.f90 @@ -738,14 +738,6 @@ recursive function tScalar_asFormattedString(self,indent) class (tScalar), intent(in), target :: self integer, intent(in), optional :: indent - integer :: indent_ - - if(present(indent)) then - indent_ = indent - else - indent_ = 0 - endif - tScalar_asFormattedString = trim(self%value)//IO_EOL end function tScalar_asFormattedString From 1bb819ab3f04352eb177e107e6cb760bf06987df Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 11 May 2020 14:33:27 +0200 Subject: [PATCH 52/54] [skip ci] updated version information after successful test of v2.0.3-2431-gfe221460 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2b197ce0e..d7e0378cb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-2428-g7b89d748 +v2.0.3-2431-gfe221460 From ae408baf2719996c1d49a967591d64c8fe6ba91c Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 12 May 2020 11:31:59 +0200 Subject: [PATCH 53/54] [skip ci] updated version information after successful test of v2.0.3-2449-g24c2e5ba --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d7e0378cb..c998127ba 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-2431-gfe221460 +v2.0.3-2449-g24c2e5ba From 45e608e71b12e4113957929c96adce58ca4ee489 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 13 May 2020 02:07:50 +0200 Subject: [PATCH 54/54] [skip ci] updated version information after successful test of v2.0.3-2464-g90f93d23 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c998127ba..29f305cbe 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-2449-g24c2e5ba +v2.0.3-2464-g90f93d23