291 lines
14 KiB
Fortran
291 lines
14 KiB
Fortran
!--------------------------------------------------------------------------------------------------
|
|
! $Id$
|
|
!--------------------------------------------------------------------------------------------------
|
|
!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH
|
|
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
|
|
!> @brief Isostrain (full constraint Taylor assuption) homogenization scheme
|
|
!--------------------------------------------------------------------------------------------------
|
|
module homogenization_isostrain
|
|
use prec, only: &
|
|
pInt
|
|
|
|
implicit none
|
|
private
|
|
integer(pInt), dimension(:), allocatable, public, protected :: &
|
|
homogenization_isostrain_sizePostResults
|
|
integer(pInt), dimension(:,:), allocatable, target, public :: &
|
|
homogenization_isostrain_sizePostResult
|
|
|
|
character(len=64), dimension(:,:), allocatable, target, public :: &
|
|
homogenization_isostrain_output !< name of each post result output
|
|
integer(pInt), dimension(:), allocatable, private :: &
|
|
homogenization_isostrain_Ngrains
|
|
enum, bind(c)
|
|
enumerator :: undefined_ID, &
|
|
nconstituents_ID, &
|
|
temperature_ID, &
|
|
ipcoords_ID, &
|
|
avgdefgrad_ID, &
|
|
avgfirstpiola_ID
|
|
end enum
|
|
enum, bind(c)
|
|
enumerator :: parallel_ID, &
|
|
average_ID
|
|
end enum
|
|
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
|
|
homogenization_isostrain_outputID !< ID of each post result output
|
|
integer(kind(average_ID)), dimension(:), allocatable, private :: &
|
|
homogenization_isostrain_mapping !< mapping type
|
|
|
|
|
|
public :: &
|
|
homogenization_isostrain_init, &
|
|
homogenization_isostrain_partitionDeformation, &
|
|
homogenization_isostrain_averageStressAndItsTangent, &
|
|
homogenization_isostrain_postResults
|
|
|
|
contains
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
!> @brief allocates all neccessary fields, reads information from material configuration file
|
|
!--------------------------------------------------------------------------------------------------
|
|
subroutine homogenization_isostrain_init(fileUnit)
|
|
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
|
|
use IO
|
|
use material
|
|
|
|
implicit none
|
|
integer(pInt), intent(in) :: fileUnit
|
|
integer(pInt), parameter :: MAXNCHUNKS = 2_pInt
|
|
integer(pInt), dimension(1_pInt+2_pInt*MAXNCHUNKS) :: positions
|
|
integer(pInt) :: &
|
|
section = 0_pInt, i, j, output, mySize
|
|
integer :: &
|
|
maxNinstance, k ! no pInt (stores a system dependen value from 'count'
|
|
character(len=65536) :: &
|
|
tag = '', &
|
|
line = ''
|
|
|
|
write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_ISOSTRAIN_label//' init -+>>>'
|
|
write(6,'(a)') ' $Id$'
|
|
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
|
|
#include "compilation_info.f90"
|
|
|
|
maxNinstance = count(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)
|
|
if (maxNinstance == 0) return
|
|
|
|
allocate(homogenization_isostrain_sizePostResults(maxNinstance), source=0_pInt)
|
|
allocate(homogenization_isostrain_sizePostResult(maxval(homogenization_Noutput),maxNinstance), &
|
|
source=0_pInt)
|
|
allocate(homogenization_isostrain_Ngrains(maxNinstance), source=0_pInt)
|
|
allocate(homogenization_isostrain_mapping(maxNinstance), source=average_ID)
|
|
allocate(homogenization_isostrain_output(maxval(homogenization_Noutput),maxNinstance))
|
|
homogenization_isostrain_output = ''
|
|
allocate(homogenization_isostrain_outputID(maxval(homogenization_Noutput),maxNinstance), &
|
|
source=undefined_ID)
|
|
|
|
rewind(fileUnit)
|
|
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
|
|
line = IO_read(fileUnit)
|
|
enddo
|
|
|
|
do while (trim(line) /= IO_EOF) ! read through sections of homogenization part
|
|
line = IO_read(fileUnit)
|
|
if (IO_isBlank(line)) cycle ! skip empty lines
|
|
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
|
|
line = IO_read(fileUnit, .true.) ! reset IO_read
|
|
exit
|
|
endif
|
|
if (IO_getTag(line,'[',']') /= '') then ! next section
|
|
section = section + 1_pInt
|
|
output = 0_pInt ! reset output counter
|
|
cycle
|
|
endif
|
|
if (section > 0_pInt ) then ! do not short-circuit here (.and. with next if-statement). It's not safe in Fortran
|
|
if (homogenization_type(section) == HOMOGENIZATION_ISOSTRAIN_ID) then ! one of my sections
|
|
i = homogenization_typeInstance(section) ! which instance of my type is present homogenization
|
|
positions = IO_stringPos(line,MAXNCHUNKS)
|
|
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
|
|
select case(tag)
|
|
case('type')
|
|
case ('(output)')
|
|
output = output + 1_pInt
|
|
homogenization_isostrain_output(output,i) = IO_lc(IO_stringValue(line,positions,2_pInt))
|
|
select case(homogenization_isostrain_output(output,i))
|
|
case('nconstituents','ngrains')
|
|
homogenization_isostrain_outputID(output,i) = nconstituents_ID
|
|
case('temperature')
|
|
homogenization_isostrain_outputID(output,i) = temperature_ID
|
|
case('ipcoords')
|
|
homogenization_isostrain_outputID(output,i) = ipcoords_ID
|
|
case('avgdefgrad','avgf')
|
|
homogenization_isostrain_outputID(output,i) = avgdefgrad_ID
|
|
case('avgp','avgfirstpiola','avg1stpiola')
|
|
homogenization_isostrain_outputID(output,i) = avgfirstpiola_ID
|
|
case default
|
|
call IO_error(105_pInt,ext_msg=IO_stringValue(line,positions,2_pInt)//&
|
|
' ('//HOMOGENIZATION_isostrain_label//')')
|
|
end select
|
|
case ('nconstituents','ngrains')
|
|
homogenization_isostrain_Ngrains(i) = IO_intValue(line,positions,2_pInt)
|
|
case ('mapping')
|
|
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
|
|
case ('parallel','sum')
|
|
homogenization_isostrain_mapping(i) = parallel_ID
|
|
case ('average','mean','avg')
|
|
homogenization_isostrain_mapping(i) = average_ID
|
|
case default
|
|
call IO_error(211_pInt,ext_msg=trim(tag)//' ('//HOMOGENIZATION_isostrain_label//')')
|
|
end select
|
|
case default
|
|
call IO_error(210_pInt,ext_msg=trim(tag)//' ('//HOMOGENIZATION_isostrain_label//')')
|
|
end select
|
|
endif
|
|
endif
|
|
enddo
|
|
|
|
do i = 1,maxNinstance
|
|
|
|
do j = 1_pInt,maxval(homogenization_Noutput)
|
|
select case(homogenization_isostrain_outputID(j,i))
|
|
case(nconstituents_ID, temperature_ID)
|
|
mySize = 1_pInt
|
|
case(ipcoords_ID)
|
|
mySize = 3_pInt
|
|
case(avgdefgrad_ID, avgfirstpiola_ID)
|
|
mySize = 9_pInt
|
|
case default
|
|
mySize = 0_pInt
|
|
end select
|
|
|
|
outputFound: if (mySize > 0_pInt) then
|
|
homogenization_isostrain_sizePostResult(j,i) = mySize
|
|
homogenization_isostrain_sizePostResults(i) = &
|
|
homogenization_isostrain_sizePostResults(i) + mySize
|
|
endif outputFound
|
|
enddo
|
|
enddo
|
|
|
|
end subroutine homogenization_isostrain_init
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
!> @brief partitions the deformation gradient onto the constituents
|
|
!--------------------------------------------------------------------------------------------------
|
|
subroutine homogenization_isostrain_partitionDeformation(F,avgF,el)
|
|
use prec, only: &
|
|
pReal
|
|
use mesh, only: &
|
|
mesh_element
|
|
use material, only: &
|
|
homogenization_maxNgrains, &
|
|
homogenization_Ngrains
|
|
|
|
implicit none
|
|
real(pReal), dimension (3,3,homogenization_maxNgrains), intent(out) :: F !< partioned def grad per grain
|
|
real(pReal), dimension (3,3), intent(in) :: avgF !< my average def grad
|
|
integer(pInt), intent(in) :: &
|
|
el !< element number
|
|
F=0.0_pReal
|
|
F(1:3,1:3,1:homogenization_Ngrains(mesh_element(3,el)))= &
|
|
spread(avgF,3,homogenization_Ngrains(mesh_element(3,el)))
|
|
|
|
end subroutine homogenization_isostrain_partitionDeformation
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
!> @brief derive average stress and stiffness from constituent quantities
|
|
!--------------------------------------------------------------------------------------------------
|
|
subroutine homogenization_isostrain_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,el)
|
|
use prec, only: &
|
|
pReal
|
|
use mesh, only: &
|
|
mesh_element
|
|
use material, only: &
|
|
homogenization_maxNgrains, &
|
|
homogenization_Ngrains, &
|
|
homogenization_typeInstance
|
|
|
|
implicit none
|
|
real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point
|
|
real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
|
|
real(pReal), dimension (3,3,homogenization_maxNgrains), intent(in) :: P !< array of current grain stresses
|
|
real(pReal), dimension (3,3,3,3,homogenization_maxNgrains), intent(in) :: dPdF !< array of current grain stiffnesses
|
|
integer(pInt), intent(in) :: el !< element number
|
|
integer(pInt) :: &
|
|
homID, &
|
|
Ngrains
|
|
|
|
homID = homogenization_typeInstance(mesh_element(3,el))
|
|
Ngrains = homogenization_Ngrains(mesh_element(3,el))
|
|
|
|
select case (homogenization_isostrain_mapping(homID))
|
|
case (parallel_ID)
|
|
avgP = sum(P,3)
|
|
dAvgPdAvgF = sum(dPdF,5)
|
|
case (average_ID)
|
|
avgP = sum(P,3) /real(Ngrains,pReal)
|
|
dAvgPdAvgF = sum(dPdF,5)/real(Ngrains,pReal)
|
|
end select
|
|
|
|
end subroutine homogenization_isostrain_averageStressAndItsTangent
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
!> @brief return array of homogenization results for post file inclusion
|
|
!--------------------------------------------------------------------------------------------------
|
|
pure function homogenization_isostrain_postResults(ip,el,avgP,avgF)
|
|
use prec, only: &
|
|
pReal
|
|
use mesh, only: &
|
|
mesh_element, &
|
|
mesh_ipCoordinates
|
|
use material, only: &
|
|
homogenization_typeInstance, &
|
|
homogenization_Noutput
|
|
use crystallite, only: &
|
|
crystallite_temperature
|
|
|
|
implicit none
|
|
integer(pInt), intent(in) :: &
|
|
ip, & !< integration point number
|
|
el !< element number
|
|
real(pReal), dimension(3,3), intent(in) :: &
|
|
avgP, & !< average stress at material point
|
|
avgF !< average deformation gradient at material point
|
|
real(pReal), dimension(homogenization_isostrain_sizePostResults &
|
|
(homogenization_typeInstance(mesh_element(3,el)))) :: &
|
|
homogenization_isostrain_postResults
|
|
|
|
integer(pInt) :: &
|
|
homID, &
|
|
o, c
|
|
|
|
c = 0_pInt
|
|
homID = homogenization_typeInstance(mesh_element(3,el))
|
|
homogenization_isostrain_postResults = 0.0_pReal
|
|
|
|
do o = 1_pInt,homogenization_Noutput(mesh_element(3,el))
|
|
select case(homogenization_isostrain_outputID(o,homID))
|
|
case (nconstituents_ID)
|
|
homogenization_isostrain_postResults(c+1_pInt) = real(homogenization_isostrain_Ngrains(homID),pReal)
|
|
c = c + 1_pInt
|
|
case (temperature_ID)
|
|
homogenization_isostrain_postResults(c+1_pInt) = crystallite_temperature(ip,el)
|
|
c = c + 1_pInt
|
|
case (avgdefgrad_ID)
|
|
homogenization_isostrain_postResults(c+1_pInt:c+9_pInt) = reshape(avgF,[9])
|
|
c = c + 9_pInt
|
|
case (avgfirstpiola_ID)
|
|
homogenization_isostrain_postResults(c+1_pInt:c+9_pInt) = reshape(avgP,[9])
|
|
c = c + 9_pInt
|
|
case (ipcoords_ID)
|
|
homogenization_isostrain_postResults(c+1_pInt:c+3_pInt) = mesh_ipCoordinates(1:3,ip,el) ! current ip coordinates
|
|
c = c + 3_pInt
|
|
end select
|
|
enddo
|
|
|
|
end function homogenization_isostrain_postResults
|
|
|
|
end module homogenization_isostrain
|