major restructuring of multi field handling in DAMASK and added some example config files for multi field simulations. please report bugs

This commit is contained in:
Pratheek Shanthraj 2015-05-28 17:02:23 +00:00
parent aed29e3b77
commit 8f4663985a
67 changed files with 9782 additions and 7251 deletions

View File

@ -45,7 +45,7 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief call (thread safe) all module initializations !> @brief call (thread safe) all module initializations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine CPFEM_initAll(temperature,el,ip) subroutine CPFEM_initAll(temperature_inp,el,ip)
use prec, only: & use prec, only: &
prec_init prec_init
use numerics, only: & use numerics, only: &
@ -79,7 +79,7 @@ subroutine CPFEM_initAll(temperature,el,ip)
implicit none implicit none
integer(pInt), intent(in) :: el, & !< FE el number integer(pInt), intent(in) :: el, & !< FE el number
ip !< FE integration point number ip !< FE integration point number
real(pReal), intent(in) :: temperature !< temperature real(pReal), intent(in) :: temperature_inp !< temperature
!$OMP CRITICAL (init) !$OMP CRITICAL (init)
if (.not. CPFEM_init_done) then if (.not. CPFEM_init_done) then
@ -97,10 +97,10 @@ subroutine CPFEM_initAll(temperature,el,ip)
call FE_init call FE_init
call mesh_init(ip, el) ! pass on coordinates to alter calcMode of first ip call mesh_init(ip, el) ! pass on coordinates to alter calcMode of first ip
call lattice_init call lattice_init
call material_init(temperature) call material_init
call constitutive_init(temperature) call constitutive_init
call crystallite_init call crystallite_init
call homogenization_init call homogenization_init(temperature_inp)
call CPFEM_init call CPFEM_init
#if defined(Marc4DAMASK) || defined(Abaqus) #if defined(Marc4DAMASK) || defined(Abaqus)
call DAMASK_interface_init ! Spectral solver and FEM init is already done call DAMASK_interface_init ! Spectral solver and FEM init is already done
@ -262,9 +262,9 @@ end subroutine CPFEM_init
!> @brief perform initialization at first call, update variables and call the actual material model !> @brief perform initialization at first call, update variables and call the actual material model
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
#if defined(Marc4DAMASK) || defined(Abaqus) #if defined(Marc4DAMASK) || defined(Abaqus)
subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature, dt, elFE, ip, cauchyStress, jacobian) subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyStress, jacobian)
#else #else
subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip)
#endif #endif
use numerics, only: & use numerics, only: &
defgradTolerance, & defgradTolerance, &
@ -316,13 +316,19 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
use material, only: & use material, only: &
microstructure_elemhomo, & microstructure_elemhomo, &
plasticState, & plasticState, &
damageState, & sourceState, &
homogState, & homogState, &
thermalState, & thermalState, &
vacancyState,& damageState, &
vacancyfluxState, &
hydrogenfluxState, &
mappingConstitutive, & mappingConstitutive, &
material_phase, & material_phase, &
phase_plasticity, & phase_plasticity, &
temperature, &
thermalMapping, &
phase_Nsources, &
material_homog, &
material_Nhomogenization material_Nhomogenization
use crystallite, only: & use crystallite, only: &
crystallite_partionedF,& crystallite_partionedF,&
@ -349,8 +355,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
materialpoint_sizeResults, & materialpoint_sizeResults, &
#endif #endif
materialpoint_stressAndItsTangent, & materialpoint_stressAndItsTangent, &
materialpoint_postResults, & materialpoint_postResults
field_putFieldTemperature
use IO, only: & use IO, only: &
IO_write_jobRealFile, & IO_write_jobRealFile, &
IO_warning IO_warning
@ -359,7 +364,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
implicit none implicit none
integer(pInt), intent(in) :: elFE, & !< FE element number integer(pInt), intent(in) :: elFE, & !< FE element number
ip !< integration point number ip !< integration point number
real(pReal), intent(in) :: temperature !< temperature real(pReal), intent(in) :: temperature_inp !< temperature
real(pReal), intent(in) :: dt !< time increment real(pReal), intent(in) :: dt !< time increment
real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0 real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0
ffn1 !< deformation gradient for t=t1 ffn1 !< deformation gradient for t=t1
@ -381,7 +386,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
#endif #endif
integer(pInt) elCP, & ! crystal plasticity element number integer(pInt) elCP, & ! crystal plasticity element number
i, j, k, l, m, n, ph, homog i, j, k, l, m, n, ph, homog, mySource
logical updateJaco ! flag indicating if JAcobian has to be updated logical updateJaco ! flag indicating if JAcobian has to be updated
character(len=1024) :: rankStr character(len=1024) :: rankStr
@ -427,10 +432,11 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
crystallite_dPdF0 = crystallite_dPdF ! crystallite stiffness crystallite_dPdF0 = crystallite_dPdF ! crystallite stiffness
crystallite_Tstar0_v = crystallite_Tstar_v ! crystallite 2nd Piola Kirchhoff stress crystallite_Tstar0_v = crystallite_Tstar_v ! crystallite 2nd Piola Kirchhoff stress
forall ( i = 1:size(plasticState)) plasticState(i)%state0= plasticState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array forall ( i = 1:size(plasticState )) plasticState(i)%state0 = plasticState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array
forall ( i = 1:size(damageState)) damageState(i)%state0 = damageState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array do i = 1, size(sourceState)
forall ( i = 1:size(thermalState)) thermalState(i)%state0= thermalState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array do mySource = 1,phase_Nsources(i)
forall ( i = 1:size(vacancyState)) vacancyState(i)%state0= vacancyState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array sourceState(i)%p(mySource)%state0 = sourceState(i)%p(mySource)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array
enddo; enddo
if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then
write(6,'(a)') '<< CPFEM >> aging states' write(6,'(a)') '<< CPFEM >> aging states'
if (debug_e <= mesh_NcpElems .and. debug_i <= mesh_maxNips) then if (debug_e <= mesh_NcpElems .and. debug_i <= mesh_maxNips) then
@ -441,7 +447,11 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
endif endif
do homog = 1_pInt, material_Nhomogenization do homog = 1_pInt, material_Nhomogenization
homogState(homog)%state0 = homogState(homog)%state homogState (homog)%state0 = homogState (homog)%state
thermalState (homog)%state0 = thermalState (homog)%state
damageState (homog)%state0 = damageState (homog)%state
vacancyfluxState (homog)%state0 = vacancyfluxState (homog)%state
hydrogenfluxState(homog)%state0 = hydrogenfluxState(homog)%state
enddo enddo
@ -523,7 +533,8 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
if (.not. parallelExecution) then if (.not. parallelExecution) then
#if defined(Marc4DAMASK) || defined(Abaqus) #if defined(Marc4DAMASK) || defined(Abaqus)
call field_putFieldTemperature(ip,elCP,temperature) temperature(material_homog(ip,elCP))%p(thermalMapping(material_homog(ip,elCP))%p(ip,elCP)) = &
temperature_inp
#endif #endif
materialpoint_F0(1:3,1:3,ip,elCP) = ffn materialpoint_F0(1:3,1:3,ip,elCP) = ffn
materialpoint_F(1:3,1:3,ip,elCP) = ffn1 materialpoint_F(1:3,1:3,ip,elCP) = ffn1
@ -536,7 +547,8 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip)
CPFEM_dcsde(1:6,1:6,ip,elCP) = CPFEM_odd_jacobian * math_identity2nd(6) CPFEM_dcsde(1:6,1:6,ip,elCP) = CPFEM_odd_jacobian * math_identity2nd(6)
#endif #endif
#if defined(Marc4DAMASK) || defined(Abaqus) #if defined(Marc4DAMASK) || defined(Abaqus)
call field_putFieldTemperature(ip,elCP,temperature) temperature(material_homog(ip,elCP))%p(thermalMapping(material_homog(ip,elCP))%p(ip,elCP)) = &
temperature_inp
#endif #endif
materialpoint_F0(1:3,1:3,ip,elCP) = ffn materialpoint_F0(1:3,1:3,ip,elCP) = ffn
materialpoint_F(1:3,1:3,ip,elCP) = ffn1 materialpoint_F(1:3,1:3,ip,elCP) = ffn1

View File

@ -140,7 +140,7 @@ program DAMASK_spectral_Driver
external :: quit external :: quit
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! init DAMASK (all modules) ! init DAMASK (all modules)
call CPFEM_initAll(temperature = 300.0_pReal, el = 1_pInt, ip = 1_pInt) call CPFEM_initAll(temperature_inp = 300.0_pReal, el = 1_pInt, ip = 1_pInt)
mainProcess: if (worldrank == 0) then mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- DAMASK_spectral_driver init -+>>>' write(6,'(/,a)') ' <<<+- DAMASK_spectral_driver init -+>>>'
write(6,'(a)') ' $Id$' write(6,'(a)') ' $Id$'

View File

@ -205,7 +205,7 @@ subroutine basicPETSc_init(temperature)
call Utilities_updateIPcoords(F) call Utilities_updateIPcoords(F)
call Utilities_constitutiveResponse(F_lastInc, F, & call Utilities_constitutiveResponse(F_lastInc, F, &
temperature, & temperature, &
0.0_pReal, & 1.0_pReal, &
P, & P, &
C_volAvg,C_minMaxAvg, & ! global average of stiffness and (min+max)/2 C_volAvg,C_minMaxAvg, & ! global average of stiffness and (min+max)/2
temp33_Real, & temp33_Real, &

View File

@ -395,10 +395,13 @@ subroutine utilities_FFTforward()
use numerics, only: & use numerics, only: &
worldrank worldrank
use mesh, only: & use mesh, only: &
gridOffset, &
gridLocal gridLocal
implicit none implicit none
external :: &
MPI_Bcast, &
MPI_reduce
integer(pInt) :: row, column ! if debug FFTW, compare 3D array field of row and column integer(pInt) :: row, column ! if debug FFTW, compare 3D array field of row and column
real(pReal), dimension(2) :: myRand, maxScalarField ! random numbers real(pReal), dimension(2) :: myRand, maxScalarField ! random numbers
integer(pInt) :: i, j, k integer(pInt) :: i, j, k
@ -433,7 +436,7 @@ subroutine utilities_FFTforward()
field_fourierMPI(row,column,1:grid1Red,1:gridLocal(2),1:gridLocal(3)))/& field_fourierMPI(row,column,1:grid1Red,1:gridLocal(2),1:gridLocal(3)))/&
scalarField_fourierMPI(1:grid1Red,1:gridLocal(2),1:gridLocal(3)) scalarField_fourierMPI(1:grid1Red,1:gridLocal(2),1:gridLocal(3))
else where else where
scalarField_realMPI = cmplx(0.0,0.0,pReal) scalarField_fourierMPI = cmplx(0.0,0.0,pReal)
end where end where
maxScalarField(1) = maxval(real (scalarField_fourierMPI(1:grid1Red,1:gridLocal(2), & maxScalarField(1) = maxval(real (scalarField_fourierMPI(1:grid1Red,1:gridLocal(2), &
1:gridLocal(3)))) 1:gridLocal(3))))
@ -451,7 +454,7 @@ subroutine utilities_FFTforward()
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! applying filter ! applying filter
do k = 1_pInt, gridLocal(3); do j = 1_pInt, gridLocal(2); do i = 1_pInt,grid1Red do k = 1_pInt, gridLocal(3); do j = 1_pInt, gridLocal(2); do i = 1_pInt,grid1Red
field_fourierMPI(1:3,1:3,i,j,k) = utilities_getFilter(xi(1:3,i,j,k))* & field_fourierMPI(1:3,1:3,i,j,k) = cmplx(utilities_getFilter(xi(1:3,i,j,k)),0.0,pReal)* &
field_fourierMPI(1:3,1:3,i,j,k) field_fourierMPI(1:3,1:3,i,j,k)
enddo; enddo; enddo enddo; enddo; enddo
@ -473,6 +476,10 @@ subroutine utilities_FFTbackward()
gridLocal gridLocal
implicit none implicit none
external :: &
MPI_Bcast, &
MPI_reduce
integer(pInt) :: row, column !< if debug FFTW, compare 3D array field of row and column integer(pInt) :: row, column !< if debug FFTW, compare 3D array field of row and column
real(pReal), dimension(2) :: myRand real(pReal), dimension(2) :: myRand
real(pReal) :: maxScalarField real(pReal) :: maxScalarField
@ -506,7 +513,7 @@ subroutine utilities_FFTbackward()
- field_realMPI (row,column,1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)))/ & - field_realMPI (row,column,1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)))/ &
scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)) scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3))
else where else where
scalarField_realMPI = cmplx(0.0,0.0,pReal) scalarField_realMPI = 0.0_pReal
end where end where
maxScalarField = maxval(real (scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)))) maxScalarField = maxval(real (scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3))))
call MPI_reduce(MPI_IN_PLACE,maxScalarField,1,MPI_DOUBLE,MPI_MAX,0,PETSC_COMM_WORLD,ierr) call MPI_reduce(MPI_IN_PLACE,maxScalarField,1,MPI_DOUBLE,MPI_MAX,0,PETSC_COMM_WORLD,ierr)
@ -627,6 +634,10 @@ real(pReal) function utilities_divergenceRMS()
gridGlobal gridGlobal
implicit none implicit none
external :: &
MPI_reduce, &
MPI_Allreduce
integer(pInt) :: i, j, k integer(pInt) :: i, j, k
real(pReal) :: & real(pReal) :: &
err_real_div_RMS, & !< RMS of divergence in real space err_real_div_RMS, & !< RMS of divergence in real space
@ -714,6 +725,9 @@ real(pReal) function utilities_curlRMS()
gridGlobal gridGlobal
implicit none implicit none
external :: &
MPI_Allreduce
integer(pInt) :: i, j, k, l integer(pInt) :: i, j, k, l
complex(pReal), dimension(3,3) :: curl_fourier complex(pReal), dimension(3,3) :: curl_fourier
PetscErrorCode :: ierr PetscErrorCode :: ierr
@ -898,10 +912,14 @@ subroutine utilities_constitutiveResponse(F_lastInc,F,temperature,timeinc,&
materialpoint_F, & materialpoint_F, &
materialpoint_P, & materialpoint_P, &
materialpoint_dPdF materialpoint_dPdF
use thermal_isothermal, only: & ! use thermal_isothermal, only: &
thermal_isothermal_temperature ! thermal_isothermal_temperature
implicit none implicit none
external :: &
MPI_reduce, &
MPI_Allreduce
real(pReal), intent(in) :: temperature !< temperature (no field) real(pReal), intent(in) :: temperature !< temperature (no field)
real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: & real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: &
F_lastInc, & !< target deformation gradient F_lastInc, & !< target deformation gradient
@ -937,7 +955,7 @@ subroutine utilities_constitutiveResponse(F_lastInc,F,temperature,timeinc,&
call CPFEM_general(CPFEM_COLLECT,F_lastInc(1:3,1:3,1,1,1),F(1:3,1:3,1,1,1), & call CPFEM_general(CPFEM_COLLECT,F_lastInc(1:3,1:3,1,1,1),F(1:3,1:3,1,1,1), &
temperature,timeinc,1_pInt,1_pInt) temperature,timeinc,1_pInt,1_pInt)
thermal_isothermal_temperature(:) = temperature ! thermal_isothermal_temperature(:) = temperature
materialpoint_F = reshape(F,[3,3,1,product(gridLocal)]) materialpoint_F = reshape(F,[3,3,1,product(gridLocal)])
call debug_reset() call debug_reset()
@ -1044,6 +1062,9 @@ function utilities_forwardField(timeinc,field_lastInc,rate,aim)
gridLocal gridLocal
implicit none implicit none
external :: &
MPI_Allreduce
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
timeinc !< timeinc of current step timeinc !< timeinc of current step
real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: & real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: &
@ -1143,6 +1164,8 @@ subroutine utilities_updateIPcoords(F)
geomSizeGlobal, & geomSizeGlobal, &
mesh_ipCoordinates mesh_ipCoordinates
implicit none implicit none
external :: &
MPI_Bcast
real(pReal), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)), intent(in) :: F real(pReal), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)), intent(in) :: F
integer(pInt) :: i, j, k, m integer(pInt) :: i, j, k, m

View File

@ -187,7 +187,8 @@ COMPILE_OPTIONS_gfortran +=-ffree-line-length-132\
-Wsuggest-attribute=pure\ -Wsuggest-attribute=pure\
-Wsuggest-attribute=noreturn\ -Wsuggest-attribute=noreturn\
-Wconversion-extra\ -Wconversion-extra\
-Wimplicit-procedure -Wimplicit-procedure\
-Wno-unused-parameter
endif endif
################################################################################################### ###################################################################################################
#COMPILE SWITCHES #COMPILE SWITCHES
@ -305,22 +306,37 @@ PRECISION_gfortran :=-fdefault-real-8 -fdefault-double-8 -DFLOAT=8 -DINT=4
COMPILE =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(OPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90)) COMPILE =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(OPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90))
COMPILE_MAXOPTI =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90)) COMPILE_MAXOPTI =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90))
################################################################################################### ###################################################################################################
DAMAGE_FILES = \ SOURCE_FILES = \
damage_none.o damage_isoBrittle.o damage_isoDuctile.o damage_gurson.o damage_anisoBrittle.o damage_anisoDuctile.o damage_phaseField.o source_thermal_dissipation.o \
source_damage_isoBrittle.o source_damage_isoDuctile.o source_damage_anisoBrittle.o source_damage_anisoDuctile.o \
source_vacancy_phenoplasticity.o source_vacancy_irradiation.o source_vacancy_thermalfluc.o
THERMAL_FILES = \ KINEMATICS_FILES = \
thermal_isothermal.o thermal_adiabatic.o kinematics_cleavage_opening.o kinematics_slipplane_opening.o \
kinematics_thermal_expansion.o \
VACANCY_FILES = \ kinematics_vacancy_strain.o kinematics_hydrogen_strain.o
vacancy_constant.o vacancy_generation.o
PLASTIC_FILES = \ PLASTIC_FILES = \
plastic_dislotwin.o plastic_disloUCLA.o plastic_disloKMC.o plastic_j2.o plastic_phenopowerlaw.o \ plastic_dislotwin.o plastic_disloUCLA.o plastic_disloKMC.o plastic_j2.o plastic_phenopowerlaw.o \
plastic_titanmod.o plastic_nonlocal.o plastic_none.o plastic_titanmod.o plastic_nonlocal.o plastic_none.o
THERMAL_FILES = \
thermal_isothermal.o thermal_adiabatic.o thermal_conduction.o
DAMAGE_FILES = \
damage_none.o damage_local.o damage_nonlocal.o
VACANCYFLUX_FILES = \
vacancyflux_isoconc.o vacancyflux_isochempot.o vacancyflux_cahnhilliard.o
POROSITY_FILES = \
porosity_none.o porosity_phasefield.o
HYDROGENFLUX_FILES = \
hydrogenflux_isoconc.o hydrogenflux_cahnhilliard.o
HOMOGENIZATION_FILES = \ HOMOGENIZATION_FILES = \
homogenization_RGC.o homogenization_isostrain.o homogenization_none.o homogenization.o homogenization_RGC.o homogenization_isostrain.o homogenization_none.o
##################### #####################
# Spectral Solver # Spectral Solver
@ -332,12 +348,17 @@ DAMASK_spectral.exe: MESHNAME := mesh.f90
DAMASK_spectral.exe: INTERFACENAME := DAMASK_spectral_interface.f90 DAMASK_spectral.exe: INTERFACENAME := DAMASK_spectral_interface.f90
SPECTRAL_SOLVER_FILES = DAMASK_spectral_solverAL.o DAMASK_spectral_solverBasicPETSc.o DAMASK_spectral_solverPolarisation.o
SPECTRAL_FILES = prec.o DAMASK_interface.o IO.o libs.o numerics.o debug.o math.o \ SPECTRAL_FILES = prec.o DAMASK_interface.o IO.o libs.o numerics.o debug.o math.o \
FEsolving.o mesh.o material.o lattice.o constitutive.o \ FEsolving.o mesh.o material.o lattice.o \
$(DAMAGE_FILES) $(THERMAL_FILES) $(VACANCY_FILES) $(PLASTIC_FILES) \ $(SOURCE_FILES) $(KINEMATICS_FILES) $(PLASTIC_FILES) constitutive.o \
crystallite.o $(HOMOGENIZATION_FILES) CPFEM.o \ crystallite.o \
$(THERMAL_FILES) $(DAMAGE_FILES) $(VACANCYFLUX_FILES) $(HYDROGENFLUX_FILES) $(POROSITY_FILES) \
$(HOMOGENIZATION_FILES) homogenization.o \
CPFEM.o \
DAMASK_spectral_utilities.o \ DAMASK_spectral_utilities.o \
DAMASK_spectral_solverAL.o DAMASK_spectral_solverBasicPETSc.o DAMASK_spectral_solverPolarisation.o $(SPECTRAL_SOLVER_FILES)
DAMASK_spectral.exe: DAMASK_spectral_driver.o DAMASK_spectral.exe: DAMASK_spectral_driver.o
$(PREFIX) $(LINKERNAME) $(OPENMP_FLAG_$(F90)) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \ $(PREFIX) $(LINKERNAME) $(OPENMP_FLAG_$(F90)) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \
@ -346,9 +367,7 @@ DAMASK_spectral.exe: DAMASK_spectral_driver.o
DAMASK_spectral_driver.o: DAMASK_spectral_driver.f90 \ DAMASK_spectral_driver.o: DAMASK_spectral_driver.f90 \
DAMASK_spectral_solverAL.o \ $(SPECTRAL_SOLVER_FILES)
DAMASK_spectral_solverBasicPETSc.o \
DAMASK_spectral_solverPolarisation.o
$(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c DAMASK_spectral_driver.f90 $(SUFFIX) $(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c DAMASK_spectral_driver.f90 $(SUFFIX)
DAMASK_spectral_solverAL.o: DAMASK_spectral_solverAL.f90 \ DAMASK_spectral_solverAL.o: DAMASK_spectral_solverAL.f90 \
@ -373,18 +392,23 @@ DAMASK_FEM.exe: MESHNAME := ../private/FEM/code/meshFEM.f90
DAMASK_FEM.exe: INTERFACENAME := ../private/FEM/code/DAMASK_FEM_interface.f90 DAMASK_FEM.exe: INTERFACENAME := ../private/FEM/code/DAMASK_FEM_interface.f90
DAMASK_FEM.exe: INCLUDE_DIRS += -I./ DAMASK_FEM.exe: INCLUDE_DIRS += -I./
FEM_SOLVER_FILES = FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyflux.o FEM_porosity.o FEM_hydrogenflux.o
FEM_FILES = prec.o DAMASK_interface.o FEZoo.o IO.o libs.o numerics.o debug.o math.o \ FEM_FILES = prec.o DAMASK_interface.o FEZoo.o IO.o libs.o numerics.o debug.o math.o \
FEsolving.o mesh.o material.o lattice.o \ FEsolving.o mesh.o material.o lattice.o \
$(DAMAGE_FILES) $(THERMAL_FILES) $(VACANCY_FILES) $(PLASTIC_FILES) \ $(SOURCE_FILES) $(KINEMATICS_FILES) $(PLASTIC_FILES) constitutive.o \
crystallite.o $(HOMOGENIZATION_FILES) CPFEM.o \ crystallite.o \
FEM_utilities.o FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyDiffusion.o $(THERMAL_FILES) $(DAMAGE_FILES) $(VACANCYFLUX_FILES) $(HYDROGENFLUX_FILES) $(POROSITY_FILES) \
$(HOMOGENIZATION_FILES) homogenization.o \
CPFEM.o \
FEM_utilities.o $(FEM_SOLVER_FILES)
DAMASK_FEM.exe: DAMASK_FEM_driver.o DAMASK_FEM.exe: DAMASK_FEM_driver.o
$(PREFIX) $(LINKERNAME) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \ $(PREFIX) $(LINKERNAME) $(OPENMP_FLAG_$(F90)) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \
-o DAMASK_FEM.exe DAMASK_FEM_driver.o \ -o DAMASK_FEM.exe DAMASK_FEM_driver.o \
$(FEM_FILES) $(LIBRARIES) $(SUFFIX) $(FEM_FILES) $(LIBRARIES) $(SUFFIX)
DAMASK_FEM_driver.o: DAMASK_FEM_driver.f90 FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyDiffusion.o DAMASK_FEM_driver.o: DAMASK_FEM_driver.f90 $(FEM_SOLVER_FILES)
$(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c ../private/FEM/code/DAMASK_FEM_driver.f90 $(SUFFIX) $(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c ../private/FEM/code/DAMASK_FEM_driver.f90 $(SUFFIX)
FEM_mech.o: FEM_mech.f90 \ FEM_mech.o: FEM_mech.f90 \
@ -396,7 +420,13 @@ FEM_thermal.o: FEM_thermal.f90 \
FEM_damage.o: FEM_damage.f90 \ FEM_damage.o: FEM_damage.f90 \
FEM_utilities.o FEM_utilities.o
FEM_vacancyDiffusion.o: FEM_vacancyDiffusion.f90 \ FEM_vacancyflux.o: FEM_vacancyflux.f90 \
FEM_utilities.o
FEM_porosity.o: FEM_porosity.f90 \
FEM_utilities.o
FEM_hydrogenflux.o: FEM_hydrogenflux.f90 \
FEM_utilities.o FEM_utilities.o
FEM_utilities.o: FEM_utilities.f90 \ FEM_utilities.o: FEM_utilities.f90 \
@ -411,9 +441,54 @@ CPFEM.o: CPFEM.f90\
homogenization.o homogenization.o
homogenization.o: homogenization.f90\ homogenization.o: homogenization.f90\
homogenization_none.o \ $(THERMAL_FILES) \
homogenization_RGC.o \ $(DAMAGE_FILES) \
homogenization_isostrain.o $(VACANCYFLUX_FILES) \
$(POROSITY_FILES) \
$(HYDROGENFLUX_FILES) \
$(HOMOGENIZATION_FILES)
thermal_isothermal.o: thermal_isothermal.f90 \
crystallite.o
thermal_adiabatic.o: thermal_adiabatic.f90 \
crystallite.o
thermal_conduction.o: thermal_conduction.f90 \
crystallite.o
damage_none.o: damage_none.f90 \
crystallite.o
damage_local.o: damage_local.f90 \
crystallite.o
damage_nonlocal.o: damage_nonlocal.f90 \
crystallite.o
thermal_conduction.o: thermal_conduction.f90 \
crystallite.o
vacancyflux_isoconc.o: vacancyflux_isoconc.f90 \
crystallite.o
vacancyflux_isochempot.o: vacancyflux_isochempot.f90 \
crystallite.o
vacancyflux_cahnhilliard.o: vacancyflux_cahnhilliard.f90 \
crystallite.o
porosity_none.o: porosity_none.f90 \
crystallite.o
porosity_phasefield.o: porosity_phasefield.f90 \
crystallite.o
hydrogenflux_isoconc.o: hydrogenflux_isoconc.f90 \
crystallite.o
hydrogenflux_cahnhilliard.o: hydrogenflux_cahnhilliard.f90 \
crystallite.o
homogenization_RGC.o: homogenization_RGC.f90 \ homogenization_RGC.o: homogenization_RGC.f90 \
crystallite.o crystallite.o
@ -428,10 +503,48 @@ crystallite.o: crystallite.f90 \
constitutive.o constitutive.o
constitutive.o: constitutive.f90 \ constitutive.o: constitutive.f90 \
$(PLASTIC_FILES) \ $(SOURCE_FILES) \
$(DAMAGE_FILES) \ $(KINEMATICS_FILES) \
$(THERMAL_FILES) \ $(PLASTIC_FILES)
$(VACANCY_FILES)
source_thermal_dissipation.o: source_thermal_dissipation.f90 \
lattice.o
source_damage_isoBrittle.o: source_damage_isoBrittle.f90 \
lattice.o
source_damage_isoDuctile.o: source_damage_isoDuctile.f90 \
lattice.o
source_damage_anisoBrittle.o: source_damage_anisoBrittle.f90 \
lattice.o
source_damage_anisoDuctile.o: source_damage_anisoDuctile.f90 \
lattice.o
source_vacancy_phenoplasticity.o: source_vacancy_phenoplasticity.f90 \
lattice.o
source_vacancy_irradiation.o: source_vacancy_irradiation.f90 \
lattice.o
source_vacancy_thermalfluc.o: source_vacancy_thermalfluc.f90 \
lattice.o
kinematics_cleavage_opening.o: kinematics_cleavage_opening.f90 \
lattice.o
kinematics_slipplane_opening.o: kinematics_slipplane_opening.f90 \
lattice.o
kinematics_thermal_expansion.o: kinematics_thermal_expansion.f90 \
lattice.o
kinematics_vacancy_strain.o: kinematics_vacancy_strain.f90 \
lattice.o
kinematics_hydrogen_strain.o: kinematics_hydrogen_strain.f90 \
lattice.o
plastic_nonlocal.o: plastic_nonlocal.f90 \ plastic_nonlocal.o: plastic_nonlocal.f90 \
lattice.o lattice.o
@ -457,39 +570,6 @@ plastic_j2.o: plastic_j2.f90 \
plastic_none.o: plastic_none.f90 \ plastic_none.o: plastic_none.f90 \
lattice.o lattice.o
damage_none.o: damage_none.f90 \
lattice.o
damage_isoBrittle.o: damage_isoBrittle.f90 \
lattice.o
damage_isoDuctile.o: damage_isoDuctile.f90 \
lattice.o
damage_anisoBrittle.o: damage_anisoBrittle.f90 \
lattice.o
damage_anisoDuctile.o: damage_anisoDuctile.f90 \
lattice.o
damage_phaseField.o: damage_phaseField.f90 \
lattice.o
damage_gurson.o: damage_gurson.f90 \
lattice.o
thermal_isothermal.o: thermal_isothermal.f90 \
lattice.o
thermal_adiabatic.o: thermal_adiabatic.f90 \
lattice.o
vacancy_constant.o: vacancy_constant.f90 \
lattice.o
vacancy_generation.o: vacancy_generation.f90 \
lattice.o
lattice.o: lattice.f90 \ lattice.o: lattice.f90 \
material.o material.o

View File

@ -1,5 +1,5 @@
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! $Id: libs.f90 3413 2014-08-24 22:07:53Z MPIE\m.diehl $ ! $Id$
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
!> @brief all DAMASK files without solver !> @brief all DAMASK files without solver
@ -14,17 +14,19 @@
#include "mesh.f90" #include "mesh.f90"
#include "material.f90" #include "material.f90"
#include "lattice.f90" #include "lattice.f90"
#include "damage_none.f90" #include "source_thermal_dissipation.f90"
#include "damage_isoBrittle.f90" #include "source_damage_isoBrittle.f90"
#include "damage_isoDuctile.f90" #include "source_damage_isoDuctile.f90"
#include "damage_anisoBrittle.f90" #include "source_damage_anisoBrittle.f90"
#include "damage_anisoDuctile.f90" #include "source_damage_anisoDuctile.f90"
#include "damage_gurson.f90" #include "source_vacancy_phenoplasticity.f90"
#include "damage_phaseField.f90" #include "source_vacancy_irradiation.f90"
#include "thermal_isothermal.f90" #include "source_vacancy_thermalfluc.f90"
#include "thermal_adiabatic.f90" #include "kinematics_cleavage_opening.f90"
#include "vacancy_constant.f90" #include "kinematics_slipplane_opening.f90"
#include "vacancy_generation.f90" #include "kinematics_thermal_expansion.f90"
#include "kinematics_vacancy_strain.f90"
#include "kinematics_hydrogen_strain.f90"
#include "plastic_none.f90" #include "plastic_none.f90"
#include "plastic_j2.f90" #include "plastic_j2.f90"
#include "plastic_phenopowerlaw.f90" #include "plastic_phenopowerlaw.f90"
@ -38,5 +40,18 @@
#include "homogenization_none.f90" #include "homogenization_none.f90"
#include "homogenization_isostrain.f90" #include "homogenization_isostrain.f90"
#include "homogenization_RGC.f90" #include "homogenization_RGC.f90"
#include "thermal_isothermal.f90"
#include "thermal_adiabatic.f90"
#include "thermal_conduction.f90"
#include "damage_none.f90"
#include "damage_local.f90"
#include "damage_nonlocal.f90"
#include "vacancyflux_isoconc.f90"
#include "vacancyflux_isochempot.f90"
#include "vacancyflux_cahnhilliard.f90"
#include "porosity_none.f90"
#include "porosity_phasefield.f90"
#include "hydrogenflux_isoconc.f90"
#include "hydrogenflux_cahnhilliard.f90"
#include "homogenization.f90" #include "homogenization.f90"
#include "CPFEM.f90" #include "CPFEM.f90"

View File

@ -0,0 +1,3 @@
### $Id$ ###
damage nonlocal
(output) damage

View File

@ -0,0 +1,3 @@
### $Id$ ###
hydrogenflux cahnhilliard
(output) hydrogenconc

View File

@ -0,0 +1,3 @@
### $Id$ ###
porosity phasefield
(output) porosity

View File

@ -0,0 +1,3 @@
### $Id$ ###
thermal conduction
(output) temperature

View File

@ -0,0 +1,3 @@
### $Id$ ###
vacancyflux cahnhilliard
(output) vacancyconc

View File

@ -0,0 +1,9 @@
### $Id$ ###
[SX]
type isostrain
Ngrains 1
{./Homogenization_Damage_NonLocal.config}
{./Homogenization_Thermal_Conduction.config}
{./Homogenization_VacancyFlux_CahnHilliard.config}
{./Homogenization_Porosity_PhaseField.config}
{./Homogenization_HydrogenFlux_CahnHilliard.config}

View File

@ -0,0 +1,3 @@
### $Id$ ###
(kinematics) vacancy_strain
vacancy_strain_coeff 0.006

View File

@ -0,0 +1,3 @@
### $Id$ ###
(kinematics) thermal_expansion
thermal_expansion_coeff 0.00231

View File

@ -0,0 +1,3 @@
### $Id$ ###
(kinematics) hydrogen_strain
hydrogen_strain_coeff 0.06

View File

@ -0,0 +1,3 @@
### $Id$ ###
damage_diffusion11 1.0
damage_mobility 0.001

View File

@ -0,0 +1,4 @@
### $Id$ ###
hydrogenflux_diffusion11 1.0
hydrogenflux_mobility11 1.0
hydrogenVolume 1e-28

View File

@ -0,0 +1,62 @@
### $Id$ ###
[Aluminum]
elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
(output) shearrate_slip
(output) resolvedstress_slip
(output) accumulated_shear_slip
(output) totalshear
(output) resistance_twin
(output) shearrate_twin
(output) resolvedstress_twin
(output) accumulated_shear_twin
(output) totalvolfrac_twin
lattice_structure fcc
Nslip 12 # per family
Ntwin 0 # per family
c11 106.75e9
c12 60.41e9
c44 28.34e9
gdot0_slip 0.001
n_slip 20
tau0_slip 31e6 # per family
tausat_slip 63e6 # per family
a_slip 2.25
gdot0_twin 0.001
n_twin 20
tau0_twin 31e6 # per family
s_pr 0 # push-up factor for slip saturation due to twinning
twin_b 0
twin_c 0
twin_d 0
twin_e 0
h0_slipslip 75e6
h0_twinslip 0
h0_twintwin 0
interaction_slipslip 1 1 1.4 1.4 1.4 1.4
interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
atol_resistance 1
(stiffness_degradation) damage
(stiffness_degradation) porosity
{./Phase_Damage.config}
{./Phase_Thermal.config}
{./Phase_Vacancy.config}
{./Phase_Porosity.config}
{./Phase_Hydrogen.config}
{./Source_Damage_IsoBrittle.config}
{./Source_Thermal_Dissipation.config}
{./Source_Vacancy_PhenoPlasticity.config}
{./Source_Vacancy_Irradiation.config}
{./Kinematics_Thermal_Expansion.config}
{./Kinematics_Vacancy_Strain.config}
{./Kinematics_Hydrogen_Strain.config}

View File

@ -0,0 +1,3 @@
### $Id$ ###
porosity_diffusion11 1.0
porosity_mobility 0.001

View File

@ -0,0 +1,5 @@
### $Id$ ###
thermal_conductivity11 237.0
specific_heat 910.0
mass_density 2700.0
reference_temperature 300.0

View File

@ -0,0 +1,6 @@
### $Id$ ###
vacancyflux_diffusion11 1.0
vacancyflux_mobility11 1.0
vacancyFormationEnergy 1e-19
voidSurfaceEnergy 1e+10
vacancyVolume 1e-28

View File

@ -0,0 +1,5 @@
### $Id$ ###
(source) damage_isoBrittle
isobrittle_criticalStrainEnergy 1400000.0
isobrittle_atol 0.01
(output) isoBrittle_DrivingForce

View File

@ -0,0 +1,3 @@
### $Id$ ###
(source) thermal_dissipation
dissipation_ColdWorkCoeff 0.95

View File

@ -0,0 +1,4 @@
### $Id$ ###
(source) vacancy_irradiation
irradiation_cascadeprobability 0.00001
irradiation_cascadevolume 1000.0

View File

@ -0,0 +1,3 @@
### $Id$ ###
(source) vacancy_phenoplasticity
phenoplasticity_ratecoeff 0.01

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,635 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @brief material subroutine incorporating anisotropic ductile damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_anisoBrittle
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_anisoBrittle_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_anisoBrittle_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_anisoBrittle_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_anisoBrittle_Noutput !< number of outputs per instance of this damage
integer(pInt), dimension(:), allocatable, private :: &
damage_anisoBrittle_totalNcleavage !< total number of cleavage systems
integer(pInt), dimension(:,:), allocatable, private :: &
damage_anisoBrittle_Ncleavage !< number of cleavage systems per family
real(pReal), dimension(:), allocatable, private :: &
damage_anisoBrittle_aTol_damage, &
damage_anisoBrittle_aTol_disp, &
damage_anisoBrittle_sdot_0, &
damage_anisoBrittle_N
real(pReal), dimension(:,:), allocatable, private :: &
damage_anisoBrittle_critDisp, &
damage_anisoBrittle_critLoad
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_anisoBrittle_outputID !< ID of each post result output
public :: &
damage_anisoBrittle_init, &
damage_anisoBrittle_stateInit, &
damage_anisoBrittle_aTolState, &
damage_anisoBrittle_microstructure, &
damage_anisoBrittle_LdAndItsTangent, &
damage_anisoBrittle_getDamage, &
damage_anisoBrittle_putLocalDamage, &
damage_anisoBrittle_getLocalDamage, &
damage_anisoBrittle_getDamageDiffusion33, &
damage_anisoBrittle_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_damage_anisoBrittle_label, &
LOCAL_damage_anisoBrittle_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
use lattice, only: &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_anisoBrittle_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_damage_anisoBrittle_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_anisoBrittle_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_anisoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt)
allocate(damage_anisoBrittle_output(maxval(phase_Noutput),maxNinstance))
damage_anisoBrittle_output = ''
allocate(damage_anisoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_anisoBrittle_Noutput(maxNinstance), source=0_pInt)
allocate(damage_anisoBrittle_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(damage_anisoBrittle_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(damage_anisoBrittle_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt)
allocate(damage_anisoBrittle_totalNcleavage(maxNinstance), source=0_pInt)
allocate(damage_anisoBrittle_aTol_damage(maxNinstance), source=0.0_pReal)
allocate(damage_anisoBrittle_aTol_disp(maxNinstance), source=0.0_pReal)
allocate(damage_anisoBrittle_sdot_0(maxNinstance), source=0.0_pReal)
allocate(damage_anisoBrittle_N(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_anisoBrittle_Noutput(instance) = damage_anisoBrittle_Noutput(instance) + 1_pInt
damage_anisoBrittle_outputID(damage_anisoBrittle_Noutput(instance),instance) = local_damage_ID
damage_anisoBrittle_output(damage_anisoBrittle_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('atol_damage')
damage_anisoBrittle_aTol_damage(instance) = IO_floatValue(line,positions,2_pInt)
case ('atol_disp')
damage_anisoBrittle_aTol_disp(instance) = IO_floatValue(line,positions,2_pInt)
case ('sdot0')
damage_anisoBrittle_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('damageratesensitivity')
damage_anisoBrittle_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('ncleavage') !
Nchunks_CleavageFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_CleavageFamilies
damage_anisoBrittle_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('criticaldisplacement')
do j = 1_pInt, Nchunks_CleavageFamilies
damage_anisoBrittle_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('criticalload')
do j = 1_pInt, Nchunks_CleavageFamilies
damage_anisoBrittle_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
sanityChecks: do phase = 1_pInt, size(phase_damage)
myPhase: if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
! sanity checks
damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance) = &
min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested
damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance))
damage_anisoBrittle_totalNcleavage(instance) = sum(damage_anisoBrittle_Ncleavage(:,instance)) ! how many cleavage systems altogether
if (damage_anisoBrittle_aTol_damage(instance) < 0.0_pReal) &
damage_anisoBrittle_aTol_damage(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_anisoBrittle_aTol_disp(instance) >= 1.0e-3_pReal) &
damage_anisoBrittle_aTol_disp(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_anisoBrittle_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')')
if (any(damage_anisoBrittle_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')')
if (any(damage_anisoBrittle_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')')
if (damage_anisoBrittle_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity_damage ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_anisoBrittle_Noutput(instance)
select case(damage_anisoBrittle_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_anisoBrittle_sizePostResult(o,instance) = mySize
damage_anisoBrittle_sizePostResults(instance) = damage_anisoBrittle_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = sizeDotState + &
1_pInt + & ! non-local damage
1_pInt ! opening on each damage system
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_anisoBrittle_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_anisoBrittle_stateInit(phase,instance)
call damage_anisoBrittle_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_anisoBrittle_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_stateInit(phase,instance)
use material, only: &
damageState
use math, only: &
math_I3
implicit none
integer(pInt), intent(in) :: phase, instance !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState(1) = 1.0_pReal
tempState(2) = 1.0_pReal
damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:)))
end subroutine damage_anisoBrittle_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol(1) = damage_anisoBrittle_aTol_damage(instance)
tempTol(2) = damage_anisoBrittle_aTol_disp (instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_anisoBrittle_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_microstructure(Tstar_v, subdt, ipc, ip, el)
use numerics, only: &
residualStiffness
use material, only: &
mappingConstitutive, &
phase_damageInstance, &
damageState
use lattice, only: &
lattice_DamageMobility, &
lattice_Scleavage_v, &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel)
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, &
constituent, &
instance, &
f, i, index_myFamily
real(pReal) :: &
localDamage
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
damageState(phase)%state(2,constituent) = damageState(phase)%subState0(2,constituent)
do f = 1_pInt,lattice_maxNcleavageFamily
index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family
traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase))
traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase))
traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase))
traction_crit = damage_anisoBrittle_critLoad(f,instance)* &
damage_anisoBrittle_getDamage(ipc, ip, el)
damageState(phase)%state(2,constituent) = &
damageState(phase)%state(2,constituent) + &
subdt*damage_anisoBrittle_sdot_0(instance)* &
((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) + &
(max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) + &
(max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance))/ &
damage_anisoBrittle_critDisp(f,instance)
enddo
enddo
localDamage = max(residualStiffness,1.0_pReal/damageState(phase)%state(2,constituent))
damageState(phase)%state(1,constituent) = &
localDamage + &
(damageState(phase)%subState0(1,constituent) - localDamage)* &
exp(-subdt/lattice_DamageMobility(phase))
end subroutine damage_anisoBrittle_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_LdAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el)
use prec, only: &
tol_math_check
use material, only: &
mappingConstitutive, &
phase_damageInstance
use math, only: &
math_Plain3333to99
use lattice, only: &
lattice_Scleavage, &
lattice_Scleavage_v, &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(out), dimension(3,3) :: &
Ld !< damage velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
constituent, &
instance, &
f, i, index_myFamily, k, l, m, n
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit, &
udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
Ld = 0.0_pReal
dLd_dTstar3333 = 0.0_pReal
do f = 1_pInt,lattice_maxNcleavageFamily
index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family
traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase))
traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase))
traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase))
traction_crit = damage_anisoBrittle_critLoad(f,instance)* &
damage_anisoBrittle_getDamage(ipc, ip, el)
udotd = &
sign(1.0_pReal,traction_d)* &
damage_anisoBrittle_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance)
if (abs(udotd) > tol_math_check) then
Ld = Ld + udotd*lattice_Scleavage(1:3,1:3,1,index_myFamily+i,phase)
dudotd_dt = sign(1.0_pReal,traction_d)*udotd*damage_anisoBrittle_N(instance)/ &
max(0.0_pReal, abs(traction_d) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotd_dt*lattice_Scleavage(k,l,1,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,1,index_myFamily+i,phase)
endif
udott = &
sign(1.0_pReal,traction_t)* &
damage_anisoBrittle_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance)
if (abs(udott) > tol_math_check) then
Ld = Ld + udott*lattice_Scleavage(1:3,1:3,2,index_myFamily+i,phase)
dudott_dt = sign(1.0_pReal,traction_t)*udott*damage_anisoBrittle_N(instance)/ &
max(0.0_pReal, abs(traction_t) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudott_dt*lattice_Scleavage(k,l,2,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,2,index_myFamily+i,phase)
endif
udotn = &
sign(1.0_pReal,traction_n)* &
damage_anisoBrittle_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance)
if (abs(udotn) > tol_math_check) then
Ld = Ld + udotn*lattice_Scleavage(1:3,1:3,3,index_myFamily+i,phase)
dudotn_dt = sign(1.0_pReal,traction_n)*udotn*damage_anisoBrittle_N(instance)/ &
max(0.0_pReal, abs(traction_n) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotn_dt*lattice_Scleavage(k,l,3,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,3,index_myFamily+i,phase)
endif
enddo
enddo
end subroutine damage_anisoBrittle_LdAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
pure function damage_anisoBrittle_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
mappingConstitutive, &
damageState, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_LOCAL_ID, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_anisoBrittle_getDamage
select case(field_damage_type(material_homog(ip,el)))
case default
damage_anisoBrittle_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% &
state(1,mappingConstitutive(1,ipc,ip,el))
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_anisoBrittle_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function damage_anisoBrittle_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns damage value based on local damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoBrittle_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_anisoBrittle_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
pure function damage_anisoBrittle_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: &
damage_anisoBrittle_getLocalDamage
damage_anisoBrittle_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_anisoBrittle_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns brittle damage diffusion tensor
!--------------------------------------------------------------------------------------------------
pure function damage_anisoBrittle_getDamageDiffusion33(ipc, ip, el)
use lattice, only: &
lattice_DamageDiffusion33
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
damage_anisoBrittle_getDamageDiffusion33
integer(pInt) :: &
phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage_anisoBrittle_getDamageDiffusion33 = &
lattice_DamageDiffusion33(1:3,1:3,phase)
end function damage_anisoBrittle_getDamageDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_anisoBrittle_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_damageInstance
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_anisoBrittle_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_anisoBrittle_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_anisoBrittle_postResults = 0.0_pReal
do o = 1_pInt,damage_anisoBrittle_Noutput(instance)
select case(damage_anisoBrittle_outputID(o,instance))
case (local_damage_ID)
damage_anisoBrittle_postResults(c+1_pInt) = &
damage_anisoBrittle_getLocalDamage(ipc, ip, el)
c = c + 1_pInt
end select
enddo
end function damage_anisoBrittle_postResults
end module damage_anisoBrittle

View File

@ -1,608 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating anisotropic ductile damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_anisoDuctile
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_anisoDuctile_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_anisoDuctile_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_anisoDuctile_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_anisoDuctile_Noutput !< number of outputs per instance of this damage
integer(pInt), dimension(:), allocatable, private :: &
damage_anisoDuctile_totalNslip !< total number of slip systems
integer(pInt), dimension(:,:), allocatable, private :: &
damage_anisoDuctile_Nslip !< number of slip systems per family
real(pReal), dimension(:), allocatable, private :: &
damage_anisoDuctile_aTol_damage
real(pReal), dimension(:,:), allocatable, private :: &
damage_anisoDuctile_critPlasticStrain
real(pReal), dimension(:), allocatable, private :: &
damage_anisoDuctile_sdot_0, &
damage_anisoDuctile_N
real(pReal), dimension(:,:), allocatable, private :: &
damage_anisoDuctile_critLoad
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_anisoDuctile_outputID !< ID of each post result output
public :: &
damage_anisoDuctile_init, &
damage_anisoDuctile_stateInit, &
damage_anisoDuctile_aTolState, &
damage_anisoDuctile_microstructure, &
damage_anisoDuctile_LdAndItsTangent, &
damage_anisoDuctile_getDamage, &
damage_anisoDuctile_putLocalDamage, &
damage_anisoDuctile_getLocalDamage, &
damage_anisoDuctile_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_damage_anisoDuctile_label, &
LOCAL_damage_anisoDuctile_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
use lattice, only: &
lattice_maxNslipFamily, &
lattice_NslipSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_anisoDuctile_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_damage_anisoDuctile_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_anisoDuctile_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_anisoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(damage_anisoDuctile_output(maxval(phase_Noutput),maxNinstance))
damage_anisoDuctile_output = ''
allocate(damage_anisoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_anisoDuctile_Noutput(maxNinstance), source=0_pInt)
allocate(damage_anisoDuctile_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal)
allocate(damage_anisoDuctile_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal)
allocate(damage_anisoDuctile_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt)
allocate(damage_anisoDuctile_totalNslip(maxNinstance), source=0_pInt)
allocate(damage_anisoDuctile_N(maxNinstance), source=0.0_pReal)
allocate(damage_anisoDuctile_sdot_0(maxNinstance), source=0.0_pReal)
allocate(damage_anisoDuctile_aTol_damage(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_anisoDuctile_Noutput(instance) = damage_anisoDuctile_Noutput(instance) + 1_pInt
damage_anisoDuctile_outputID(damage_anisoDuctile_Noutput(instance),instance) = local_damage_ID
damage_anisoDuctile_output(damage_anisoDuctile_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('atol_damage')
damage_anisoDuctile_aTol_damage(instance) = IO_floatValue(line,positions,2_pInt)
case ('nslip') !
Nchunks_SlipFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_SlipFamilies
damage_anisoDuctile_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('sdot0')
damage_anisoDuctile_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('criticalplasticstrain')
do j = 1_pInt, Nchunks_SlipFamilies
damage_anisoDuctile_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('damageratesensitivity')
damage_anisoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('criticalload')
do j = 1_pInt, Nchunks_SlipFamilies
damage_anisoDuctile_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
sanityChecks: do phase = 1_pInt, size(phase_damage)
myPhase: if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
! sanity checks
damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance) = &
min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested
damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance))
damage_anisoDuctile_totalNslip(instance) = sum(damage_anisoDuctile_Nslip(:,instance))
if (damage_anisoDuctile_aTol_damage(instance) < 0.0_pReal) &
damage_anisoDuctile_aTol_damage(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_anisoDuctile_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')')
if (any(damage_anisoDuctile_critPlasticStrain(:,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')')
if (damage_anisoDuctile_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity_damage ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_anisoDuctile_Noutput(instance)
select case(damage_anisoDuctile_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_anisoDuctile_sizePostResult(o,instance) = mySize
damage_anisoDuctile_sizePostResults(instance) = damage_anisoDuctile_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = sizeDotState + &
1_pInt + & ! time regularised damage
1_pInt ! damaged plasticity
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_anisoDuctile_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_anisoDuctile_stateInit(phase,instance)
call damage_anisoDuctile_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_anisoDuctile_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_stateInit(phase, instance)
use material, only: &
damageState
use math, only: &
math_I3
implicit none
integer(pInt), intent(in) :: phase , instance !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState(1) = 1.0_pReal
tempState(2) = 0.0_pReal
damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:)))
end subroutine damage_anisoDuctile_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol = damage_anisoDuctile_aTol_damage(instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_anisoDuctile_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_microstructure(subdt, ipc, ip, el)
use numerics, only: &
residualStiffness
use material, only: &
mappingConstitutive, &
phase_damageInstance, &
plasticState, &
damageState
use lattice, only: &
lattice_maxNslipFamily, &
lattice_DamageMobility
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, &
constituent, &
instance, &
index, f, i
real(pReal) :: &
localDamage
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
index = 1_pInt
damageState(phase)%state(2,constituent) = damageState(phase)%subState0(2,constituent)
do f = 1_pInt,lattice_maxNslipFamily
do i = 1_pInt,damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family
damageState(phase)%state(2,constituent) = &
damageState(phase)%state(2,constituent) + &
subdt* &
plasticState(phase)%slipRate(index,constituent)/ &
(damage_anisoDuctile_getDamage(ipc, ip, el)**damage_anisoDuctile_N(instance))/ &
damage_anisoDuctile_critPlasticStrain(f,instance)
index = index + 1_pInt
enddo
enddo
localDamage = &
max(residualStiffness,min(1.0_pReal,1.0_pReal/damageState(phase)%state(2,constituent)))
damageState(phase)%state(1,constituent) = &
localDamage + &
(damageState(phase)%subState0(1,constituent) - localDamage)* &
exp(-subdt/lattice_DamageMobility(phase))
end subroutine damage_anisoDuctile_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_LdAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el)
use prec, only: &
tol_math_check
use lattice, only: &
lattice_maxNslipFamily, &
lattice_NslipSystem, &
lattice_sd, &
lattice_st, &
lattice_sn
use material, only: &
mappingConstitutive, &
phase_damageInstance
use math, only: &
math_Plain3333to99, &
math_I3, &
math_identity4th, &
math_symmetric33, &
math_Mandel33to6, &
math_tensorproduct, &
math_det33, &
math_mul33x33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(out), dimension(3,3) :: &
Ld !< damage velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor)
real(pReal), dimension(3,3) :: &
projection_d, projection_t, projection_n !< projection modes 3x3 tensor
real(pReal), dimension(6) :: &
projection_d_v, projection_t_v, projection_n_v !< projection modes 3x3 vector
integer(pInt) :: &
phase, &
constituent, &
instance, &
f, i, index_myFamily, k, l, m, n
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit, &
udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
Ld = 0.0_pReal
dLd_dTstar3333 = 0.0_pReal
do f = 1_pInt,lattice_maxNslipFamily
index_myFamily = sum(lattice_NslipSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family
projection_d = math_tensorproduct(lattice_sd(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_t = math_tensorproduct(lattice_st(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_n = math_tensorproduct(lattice_sn(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_d_v(1:6) = math_Mandel33to6(math_symmetric33(projection_d(1:3,1:3)))
projection_t_v(1:6) = math_Mandel33to6(math_symmetric33(projection_t(1:3,1:3)))
projection_n_v(1:6) = math_Mandel33to6(math_symmetric33(projection_n(1:3,1:3)))
traction_d = dot_product(Tstar_v,projection_d_v(1:6))
traction_t = dot_product(Tstar_v,projection_t_v(1:6))
traction_n = dot_product(Tstar_v,projection_n_v(1:6))
traction_crit = damage_anisoDuctile_critLoad(f,instance)* &
damage_anisoDuctile_getDamage(ipc, ip, el) ! degrading critical load carrying capacity by damage
udotd = &
sign(1.0_pReal,traction_d)* &
damage_anisoDuctile_sdot_0(instance)* &
(abs(traction_d)/traction_crit - &
abs(traction_d)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance)
if (abs(udotd) > tol_math_check) then
Ld = Ld + udotd*projection_d
dudotd_dt = udotd*damage_anisoDuctile_N(instance)/traction_d
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotd_dt*projection_d(k,l)*projection_d(m,n)
endif
udott = &
sign(1.0_pReal,traction_t)* &
damage_anisoDuctile_sdot_0(instance)* &
(abs(traction_t)/traction_crit - &
abs(traction_t)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance)
if (abs(udott) > tol_math_check) then
Ld = Ld + udott*projection_t
dudott_dt = udott*damage_anisoDuctile_N(instance)/traction_t
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudott_dt*projection_t(k,l)*projection_t(m,n)
endif
udotn = &
damage_anisoDuctile_sdot_0(instance)* &
(max(0.0_pReal,traction_n)/traction_crit - &
max(0.0_pReal,traction_n)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance)
if (abs(udotn) > tol_math_check) then
Ld = Ld + udotn*projection_n
dudotn_dt = udotn*damage_anisoDuctile_N(instance)/traction_n
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotn_dt*projection_n(k,l)*projection_n(m,n)
endif
enddo
enddo
end subroutine damage_anisoDuctile_LdAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
pure function damage_anisoDuctile_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
mappingConstitutive, &
damageState, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_LOCAL_ID, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_anisoDuctile_getDamage
select case(field_damage_type(material_homog(ip,el)))
case default
damage_anisoDuctile_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% &
state(1,mappingConstitutive(1,ipc,ip,el))
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_anisoDuctile_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function damage_anisoDuctile_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns damage value based on local damage
!--------------------------------------------------------------------------------------------------
subroutine damage_anisoDuctile_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_anisoDuctile_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
pure function damage_anisoDuctile_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: &
damage_anisoDuctile_getLocalDamage
damage_anisoDuctile_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_anisoDuctile_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_anisoDuctile_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_damageInstance
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_anisoDuctile_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_anisoDuctile_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_anisoDuctile_postResults = 0.0_pReal
do o = 1_pInt,damage_anisoDuctile_Noutput(instance)
select case(damage_anisoDuctile_outputID(o,instance))
case (local_damage_ID)
damage_anisoDuctile_postResults(c+1_pInt) = &
damage_anisoDuctile_getLocalDamage(ipc, ip, el)
c = c + 1_pInt
end select
enddo
end function damage_anisoDuctile_postResults
end module damage_anisoDuctile

View File

@ -1,503 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incoprorating gurson damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_gurson
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_gurson_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_gurson_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_gurson_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_gurson_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
damage_gurson_aTol, &
damage_gurson_coeff_torsion, &
damage_gurson_coeff_ten_comp, &
damage_gurson_coeff_triaxiality, &
damage_gurson_fracture_tough, &
damage_gurson_lengthscale, &
damage_gurson_crit_void_fraction
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum !!!!! ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_gurson_outputID !< ID of each post result output
public :: &
damage_gurson_init, &
damage_gurson_stateInit, &
damage_gurson_aTolState, &
damage_gurson_dotState, &
damage_gurson_microstructure, &
damage_gurson_getDamage, &
damage_gurson_getSlipDamage, &
damage_gurson_putLocalDamage, &
damage_gurson_getLocalDamage, &
damage_gurson_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_DAMAGE_gurson_label, &
LOCAL_DAMAGE_gurson_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_DAMAGE_gurson_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_DAMAGE_gurson_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_gurson_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_gurson_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(damage_gurson_output(maxval(phase_Noutput),maxNinstance))
damage_gurson_output = ''
allocate(damage_gurson_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_gurson_Noutput(maxNinstance), source=0_pInt)
allocate(damage_gurson_coeff_torsion(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_coeff_ten_comp(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_coeff_triaxiality(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_fracture_tough(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_lengthscale(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_crit_void_fraction(maxNinstance), source=0.0_pReal)
allocate(damage_gurson_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_gurson_Noutput(instance) = damage_gurson_Noutput(instance) + 1_pInt
damage_gurson_outputID(damage_gurson_Noutput(instance),instance) = local_damage_ID
damage_gurson_output(damage_gurson_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
! input parameters
case ('coeff_torsion')
damage_gurson_coeff_torsion(instance) = IO_floatValue(line,positions,2_pInt) !> coefficent of torsional stress component
case ('coeff_tension_comp')
damage_gurson_coeff_ten_comp(instance) = IO_floatValue(line,positions,2_pInt) !> coefficent of tensile or compressive stress component
case ('coeff_triaxiality')
damage_gurson_coeff_triaxiality(instance) = IO_floatValue(line,positions,2_pInt)
case ('fracture_toughness')
damage_gurson_fracture_tough(instance) = IO_floatValue(line,positions,2_pInt)
case ('lengthscale')
damage_gurson_lengthscale(instance) = IO_floatValue(line,positions,2_pInt)
case ('critical_voidFraction')
damage_gurson_crit_void_fraction(instance) = IO_floatValue(line,positions,2_pInt)
case ('atol_damage')
damage_gurson_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_gurson_Noutput(instance)
select case(damage_gurson_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_gurson_sizePostResult(o,instance) = mySize
damage_gurson_sizePostResults(instance) = damage_gurson_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 3_pInt
sizeState = 4_pInt
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_gurson_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_gurson_stateInit(phase)
call damage_gurson_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_gurson_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant NEW state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_stateInit(phase)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState(1) = 1.0_pReal
tempState(2) = 1.0_pReal
tempState(3) = 1.0_pReal
tempState(4) = 1.0_pReal
damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:)))
damageState(phase)%state0 = damageState(phase)%state
damageState(phase)%partionedState0 = damageState(phase)%state
end subroutine damage_gurson_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol = damage_gurson_aTol(instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_gurson_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_dotState(Tstar_v, Lp, ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
use math, only: &
math_equivStrain33, &
math_norm33, &
math_j3_33, &
math_trace33, &
math_I3, &
math_Mandel6to33
use lattice, only: &
lattice_DamageMobility
implicit none
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel)
real(pReal), intent(in), dimension(3,3) :: &
Lp
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
integer(pInt) :: &
phase, constituent
real(pReal) :: &
i1, j2, j3
real(pReal) , dimension(3,3) :: &
Tstar_dev
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
Tstar_dev = math_Mandel6to33(Tstar_v) - math_trace33(math_Mandel6to33(Tstar_v))/3.0_pReal*math_I3
i1 = sum(Tstar_v(1:3))
j2 = 0.5_pReal*(math_norm33(Tstar_dev))**2.0_pReal
j3 = math_j3_33(math_Mandel6to33(Tstar_v))
damageState(phase)%dotState(1,constituent) = &
(1.0_pReal/lattice_DamageMobility(phase))* &
(damageState(phase)%state(4,constituent) - &
damageState(phase)%state(1,constituent))
damageState(phase)%dotState(2,constituent) = & !> void nucleation rate
math_norm33(Lp)*sqrt(damage_gurson_lengthscale(phase))/damage_gurson_fracture_tough(phase)* &
damageState(phase)%state(2,constituent) * ( &
damage_gurson_coeff_torsion(phase) * ((4_pReal/27_pReal) - (j3**(2)/j2**(3))) + &
damage_gurson_coeff_ten_comp(phase) * (j3/j2**(1.5_pReal)) + &
damage_gurson_coeff_triaxiality(phase) * abs(i1/sqrt(j2))) !> to be coupled with vacancy generation
damageState(phase)%dotState(3,constituent) = &
( damageState(phase)%state(4,constituent)) * math_trace33(Lp) !> void growth rate
end subroutine damage_gurson_dotState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_microstructure(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
use math, only: &
math_Mandel6to33, &
math_mul33x33, &
math_norm33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal) :: &
voidFraction
integer(pInt) :: &
phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
voidFraction = damageState(phase)%state(2,constituent) + damageState(phase)%state(3,constituent)
if(voidFraction < damage_gurson_crit_void_fraction(phase)) then
damageState(phase)%state(4,constituent) = 1.0_pReal - voidFraction ! damage parameter is 1 when no void present
else
damageState(phase)%state(4,constituent) = 1.0_pReal - damage_gurson_crit_void_fraction(phase) + &
5.0_pReal * (voidFraction - damage_gurson_crit_void_fraction(phase)) ! this accelerated void increase models the effect of void coalescence
endif
end subroutine damage_gurson_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
function damage_gurson_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_LOCAL_ID, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_gurson_getDamage
select case(field_damage_type(material_homog(ip,el)))
case (FIELD_DAMAGE_LOCAL_ID)
damage_gurson_getDamage = damage_gurson_getLocalDamage(ipc, ip, el)
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_gurson_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function damage_gurson_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns slip damage
!--------------------------------------------------------------------------------------------------
function damage_gurson_getSlipDamage(Tstar_v, ipc, ip, el)
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(6), intent(in) :: &
Tstar_v !< 2nd Piola Kirchhoff stress tensor in Mandel notation
real(pReal) :: damage_gurson_getSlipDamage, porosity
porosity = damage_gurson_getDamage(ipc, ip, el)
damage_gurson_getSlipDamage = porosity*porosity ! Gurson yield function should go here
end function damage_gurson_getSlipDamage
!--------------------------------------------------------------------------------------------------
!> @brief puts local damage
!--------------------------------------------------------------------------------------------------
subroutine damage_gurson_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_gurson_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
function damage_gurson_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_gurson_getLocalDamage
damage_gurson_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_gurson_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_gurson_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_damageInstance,&
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_gurson_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_gurson_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_gurson_postResults = 0.0_pReal
do o = 1_pInt,damage_gurson_Noutput(instance)
select case(damage_gurson_outputID(o,instance))
case (local_damage_ID)
damage_gurson_postResults(c+1_pInt) = damageState(phase)%state(1,constituent)
c = c + 1
end select
enddo
end function damage_gurson_postResults
end module damage_gurson

View File

@ -1,484 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incoprorating isotropic brittle damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_isoBrittle
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_isoBrittle_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_isoBrittle_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_isoBrittle_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_isoBrittle_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
damage_isoBrittle_aTol, &
damage_isoBrittle_critStrainEnergy
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_isoBrittle_outputID !< ID of each post result output
public :: &
damage_isoBrittle_init, &
damage_isoBrittle_stateInit, &
damage_isoBrittle_aTolState, &
damage_isoBrittle_microstructure, &
damage_isoBrittle_getDamage, &
damage_isoBrittle_putLocalDamage, &
damage_isoBrittle_getLocalDamage, &
damage_isoBrittle_getDamageDiffusion33, &
damage_isoBrittle_getDamagedC66, &
damage_isoBrittle_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_isoBrittle_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_damage_isoBrittle_label, &
LOCAL_damage_isoBrittle_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_isoBrittle_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_damage_isoBrittle_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_isoBrittle_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_isoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(damage_isoBrittle_output(maxval(phase_Noutput),maxNinstance))
damage_isoBrittle_output = ''
allocate(damage_isoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_isoBrittle_Noutput(maxNinstance), source=0_pInt)
allocate(damage_isoBrittle_critStrainEnergy(maxNinstance), source=0.0_pReal)
allocate(damage_isoBrittle_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_isoBrittle_Noutput(instance) = damage_isoBrittle_Noutput(instance) + 1_pInt
damage_isoBrittle_outputID(damage_isoBrittle_Noutput(instance),instance) = local_damage_ID
damage_isoBrittle_output(damage_isoBrittle_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('criticalstrainenergy')
damage_isoBrittle_critStrainEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('atol_damage')
damage_isoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
sanityChecks: do phase = 1_pInt, size(phase_damage)
myPhase: if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
! sanity checks
if (damage_isoBrittle_aTol(instance) < 0.0_pReal) &
damage_isoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_isoBrittle_critStrainEnergy(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='criticalStrainEnergy ('//LOCAL_DAMAGE_isoBrittle_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_isoBrittle_Noutput(instance)
select case(damage_isoBrittle_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_isoBrittle_sizePostResult(o,instance) = mySize
damage_isoBrittle_sizePostResults(instance) = damage_isoBrittle_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 2_pInt
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_isoBrittle_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_isoBrittle_stateInit(phase)
call damage_isoBrittle_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_isoBrittle_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant NEW state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_isoBrittle_stateInit(phase)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState = 1.0_pReal
damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:)))
damageState(phase)%state0 = damageState(phase)%state
damageState(phase)%partionedState0 = damageState(phase)%state
end subroutine damage_isoBrittle_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_isoBrittle_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol = damage_isoBrittle_aTol(instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_isoBrittle_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_isoBrittle_microstructure(C, Fe, subdt, ipc, ip, el)
use numerics, only: &
residualStiffness
use material, only: &
mappingConstitutive, &
phase_damageInstance, &
damageState
use math, only : &
math_mul33x33, &
math_mul66x6, &
math_Mandel33to6, &
math_transpose33, &
math_I3
use lattice, only: &
lattice_DamageMobility
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in), dimension(3,3) :: &
Fe
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, constituent, instance
real(pReal) :: &
strain(6), &
stress(6), &
C(6,6)
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3)
stress = math_mul66x6(C,strain)
damageState(phase)%state(2,constituent) = &
max(residualStiffness, &
min(damageState(phase)%state0(2,constituent), &
damage_isoBrittle_critStrainEnergy(instance)/(2.0_pReal*sum(abs(stress*strain))))) !< residualStiffness < damage < damage0
damageState(phase)%state(1,constituent) = &
damageState(phase)%state(2,constituent) + &
(damageState(phase)%subState0(1,constituent) - damageState(phase)%state(2,constituent))* &
exp(-subdt/lattice_DamageMobility(phase))
end subroutine damage_isoBrittle_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
pure function damage_isoBrittle_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
mappingConstitutive, &
damageState, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_isoBrittle_getDamage
select case(field_damage_type(material_homog(ip,el)))
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_isoBrittle_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
case default
damage_isoBrittle_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% &
state0(1,mappingConstitutive(1,ipc,ip,el))
end select
end function damage_isoBrittle_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
subroutine damage_isoBrittle_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_isoBrittle_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
pure function damage_isoBrittle_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_isoBrittle_getLocalDamage
damage_isoBrittle_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_isoBrittle_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns brittle damage diffusion tensor
!--------------------------------------------------------------------------------------------------
pure function damage_isoBrittle_getDamageDiffusion33(ipc, ip, el)
use lattice, only: &
lattice_DamageDiffusion33
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
damage_isoBrittle_getDamageDiffusion33
integer(pInt) :: &
phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage_isoBrittle_getDamageDiffusion33 = &
lattice_DamageDiffusion33(1:3,1:3,phase)
end function damage_isoBrittle_getDamageDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief returns brittle damaged stiffness tensor
!--------------------------------------------------------------------------------------------------
pure function damage_isoBrittle_getDamagedC66(C, ipc, ip, el)
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6,6) :: &
C
real(pReal), dimension(6,6) :: &
damage_isoBrittle_getDamagedC66
integer(pInt) :: &
phase, constituent
real(pReal) :: &
damage
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage = damage_isoBrittle_getDamage(ipc, ip, el)
damage_isoBrittle_getDamagedC66 = &
damage*damage*C
end function damage_isoBrittle_getDamagedC66
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_isoBrittle_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
damageState, &
phase_damageInstance
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_isoBrittle_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_isoBrittle_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_isoBrittle_postResults = 0.0_pReal
do o = 1_pInt,damage_isoBrittle_Noutput(instance)
select case(damage_isoBrittle_outputID(o,instance))
case (local_damage_ID)
damage_isoBrittle_postResults(c+1_pInt) = damageState(phase)%state(1,constituent)
c = c + 1
end select
enddo
end function damage_isoBrittle_postResults
end module damage_isoBrittle

View File

@ -1,457 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @brief material subroutine incoprorating isotropic ductile damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_isoDuctile
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_isoDuctile_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_isoDuctile_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_isoDuctile_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_isoDuctile_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
damage_isoDuctile_aTol, &
damage_isoDuctile_critPlasticStrain, &
damage_isoDuctile_N
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_isoDuctile_outputID !< ID of each post result output
public :: &
damage_isoDuctile_init, &
damage_isoDuctile_stateInit, &
damage_isoDuctile_aTolState, &
damage_isoDuctile_microstructure, &
damage_isoDuctile_getDamage, &
damage_isoDuctile_putLocalDamage, &
damage_isoDuctile_getLocalDamage, &
damage_isoDuctile_getDamagedC66, &
damage_isoDuctile_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_isoDuctile_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_damage_isoDuctile_label, &
LOCAL_damage_isoDuctile_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_isoDuctile_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_damage_isoDuctile_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_isoDuctile_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_isoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(damage_isoDuctile_output(maxval(phase_Noutput),maxNinstance))
damage_isoDuctile_output = ''
allocate(damage_isoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_isoDuctile_Noutput(maxNinstance), source=0_pInt)
allocate(damage_isoDuctile_critPlasticStrain(maxNinstance), source=0.0_pReal)
allocate(damage_isoDuctile_N(maxNinstance), source=0.0_pReal)
allocate(damage_isoDuctile_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_isoDuctile_Noutput(instance) = damage_isoDuctile_Noutput(instance) + 1_pInt
damage_isoDuctile_outputID(damage_isoDuctile_Noutput(instance),instance) = local_damage_ID
damage_isoDuctile_output(damage_isoDuctile_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('criticalplasticstrain')
damage_isoDuctile_critPlasticStrain(instance) = IO_floatValue(line,positions,2_pInt)
case ('damageratesensitivity')
damage_isoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('atol_damage')
damage_isoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
sanityChecks: do phase = 1_pInt, size(phase_damage)
myPhase: if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
! sanity checks
if (damage_isoDuctile_aTol(instance) < 0.0_pReal) &
damage_isoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_isoDuctile_critPlasticStrain(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='critical_plastic_strain ('//LOCAL_DAMAGE_isoDuctile_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_isoDuctile_Noutput(instance)
select case(damage_isoDuctile_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_isoDuctile_sizePostResult(o,instance) = mySize
damage_isoDuctile_sizePostResults(instance) = damage_isoDuctile_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 2_pInt
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_isoDuctile_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_isoDuctile_stateInit(phase)
call damage_isoDuctile_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_isoDuctile_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_isoDuctile_stateInit(phase)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState(1) = 1.0_pReal
tempState(2) = 0.0_pReal
damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:)))
end subroutine damage_isoDuctile_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_isoDuctile_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol = damage_isoDuctile_aTol(instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_isoDuctile_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_isoDuctile_microstructure(subdt,ipc, ip, el)
use numerics, only: &
residualStiffness
use material, only: &
phase_damageInstance, &
mappingConstitutive, &
plasticState, &
damageState
use lattice, only: &
lattice_DamageMobility
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, constituent, instance
real(pReal) :: &
localDamage
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
damageState(phase)%state(2,constituent) = &
damageState(phase)%subState0(2,constituent) + &
subdt* &
sum(plasticState(phase)%slipRate(:,constituent))/ &
(damage_isoDuctile_getDamage(ipc, ip, el)**damage_isoDuctile_N(instance))/ &
damage_isoDuctile_critPlasticStrain(instance)
localDamage = &
max(residualStiffness,min(1.0_pReal, 1.0_pReal/damageState(phase)%state(2,constituent)))
damageState(phase)%state(1,constituent) = &
localDamage + &
(damageState(phase)%subState0(1,constituent) - localDamage)* &
exp(-subdt/lattice_DamageMobility(phase))
end subroutine damage_isoDuctile_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
pure function damage_isoDuctile_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
mappingConstitutive, &
damageState, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_LOCAL_ID, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_isoDuctile_getDamage
select case(field_damage_type(material_homog(ip,el)))
case default
damage_isoDuctile_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% &
state0(1,mappingConstitutive(1,ipc,ip,el))
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_isoDuctile_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function damage_isoDuctile_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief puts local damage
!--------------------------------------------------------------------------------------------------
subroutine damage_isoDuctile_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_isoDuctile_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
pure function damage_isoDuctile_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_isoDuctile_getLocalDamage
damage_isoDuctile_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_isoDuctile_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns ductile damaged stiffness tensor
!--------------------------------------------------------------------------------------------------
pure function damage_isoDuctile_getDamagedC66(C, ipc, ip, el)
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6,6) :: &
C
real(pReal), dimension(6,6) :: &
damage_isoDuctile_getDamagedC66
integer(pInt) :: &
phase, constituent
real(pReal) :: &
damage
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage = damage_isoDuctile_getDamage(ipc, ip, el)
damage_isoDuctile_getDamagedC66 = &
damage*damage*C
end function damage_isoDuctile_getDamagedC66
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_isoDuctile_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_damageInstance,&
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_isoDuctile_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_isoDuctile_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_isoDuctile_postResults = 0.0_pReal
do o = 1_pInt,damage_isoDuctile_Noutput(instance)
select case(damage_isoDuctile_outputID(o,instance))
case (local_damage_ID)
damage_isoDuctile_postResults(c+1_pInt) = damageState(phase)%state(1,constituent)
c = c + 1
end select
enddo
end function damage_isoDuctile_postResults
end module damage_isoDuctile

327
code/damage_local.f90 Normal file
View File

@ -0,0 +1,327 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for locally evolving damage field
!--------------------------------------------------------------------------------------------------
module damage_local
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_local_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_local_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_local_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_local_Noutput !< number of outputs per instance of this damage
enum, bind(c)
enumerator :: undefined_ID, &
damage_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_local_outputID !< ID of each post result output
public :: &
damage_local_init, &
damage_local_updateState, &
damage_local_postResults
private :: &
damage_local_getSourceAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief allocates all neccessary fields, reads information from material configuration file
!--------------------------------------------------------------------------------------------------
subroutine damage_local_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, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
damage_type, &
damage_typeInstance, &
homogenization_Noutput, &
DAMAGE_local_label, &
DAMAGE_local_ID, &
material_homog, &
mappingHomogenization, &
damageState, &
damageMapping, &
damage, &
material_partHomogenization
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,homog,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_local_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(damage_type == DAMAGE_local_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(damage_local_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_local_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(damage_local_output (maxval(homogenization_Noutput),maxNinstance))
damage_local_output = ''
allocate(damage_local_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(damage_local_Noutput (maxNinstance), source=0_pInt)
rewind(fileUnit)
homog = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
homog = homog + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (homog > 0_pInt ) then; if (damage_type(homog) == DAMAGE_local_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = damage_typeInstance(homog) ! which instance of my damage is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('damage')
damage_local_Noutput(instance) = damage_local_Noutput(instance) + 1_pInt
damage_local_outputID(damage_local_Noutput(instance),instance) = damage_ID
damage_local_output(damage_local_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingFile
initializeInstances: do homog = 1_pInt, size(damage_type)
myhomog: if (damage_type(homog) == DAMAGE_local_ID) then
NofMyHomog = count(material_homog == homog)
instance = damage_typeInstance(homog)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_local_Noutput(instance)
select case(damage_local_outputID(o,instance))
case(damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_local_sizePostResult(o,instance) = mySize
damage_local_sizePostResults(instance) = damage_local_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 1_pInt
damageState(homog)%sizeState = sizeState
damageState(homog)%sizePostResults = damage_local_sizePostResults(instance)
allocate(damageState(homog)%state0 (sizeState,NofMyHomog))
allocate(damageState(homog)%subState0(sizeState,NofMyHomog))
allocate(damageState(homog)%state (sizeState,NofMyHomog))
nullify(damageMapping(homog)%p)
damageMapping(homog)%p => mappingHomogenization(1,:,:)
deallocate(damage(homog)%p)
damage(homog)%p => damageState(homog)%state(1,:)
endif myhomog
enddo initializeInstances
end subroutine damage_local_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates local change in damage field
!--------------------------------------------------------------------------------------------------
function damage_local_updateState(subdt, ip, el)
use numerics, only: &
err_damage_tolAbs, &
err_damage_tolRel
use material, only: &
mappingHomogenization, &
damageState
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
subdt
logical, dimension(2) :: &
damage_local_updateState
integer(pInt) :: &
homog, &
offset
real(pReal) :: &
phi, phiDot, dPhiDot_dPhi
homog = mappingHomogenization(2,ip,el)
offset = mappingHomogenization(1,ip,el)
phi = damageState(homog)%subState0(1,offset)
call damage_local_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el)
phi = phi + subdt*phiDot
damage_local_updateState = [ abs(phi - damageState(homog)%state(1,offset)) &
<= err_damage_tolAbs &
.or. abs(phi - damageState(homog)%state(1,offset)) &
<= err_damage_tolRel*abs(damageState(homog)%state(1,offset)), &
.true.]
damageState(homog)%state(1,offset) = phi
end function damage_local_updateState
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized local damage driving forces
!--------------------------------------------------------------------------------------------------
subroutine damage_local_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el)
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
phase_source, &
phase_Nsources, &
SOURCE_damage_isoBrittle_ID, &
SOURCE_damage_isoDuctile_ID, &
SOURCE_damage_anisoBrittle_ID, &
SOURCE_damage_anisoDuctile_ID
use source_damage_isoBrittle, only: &
source_damage_isobrittle_getRateAndItsTangent
use source_damage_isoDuctile, only: &
source_damage_isoductile_getRateAndItsTangent
use source_damage_anisoBrittle, only: &
source_damage_anisobrittle_getRateAndItsTangent
use source_damage_anisoDuctile, only: &
source_damage_anisoductile_getRateAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer(pInt) :: &
phase, &
grain, &
source
real(pReal) :: &
phiDot, dPhiDot_dPhi, localphiDot, dLocalphiDot_dPhi
phiDot = 0.0_pReal
dPhiDot_dPhi = 0.0_pReal
do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el))
phase = mappingConstitutive(2,grain,ip,el)
do source = 1, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_damage_isoBrittle_ID)
call source_damage_isobrittle_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_isoDuctile_ID)
call source_damage_isoductile_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_anisoBrittle_ID)
call source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_anisoDuctile_ID)
call source_damage_anisoductile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case default
localphiDot = 0.0_pReal
dLocalphiDot_dPhi = 0.0_pReal
end select
phiDot = phiDot + localphiDot
dPhiDot_dPhi = dPhiDot_dPhi + dLocalphiDot_dPhi
enddo
enddo
phiDot = phiDot/homogenization_Ngrains(mappingHomogenization(2,ip,el))
dPhiDot_dPhi = dPhiDot_dPhi/homogenization_Ngrains(mappingHomogenization(2,ip,el))
end subroutine damage_local_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of damage results
!--------------------------------------------------------------------------------------------------
function damage_local_postResults(ip,el)
use material, only: &
mappingHomogenization, &
damage_typeInstance, &
damageMapping, &
damage
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(damage_local_sizePostResults(damage_typeInstance(mappingHomogenization(2,ip,el)))) :: &
damage_local_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = damageMapping(homog)%p(ip,el)
instance = damage_typeInstance(homog)
c = 0_pInt
damage_local_postResults = 0.0_pReal
do o = 1_pInt,damage_local_Noutput(instance)
select case(damage_local_outputID(o,instance))
case (damage_ID)
damage_local_postResults(c+1_pInt) = damage(homog)%p(offset)
c = c + 1
end select
enddo
end function damage_local_postResults
end module damage_local

View File

@ -1,100 +1,61 @@
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! $Id$ ! $Id$
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for constant damage field
!> @brief material subroutine for purely elastic material
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module damage_none module damage_none
use prec, only: &
pInt
implicit none implicit none
private private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_none_sizePostResults
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_none_sizePostResult !< size of each post result output
public :: & public :: &
damage_none_init damage_none_init
contains contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief module initialization !> @brief allocates all neccessary fields, reads information from material configuration file
!> @details reads in material parameters, allocates arrays, and does sanity checks
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine damage_none_init subroutine damage_none_init()
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: & use prec, only: &
debug_level, & pReal, &
debug_constitutive, & pInt
debug_levelBasic
use IO, only: & use IO, only: &
IO_timeStamp IO_timeStamp
use material
use numerics, only: & use numerics, only: &
worldrank, & worldrank
numerics_integrator
use material, only: &
phase_damage, &
LOCAL_DAMAGE_NONE_label, &
LOCAL_DAMAGE_NONE_ID, &
material_phase, &
damageState
implicit none implicit none
integer(pInt) :: & integer(pInt) :: &
maxNinstance, & homog, &
phase, & NofMyHomog
NofMyPhase, &
sizeState, &
sizeDotState
mainProcess: if (worldrank == 0) then mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_DAMAGE_NONE_label//' init -+>>>' write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_none_label//' init -+>>>'
write(6,'(a)') ' $Id$' write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp() write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90" #include "compilation_info.f90"
endif mainProcess endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_DAMAGE_NONE_ID),pInt) initializeInstances: do homog = 1_pInt, material_Nhomogenization
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & myhomog: if (damage_type(homog) == DAMAGE_none_ID) then
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance NofMyHomog = count(material_homog == homog)
damageState(homog)%sizeState = 0_pInt
damageState(homog)%sizePostResults = 0_pInt
allocate(damageState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal)
allocate(damageState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal)
allocate(damageState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal)
initializeInstances: do phase = 1_pInt, size(phase_damage) deallocate(damage(homog)%p)
NofMyPhase=count(material_phase==phase) allocate (damage(homog)%p(1), source=1.0_pReal)
if (phase_damage(phase) == LOCAL_DAMAGE_none_ID) then
sizeState = 0_pInt endif myhomog
damageState(phase)%sizeState = sizeState
sizeDotState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = 0_pInt
allocate(damageState(phase)%state0 (sizeState,NofMyPhase))
allocate(damageState(phase)%partionedState0(sizeState,NofMyPhase))
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase))
allocate(damageState(phase)%state (sizeState,NofMyPhase))
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase))
allocate(damageState(phase)%aTolState (NofMyPhase))
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase))
allocate(damageState(phase)%dotState_backup(sizeDotState,NofMyPhase))
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase))
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase))
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase))
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase))
endif
enddo initializeInstances enddo initializeInstances
allocate(damage_none_sizePostResults(maxNinstance), source=0_pInt)
end subroutine damage_none_init end subroutine damage_none_init

378
code/damage_nonlocal.f90 Normal file
View File

@ -0,0 +1,378 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for non-locally evolving damage field
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_nonlocal
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_nonlocal_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_nonlocal_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_nonlocal_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_nonlocal_Noutput !< number of outputs per instance of this damage
enum, bind(c)
enumerator :: undefined_ID, &
damage_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_nonlocal_outputID !< ID of each post result output
public :: &
damage_nonlocal_init, &
damage_nonlocal_getSourceAndItsTangent, &
damage_nonlocal_getDiffusion33, &
damage_nonlocal_getMobility, &
damage_nonlocal_putNonLocalDamage, &
damage_nonlocal_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
damage_type, &
damage_typeInstance, &
homogenization_Noutput, &
DAMAGE_nonlocal_label, &
DAMAGE_nonlocal_ID, &
material_homog, &
mappingHomogenization, &
damageState, &
damageMapping, &
damage, &
material_partHomogenization
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_nonlocal_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(damage_type == DAMAGE_nonlocal_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(damage_nonlocal_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_nonlocal_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(damage_nonlocal_output (maxval(homogenization_Noutput),maxNinstance))
damage_nonlocal_output = ''
allocate(damage_nonlocal_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(damage_nonlocal_Noutput (maxNinstance), source=0_pInt)
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (damage_type(section) == DAMAGE_nonlocal_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = damage_typeInstance(section) ! which instance of my damage is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('damage')
damage_nonlocal_Noutput(instance) = damage_nonlocal_Noutput(instance) + 1_pInt
damage_nonlocal_outputID(damage_nonlocal_Noutput(instance),instance) = damage_ID
damage_nonlocal_output(damage_nonlocal_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingFile
initializeInstances: do section = 1_pInt, size(damage_type)
if (damage_type(section) == DAMAGE_nonlocal_ID) then
NofMyHomog=count(material_homog==section)
instance = damage_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_nonlocal_Noutput(instance)
select case(damage_nonlocal_outputID(o,instance))
case(damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_nonlocal_sizePostResult(o,instance) = mySize
damage_nonlocal_sizePostResults(instance) = damage_nonlocal_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 0_pInt
damageState(section)%sizeState = sizeState
damageState(section)%sizePostResults = damage_nonlocal_sizePostResults(instance)
allocate(damageState(section)%state0 (sizeState,NofMyHomog))
allocate(damageState(section)%subState0(sizeState,NofMyHomog))
allocate(damageState(section)%state (sizeState,NofMyHomog))
nullify(damageMapping(section)%p)
damageMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(damage(section)%p)
allocate(damage(section)%p(NofMyHomog), source=1.0_pReal)
endif
enddo initializeInstances
end subroutine damage_nonlocal_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized damage driving forces
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el)
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
phase_source, &
phase_Nsources, &
SOURCE_damage_isoBrittle_ID, &
SOURCE_damage_isoDuctile_ID, &
SOURCE_damage_anisoBrittle_ID, &
SOURCE_damage_anisoDuctile_ID
use source_damage_isoBrittle, only: &
source_damage_isobrittle_getRateAndItsTangent
use source_damage_isoDuctile, only: &
source_damage_isoductile_getRateAndItsTangent
use source_damage_anisoBrittle, only: &
source_damage_anisobrittle_getRateAndItsTangent
use source_damage_anisoDuctile, only: &
source_damage_anisoductile_getRateAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer(pInt) :: &
phase, &
grain, &
source
real(pReal) :: &
phiDot, dPhiDot_dPhi, localphiDot, dLocalphiDot_dPhi
phiDot = 0.0_pReal
dPhiDot_dPhi = 0.0_pReal
do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el))
phase = mappingConstitutive(2,grain,ip,el)
do source = 1_pInt, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_damage_isoBrittle_ID)
call source_damage_isobrittle_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_isoDuctile_ID)
call source_damage_isoductile_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_anisoBrittle_ID)
call source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case (SOURCE_damage_anisoDuctile_ID)
call source_damage_anisoductile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el)
case default
localphiDot = 0.0_pReal
dLocalphiDot_dPhi = 0.0_pReal
end select
phiDot = phiDot + localphiDot
dPhiDot_dPhi = dPhiDot_dPhi + dLocalphiDot_dPhi
enddo
enddo
phiDot = phiDot/homogenization_Ngrains(mappingHomogenization(2,ip,el))
dPhiDot_dPhi = dPhiDot_dPhi/homogenization_Ngrains(mappingHomogenization(2,ip,el))
end subroutine damage_nonlocal_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized non local damage diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function damage_nonlocal_getDiffusion33(ip,el)
use lattice, only: &
lattice_DamageDiffusion33
use material, only: &
homogenization_Ngrains, &
material_phase, &
mappingHomogenization
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
damage_nonlocal_getDiffusion33
integer(pInt) :: &
homog, &
grain
homog = mappingHomogenization(2,ip,el)
damage_nonlocal_getDiffusion33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(homog)
damage_nonlocal_getDiffusion33 = damage_nonlocal_getDiffusion33 + &
crystallite_push33ToRef(grain,ip,el,lattice_DamageDiffusion33(1:3,1:3,material_phase(grain,ip,el)))
enddo
damage_nonlocal_getDiffusion33 = &
damage_nonlocal_getDiffusion33/ &
homogenization_Ngrains(homog)
end function damage_nonlocal_getDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief Returns homogenized nonlocal damage mobility
!--------------------------------------------------------------------------------------------------
real(pReal) function damage_nonlocal_getMobility(ip,el)
use mesh, only: &
mesh_element
use lattice, only: &
lattice_damageMobility
use material, only: &
material_phase, &
homogenization_Ngrains
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
integer(pInt) :: &
ipc
damage_nonlocal_getMobility = 0.0_pReal
do ipc = 1, homogenization_Ngrains(mesh_element(3,el))
damage_nonlocal_getMobility = damage_nonlocal_getMobility + lattice_DamageMobility(material_phase(ipc,ip,el))
enddo
damage_nonlocal_getMobility = damage_nonlocal_getMobility /homogenization_Ngrains(mesh_element(3,el))
end function damage_nonlocal_getMobility
!--------------------------------------------------------------------------------------------------
!> @brief updated nonlocal damage field with solution from damage phase field PDE
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_putNonLocalDamage(phi,ip,el)
use material, only: &
material_homog, &
damageMapping, &
damage
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer(pInt) :: &
homog, &
offset
homog = material_homog(ip,el)
offset = damageMapping(homog)%p(ip,el)
damage(homog)%p(offset) = phi
end subroutine damage_nonlocal_putNonLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief return array of damage results
!--------------------------------------------------------------------------------------------------
function damage_nonlocal_postResults(ip,el)
use material, only: &
mappingHomogenization, &
damage_typeInstance, &
damage
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(damage_nonlocal_sizePostResults(damage_typeInstance(mappingHomogenization(2,ip,el)))) :: &
damage_nonlocal_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = mappingHomogenization(1,ip,el)
instance = damage_typeInstance(homog)
c = 0_pInt
damage_nonlocal_postResults = 0.0_pReal
do o = 1_pInt,damage_nonlocal_Noutput(instance)
select case(damage_nonlocal_outputID(o,instance))
case (damage_ID)
damage_nonlocal_postResults(c+1_pInt) = damage(homog)%p(offset)
c = c + 1
end select
enddo
end function damage_nonlocal_postResults
end module damage_nonlocal

View File

@ -1,510 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incoprorating isotropic brittle damage
!> @details to be done
!--------------------------------------------------------------------------------------------------
module damage_phaseField
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
damage_phaseField_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
damage_phaseField_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
damage_phaseField_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
damage_phaseField_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
damage_phaseField_aTol, &
damage_phaseField_surfaceEnergy, &
damage_phaseField_vacancyFormationEnergy, &
damage_phaseField_atomicVol, &
damage_phaseField_specificVacancyFormationEnergy
enum, bind(c)
enumerator :: undefined_ID, &
local_damage_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
damage_phaseField_outputID !< ID of each post result output
public :: &
damage_phaseField_init, &
damage_phaseField_stateInit, &
damage_phaseField_aTolState, &
damage_phaseField_microstructure, &
damage_phaseField_getDamage, &
damage_phaseField_putLocalDamage, &
damage_phaseField_getLocalDamage, &
damage_phaseField_getDamageDiffusion33, &
damage_phaseField_getDamagedC66, &
damage_phaseField_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_phaseField_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_damage, &
phase_damageInstance, &
phase_Noutput, &
LOCAL_damage_phaseField_label, &
LOCAL_damage_phaseField_ID, &
material_phase, &
damageState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_phaseField_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_damage == LOCAL_damage_phaseField_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(damage_phaseField_sizePostResults(maxNinstance), source=0_pInt)
allocate(damage_phaseField_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(damage_phaseField_output(maxval(phase_Noutput),maxNinstance))
damage_phaseField_output = ''
allocate(damage_phaseField_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(damage_phaseField_Noutput(maxNinstance), source=0_pInt)
allocate(damage_phaseField_surfaceEnergy(maxNinstance), source=0.0_pReal)
allocate(damage_phaseField_vacancyFormationEnergy(maxNinstance), source=0.0_pReal)
allocate(damage_phaseField_atomicVol(maxNinstance), source=0.0_pReal)
allocate(damage_phaseField_specificVacancyFormationEnergy(maxNinstance), source=0.0_pReal)
allocate(damage_phaseField_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_damageInstance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('local_damage')
damage_phaseField_Noutput(instance) = damage_phaseField_Noutput(instance) + 1_pInt
damage_phaseField_outputID(damage_phaseField_Noutput(instance),instance) = local_damage_ID
damage_phaseField_output(damage_phaseField_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('surfaceenergy')
damage_phaseField_surfaceEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancyformationenergy')
damage_phaseField_vacancyFormationEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('atomicvolume')
damage_phaseField_atomicVol(instance) = IO_floatValue(line,positions,2_pInt)
case ('atol_damage')
damage_phaseField_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
sanityChecks: do phase = 1_pInt, size(phase_damage)
myPhase: if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
! sanity checks
if (damage_phaseField_aTol(instance) < 0.0_pReal) &
damage_phaseField_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (damage_phaseField_surfaceEnergy(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='surfaceEnergy ('//LOCAL_damage_phaseField_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, size(phase_damage)
if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_damageInstance(phase)
!--------------------------------------------------------------------------------------------------
! pre-calculating derived material parameters
damage_phaseField_specificVacancyFormationEnergy(instance) = &
damage_phaseField_vacancyFormationEnergy(instance)/damage_phaseField_atomicVol(instance)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,damage_phaseField_Noutput(instance)
select case(damage_phaseField_outputID(o,instance))
case(local_damage_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
damage_phaseField_sizePostResult(o,instance) = mySize
damage_phaseField_sizePostResults(instance) = damage_phaseField_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 2_pInt
damageState(phase)%sizeState = sizeState
damageState(phase)%sizeDotState = sizeDotState
damageState(phase)%sizePostResults = damage_phaseField_sizePostResults(instance)
allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call damage_phaseField_stateInit(phase)
call damage_phaseField_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine damage_phaseField_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant NEW state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_phaseField_stateInit(phase)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempState
tempState = 1.0_pReal
damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:)))
damageState(phase)%state0 = damageState(phase)%state
damageState(phase)%partionedState0 = damageState(phase)%state
end subroutine damage_phaseField_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this damage
!--------------------------------------------------------------------------------------------------
subroutine damage_phaseField_aTolState(phase,instance)
use material, only: &
damageState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the damage
real(pReal), dimension(damageState(phase)%sizeState) :: tempTol
tempTol = damage_phaseField_aTol(instance)
damageState(phase)%aTolState = tempTol
end subroutine damage_phaseField_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine damage_phaseField_microstructure(C, Fe, Cv, subdt, ipc, ip, el)
use numerics, only: &
residualStiffness
use material, only: &
mappingConstitutive, &
phase_damageInstance, &
damageState
use math, only : &
math_mul33x33, &
math_mul66x6, &
math_Mandel33to6, &
math_transpose33, &
math_I3
use lattice, only: &
lattice_DamageMobility
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in), dimension(3,3) :: &
Fe
real(pReal), intent(in), dimension(6,6) :: &
C
real(pReal), intent(in) :: &
Cv
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, constituent, instance
real(pReal) :: &
strain(6), &
stress(6), &
drivingForce
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3)
stress = math_mul66x6(C,strain)
drivingForce = (1.0_pReal - Cv)*(1.0_pReal - Cv) + &
(Cv*damage_phaseField_specificVacancyFormationEnergy(instance) + &
sum(abs(stress*strain)))/damage_phaseField_surfaceEnergy(instance)
damageState(phase)%state(2,constituent) = &
max(residualStiffness,(1.0_pReal - Cv)*(1.0_pReal - Cv)/drivingForce)
damageState(phase)%state(1,constituent) = &
damageState(phase)%state(2,constituent) + &
(damageState(phase)%subState0(1,constituent) - damageState(phase)%state(2,constituent))* &
exp(-2.0_pReal*subdt*drivingForce/lattice_DamageMobility(phase))
end subroutine damage_phaseField_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief returns damage
!--------------------------------------------------------------------------------------------------
pure function damage_phaseField_getDamage(ipc, ip, el)
use material, only: &
material_homog, &
mappingHomogenization, &
mappingConstitutive, &
damageState, &
fieldDamage, &
field_damage_type, &
FIELD_DAMAGE_LOCAL_ID, &
FIELD_DAMAGE_NONLOCAL_ID
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_phaseField_getDamage
select case(field_damage_type(material_homog(ip,el)))
case default
damage_phaseField_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% &
state0(1,mappingConstitutive(1,ipc,ip,el))
case (FIELD_DAMAGE_NONLOCAL_ID)
damage_phaseField_getDamage = fieldDamage(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function damage_phaseField_getDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
subroutine damage_phaseField_putLocalDamage(ipc, ip, el, localDamage)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: localDamage
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = &
localDamage
end subroutine damage_phaseField_putLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns local damage
!--------------------------------------------------------------------------------------------------
pure function damage_phaseField_getLocalDamage(ipc, ip, el)
use material, only: &
mappingConstitutive, &
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: damage_phaseField_getLocalDamage
damage_phaseField_getLocalDamage = &
damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function damage_phaseField_getLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief returns brittle damage diffusion tensor
!--------------------------------------------------------------------------------------------------
pure function damage_phaseField_getDamageDiffusion33(ipc, ip, el)
use lattice, only: &
lattice_DamageDiffusion33
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
damage_phaseField_getDamageDiffusion33
integer(pInt) :: &
phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage_phaseField_getDamageDiffusion33 = &
lattice_DamageDiffusion33(1:3,1:3,phase)
end function damage_phaseField_getDamageDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief returns brittle damaged stiffness tensor
!--------------------------------------------------------------------------------------------------
pure function damage_phaseField_getDamagedC66(C, ipc, ip, el)
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6,6) :: &
C
real(pReal), dimension(6,6) :: &
damage_phaseField_getDamagedC66
integer(pInt) :: &
phase, constituent
real(pReal) :: &
damage
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
damage = damage_phaseField_getDamage(ipc, ip, el)
damage_phaseField_getDamagedC66 = &
damage*damage*C
end function damage_phaseField_getDamagedC66
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function damage_phaseField_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_damageInstance,&
damageState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(damage_phaseField_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
damage_phaseField_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_damageInstance(phase)
c = 0_pInt
damage_phaseField_postResults = 0.0_pReal
do o = 1_pInt,damage_phaseField_Noutput(instance)
select case(damage_phaseField_outputID(o,instance))
case (local_damage_ID)
damage_phaseField_postResults(c+1_pInt) = damageState(phase)%state(2,constituent)
c = c + 1
end select
enddo
end function damage_phaseField_postResults
end module damage_phaseField

File diff suppressed because it is too large Load Diff

View File

@ -336,7 +336,6 @@ subroutine homogenization_RGC_partitionDeformation(F,avgF,ip,el)
use material, only: & use material, only: &
homogenization_maxNgrains, & homogenization_maxNgrains, &
homogenization_Ngrains,& homogenization_Ngrains,&
mappingHomogenization, &
homogenization_typeInstance homogenization_typeInstance
use FEsolving, only: & use FEsolving, only: &
theInc,& theInc,&
@ -903,7 +902,6 @@ subroutine homogenization_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,
use mesh, only: mesh_element use mesh, only: mesh_element
use material, only: & use material, only: &
homogenization_maxNgrains, & homogenization_maxNgrains, &
mappingHomogenization, &
homogenization_Ngrains, & homogenization_Ngrains, &
homogenization_typeInstance homogenization_typeInstance
use math, only: math_Plain3333to99 use math, only: math_Plain3333to99

View File

@ -0,0 +1,544 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for conservative transport of solute hydrogen
!> @details to be done
!--------------------------------------------------------------------------------------------------
module hydrogenflux_cahnhilliard
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
hydrogenflux_cahnhilliard_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
hydrogenflux_cahnhilliard_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
hydrogenflux_cahnhilliard_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
hydrogenflux_cahnhilliard_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
hydrogenflux_cahnhilliard_formationEnergyCoeff, &
hydrogenflux_cahnhilliard_kBCoeff
real(pReal), parameter, private :: &
kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin
enum, bind(c)
enumerator :: undefined_ID, &
hydrogenConc_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
hydrogenflux_cahnhilliard_outputID !< ID of each post result output
public :: &
hydrogenflux_cahnhilliard_init, &
hydrogenflux_cahnhilliard_getMobility33, &
hydrogenflux_cahnhilliard_getDiffusion33, &
hydrogenflux_cahnhilliard_getFormationEnergy, &
hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent, &
hydrogenflux_cahnhilliard_getChemPotAndItsTangent, &
hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate, &
hydrogenflux_cahnhilliard_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine hydrogenflux_cahnhilliard_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, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use lattice, only: &
lattice_hydrogenVol
use material, only: &
hydrogenflux_type, &
hydrogenflux_typeInstance, &
homogenization_Noutput, &
HYDROGENFLUX_cahnhilliard_label, &
HYDROGENFLUX_cahnhilliard_ID, &
material_homog, &
material_Nphase, &
mappingHomogenization, &
hydrogenfluxState, &
hydrogenfluxMapping, &
hydrogenConc, &
hydrogenConcRate, &
material_partHomogenization, &
material_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- hydrogenflux_'//HYDROGENFLUX_cahnhilliard_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(hydrogenflux_type == HYDROGENFLUX_cahnhilliard_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(hydrogenflux_cahnhilliard_sizePostResults(maxNinstance), source=0_pInt)
allocate(hydrogenflux_cahnhilliard_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(hydrogenflux_cahnhilliard_output (maxval(homogenization_Noutput),maxNinstance))
hydrogenflux_cahnhilliard_output = ''
allocate(hydrogenflux_cahnhilliard_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(hydrogenflux_cahnhilliard_Noutput (maxNinstance), source=0_pInt)
allocate(hydrogenflux_cahnhilliard_kBCoeff (material_Nphase), source=0.0_pReal)
allocate(hydrogenflux_cahnhilliard_formationEnergyCoeff(material_Nphase), source=0.0_pReal)
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = hydrogenflux_typeInstance(section) ! which instance of my hydrogenflux is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('hydrogenconc')
hydrogenflux_cahnhilliard_Noutput(instance) = hydrogenflux_cahnhilliard_Noutput(instance) + 1_pInt
hydrogenflux_cahnhilliard_outputID(hydrogenflux_cahnhilliard_Noutput(instance),instance) = hydrogenConc_ID
hydrogenflux_cahnhilliard_output(hydrogenflux_cahnhilliard_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingHomog
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('hydrogenformationenergy')
hydrogenflux_cahnhilliard_formationEnergyCoeff(section) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingPhase
initializeInstances: do section = 1_pInt, size(hydrogenflux_type)
if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then
NofMyHomog=count(material_homog==section)
instance = hydrogenflux_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,hydrogenflux_cahnhilliard_Noutput(instance)
select case(hydrogenflux_cahnhilliard_outputID(o,instance))
case(hydrogenConc_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
hydrogenflux_cahnhilliard_sizePostResult(o,instance) = mySize
hydrogenflux_cahnhilliard_sizePostResults(instance) = hydrogenflux_cahnhilliard_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 0_pInt
hydrogenfluxState(section)%sizeState = sizeState
hydrogenfluxState(section)%sizePostResults = hydrogenflux_cahnhilliard_sizePostResults(instance)
allocate(hydrogenfluxState(section)%state0 (sizeState,NofMyHomog))
allocate(hydrogenfluxState(section)%subState0(sizeState,NofMyHomog))
allocate(hydrogenfluxState(section)%state (sizeState,NofMyHomog))
nullify(hydrogenfluxMapping(section)%p)
hydrogenfluxMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(hydrogenConc (section)%p)
deallocate(hydrogenConcRate(section)%p)
allocate (hydrogenConc (section)%p(NofMyHomog), source=0.0_pReal)
allocate (hydrogenConcRate(section)%p(NofMyHomog), source=0.0_pReal)
endif
enddo initializeInstances
initializeParams: do section = 1_pInt, material_Nphase
hydrogenflux_cahnhilliard_kBCoeff(section) = &
kB/ &
hydrogenflux_cahnhilliard_formationEnergyCoeff(section)
hydrogenflux_cahnhilliard_formationEnergyCoeff(section) = &
hydrogenflux_cahnhilliard_formationEnergyCoeff(section)/ &
lattice_hydrogenVol(section)
enddo initializeParams
end subroutine hydrogenflux_cahnhilliard_init
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized solute mobility tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function hydrogenflux_cahnhilliard_getMobility33(ip,el)
use lattice, only: &
lattice_hydrogenfluxMobility33
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
hydrogenflux_cahnhilliard_getMobility33
integer(pInt) :: &
grain
hydrogenflux_cahnhilliard_getMobility33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
hydrogenflux_cahnhilliard_getMobility33 = hydrogenflux_cahnhilliard_getMobility33 + &
crystallite_push33ToRef(grain,ip,el,lattice_hydrogenfluxMobility33(:,:,material_phase(grain,ip,el)))
enddo
hydrogenflux_cahnhilliard_getMobility33 = &
hydrogenflux_cahnhilliard_getMobility33/ &
homogenization_Ngrains(mesh_element(3,el))
end function hydrogenflux_cahnhilliard_getMobility33
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized solute nonlocal diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function hydrogenflux_cahnhilliard_getDiffusion33(ip,el)
use lattice, only: &
lattice_hydrogenfluxDiffusion33
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
hydrogenflux_cahnhilliard_getDiffusion33
integer(pInt) :: &
grain
hydrogenflux_cahnhilliard_getDiffusion33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
hydrogenflux_cahnhilliard_getDiffusion33 = hydrogenflux_cahnhilliard_getDiffusion33 + &
crystallite_push33ToRef(grain,ip,el,lattice_hydrogenfluxDiffusion33(:,:,material_phase(grain,ip,el)))
enddo
hydrogenflux_cahnhilliard_getDiffusion33 = &
hydrogenflux_cahnhilliard_getDiffusion33/ &
homogenization_Ngrains(mesh_element(3,el))
end function hydrogenflux_cahnhilliard_getDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized solution energy
!--------------------------------------------------------------------------------------------------
function hydrogenflux_cahnhilliard_getFormationEnergy(ip,el)
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
hydrogenflux_cahnhilliard_getFormationEnergy
integer(pInt) :: &
grain
hydrogenflux_cahnhilliard_getFormationEnergy = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
hydrogenflux_cahnhilliard_getFormationEnergy = hydrogenflux_cahnhilliard_getFormationEnergy + &
hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el))
enddo
hydrogenflux_cahnhilliard_getFormationEnergy = &
hydrogenflux_cahnhilliard_getFormationEnergy/ &
homogenization_Ngrains(mesh_element(3,el))
end function hydrogenflux_cahnhilliard_getFormationEnergy
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized hydrogen entropy coefficient
!--------------------------------------------------------------------------------------------------
function hydrogenflux_cahnhilliard_getEntropicCoeff(ip,el)
use material, only: &
homogenization_Ngrains, &
material_homog, &
material_phase, &
temperature, &
thermalMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
hydrogenflux_cahnhilliard_getEntropicCoeff
integer(pInt) :: &
grain
hydrogenflux_cahnhilliard_getEntropicCoeff = 0.0_pReal
do grain = 1, homogenization_Ngrains(material_homog(ip,el))
hydrogenflux_cahnhilliard_getEntropicCoeff = hydrogenflux_cahnhilliard_getEntropicCoeff + &
hydrogenflux_cahnhilliard_kBCoeff(material_phase(grain,ip,el))
enddo
hydrogenflux_cahnhilliard_getEntropicCoeff = &
hydrogenflux_cahnhilliard_getEntropicCoeff* &
temperature(material_homog(ip,el))%p(thermalMapping(material_homog(ip,el))%p(ip,el))/ &
homogenization_Ngrains(material_homog(ip,el))
end function hydrogenflux_cahnhilliard_getEntropicCoeff
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized kinematic contribution to chemical potential
!--------------------------------------------------------------------------------------------------
subroutine hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCh, Ch, ip, el)
use material, only: &
homogenization_Ngrains, &
material_homog, &
phase_kinematics, &
phase_Nkinematics, &
material_phase, &
KINEMATICS_hydrogen_strain_ID
use crystallite, only: &
crystallite_Tstar_v, &
crystallite_Fi0, &
crystallite_Fi
use kinematics_hydrogen_strain, only: &
kinematics_hydrogen_strain_ChemPotAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Ch
real(pReal), intent(out) :: &
KPot, dKPot_dCh
real(pReal) :: &
my_KPot, my_dKPot_dCh
integer(pInt) :: &
grain, kinematics
KPot = 0.0_pReal
dKPot_dCh = 0.0_pReal
do grain = 1_pInt,homogenization_Ngrains(material_homog(ip,el))
do kinematics = 1_pInt, phase_Nkinematics(material_phase(grain,ip,el))
select case (phase_kinematics(kinematics,material_phase(grain,ip,el)))
case (KINEMATICS_hydrogen_strain_ID)
call kinematics_hydrogen_strain_ChemPotAndItsTangent(my_KPot, my_dKPot_dCh, &
crystallite_Tstar_v(1:6,grain,ip,el), &
crystallite_Fi0(1:3,1:3,grain,ip,el), &
crystallite_Fi (1:3,1:3,grain,ip,el), &
grain,ip, el)
case default
my_KPot = 0.0_pReal
my_dKPot_dCh = 0.0_pReal
end select
KPot = KPot + my_KPot/hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el))
dKPot_dCh = dKPot_dCh + my_dKPot_dCh/hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el))
enddo
enddo
KPot = KPot/homogenization_Ngrains(material_homog(ip,el))
dKPot_dCh = dKPot_dCh/homogenization_Ngrains(material_homog(ip,el))
end subroutine hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized chemical potential
!--------------------------------------------------------------------------------------------------
subroutine hydrogenflux_cahnhilliard_getChemPotAndItsTangent(ChemPot,dChemPot_dCh,Ch,ip,el)
use numerics, only: &
hydrogenBoundPenalty, &
hydrogenPolyOrder
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Ch
real(pReal), intent(out) :: &
ChemPot, &
dChemPot_dCh
real(pReal) :: &
kBT, KPot, dKPot_dCh
integer(pInt) :: &
o
ChemPot = 1.0_pReal
dChemPot_dCh = 0.0_pReal
kBT = hydrogenflux_cahnhilliard_getEntropicCoeff(ip,el)
do o = 1_pInt, hydrogenPolyOrder
ChemPot = ChemPot + kBT*((2.0_pReal*Ch - 1.0_pReal)**real(2_pInt*o-1_pInt,pReal))/ &
real(2_pInt*o-1_pInt,pReal)
dChemPot_dCh = dChemPot_dCh + 2.0_pReal*kBT*(2.0_pReal*Ch - 1.0_pReal)**real(2_pInt*o-2_pInt,pReal)
enddo
call hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCh, Ch, ip, el)
ChemPot = ChemPot + KPot
dChemPot_dCh = dChemPot_dCh + dKPot_dCh
if (Ch < 0.0_pReal) then
ChemPot = ChemPot - 3.0_pReal*hydrogenBoundPenalty*Ch*Ch
dChemPot_dCh = dChemPot_dCh - 6.0_pReal*hydrogenBoundPenalty*Ch
elseif (Ch > 1.0_pReal) then
ChemPot = ChemPot + 3.0_pReal*hydrogenBoundPenalty*(1.0_pReal - Ch)*(1.0_pReal - Ch)
dChemPot_dCh = dChemPot_dCh - 6.0_pReal*hydrogenBoundPenalty*(1.0_pReal - Ch)
endif
end subroutine hydrogenflux_cahnhilliard_getChemPotAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief updates hydrogen concentration with solution from Cahn-Hilliard PDE for solute transport
!--------------------------------------------------------------------------------------------------
subroutine hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate(Ch,Chdot,ip,el)
use material, only: &
mappingHomogenization, &
hydrogenConc, &
hydrogenConcRate, &
hydrogenfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Ch, &
Chdot
integer(pInt) :: &
homog, &
offset
homog = mappingHomogenization(2,ip,el)
offset = hydrogenfluxMapping(homog)%p(ip,el)
hydrogenConc (homog)%p(offset) = Ch
hydrogenConcRate(homog)%p(offset) = Chdot
end subroutine hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate
!--------------------------------------------------------------------------------------------------
!> @brief return array of hydrogen transport results
!--------------------------------------------------------------------------------------------------
function hydrogenflux_cahnhilliard_postResults(ip,el)
use material, only: &
mappingHomogenization, &
hydrogenflux_typeInstance, &
hydrogenConc, &
hydrogenfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(hydrogenflux_cahnhilliard_sizePostResults(hydrogenflux_typeInstance(mappingHomogenization(2,ip,el)))) :: &
hydrogenflux_cahnhilliard_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = hydrogenfluxMapping(homog)%p(ip,el)
instance = hydrogenflux_typeInstance(homog)
c = 0_pInt
hydrogenflux_cahnhilliard_postResults = 0.0_pReal
do o = 1_pInt,hydrogenflux_cahnhilliard_Noutput(instance)
select case(hydrogenflux_cahnhilliard_outputID(o,instance))
case (hydrogenConc_ID)
hydrogenflux_cahnhilliard_postResults(c+1_pInt) = hydrogenConc(homog)%p(offset)
c = c + 1
end select
enddo
end function hydrogenflux_cahnhilliard_postResults
end module hydrogenflux_cahnhilliard

View File

@ -0,0 +1,64 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for constant hydrogen concentration
!--------------------------------------------------------------------------------------------------
module hydrogenflux_isoconc
implicit none
private
public :: &
hydrogenflux_isoconc_init
contains
!--------------------------------------------------------------------------------------------------
!> @brief allocates all neccessary fields, reads information from material configuration file
!--------------------------------------------------------------------------------------------------
subroutine hydrogenflux_isoconc_init()
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use prec, only: &
pReal, &
pInt
use IO, only: &
IO_timeStamp
use material
use numerics, only: &
worldrank
implicit none
integer(pInt) :: &
homog, &
NofMyHomog
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- hydrogenflux_'//HYDROGENFLUX_isoconc_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
initializeInstances: do homog = 1_pInt, material_Nhomogenization
myhomog: if (hydrogenflux_type(homog) == HYDROGENFLUX_isoconc_ID) then
NofMyHomog = count(material_homog == homog)
hydrogenfluxState(homog)%sizeState = 0_pInt
hydrogenfluxState(homog)%sizePostResults = 0_pInt
allocate(hydrogenfluxState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal)
allocate(hydrogenfluxState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal)
allocate(hydrogenfluxState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal)
deallocate(hydrogenConc (homog)%p)
deallocate(hydrogenConcRate(homog)%p)
allocate (hydrogenConc (homog)%p(1), source=0.0_pReal)
allocate (hydrogenConcRate(homog)%p(1), source=0.0_pReal)
endif myhomog
enddo initializeInstances
end subroutine hydrogenflux_isoconc_init
end module hydrogenflux_isoconc

View File

@ -0,0 +1,305 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @brief material subroutine incorporating kinematics resulting from opening of cleavage planes
!> @details to be done
!--------------------------------------------------------------------------------------------------
module kinematics_cleavage_opening
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
kinematics_cleavage_opening_sizePostResults, & !< cumulative size of post results
kinematics_cleavage_opening_offset, & !< which kinematics is my current damage mechanism?
kinematics_cleavage_opening_instance !< instance of damage kinematics mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
kinematics_cleavage_opening_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
kinematics_cleavage_opening_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
kinematics_cleavage_opening_Noutput !< number of outputs per instance of this damage
integer(pInt), dimension(:), allocatable, private :: &
kinematics_cleavage_opening_totalNcleavage !< total number of cleavage systems
integer(pInt), dimension(:,:), allocatable, private :: &
kinematics_cleavage_opening_Ncleavage !< number of cleavage systems per family
real(pReal), dimension(:), allocatable, private :: &
kinematics_cleavage_opening_sdot_0, &
kinematics_cleavage_opening_N
real(pReal), dimension(:,:), allocatable, private :: &
kinematics_cleavage_opening_critDisp, &
kinematics_cleavage_opening_critLoad
public :: &
kinematics_cleavage_opening_init, &
kinematics_cleavage_opening_LiAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine kinematics_cleavage_opening_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_kinematics, &
phase_Nkinematics, &
phase_Noutput, &
KINEMATICS_cleavage_opening_label, &
KINEMATICS_cleavage_opening_ID, &
material_Nphase, &
MATERIAL_partPhase
use numerics,only: &
worldrank
use lattice, only: &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,kinematics
integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_cleavage_opening_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_kinematics == KINEMATICS_cleavage_opening_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(kinematics_cleavage_opening_offset(material_Nphase), source=0_pInt)
allocate(kinematics_cleavage_opening_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
kinematics_cleavage_opening_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_cleavage_opening_ID)
do kinematics = 1, phase_Nkinematics(phase)
if (phase_kinematics(kinematics,phase) == kinematics_cleavage_opening_ID) &
kinematics_cleavage_opening_offset(phase) = kinematics
enddo
enddo
allocate(kinematics_cleavage_opening_sizePostResults(maxNinstance), source=0_pInt)
allocate(kinematics_cleavage_opening_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt)
allocate(kinematics_cleavage_opening_output(maxval(phase_Noutput),maxNinstance))
kinematics_cleavage_opening_output = ''
allocate(kinematics_cleavage_opening_Noutput(maxNinstance), source=0_pInt)
allocate(kinematics_cleavage_opening_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(kinematics_cleavage_opening_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(kinematics_cleavage_opening_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt)
allocate(kinematics_cleavage_opening_totalNcleavage(maxNinstance), source=0_pInt)
allocate(kinematics_cleavage_opening_sdot_0(maxNinstance), source=0.0_pReal)
allocate(kinematics_cleavage_opening_N(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_cleavage_opening_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = kinematics_cleavage_opening_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('anisobrittle_sdot0')
kinematics_cleavage_opening_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisobrittle_ratesensitivity')
kinematics_cleavage_opening_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('ncleavage') !
Nchunks_CleavageFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_CleavageFamilies
kinematics_cleavage_opening_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('anisobrittle_criticaldisplacement')
do j = 1_pInt, Nchunks_CleavageFamilies
kinematics_cleavage_opening_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('anisobrittle_criticalload')
do j = 1_pInt, Nchunks_CleavageFamilies
kinematics_cleavage_opening_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, material_Nphase
myPhase: if (any(phase_kinematics(:,phase) == KINEMATICS_cleavage_opening_ID)) then
instance = kinematics_cleavage_opening_instance(phase)
kinematics_cleavage_opening_Ncleavage(1:lattice_maxNcleavageFamily,instance) = &
min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested
kinematics_cleavage_opening_Ncleavage(1:lattice_maxNcleavageFamily,instance))
kinematics_cleavage_opening_totalNcleavage(instance) = sum(kinematics_cleavage_opening_Ncleavage(:,instance)) ! how many cleavage systems altogether
if (kinematics_cleavage_opening_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//KINEMATICS_cleavage_opening_LABEL//')')
if (any(kinematics_cleavage_opening_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//KINEMATICS_cleavage_opening_LABEL//')')
if (any(kinematics_cleavage_opening_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//KINEMATICS_cleavage_opening_LABEL//')')
if (kinematics_cleavage_opening_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//KINEMATICS_cleavage_opening_LABEL//')')
endif myPhase
enddo sanityChecks
end subroutine kinematics_cleavage_opening_init
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine kinematics_cleavage_opening_LiAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el)
use prec, only: &
tol_math_check
use material, only: &
mappingConstitutive, &
material_homog, &
damage, &
damageMapping
use lattice, only: &
lattice_Scleavage, &
lattice_Scleavage_v, &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(out), dimension(3,3) :: &
Ld !< damage velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
constituent, &
instance, &
homog, damageOffset, &
f, i, index_myFamily, k, l, m, n
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit, &
udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = kinematics_cleavage_opening_instance(phase)
homog = material_homog(ip,el)
damageOffset = damageMapping(homog)%p(ip,el)
Ld = 0.0_pReal
dLd_dTstar3333 = 0.0_pReal
do f = 1_pInt,lattice_maxNcleavageFamily
index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,kinematics_cleavage_opening_Ncleavage(f,instance) ! process each (active) cleavage system in family
traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase))
traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase))
traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase))
traction_crit = kinematics_cleavage_opening_critLoad(f,instance)* &
damage(homog)%p(damageOffset)
udotd = &
sign(1.0_pReal,traction_d)* &
kinematics_cleavage_opening_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance)
if (abs(udotd) > tol_math_check) then
Ld = Ld + udotd*lattice_Scleavage(1:3,1:3,1,index_myFamily+i,phase)
dudotd_dt = sign(1.0_pReal,traction_d)*udotd*kinematics_cleavage_opening_N(instance)/ &
max(0.0_pReal, abs(traction_d) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotd_dt*lattice_Scleavage(k,l,1,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,1,index_myFamily+i,phase)
endif
udott = &
sign(1.0_pReal,traction_t)* &
kinematics_cleavage_opening_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance)
if (abs(udott) > tol_math_check) then
Ld = Ld + udott*lattice_Scleavage(1:3,1:3,2,index_myFamily+i,phase)
dudott_dt = sign(1.0_pReal,traction_t)*udott*kinematics_cleavage_opening_N(instance)/ &
max(0.0_pReal, abs(traction_t) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudott_dt*lattice_Scleavage(k,l,2,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,2,index_myFamily+i,phase)
endif
udotn = &
sign(1.0_pReal,traction_n)* &
kinematics_cleavage_opening_sdot_0(instance)* &
(max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance)
if (abs(udotn) > tol_math_check) then
Ld = Ld + udotn*lattice_Scleavage(1:3,1:3,3,index_myFamily+i,phase)
dudotn_dt = sign(1.0_pReal,traction_n)*udotn*kinematics_cleavage_opening_N(instance)/ &
max(0.0_pReal, abs(traction_n) - traction_crit)
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotn_dt*lattice_Scleavage(k,l,3,index_myFamily+i,phase)* &
lattice_Scleavage(m,n,3,index_myFamily+i,phase)
endif
enddo
enddo
end subroutine kinematics_cleavage_opening_LiAndItsTangent
end module kinematics_cleavage_opening

View File

@ -0,0 +1,220 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating kinematics resulting from interstitial hydrogen
!> @details to be done
!--------------------------------------------------------------------------------------------------
module kinematics_hydrogen_strain
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
kinematics_hydrogen_strain_sizePostResults, & !< cumulative size of post results
kinematics_hydrogen_strain_offset, & !< which kinematics is my current damage mechanism?
kinematics_hydrogen_strain_instance !< instance of damage kinematics mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
kinematics_hydrogen_strain_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
kinematics_hydrogen_strain_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
kinematics_hydrogen_strain_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
kinematics_hydrogen_strain_coeff
public :: &
kinematics_hydrogen_strain_init, &
kinematics_hydrogen_strain_LiAndItsTangent, &
kinematics_hydrogen_strain_ChemPotAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine kinematics_hydrogen_strain_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_kinematics, &
phase_Nkinematics, &
phase_Noutput, &
KINEMATICS_hydrogen_strain_label, &
KINEMATICS_hydrogen_strain_ID, &
material_Nphase, &
MATERIAL_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,kinematics
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_hydrogen_strain_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_kinematics == KINEMATICS_hydrogen_strain_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(kinematics_hydrogen_strain_offset(material_Nphase), source=0_pInt)
allocate(kinematics_hydrogen_strain_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
kinematics_hydrogen_strain_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_hydrogen_strain_ID)
do kinematics = 1, phase_Nkinematics(phase)
if (phase_kinematics(kinematics,phase) == kinematics_hydrogen_strain_ID) &
kinematics_hydrogen_strain_offset(phase) = kinematics
enddo
enddo
allocate(kinematics_hydrogen_strain_sizePostResults(maxNinstance), source=0_pInt)
allocate(kinematics_hydrogen_strain_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(kinematics_hydrogen_strain_output(maxval(phase_Noutput),maxNinstance))
kinematics_hydrogen_strain_output = ''
allocate(kinematics_hydrogen_strain_Noutput(maxNinstance), source=0_pInt)
allocate(kinematics_hydrogen_strain_coeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_hydrogen_strain_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = kinematics_hydrogen_strain_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('hydrogen_strain_coeff')
kinematics_hydrogen_strain_coeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
end subroutine kinematics_hydrogen_strain_init
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine kinematics_hydrogen_strain_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el)
use material, only: &
material_phase, &
material_homog, &
hydrogenConcRate, &
hydrogenfluxMapping
use math, only: &
math_I3
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out), dimension(3,3) :: &
Li !< thermal velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
instance, &
homog, offset
phase = material_phase(ipc,ip,el)
instance = kinematics_hydrogen_strain_instance(phase)
homog = material_homog(ip,el)
offset = hydrogenfluxMapping(homog)%p(ip,el)
Li = hydrogenConcRate(homog)%p(offset)* &
kinematics_hydrogen_strain_coeff(instance)* &
math_I3
dLi_dTstar3333 = 0.0_pReal
end subroutine kinematics_hydrogen_strain_LiAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief contains the kinematic contribution to hydrogen chemical potential
!--------------------------------------------------------------------------------------------------
subroutine kinematics_hydrogen_strain_ChemPotAndItsTangent(ChemPot, dChemPot_dCh, Tstar_v, Fi0, Fi, ipc, ip, el)
use material, only: &
material_phase
use math, only: &
math_inv33, &
math_mul33x33, &
math_Mandel6to33, &
math_transpose33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v
real(pReal), intent(in), dimension(3,3) :: &
Fi0, Fi
real(pReal), intent(out) :: &
ChemPot, dChemPot_dCh
integer(pInt) :: &
phase, &
instance
phase = material_phase(ipc,ip,el)
instance = kinematics_hydrogen_strain_instance(phase)
ChemPot = -kinematics_hydrogen_strain_coeff(instance)* &
sum(math_mul33x33(Fi,math_Mandel6to33(Tstar_v))* &
math_mul33x33(math_mul33x33(Fi,math_inv33(Fi0)),Fi))
dChemPot_dCh = 0.0_pReal
end subroutine kinematics_hydrogen_strain_ChemPotAndItsTangent
end module kinematics_hydrogen_strain

View File

@ -0,0 +1,325 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating kinematics resulting from opening of slip planes
!> @details to be done
!--------------------------------------------------------------------------------------------------
module kinematics_slipplane_opening
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
kinematics_slipplane_opening_sizePostResults, & !< cumulative size of post results
kinematics_slipplane_opening_offset, & !< which kinematics is my current damage mechanism?
kinematics_slipplane_opening_instance !< instance of damage kinematics mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
kinematics_slipplane_opening_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
kinematics_slipplane_opening_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
kinematics_slipplane_opening_Noutput !< number of outputs per instance of this damage
integer(pInt), dimension(:), allocatable, private :: &
kinematics_slipplane_opening_totalNslip !< total number of slip systems
integer(pInt), dimension(:,:), allocatable, private :: &
kinematics_slipplane_opening_Nslip !< number of slip systems per family
real(pReal), dimension(:), allocatable, private :: &
kinematics_slipplane_opening_sdot_0, &
kinematics_slipplane_opening_N
real(pReal), dimension(:,:), allocatable, private :: &
kinematics_slipplane_opening_critPlasticStrain, &
kinematics_slipplane_opening_critLoad
public :: &
kinematics_slipplane_opening_init, &
kinematics_slipplane_opening_LiAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine kinematics_slipplane_opening_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_kinematics, &
phase_Nkinematics, &
phase_Noutput, &
KINEMATICS_slipplane_opening_label, &
KINEMATICS_slipplane_opening_ID, &
material_Nphase, &
MATERIAL_partPhase
use numerics,only: &
worldrank
use lattice, only: &
lattice_maxNslipFamily, &
lattice_NslipSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,kinematics
integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_slipplane_opening_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_kinematics == KINEMATICS_slipplane_opening_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(kinematics_slipplane_opening_offset(material_Nphase), source=0_pInt)
allocate(kinematics_slipplane_opening_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
kinematics_slipplane_opening_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_slipplane_opening_ID)
do kinematics = 1, phase_Nkinematics(phase)
if (phase_kinematics(kinematics,phase) == kinematics_slipplane_opening_ID) &
kinematics_slipplane_opening_offset(phase) = kinematics
enddo
enddo
allocate(kinematics_slipplane_opening_sizePostResults(maxNinstance), source=0_pInt)
allocate(kinematics_slipplane_opening_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(kinematics_slipplane_opening_output(maxval(phase_Noutput),maxNinstance))
kinematics_slipplane_opening_output = ''
allocate(kinematics_slipplane_opening_Noutput(maxNinstance), source=0_pInt)
allocate(kinematics_slipplane_opening_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal)
allocate(kinematics_slipplane_opening_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal)
allocate(kinematics_slipplane_opening_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt)
allocate(kinematics_slipplane_opening_totalNslip(maxNinstance), source=0_pInt)
allocate(kinematics_slipplane_opening_N(maxNinstance), source=0.0_pReal)
allocate(kinematics_slipplane_opening_sdot_0(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_slipplane_opening_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = kinematics_slipplane_opening_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('nslip') !
Nchunks_SlipFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_SlipFamilies
kinematics_slipplane_opening_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('anisoductile_sdot0')
kinematics_slipplane_opening_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisoductile_criticalplasticstrain')
do j = 1_pInt, Nchunks_SlipFamilies
kinematics_slipplane_opening_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('anisoductile_ratesensitivity')
kinematics_slipplane_opening_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisoductile_criticalload')
do j = 1_pInt, Nchunks_SlipFamilies
kinematics_slipplane_opening_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, material_Nphase
myPhase: if (any(phase_kinematics(:,phase) == KINEMATICS_slipplane_opening_ID)) then
instance = kinematics_slipplane_opening_instance(phase)
kinematics_slipplane_opening_Nslip(1:lattice_maxNslipFamily,instance) = &
min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested
kinematics_slipplane_opening_Nslip(1:lattice_maxNslipFamily,instance))
kinematics_slipplane_opening_totalNslip(instance) = sum(kinematics_slipplane_opening_Nslip(:,instance))
if (kinematics_slipplane_opening_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//KINEMATICS_slipplane_opening_LABEL//')')
if (any(kinematics_slipplane_opening_critPlasticStrain(:,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//KINEMATICS_slipplane_opening_LABEL//')')
if (kinematics_slipplane_opening_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//KINEMATICS_slipplane_opening_LABEL//')')
endif myPhase
enddo sanityChecks
end subroutine kinematics_slipplane_opening_init
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine kinematics_slipplane_opening_LiAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el)
use prec, only: &
tol_math_check
use lattice, only: &
lattice_maxNslipFamily, &
lattice_NslipSystem, &
lattice_sd, &
lattice_st, &
lattice_sn
use material, only: &
mappingConstitutive, &
material_homog, &
damage, &
damageMapping
use math, only: &
math_Plain3333to99, &
math_I3, &
math_identity4th, &
math_symmetric33, &
math_Mandel33to6, &
math_tensorproduct, &
math_det33, &
math_mul33x33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(out), dimension(3,3) :: &
Ld !< damage velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor)
real(pReal), dimension(3,3) :: &
projection_d, projection_t, projection_n !< projection modes 3x3 tensor
real(pReal), dimension(6) :: &
projection_d_v, projection_t_v, projection_n_v !< projection modes 3x3 vector
integer(pInt) :: &
phase, &
constituent, &
instance, &
homog, damageOffset, &
f, i, index_myFamily, k, l, m, n
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit, &
udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = kinematics_slipplane_opening_instance(phase)
homog = material_homog(ip,el)
damageOffset = damageMapping(homog)%p(ip,el)
Ld = 0.0_pReal
dLd_dTstar3333 = 0.0_pReal
do f = 1_pInt,lattice_maxNslipFamily
index_myFamily = sum(lattice_NslipSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,kinematics_slipplane_opening_Nslip(f,instance) ! process each (active) slip system in family
projection_d = math_tensorproduct(lattice_sd(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_t = math_tensorproduct(lattice_st(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_n = math_tensorproduct(lattice_sn(1:3,index_myFamily+i,phase),&
lattice_sn(1:3,index_myFamily+i,phase))
projection_d_v(1:6) = math_Mandel33to6(math_symmetric33(projection_d(1:3,1:3)))
projection_t_v(1:6) = math_Mandel33to6(math_symmetric33(projection_t(1:3,1:3)))
projection_n_v(1:6) = math_Mandel33to6(math_symmetric33(projection_n(1:3,1:3)))
traction_d = dot_product(Tstar_v,projection_d_v(1:6))
traction_t = dot_product(Tstar_v,projection_t_v(1:6))
traction_n = dot_product(Tstar_v,projection_n_v(1:6))
traction_crit = kinematics_slipplane_opening_critLoad(f,instance)* &
damage(homog)%p(damageOffset) ! degrading critical load carrying capacity by damage
udotd = &
sign(1.0_pReal,traction_d)* &
kinematics_slipplane_opening_sdot_0(instance)* &
(abs(traction_d)/traction_crit - &
abs(traction_d)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance)
if (abs(udotd) > tol_math_check) then
Ld = Ld + udotd*projection_d
dudotd_dt = udotd*kinematics_slipplane_opening_N(instance)/traction_d
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotd_dt*projection_d(k,l)*projection_d(m,n)
endif
udott = &
sign(1.0_pReal,traction_t)* &
kinematics_slipplane_opening_sdot_0(instance)* &
(abs(traction_t)/traction_crit - &
abs(traction_t)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance)
if (abs(udott) > tol_math_check) then
Ld = Ld + udott*projection_t
dudott_dt = udott*kinematics_slipplane_opening_N(instance)/traction_t
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudott_dt*projection_t(k,l)*projection_t(m,n)
endif
udotn = &
kinematics_slipplane_opening_sdot_0(instance)* &
(max(0.0_pReal,traction_n)/traction_crit - &
max(0.0_pReal,traction_n)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance)
if (abs(udotn) > tol_math_check) then
Ld = Ld + udotn*projection_n
dudotn_dt = udotn*kinematics_slipplane_opening_N(instance)/traction_n
forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) &
dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + &
dudotn_dt*projection_n(k,l)*projection_n(m,n)
endif
enddo
enddo
end subroutine kinematics_slipplane_opening_LiAndItsTangent
end module kinematics_slipplane_opening

View File

@ -0,0 +1,182 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating kinematics resulting from thermal expansion
!> @details to be done
!--------------------------------------------------------------------------------------------------
module kinematics_thermal_expansion
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
kinematics_thermal_expansion_sizePostResults, & !< cumulative size of post results
kinematics_thermal_expansion_offset, & !< which kinematics is my current damage mechanism?
kinematics_thermal_expansion_instance !< instance of damage kinematics mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
kinematics_thermal_expansion_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
kinematics_thermal_expansion_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
kinematics_thermal_expansion_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
kinematics_thermal_expansion_coeff
public :: &
kinematics_thermal_expansion_init, &
kinematics_thermal_expansion_LiAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine kinematics_thermal_expansion_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_kinematics, &
phase_Nkinematics, &
phase_Noutput, &
KINEMATICS_thermal_expansion_label, &
KINEMATICS_thermal_expansion_ID, &
material_Nphase, &
MATERIAL_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,kinematics
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_thermal_expansion_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_kinematics == KINEMATICS_thermal_expansion_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(kinematics_thermal_expansion_offset(material_Nphase), source=0_pInt)
allocate(kinematics_thermal_expansion_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
kinematics_thermal_expansion_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_thermal_expansion_ID)
do kinematics = 1, phase_Nkinematics(phase)
if (phase_kinematics(kinematics,phase) == kinematics_thermal_expansion_ID) &
kinematics_thermal_expansion_offset(phase) = kinematics
enddo
enddo
allocate(kinematics_thermal_expansion_sizePostResults(maxNinstance), source=0_pInt)
allocate(kinematics_thermal_expansion_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(kinematics_thermal_expansion_output(maxval(phase_Noutput),maxNinstance))
kinematics_thermal_expansion_output = ''
allocate(kinematics_thermal_expansion_Noutput(maxNinstance), source=0_pInt)
allocate(kinematics_thermal_expansion_coeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_thermal_expansion_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = kinematics_thermal_expansion_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('thermal_expansion_coeff')
kinematics_thermal_expansion_coeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
end subroutine kinematics_thermal_expansion_init
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine kinematics_thermal_expansion_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el)
use material, only: &
material_phase, &
material_homog, &
temperatureRate, &
thermalMapping
use math, only: &
math_I3
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out), dimension(3,3) :: &
Li !< thermal velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
instance, &
homog, offset
phase = material_phase(ipc,ip,el)
instance = kinematics_thermal_expansion_instance(phase)
homog = material_homog(ip,el)
offset = thermalMapping(homog)%p(ip,el)
Li = temperatureRate(homog)%p(offset)* &
kinematics_thermal_expansion_coeff(instance)* &
math_I3
dLi_dTstar3333 = 0.0_pReal
end subroutine kinematics_thermal_expansion_LiAndItsTangent
end module kinematics_thermal_expansion

View File

@ -0,0 +1,220 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating kinematics resulting from vacancy point defects
!> @details to be done
!--------------------------------------------------------------------------------------------------
module kinematics_vacancy_strain
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
kinematics_vacancy_strain_sizePostResults, & !< cumulative size of post results
kinematics_vacancy_strain_offset, & !< which kinematics is my current damage mechanism?
kinematics_vacancy_strain_instance !< instance of damage kinematics mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
kinematics_vacancy_strain_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
kinematics_vacancy_strain_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
kinematics_vacancy_strain_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
kinematics_vacancy_strain_coeff
public :: &
kinematics_vacancy_strain_init, &
kinematics_vacancy_strain_LiAndItsTangent, &
kinematics_vacancy_strain_ChemPotAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine kinematics_vacancy_strain_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_kinematics, &
phase_Nkinematics, &
phase_Noutput, &
KINEMATICS_vacancy_strain_label, &
KINEMATICS_vacancy_strain_ID, &
material_Nphase, &
MATERIAL_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,kinematics
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_vacancy_strain_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_kinematics == KINEMATICS_vacancy_strain_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(kinematics_vacancy_strain_offset(material_Nphase), source=0_pInt)
allocate(kinematics_vacancy_strain_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
kinematics_vacancy_strain_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_vacancy_strain_ID)
do kinematics = 1, phase_Nkinematics(phase)
if (phase_kinematics(kinematics,phase) == kinematics_vacancy_strain_ID) &
kinematics_vacancy_strain_offset(phase) = kinematics
enddo
enddo
allocate(kinematics_vacancy_strain_sizePostResults(maxNinstance), source=0_pInt)
allocate(kinematics_vacancy_strain_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(kinematics_vacancy_strain_output(maxval(phase_Noutput),maxNinstance))
kinematics_vacancy_strain_output = ''
allocate(kinematics_vacancy_strain_Noutput(maxNinstance), source=0_pInt)
allocate(kinematics_vacancy_strain_coeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_vacancy_strain_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = kinematics_vacancy_strain_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('vacancy_strain_coeff')
kinematics_vacancy_strain_coeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
end subroutine kinematics_vacancy_strain_init
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine kinematics_vacancy_strain_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el)
use material, only: &
material_phase, &
material_homog, &
vacancyConcRate, &
vacancyfluxMapping
use math, only: &
math_I3
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out), dimension(3,3) :: &
Li !< thermal velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
instance, &
homog, offset
phase = material_phase(ipc,ip,el)
instance = kinematics_vacancy_strain_instance(phase)
homog = material_homog(ip,el)
offset = vacancyfluxMapping(homog)%p(ip,el)
Li = vacancyConcRate(homog)%p(offset)* &
kinematics_vacancy_strain_coeff(instance)* &
math_I3
dLi_dTstar3333 = 0.0_pReal
end subroutine kinematics_vacancy_strain_LiAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief contains the kinematic contribution to vacancy chemical potential
!--------------------------------------------------------------------------------------------------
subroutine kinematics_vacancy_strain_ChemPotAndItsTangent(ChemPot, dChemPot_dCv, Tstar_v, Fi0, Fi, ipc, ip, el)
use material, only: &
material_phase
use math, only: &
math_inv33, &
math_mul33x33, &
math_Mandel6to33, &
math_transpose33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v
real(pReal), intent(in), dimension(3,3) :: &
Fi0, Fi
real(pReal), intent(out) :: &
ChemPot, dChemPot_dCv
integer(pInt) :: &
phase, &
instance
phase = material_phase(ipc,ip,el)
instance = kinematics_vacancy_strain_instance(phase)
ChemPot = -kinematics_vacancy_strain_coeff(instance)* &
sum(math_mul33x33(Fi,math_Mandel6to33(Tstar_v))* &
math_mul33x33(math_mul33x33(Fi,math_inv33(Fi0)),Fi))
dChemPot_dCv = 0.0_pReal
end subroutine kinematics_vacancy_strain_ChemPotAndItsTangent
end module kinematics_vacancy_strain

View File

@ -833,12 +833,18 @@ module lattice
lattice_thermalConductivity33, & lattice_thermalConductivity33, &
lattice_thermalExpansion33, & lattice_thermalExpansion33, &
lattice_damageDiffusion33, & lattice_damageDiffusion33, &
lattice_vacancyDiffusion33 lattice_vacancyfluxDiffusion33, &
lattice_vacancyfluxMobility33, &
lattice_porosityDiffusion33, &
lattice_hydrogenfluxDiffusion33, &
lattice_hydrogenfluxMobility33
real(pReal), dimension(:), allocatable, public, protected :: & real(pReal), dimension(:), allocatable, public, protected :: &
lattice_damageMobility, & lattice_damageMobility, &
lattice_vacancyMobility, & lattice_porosityMobility, &
lattice_massDensity, & lattice_massDensity, &
lattice_specificHeat, & lattice_specificHeat, &
lattice_vacancyVol, &
lattice_hydrogenVol, &
lattice_referenceTemperature, & lattice_referenceTemperature, &
lattice_equilibriumVacancyConcentration lattice_equilibriumVacancyConcentration
enum, bind(c) enum, bind(c)
@ -1101,15 +1107,21 @@ subroutine lattice_init
allocate(lattice_structure(Nphases),source = LATTICE_undefined_ID) allocate(lattice_structure(Nphases),source = LATTICE_undefined_ID)
allocate(lattice_C66(6,6,Nphases), source=0.0_pReal) allocate(lattice_C66(6,6,Nphases), source=0.0_pReal)
allocate(lattice_C3333(3,3,3,3,Nphases), source=0.0_pReal) allocate(lattice_C3333(3,3,3,3,Nphases), source=0.0_pReal)
allocate(lattice_thermalConductivity33(3,3,Nphases), source=0.0_pReal) allocate(lattice_thermalConductivity33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_thermalExpansion33 (3,3,Nphases), source=0.0_pReal) allocate(lattice_thermalExpansion33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_damageDiffusion33 (3,3,Nphases), source=0.0_pReal) allocate(lattice_damageDiffusion33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_vacancyDiffusion33 (3,3,Nphases), source=0.0_pReal) allocate(lattice_vacancyfluxDiffusion33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_damageMobility ( Nphases), source=0.0_pReal) allocate(lattice_vacancyfluxMobility33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_vacancyMobility ( Nphases), source=0.0_pReal) allocate(lattice_PorosityDiffusion33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_massDensity ( Nphases), source=0.0_pReal) allocate(lattice_hydrogenfluxDiffusion33(3,3,Nphases), source=0.0_pReal)
allocate(lattice_specificHeat ( Nphases), source=0.0_pReal) allocate(lattice_hydrogenfluxMobility33 (3,3,Nphases), source=0.0_pReal)
allocate(lattice_referenceTemperature ( Nphases), source=0.0_pReal) allocate(lattice_damageMobility ( Nphases), source=0.0_pReal)
allocate(lattice_PorosityMobility ( Nphases), source=0.0_pReal)
allocate(lattice_massDensity ( Nphases), source=0.0_pReal)
allocate(lattice_specificHeat ( Nphases), source=0.0_pReal)
allocate(lattice_vacancyVol ( Nphases), source=0.0_pReal)
allocate(lattice_hydrogenVol ( Nphases), source=0.0_pReal)
allocate(lattice_referenceTemperature ( Nphases), source=0.0_pReal)
allocate(lattice_equilibriumVacancyConcentration(Nphases), source=0.0_pReal) allocate(lattice_equilibriumVacancyConcentration(Nphases), source=0.0_pReal)
allocate(lattice_mu(Nphases), source=0.0_pReal) allocate(lattice_mu(Nphases), source=0.0_pReal)
@ -1232,6 +1244,10 @@ subroutine lattice_init
lattice_thermalExpansion33(3,3,section) = IO_floatValue(line,positions,2_pInt) lattice_thermalExpansion33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('specific_heat') case ('specific_heat')
lattice_specificHeat(section) = IO_floatValue(line,positions,2_pInt) lattice_specificHeat(section) = IO_floatValue(line,positions,2_pInt)
case ('vacancyvolume')
lattice_vacancyVol(section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenvolume')
lattice_hydrogenVol(section) = IO_floatValue(line,positions,2_pInt)
case ('mass_density') case ('mass_density')
lattice_massDensity(section) = IO_floatValue(line,positions,2_pInt) lattice_massDensity(section) = IO_floatValue(line,positions,2_pInt)
case ('reference_temperature') case ('reference_temperature')
@ -1244,14 +1260,38 @@ subroutine lattice_init
lattice_DamageDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) lattice_DamageDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('damage_mobility') case ('damage_mobility')
lattice_DamageMobility(section) = IO_floatValue(line,positions,2_pInt) lattice_DamageMobility(section) = IO_floatValue(line,positions,2_pInt)
case ('vacancy_diffusion11') case ('vacancyflux_diffusion11')
lattice_VacancyDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt) lattice_vacancyfluxDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancy_diffusion22') case ('vacancyflux_diffusion22')
lattice_VacancyDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt) lattice_vacancyfluxDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancy_diffusion33') case ('vacancyflux_diffusion33')
lattice_VacancyDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) lattice_vacancyfluxDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancy_mobility') case ('vacancyflux_mobility11')
lattice_VacancyMobility(section) = IO_floatValue(line,positions,2_pInt) lattice_vacancyfluxMobility33(1,1,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancyflux_mobility22')
lattice_vacancyfluxMobility33(2,2,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancyflux_mobility33')
lattice_vacancyfluxMobility33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('porosity_diffusion11')
lattice_PorosityDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt)
case ('porosity_diffusion22')
lattice_PorosityDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt)
case ('porosity_diffusion33')
lattice_PorosityDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('porosity_mobility')
lattice_PorosityMobility(section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_diffusion11')
lattice_hydrogenfluxDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_diffusion22')
lattice_hydrogenfluxDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_diffusion33')
lattice_hydrogenfluxDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_mobility11')
lattice_hydrogenfluxMobility33(1,1,section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_mobility22')
lattice_hydrogenfluxMobility33(2,2,section) = IO_floatValue(line,positions,2_pInt)
case ('hydrogenflux_mobility33')
lattice_hydrogenfluxMobility33(3,3,section) = IO_floatValue(line,positions,2_pInt)
case ('vacancy_eqcv') case ('vacancy_eqcv')
lattice_equilibriumVacancyConcentration(section) = IO_floatValue(line,positions,2_pInt) lattice_equilibriumVacancyConcentration(section) = IO_floatValue(line,positions,2_pInt)
end select end select
@ -1322,7 +1362,7 @@ subroutine lattice_initializeStructure(myPhase,CoverA,aA,aM,cM)
cd, cn, ct cd, cn, ct
integer(pInt) :: & integer(pInt) :: &
i,j, & i,j, &
myNslip, myNtwin, myNtrans, myNcleavage myNslip = 0_pInt, myNtwin = 0_pInt, myNtrans = 0_pInt, myNcleavage = 0_pInt
lattice_C66(1:6,1:6,myPhase) = lattice_symmetrizeC66(lattice_structure(myPhase),& lattice_C66(1:6,1:6,myPhase) = lattice_symmetrizeC66(lattice_structure(myPhase),&
lattice_C66(1:6,1:6,myPhase)) lattice_C66(1:6,1:6,myPhase))
@ -1347,8 +1387,16 @@ subroutine lattice_initializeStructure(myPhase,CoverA,aA,aM,cM)
lattice_thermalExpansion33(1:3,1:3,myPhase)) lattice_thermalExpansion33(1:3,1:3,myPhase))
lattice_DamageDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& lattice_DamageDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_DamageDiffusion33(1:3,1:3,myPhase)) lattice_DamageDiffusion33(1:3,1:3,myPhase))
lattice_VacancyDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& lattice_vacancyfluxDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_VacancyDiffusion33(1:3,1:3,myPhase)) lattice_vacancyfluxDiffusion33(1:3,1:3,myPhase))
lattice_vacancyfluxMobility33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_vacancyfluxMobility33(1:3,1:3,myPhase))
lattice_PorosityDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_PorosityDiffusion33(1:3,1:3,myPhase))
lattice_hydrogenfluxDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_hydrogenfluxDiffusion33(1:3,1:3,myPhase))
lattice_hydrogenfluxMobility33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),&
lattice_hydrogenfluxMobility33(1:3,1:3,myPhase))
select case(lattice_structure(myPhase)) select case(lattice_structure(myPhase))
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------

View File

@ -14,41 +14,55 @@ module material
pInt, & pInt, &
tState, & tState, &
tPlasticState, & tPlasticState, &
tFieldData, & tSourceState, &
tHomogMapping, &
tPhaseMapping, &
p_vec, &
p_intvec p_intvec
implicit none implicit none
private private
character(len=*), parameter, public :: & character(len=*), parameter, public :: &
ELASTICITY_hooke_label = 'hooke', & ELASTICITY_hooke_label = 'hooke', &
PLASTICITY_none_label = 'none', & PLASTICITY_none_label = 'none', &
PLASTICITY_j2_label = 'j2', & PLASTICITY_j2_label = 'j2', &
PLASTICITY_phenopowerlaw_label = 'phenopowerlaw', & PLASTICITY_phenopowerlaw_label = 'phenopowerlaw', &
PLASTICITY_dislotwin_label = 'dislotwin', & PLASTICITY_dislotwin_label = 'dislo&twin', &
PLASTICITY_dislokmc_label = 'dislokmc', & PLASTICITY_dislokmc_label = 'dislokmc', &
PLASTICITY_disloucla_label = 'disloucla', & PLASTICITY_disloucla_label = 'disloucla', &
PLASTICITY_titanmod_label = 'titanmod', & PLASTICITY_titanmod_label = 'titanmod', &
PLASTICITY_nonlocal_label = 'nonlocal', & PLASTICITY_nonlocal_label = 'nonlocal', &
LOCAL_DAMAGE_none_LABEL = 'none', & SOURCE_thermal_dissipation_label = 'thermal_dissipation', &
LOCAL_DAMAGE_isoBrittle_LABEL = 'isobrittle', & SOURCE_damage_isoBrittle_label = 'damage_isobrittle', &
LOCAL_DAMAGE_isoDuctile_LABEL = 'isoductile', & SOURCE_damage_isoDuctile_label = 'damage_isoductile', &
LOCAL_DAMAGE_anisoBrittle_LABEL= 'anisobrittle', & SOURCE_damage_anisoBrittle_label = 'damage_anisobrittle', &
LOCAL_DAMAGE_anisoDuctile_LABEL= 'anisoductile', & SOURCE_damage_anisoDuctile_label = 'damage_anisoductile', &
LOCAL_DAMAGE_gurson_LABEL = 'gurson', & SOURCE_vacancy_phenoplasticity_label = 'vacancy_phenoplasticity', &
LOCAL_DAMAGE_phaseField_LABEL = 'phasefield', & SOURCE_vacancy_irradiation_label = 'vacancy_irradiation', &
LOCAL_THERMAL_isothermal_label = 'isothermal', & SOURCE_vacancy_thermalfluc_label = 'vacancy_thermalfluctuation', &
LOCAL_THERMAL_adiabatic_label = 'adiabatic', & KINEMATICS_thermal_expansion_label = 'thermal_expansion', &
LOCAL_VACANCY_constant_label = 'constant', & KINEMATICS_cleavage_opening_label = 'cleavage_opening', &
LOCAL_VACANCY_generation_label = 'generation', & KINEMATICS_slipplane_opening_label = 'slipplane_opening', &
FIELD_DAMAGE_local_label = 'local', & KINEMATICS_vacancy_strain_label = 'vacancy_strain', &
FIELD_DAMAGE_nonlocal_label = 'nonlocal', & KINEMATICS_hydrogen_strain_label = 'hydrogen_strain', &
FIELD_THERMAL_local_label = 'local', & STIFFNESS_DEGRADATION_damage_label = 'damage', &
FIELD_THERMAL_nonlocal_label = 'nonlocal', & STIFFNESS_DEGRADATION_porosity_label = 'porosity', &
FIELD_VACANCY_local_label = 'local', & THERMAL_isothermal_label = 'isothermal', &
FIELD_VACANCY_nonlocal_label = 'nonlocal', & THERMAL_adiabatic_label = 'adiabatic', &
HOMOGENIZATION_none_label = 'none', & THERMAL_conduction_label = 'conduction', &
HOMOGENIZATION_isostrain_label = 'isostrain', & DAMAGE_none_label = 'none', &
HOMOGENIZATION_rgc_label = 'rgc' DAMAGE_local_label = 'local', &
DAMAGE_nonlocal_label = 'nonlocal', &
VACANCYFLUX_isoconc_label = 'isoconcentration', &
VACANCYFLUX_isochempot_label = 'isochemicalpotential', &
VACANCYFLUX_cahnhilliard_label = 'cahnhilliard', &
POROSITY_none_label = 'none', &
POROSITY_phasefield_label = 'phasefield', &
HYDROGENFLUX_isoconc_label = 'isoconcentration', &
HYDROGENFLUX_cahnhilliard_label = 'cahnhilliard', &
HOMOGENIZATION_none_label = 'none', &
HOMOGENIZATION_isostrain_label = 'isostrain', &
HOMOGENIZATION_rgc_label = 'rgc'
@ -67,37 +81,61 @@ module material
PLASTICITY_titanmod_ID, & PLASTICITY_titanmod_ID, &
PLASTICITY_nonlocal_ID PLASTICITY_nonlocal_ID
end enum end enum
enum, bind(c) enum, bind(c)
enumerator :: LOCAL_DAMAGE_none_ID, & enumerator :: SOURCE_undefined_ID, &
LOCAL_DAMAGE_isoBrittle_ID, & SOURCE_thermal_dissipation_ID, &
LOCAL_DAMAGE_isoDuctile_ID, & SOURCE_damage_isoBrittle_ID, &
LOCAL_DAMAGE_anisoBrittle_ID, & SOURCE_damage_isoDuctile_ID, &
LOCAL_DAMAGE_anisoDuctile_ID, & SOURCE_damage_anisoBrittle_ID, &
LOCAL_DAMAGE_gurson_ID, & SOURCE_damage_anisoDuctile_ID, &
LOCAL_DAMAGE_phaseField_ID SOURCE_vacancy_phenoplasticity_ID, &
end enum SOURCE_vacancy_irradiation_ID, &
enum, bind(c) SOURCE_vacancy_thermalfluc_ID
enumerator :: LOCAL_THERMAL_isothermal_ID, &
LOCAL_THERMAL_adiabatic_ID
end enum
enum, bind(c)
enumerator :: LOCAL_VACANCY_constant_ID, &
LOCAL_VACANCY_generation_ID
end enum end enum
enum, bind(c) enum, bind(c)
enumerator :: FIELD_DAMAGE_local_ID ,& enumerator :: KINEMATICS_undefined_ID, &
FIELD_DAMAGE_nonlocal_ID KINEMATICS_cleavage_opening_ID, &
KINEMATICS_slipplane_opening_ID, &
KINEMATICS_thermal_expansion_ID, &
KINEMATICS_vacancy_strain_ID, &
KINEMATICS_hydrogen_strain_ID
end enum
enum, bind(c)
enumerator :: STIFFNESS_DEGRADATION_undefined_ID, &
STIFFNESS_DEGRADATION_damage_ID, &
STIFFNESS_DEGRADATION_porosity_ID
end enum
enum, bind(c)
enumerator :: THERMAL_isothermal_ID, &
THERMAL_adiabatic_ID, &
THERMAL_conduction_ID
end enum
enum, bind(c)
enumerator :: DAMAGE_none_ID, &
DAMAGE_local_ID, &
DAMAGE_nonlocal_ID
end enum
enum, bind(c)
enumerator :: VACANCYFLUX_isoconc_ID, &
VACANCYFLUX_isochempot_ID, &
VACANCYFLUX_cahnhilliard_ID
end enum
enum, bind(c)
enumerator :: POROSITY_none_ID, &
POROSITY_phasefield_ID
end enum end enum
enum, bind(c) enum, bind(c)
enumerator :: FIELD_THERMAL_local_ID, & enumerator :: HYDROGENFLUX_isoconc_ID, &
FIELD_THERMAL_nonlocal_ID HYDROGENFLUX_cahnhilliard_ID
end enum
enum, bind(c)
enumerator :: FIELD_VACANCY_local_ID, &
FIELD_VACANCY_nonlocal_ID
end enum end enum
enum, bind(c) enum, bind(c)
enumerator :: HOMOGENIZATION_undefined_ID, & enumerator :: HOMOGENIZATION_undefined_ID, &
HOMOGENIZATION_none_ID, & HOMOGENIZATION_none_ID, &
@ -118,18 +156,21 @@ module material
phase_elasticity !< elasticity of each phase phase_elasticity !< elasticity of each phase
integer(kind(PLASTICITY_undefined_ID)), dimension(:), allocatable, public, protected :: & integer(kind(PLASTICITY_undefined_ID)), dimension(:), allocatable, public, protected :: &
phase_plasticity !< plasticity of each phase phase_plasticity !< plasticity of each phase
integer(kind(LOCAL_DAMAGE_none_ID)), dimension(:), allocatable, public, protected :: & integer(kind(THERMAL_isothermal_ID)), dimension(:), allocatable, public, protected :: &
phase_damage !< local damage of each phase thermal_type !< thermal transport model
integer(kind(LOCAL_THERMAL_isothermal_ID)), dimension(:), allocatable, public, protected :: & integer(kind(DAMAGE_none_ID)), dimension(:), allocatable, public, protected :: &
phase_thermal !< local thermal of each phase damage_type !< nonlocal damage model
integer(kind(LOCAL_VACANCY_constant_ID)), dimension(:), allocatable, public, protected :: & integer(kind(VACANCYFLUX_isoconc_ID)), dimension(:), allocatable, public, protected :: &
phase_vacancy !< local vacancy model of each phase vacancyflux_type !< vacancy transport model
integer(kind(FIELD_DAMAGE_local_ID)), dimension(:), allocatable, public, protected :: & integer(kind(POROSITY_none_ID)), dimension(:), allocatable, public, protected :: &
field_damage_type !< field damage of each phase porosity_type !< porosity evolution model
integer(kind(FIELD_THERMAL_local_ID)), dimension(:), allocatable, public, protected :: & integer(kind(HYDROGENFLUX_isoconc_ID)), dimension(:), allocatable, public, protected :: &
field_thermal_type !< field thermal of each phase hydrogenflux_type !< hydrogen transport model
integer(kind(FIELD_VACANCY_local_ID)), dimension(:), allocatable, public, protected :: &
field_vacancy_type !< field vacancy of each phase integer(kind(SOURCE_undefined_ID)), dimension(:,:), allocatable, public, protected :: &
phase_source, & !< active sources mechanisms of each phase
phase_kinematics, & !< active kinematic mechanisms of each phase
phase_stiffnessDegradation !< active stiffness degradation mechanisms of each phase
integer(kind(HOMOGENIZATION_undefined_ID)), dimension(:), allocatable, public, protected :: & integer(kind(HOMOGENIZATION_undefined_ID)), dimension(:), allocatable, public, protected :: &
homogenization_type !< type of each homogenization homogenization_type !< type of each homogenization
@ -146,17 +187,24 @@ module material
material_Nmicrostructure, & !< number of microstructures material_Nmicrostructure, & !< number of microstructures
material_Ncrystallite !< number of crystallite settings material_Ncrystallite !< number of crystallite settings
integer(pInt), dimension(:), allocatable, public, protected :: &
phase_Nsources, & !< number of source mechanisms active in each phase
phase_Nkinematics, & !< number of kinematic mechanisms active in each phase
phase_NstiffnessDegradations !< number of stiffness degradation mechanisms active in each phase
integer(pInt), dimension(:), allocatable, public, protected :: & integer(pInt), dimension(:), allocatable, public, protected :: &
homogenization_Ngrains, & !< number of grains in each homogenization homogenization_Ngrains, & !< number of grains in each homogenization
homogenization_Noutput, & !< number of '(output)' items per homogenization homogenization_Noutput, & !< number of '(output)' items per homogenization
phase_Noutput, & !< number of '(output)' items per phase phase_Noutput, & !< number of '(output)' items per phase
phase_elasticityInstance, & !< instance of particular elasticity of each phase phase_elasticityInstance, & !< instance of particular elasticity of each phase
phase_plasticityInstance, & !< instance of particular plasticity of each phase phase_plasticityInstance, & !< instance of particular plasticity of each phase
phase_damageInstance, & !< instance of particular damage of each phase
phase_thermalInstance, & !< instance of particular thermal of each phase
phase_vacancyInstance, & !< instance of particular vacancy model of each phase
crystallite_Noutput, & !< number of '(output)' items per crystallite setting crystallite_Noutput, & !< number of '(output)' items per crystallite setting
homogenization_typeInstance, & !< instance of particular type of each homogenization homogenization_typeInstance, & !< instance of particular type of each homogenization
thermal_typeInstance, & !< instance of particular type of each thermal transport
damage_typeInstance, & !< instance of particular type of each nonlocal damage
vacancyflux_typeInstance, & !< instance of particular type of each vacancy flux
porosity_typeInstance, & !< instance of particular type of each porosity model
hydrogenflux_typeInstance, & !< instance of particular type of each hydrogen flux
microstructure_crystallite !< crystallite setting ID of each microstructure microstructure_crystallite !< crystallite setting ID of each microstructure
integer(pInt), dimension(:,:,:), allocatable, public :: & integer(pInt), dimension(:,:,:), allocatable, public :: &
@ -165,19 +213,15 @@ module material
material_homog !< homogenization (index) of each IP,element material_homog !< homogenization (index) of each IP,element
type(tPlasticState), allocatable, dimension(:), public :: & type(tPlasticState), allocatable, dimension(:), public :: &
plasticState plasticState
type(tState), allocatable, dimension(:), public :: & type(tSourceState), allocatable, dimension(:), public :: &
sourceState
type(tState), allocatable, dimension(:), public :: &
homogState, &
thermalState, &
damageState, & damageState, &
thermalState,& vacancyfluxState, &
vacancyState,& porosityState, &
homogState hydrogenfluxState
type(tFieldData), allocatable, dimension(:), public :: &
fieldDamage
type(tFieldData), allocatable, dimension(:), public :: &
fieldThermal
type(tFieldData), allocatable, dimension(:), public :: &
fieldVacancy
integer(pInt), dimension(:,:,:), allocatable, public, protected :: & integer(pInt), dimension(:,:,:), allocatable, public, protected :: &
material_texture !< texture (index) of each grain,IP,element material_texture !< texture (index) of each grain,IP,element
@ -230,9 +274,27 @@ module material
logical, dimension(:), allocatable, private :: & logical, dimension(:), allocatable, private :: &
homogenization_active homogenization_active
integer(pInt), dimension(:,:,:,:), allocatable, public, protected :: mappingConstitutive integer(pInt), dimension(:,:,:,:), allocatable, public, target :: mappingConstitutive
integer(pInt), dimension(:,:,:), allocatable, public, protected :: mappingCrystallite integer(pInt), dimension(:,:,:), allocatable, public, target :: mappingCrystallite
integer(pInt), dimension(:,:,:), allocatable, public, protected :: mappingHomogenization integer(pInt), dimension(:,:,:), allocatable, public, target :: mappingHomogenization !< mapping from material points to offset in heterogenous state/field
integer(pInt), dimension(:,:), allocatable, public, target :: mappingHomogenizationConst !< mapping from material points to offset in constant state/field
type(tHomogMapping), allocatable, dimension(:), public :: &
thermalMapping, & !< mapping for thermal state/fields
damageMapping, & !< mapping for damage state/fields
vacancyfluxMapping, & !< mapping for vacancy conc state/fields
porosityMapping, & !< mapping for porosity state/fields
hydrogenfluxMapping !< mapping for hydrogen conc state/fields
type(p_vec), allocatable, dimension(:), public :: &
temperature, & !< temperature field
damage, & !< damage field
vacancyConc, & !< vacancy conc field
porosity, & !< porosity field
hydrogenConc, & !< hydrogen conc field
temperatureRate, & !< temperature change rate field
vacancyConcRate, & !< vacancy conc change field
hydrogenConcRate !< hydrogen conc change field
public :: & public :: &
material_init, & material_init, &
@ -245,23 +307,34 @@ module material
PLASTICITY_disloucla_ID, & PLASTICITY_disloucla_ID, &
PLASTICITY_titanmod_ID, & PLASTICITY_titanmod_ID, &
PLASTICITY_nonlocal_ID, & PLASTICITY_nonlocal_ID, &
LOCAL_DAMAGE_none_ID, & SOURCE_thermal_dissipation_ID, &
LOCAL_DAMAGE_isoBrittle_ID, & SOURCE_damage_isoBrittle_ID, &
LOCAL_DAMAGE_isoDuctile_ID, & SOURCE_damage_isoDuctile_ID, &
LOCAL_DAMAGE_anisoBrittle_ID, & SOURCE_damage_anisoBrittle_ID, &
LOCAL_DAMAGE_anisoDuctile_ID, & SOURCE_damage_anisoDuctile_ID, &
LOCAL_DAMAGE_gurson_ID, & SOURCE_vacancy_phenoplasticity_ID, &
LOCAL_DAMAGE_phaseField_ID, & SOURCE_vacancy_irradiation_ID, &
LOCAL_THERMAL_isothermal_ID, & SOURCE_vacancy_thermalfluc_ID, &
LOCAL_THERMAL_adiabatic_ID, & KINEMATICS_cleavage_opening_ID, &
LOCAL_VACANCY_constant_ID, & KINEMATICS_slipplane_opening_ID, &
LOCAL_VACANCY_generation_ID, & KINEMATICS_thermal_expansion_ID, &
FIELD_DAMAGE_local_ID, & KINEMATICS_vacancy_strain_ID, &
FIELD_DAMAGE_nonlocal_ID, & KINEMATICS_hydrogen_strain_ID, &
FIELD_THERMAL_local_ID, & STIFFNESS_DEGRADATION_damage_ID, &
FIELD_THERMAL_nonlocal_ID, & STIFFNESS_DEGRADATION_porosity_ID, &
FIELD_VACANCY_local_ID, & THERMAL_isothermal_ID, &
FIELD_VACANCY_nonlocal_ID, & THERMAL_adiabatic_ID, &
THERMAL_conduction_ID, &
DAMAGE_none_ID, &
DAMAGE_local_ID, &
DAMAGE_nonlocal_ID, &
VACANCYFLUX_isoconc_ID, &
VACANCYFLUX_isochempot_ID, &
VACANCYFLUX_cahnhilliard_ID, &
POROSITY_none_ID, &
POROSITY_phasefield_ID, &
HYDROGENFLUX_isoconc_ID, &
HYDROGENFLUX_cahnhilliard_ID, &
HOMOGENIZATION_none_ID, & HOMOGENIZATION_none_ID, &
HOMOGENIZATION_isostrain_ID, & HOMOGENIZATION_isostrain_ID, &
#ifdef HDF #ifdef HDF
@ -285,7 +358,7 @@ contains
!> @details figures out if solverJobName.materialConfig is present, if not looks for !> @details figures out if solverJobName.materialConfig is present, if not looks for
!> material.config !> material.config
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine material_init(temperature_init) subroutine material_init()
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use IO, only: & use IO, only: &
IO_error, & IO_error, &
@ -307,16 +380,13 @@ subroutine material_init(temperature_init)
worldrank worldrank
implicit none implicit none
real(pReal), intent(in) :: temperature_init !< initial field temperature
integer(pInt), parameter :: FILEUNIT = 200_pInt integer(pInt), parameter :: FILEUNIT = 200_pInt
integer(pInt) :: m,c,h, myDebug, myHomog integer(pInt) :: m,c,h, myDebug, myPhase, myHomog
integer(pInt) :: & integer(pInt) :: &
g, & !< grain number g, & !< grain number
i, & !< integration point number i, & !< integration point number
e, & !< element number e, & !< element number
phase, & phase
homog, &
NofMyField
integer(pInt), dimension(:), allocatable :: ConstitutivePosition integer(pInt), dimension(:), allocatable :: ConstitutivePosition
integer(pInt), dimension(:), allocatable :: CrystallitePosition integer(pInt), dimension(:), allocatable :: CrystallitePosition
integer(pInt), dimension(:), allocatable :: HomogenizationPosition integer(pInt), dimension(:), allocatable :: HomogenizationPosition
@ -344,14 +414,35 @@ subroutine material_init(temperature_init)
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6) if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6)
close(FILEUNIT) close(FILEUNIT)
allocate(plasticState(material_Nphase)) allocate(plasticState (material_Nphase))
allocate(damageState (material_Nphase)) allocate(sourceState (material_Nphase))
allocate(thermalState(material_Nphase)) do myPhase = 1,material_Nphase
allocate(vacancyState(material_Nphase)) allocate(sourceState(myPhase)%p(phase_Nsources(myPhase)))
allocate(homogState (material_Nhomogenization)) enddo
allocate(fieldDamage (material_Nhomogenization))
allocate(fieldThermal(material_Nhomogenization)) allocate(homogState (material_Nhomogenization))
allocate(fieldVacancy(material_Nhomogenization)) allocate(thermalState (material_Nhomogenization))
allocate(damageState (material_Nhomogenization))
allocate(vacancyfluxState (material_Nhomogenization))
allocate(porosityState (material_Nhomogenization))
allocate(hydrogenfluxState (material_Nhomogenization))
allocate(thermalMapping (material_Nhomogenization))
allocate(damageMapping (material_Nhomogenization))
allocate(vacancyfluxMapping (material_Nhomogenization))
allocate(porosityMapping (material_Nhomogenization))
allocate(hydrogenfluxMapping(material_Nhomogenization))
allocate(temperature (material_Nhomogenization))
allocate(damage (material_Nhomogenization))
allocate(vacancyConc (material_Nhomogenization))
allocate(porosity (material_Nhomogenization))
allocate(hydrogenConc (material_Nhomogenization))
allocate(temperatureRate (material_Nhomogenization))
allocate(vacancyConcRate (material_Nhomogenization))
allocate(hydrogenConcRate (material_Nhomogenization))
do m = 1_pInt,material_Nmicrostructure do m = 1_pInt,material_Nmicrostructure
if(microstructure_crystallite(m) < 1_pInt .or. & if(microstructure_crystallite(m) < 1_pInt .or. &
microstructure_crystallite(m) > material_Ncrystallite) & microstructure_crystallite(m) > material_Ncrystallite) &
@ -365,6 +456,7 @@ subroutine material_init(temperature_init)
if(microstructure_Nconstituents(m) < 1_pInt) & if(microstructure_Nconstituents(m) < 1_pInt) &
call IO_error(151_pInt,m) call IO_error(151_pInt,m)
enddo enddo
debugOut: if (iand(myDebug,debug_levelExtensive) /= 0_pInt) then debugOut: if (iand(myDebug,debug_levelExtensive) /= 0_pInt) then
write(6,'(/,a,/)') ' MATERIAL configuration' write(6,'(/,a,/)') ' MATERIAL configuration'
write(6,'(a32,1x,a16,1x,a6)') 'homogenization ','type ','grains' write(6,'(a32,1x,a16,1x,a6)') 'homogenization ','type ','grains'
@ -390,14 +482,14 @@ subroutine material_init(temperature_init)
call material_populateGrains call material_populateGrains
allocate(mappingConstitutive(2,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems),source=0_pInt) allocate(mappingConstitutive (2,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems),source=0_pInt)
allocate(mappingHomogenization(2,mesh_maxNips,mesh_NcpElems),source=0_pInt) allocate(mappingHomogenization (2, mesh_maxNips,mesh_NcpElems),source=0_pInt)
allocate(mappingCrystallite (2,homogenization_maxNgrains, mesh_NcpElems),source=0_pInt)
allocate(mappingCrystallite (2,homogenization_maxNgrains,mesh_NcpElems),source=0_pInt) allocate(mappingHomogenizationConst( mesh_maxNips,mesh_NcpElems),source=1_pInt)
allocate(ConstitutivePosition(material_Nphase),source=0_pInt)
allocate(ConstitutivePosition (material_Nphase), source=0_pInt)
allocate(HomogenizationPosition(material_Nhomogenization),source=0_pInt) allocate(HomogenizationPosition(material_Nhomogenization),source=0_pInt)
allocate(CrystallitePosition(material_Nphase),source=0_pInt) allocate(CrystallitePosition (material_Nphase), source=0_pInt)
ElemLoop:do e = 1_pInt,mesh_NcpElems ! loop over elements ElemLoop:do e = 1_pInt,mesh_NcpElems ! loop over elements
myHomog = mesh_element(3,e) myHomog = mesh_element(3,e)
@ -412,55 +504,21 @@ subroutine material_init(temperature_init)
enddo IPloop enddo IPloop
enddo ElemLoop enddo ElemLoop
do homog = 1,material_Nhomogenization ! hack needed to initialize field values used during constitutive and crystallite initializations
NofMyField=count(material_homog==homog) do myHomog = 1,material_Nhomogenization
select case(field_damage_type(homog)) thermalMapping (myHomog)%p => mappingHomogenizationConst
case (FIELD_DAMAGE_LOCAL_ID) damageMapping (myHomog)%p => mappingHomogenizationConst
fieldDamage(homog)%sizeField = 0_pInt vacancyfluxMapping (myHomog)%p => mappingHomogenizationConst
fieldDamage(homog)%sizePostResults = 0_pInt porosityMapping (myHomog)%p => mappingHomogenizationConst
allocate(fieldDamage(homog)%field(fieldDamage(homog)%sizeField,NofMyField), source = 1.0_pReal) hydrogenfluxMapping(myHomog)%p => mappingHomogenizationConst
allocate(temperature (myHomog)%p(1), source=300.0_pReal)
case (FIELD_DAMAGE_NONLOCAL_ID) allocate(damage (myHomog)%p(1), source=1.0_pReal)
fieldDamage(homog)%sizeField = 1_pInt allocate(vacancyConc (myHomog)%p(1), source=0.0_pReal)
fieldDamage(homog)%sizePostResults = 1_pInt allocate(porosity (myHomog)%p(1), source=1.0_pReal)
allocate(fieldDamage(homog)%field(fieldDamage(homog)%sizeField,NofMyField), source = 1.0_pReal) allocate(hydrogenConc (myHomog)%p(1), source=0.0_pReal)
allocate(temperatureRate (myHomog)%p(1), source=0.0_pReal)
end select allocate(vacancyConcRate (myHomog)%p(1), source=0.0_pReal)
enddo allocate(hydrogenConcRate(myHomog)%p(1), source=0.0_pReal)
do homog = 1,material_Nhomogenization
NofMyField=count(material_homog==homog)
select case(field_thermal_type(homog))
case (FIELD_THERMAL_local_ID)
fieldThermal(homog)%sizeField = 0_pInt
fieldThermal(homog)%sizePostResults = 0_pInt
allocate(fieldThermal(homog)%field(fieldThermal(homog)%sizeField,NofMyField))
case (FIELD_THERMAL_nonlocal_ID)
fieldThermal(homog)%sizeField = 1_pInt
fieldThermal(homog)%sizePostResults = 1_pInt
allocate(fieldThermal(homog)%field(fieldThermal(homog)%sizeField,NofMyField), &
source = temperature_init)
end select
enddo
do homog = 1,material_Nhomogenization
NofMyField=count(material_homog==homog)
select case(field_vacancy_type(homog))
case (FIELD_VACANCY_local_ID)
fieldVacancy(homog)%sizeField = 0_pInt
fieldVacancy(homog)%sizePostResults = 0_pInt
allocate(fieldVacancy(homog)%field(fieldVacancy(homog)%sizeField,NofMyField), &
source = 0.0_pReal)
case (FIELD_VACANCY_nonlocal_ID)
fieldVacancy(homog)%sizeField = 1_pInt
fieldVacancy(homog)%sizePostResults = 1_pInt
allocate(fieldVacancy(homog)%field(fieldVacancy(homog)%sizeField,NofMyField), &
source = 0.0_pReal)
end select
enddo enddo
end subroutine material_init end subroutine material_init
@ -493,7 +551,7 @@ subroutine material_parseHomogenization(fileUnit,myPart)
integer(pInt), parameter :: MAXNCHUNKS = 2_pInt integer(pInt), parameter :: MAXNCHUNKS = 2_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: Nsections, section, s integer(pInt) :: Nsections, section, s, p
character(len=65536) :: & character(len=65536) :: &
tag, line tag, line
logical :: echo logical :: echo
@ -505,10 +563,17 @@ subroutine material_parseHomogenization(fileUnit,myPart)
allocate(homogenization_name(Nsections)); homogenization_name = '' allocate(homogenization_name(Nsections)); homogenization_name = ''
allocate(homogenization_type(Nsections), source=HOMOGENIZATION_undefined_ID) allocate(homogenization_type(Nsections), source=HOMOGENIZATION_undefined_ID)
allocate(FIELD_DAMAGE_type(Nsections), source=FIELD_DAMAGE_local_ID) allocate(thermal_type(Nsections), source=THERMAL_isothermal_ID)
allocate(FIELD_THERMAL_type(Nsections), source=FIELD_THERMAL_local_ID) allocate(damage_type (Nsections), source=DAMAGE_none_ID)
allocate(FIELD_VACANCY_type(Nsections), source=FIELD_VACANCY_local_ID) allocate(vacancyflux_type(Nsections), source=VACANCYFLUX_isoconc_ID)
allocate(porosity_type (Nsections), source=POROSITY_none_ID)
allocate(hydrogenflux_type(Nsections), source=HYDROGENFLUX_isoconc_ID)
allocate(homogenization_typeInstance(Nsections), source=0_pInt) allocate(homogenization_typeInstance(Nsections), source=0_pInt)
allocate(thermal_typeInstance(Nsections), source=0_pInt)
allocate(damage_typeInstance(Nsections), source=0_pInt)
allocate(vacancyflux_typeInstance(Nsections), source=0_pInt)
allocate(porosity_typeInstance(Nsections), source=0_pInt)
allocate(hydrogenflux_typeInstance(Nsections), source=0_pInt)
allocate(homogenization_Ngrains(Nsections), source=0_pInt) allocate(homogenization_Ngrains(Nsections), source=0_pInt)
allocate(homogenization_Noutput(Nsections), source=0_pInt) allocate(homogenization_Noutput(Nsections), source=0_pInt)
allocate(homogenization_active(Nsections), source=.false.) !!!!!!!!!!!!!!! allocate(homogenization_active(Nsections), source=.false.) !!!!!!!!!!!!!!!
@ -554,32 +619,58 @@ subroutine material_parseHomogenization(fileUnit,myPart)
end select end select
homogenization_typeInstance(section) = & homogenization_typeInstance(section) = &
count(homogenization_type==homogenization_type(section)) ! count instances count(homogenization_type==homogenization_type(section)) ! count instances
case ('field_damage') case ('thermal')
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case(FIELD_DAMAGE_LOCAL_label) case(THERMAL_isothermal_label)
FIELD_DAMAGE_type(section) = FIELD_DAMAGE_LOCAL_ID thermal_type(section) = THERMAL_isothermal_ID
case(FIELD_DAMAGE_NONLOCAL_label) case(THERMAL_adiabatic_label)
FIELD_DAMAGE_type(section) = FIELD_DAMAGE_NONLOCAL_ID thermal_type(section) = THERMAL_adiabatic_ID
case(THERMAL_conduction_label)
thermal_type(section) = THERMAL_conduction_ID
case default case default
call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select end select
case ('field_thermal') case ('damage')
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case(FIELD_THERMAL_local_label) case(DAMAGE_NONE_label)
FIELD_THERMAL_type(section) = FIELD_THERMAL_local_ID damage_type(section) = DAMAGE_none_ID
case(FIELD_THERMAL_nonlocal_label) case(DAMAGE_LOCAL_label)
FIELD_THERMAL_type(section) = FIELD_THERMAL_nonlocal_ID damage_type(section) = DAMAGE_local_ID
case(DAMAGE_NONLOCAL_label)
damage_type(section) = DAMAGE_nonlocal_ID
case default case default
call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select end select
case ('field_vacancy') case ('vacancyflux')
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case(FIELD_VACANCY_local_label) case(VACANCYFLUX_isoconc_label)
FIELD_VACANCY_type(section) = FIELD_VACANCY_local_ID vacancyflux_type(section) = VACANCYFLUX_isoconc_ID
case(FIELD_VACANCY_nonlocal_label) case(VACANCYFLUX_isochempot_label)
FIELD_VACANCY_type(section) = FIELD_VACANCY_nonlocal_ID vacancyflux_type(section) = VACANCYFLUX_isochempot_ID
case(VACANCYFLUX_cahnhilliard_label)
vacancyflux_type(section) = VACANCYFLUX_cahnhilliard_ID
case default
call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select
case ('porosity')
select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case(POROSITY_NONE_label)
porosity_type(section) = POROSITY_none_ID
case(POROSITY_phasefield_label)
porosity_type(section) = POROSITY_phasefield_ID
case default
call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select
case ('hydrogenflux')
select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case(HYDROGENFLUX_isoconc_label)
hydrogenflux_type(section) = HYDROGENFLUX_isoconc_ID
case(HYDROGENFLUX_cahnhilliard_label)
hydrogenflux_type(section) = HYDROGENFLUX_cahnhilliard_ID
case default case default
call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select end select
@ -590,6 +681,15 @@ subroutine material_parseHomogenization(fileUnit,myPart)
endif endif
enddo enddo
do p=1_pInt, Nsections
homogenization_typeInstance(p) = count(homogenization_type(1:p) == homogenization_type(p))
thermal_typeInstance(p) = count(thermal_type (1:p) == thermal_type (p))
damage_typeInstance(p) = count(damage_type (1:p) == damage_type (p))
vacancyflux_typeInstance(p) = count(vacancyflux_type (1:p) == vacancyflux_type (p))
porosity_typeInstance(p) = count(porosity_type (1:p) == porosity_type (p))
hydrogenflux_typeInstance(p) = count(hydrogenflux_type (1:p) == hydrogenflux_type (p))
enddo
homogenization_maxNgrains = maxval(homogenization_Ngrains,homogenization_active) homogenization_maxNgrains = maxval(homogenization_Ngrains,homogenization_active)
end subroutine material_parseHomogenization end subroutine material_parseHomogenization
@ -775,7 +875,7 @@ subroutine material_parsePhase(fileUnit,myPart)
integer(pInt), parameter :: MAXNCHUNKS = 2_pInt integer(pInt), parameter :: MAXNCHUNKS = 2_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: Nsections, section, p integer(pInt) :: Nsections, section, sourceCtr, kinematicsCtr, stiffDegradationCtr, p
character(len=65536) :: & character(len=65536) :: &
tag,line tag,line
logical :: echo logical :: echo
@ -791,18 +891,23 @@ subroutine material_parsePhase(fileUnit,myPart)
allocate(phase_elasticityInstance(Nsections), source=0_pInt) allocate(phase_elasticityInstance(Nsections), source=0_pInt)
allocate(phase_plasticity(Nsections) , source=PLASTICITY_undefined_ID) allocate(phase_plasticity(Nsections) , source=PLASTICITY_undefined_ID)
allocate(phase_plasticityInstance(Nsections), source=0_pInt) allocate(phase_plasticityInstance(Nsections), source=0_pInt)
allocate(phase_damage(Nsections) , source=LOCAL_DAMAGE_none_ID) allocate(phase_Nsources(Nsections), source=0_pInt)
allocate(phase_damageInstance(Nsections), source=0_pInt) allocate(phase_Nkinematics(Nsections), source=0_pInt)
allocate(phase_thermal(Nsections) , source=LOCAL_THERMAL_isothermal_ID) allocate(phase_NstiffnessDegradations(Nsections),source=0_pInt)
allocate(phase_thermalInstance(Nsections), source=0_pInt)
allocate(phase_vacancy(Nsections) , source=LOCAL_VACANCY_constant_ID)
allocate(phase_vacancyInstance(Nsections), source=0_pInt)
allocate(phase_Noutput(Nsections), source=0_pInt) allocate(phase_Noutput(Nsections), source=0_pInt)
allocate(phase_localPlasticity(Nsections), source=.false.) allocate(phase_localPlasticity(Nsections), source=.false.)
phase_Noutput = IO_countTagInPart(fileUnit,myPart,'(output)',Nsections) phase_Noutput = IO_countTagInPart(fileUnit,myPart,'(output)',Nsections)
phase_Nsources = IO_countTagInPart(fileUnit,myPart,'(source)',Nsections)
phase_Nkinematics = IO_countTagInPart(fileUnit,myPart,'(kinematics)',Nsections)
phase_NstiffnessDegradations = IO_countTagInPart(fileUnit,myPart,'(stiffness_degradation)',Nsections)
phase_localPlasticity = .not. IO_spotTagInPart(fileUnit,myPart,'/nonlocal/',Nsections) phase_localPlasticity = .not. IO_spotTagInPart(fileUnit,myPart,'/nonlocal/',Nsections)
allocate(phase_source(maxval(phase_Nsources),Nsections), source=SOURCE_undefined_ID)
allocate(phase_kinematics(maxval(phase_Nkinematics),Nsections), source=KINEMATICS_undefined_ID)
allocate(phase_stiffnessDegradation(maxval(phase_NstiffnessDegradations),Nsections), &
source=STIFFNESS_DEGRADATION_undefined_ID)
rewind(fileUnit) rewind(fileUnit)
line = '' ! to have it initialized line = '' ! to have it initialized
section = 0_pInt ! - " - section = 0_pInt ! - " -
@ -821,6 +926,9 @@ subroutine material_parsePhase(fileUnit,myPart)
if (echo) write(6,'(2x,a)') trim(line) ! echo back read lines if (echo) write(6,'(2x,a)') trim(line) ! echo back read lines
if (IO_getTag(line,'[',']') /= '') then ! next section if (IO_getTag(line,'[',']') /= '') then ! next section
section = section + 1_pInt section = section + 1_pInt
sourceCtr = 0_pInt
kinematicsCtr = 0_pInt
stiffDegradationCtr = 0_pInt
phase_name(section) = IO_getTag(line,'[',']') phase_name(section) = IO_getTag(line,'[',']')
endif endif
if (section > 0_pInt) then if (section > 0_pInt) then
@ -855,42 +963,47 @@ subroutine material_parsePhase(fileUnit,myPart)
case default case default
call IO_error(201_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) call IO_error(201_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select end select
case ('damage') case ('(source)')
sourceCtr = sourceCtr + 1_pInt
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case (LOCAL_DAMAGE_none_label) case (SOURCE_thermal_dissipation_label)
phase_damage(section) = LOCAL_DAMAGE_none_ID phase_source(sourceCtr,section) = SOURCE_thermal_dissipation_ID
case (LOCAL_DAMAGE_isoBrittle_label) case (SOURCE_damage_isoBrittle_label)
phase_damage(section) = LOCAL_DAMAGE_isoBrittle_ID phase_source(sourceCtr,section) = SOURCE_damage_isoBrittle_ID
case (LOCAL_DAMAGE_isoDuctile_label) case (SOURCE_damage_isoDuctile_label)
phase_damage(section) = LOCAL_DAMAGE_isoDuctile_ID phase_source(sourceCtr,section) = SOURCE_damage_isoDuctile_ID
case (LOCAL_DAMAGE_anisoBrittle_label) case (SOURCE_damage_anisoBrittle_label)
phase_damage(section) = LOCAL_DAMAGE_anisoBrittle_ID phase_source(sourceCtr,section) = SOURCE_damage_anisoBrittle_ID
case (LOCAL_DAMAGE_anisoDuctile_label) case (SOURCE_damage_anisoDuctile_label)
phase_damage(section) = LOCAL_DAMAGE_anisoDuctile_ID phase_source(sourceCtr,section) = SOURCE_damage_anisoDuctile_ID
case (LOCAL_DAMAGE_gurson_label) case (SOURCE_vacancy_phenoplasticity_label)
phase_damage(section) = LOCAL_DAMAGE_gurson_ID phase_source(sourceCtr,section) = SOURCE_vacancy_phenoplasticity_ID
case (LOCAL_DAMAGE_phaseField_label) case (SOURCE_vacancy_irradiation_label)
phase_damage(section) = LOCAL_DAMAGE_phaseField_ID phase_source(sourceCtr,section) = SOURCE_vacancy_irradiation_ID
case default case (SOURCE_vacancy_thermalfluc_label)
call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) phase_source(sourceCtr,section) = SOURCE_vacancy_thermalfluc_ID
end select end select
case ('thermal') case ('(kinematics)')
kinematicsCtr = kinematicsCtr + 1_pInt
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case (LOCAL_THERMAL_ISOTHERMAL_label) case (KINEMATICS_cleavage_opening_label)
phase_thermal(section) = LOCAL_THERMAL_isothermal_ID phase_kinematics(kinematicsCtr,section) = KINEMATICS_cleavage_opening_ID
case (LOCAL_THERMAL_ADIABATIC_label) case (KINEMATICS_slipplane_opening_label)
phase_thermal(section) = LOCAL_THERMAL_adiabatic_ID phase_kinematics(kinematicsCtr,section) = KINEMATICS_slipplane_opening_ID
case default case (KINEMATICS_thermal_expansion_label)
call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) phase_kinematics(kinematicsCtr,section) = KINEMATICS_thermal_expansion_ID
case (KINEMATICS_vacancy_strain_label)
phase_kinematics(kinematicsCtr,section) = KINEMATICS_vacancy_strain_ID
case (KINEMATICS_hydrogen_strain_label)
phase_kinematics(kinematicsCtr,section) = KINEMATICS_hydrogen_strain_ID
end select end select
case ('vacancy') case ('(stiffness_degradation)')
stiffDegradationCtr = stiffDegradationCtr + 1_pInt
select case (IO_lc(IO_stringValue(line,positions,2_pInt))) select case (IO_lc(IO_stringValue(line,positions,2_pInt)))
case (LOCAL_VACANCY_CONSTANT_label) case (STIFFNESS_DEGRADATION_damage_label)
phase_vacancy(section) = LOCAL_VACANCY_constant_ID phase_stiffnessDegradation(stiffDegradationCtr,section) = STIFFNESS_DEGRADATION_damage_ID
case (LOCAL_VACANCY_GENERATION_label) case (STIFFNESS_DEGRADATION_porosity_label)
phase_vacancy(section) = LOCAL_VACANCY_generation_ID phase_stiffnessDegradation(stiffDegradationCtr,section) = STIFFNESS_DEGRADATION_porosity_ID
case default
call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt)))
end select end select
end select end select
@ -898,14 +1011,10 @@ subroutine material_parsePhase(fileUnit,myPart)
enddo enddo
do p=1_pInt, Nsections do p=1_pInt, Nsections
phase_elasticityInstance(p) = count(phase_elasticity(1:p) == phase_elasticity(p)) phase_elasticityInstance(p) = count(phase_elasticity(1:p) == phase_elasticity(p))
phase_plasticityInstance(p) = count(phase_plasticity(1:p) == phase_plasticity(p)) phase_plasticityInstance(p) = count(phase_plasticity(1:p) == phase_plasticity(p))
phase_damageInstance(p) = count(phase_damage(1:p) == phase_damage(p))
phase_thermalInstance(p) = count(phase_thermal(1:p) == phase_thermal(p))
phase_vacancyInstance(p) = count(phase_vacancy(1:p) == phase_vacancy(p))
enddo enddo
end subroutine material_parsePhase end subroutine material_parsePhase
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------

View File

@ -70,6 +70,31 @@ module numerics
usePingPong = .true., & usePingPong = .true., &
numerics_timeSyncing = .false. !< flag indicating if time synchronization in crystallite is used for nonlocal plasticity numerics_timeSyncing = .false. !< flag indicating if time synchronization in crystallite is used for nonlocal plasticity
!--------------------------------------------------------------------------------------------------
! field parameters:
real(pReal), protected, public :: &
err_struct_tolAbs = 1.0e-10_pReal, & !< absolute tolerance for mechanical equilibrium
err_struct_tolRel = 1.0e-4_pReal, & !< relative tolerance for mechanical equilibrium
err_thermal_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for thermal equilibrium
err_thermal_tolRel = 1.0e-6_pReal, & !< relative tolerance for thermal equilibrium
err_damage_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for damage evolution
err_damage_tolRel = 1.0e-6_pReal, & !< relative tolerance for damage evolution
err_vacancyflux_tolAbs = 1.0e-8_pReal, & !< absolute tolerance for vacancy transport
err_vacancyflux_tolRel = 1.0e-6_pReal, & !< relative tolerance for vacancy transport
err_porosity_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for porosity evolution
err_porosity_tolRel = 1.0e-6_pReal, & !< relative tolerance for porosity evolution
err_hydrogenflux_tolAbs = 1.0e-8_pReal, & !< absolute tolerance for hydrogen transport
err_hydrogenflux_tolRel = 1.0e-6_pReal, & !< relative tolerance for hydrogen transport
vacancyBoundPenalty = 1.0e+4_pReal, & !< penalty to enforce 0 < Cv < 1
hydrogenBoundPenalty = 1.0e+4_pReal !< penalty to enforce 0 < Ch < 1
integer(pInt), protected, public :: &
itmax = 250_pInt, & !< maximum number of iterations
itmin = 1_pInt, & !< minimum number of iterations
stagItMax = 10_pInt, & !< max number of field level staggered iterations
maxCutBack = 3_pInt, & !< max number of cut backs
vacancyPolyOrder = 10_pInt, & !< order of polynomial approximation of entropic contribution to vacancy chemical potential
hydrogenPolyOrder = 10_pInt !< order of polynomial approximation of entropic contribution to hydrogen chemical potential
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! spectral parameters: ! spectral parameters:
#ifdef Spectral #ifdef Spectral
@ -94,9 +119,6 @@ module numerics
&-snes_ngmres_anderson ' &-snes_ngmres_anderson '
integer(pInt), protected, public :: & integer(pInt), protected, public :: &
fftw_planner_flag = 32_pInt, & !< conversion of fftw_plan_mode to integer, basically what is usually done in the include file of fftw fftw_planner_flag = 32_pInt, & !< conversion of fftw_plan_mode to integer, basically what is usually done in the include file of fftw
itmax = 250_pInt, & !< maximum number of iterations
itmin = 2_pInt, & !< minimum number of iterations
maxCutBack = 3_pInt, & !< max number of cut backs
continueCalculation = 0_pInt, & !< 0: exit if BVP solver does not converge, 1: continue calculation if BVP solver does not converge continueCalculation = 0_pInt, & !< 0: exit if BVP solver does not converge, 1: continue calculation if BVP solver does not converge
divergence_correction = 2_pInt !< correct divergence calculation in fourier space 0: no correction, 1: size scaled to 1, 2: size scaled to Npoints divergence_correction = 2_pInt !< correct divergence calculation in fourier space 0: no correction, 1: size scaled to 1, 2: size scaled to Npoints
logical, protected, public :: & logical, protected, public :: &
@ -107,13 +129,16 @@ module numerics
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! FEM parameters: ! FEM parameters:
#ifdef FEM #ifdef FEM
real(pReal), protected, public :: & integer(pInt), protected, public :: &
err_struct_tolAbs = 1.0e-10_pReal, & !< absolute tolerance for equilibrium integrationOrder = 2_pInt, & !< order of quadrature rule required
err_struct_tolRel = 1.0e-4_pReal, & !< relative tolerance for equilibrium structOrder = 2_pInt, & !< order of displacement shape functions
err_thermal_tol = 1.0e-1_pReal, & thermalOrder = 2_pInt, & !< order of temperature field shape functions
err_damage_tol = 1.0e-2_pReal, & damageOrder = 2_pInt, & !< order of damage field shape functions
err_vacancydiffusion_tol = 1.0e-8_pReal, & vacancyfluxOrder = 2_pInt, & !< order of vacancy concentration and chemical potential field shape functions
vacancyBoundPenalty = 1.0e+4_pReal !< penalty to enforce 0 < Cv < 1 porosityOrder = 2_pInt, & !< order of porosity field shape functions
hydrogenfluxOrder = 2_pInt !< order of hydrogen concentration and chemical potential field shape functions
logical, protected, public :: &
BBarStabilisation = .false.
character(len=4096), protected, public :: & character(len=4096), protected, public :: &
petsc_optionsFEM = '-mech_snes_type newtonls & petsc_optionsFEM = '-mech_snes_type newtonls &
&-mech_snes_linesearch_type cp & &-mech_snes_linesearch_type cp &
@ -123,50 +148,43 @@ module numerics
&-mech_ksp_type fgmres & &-mech_ksp_type fgmres &
&-mech_ksp_max_it 25 & &-mech_ksp_max_it 25 &
&-mech_pc_type ml & &-mech_pc_type ml &
&-mech_pc_ml_maxNlevels 2 &
&-mech_mg_coarse_ksp_type preonly &
&-mech_mg_coarse_pc_type lu &
&-mech_mg_coarse_pc_factor_mat_solver_package superlu_dist &
&-mech_mg_levels_ksp_type chebyshev & &-mech_mg_levels_ksp_type chebyshev &
&-mech_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 &
&-mech_mg_levels_pc_type sor & &-mech_mg_levels_pc_type sor &
&-mech_pc_ml_nullspace user & &-mech_pc_ml_nullspace user &
&-damage_snes_type newtonls & &-damage_snes_type newtonls &
&-damage_snes_linesearch_type cp & &-damage_snes_linesearch_type cp &
&-damage_ksp_type fgmres & &-damage_ksp_type fgmres &
&-damage_ksp_max_it 25 &
&-damage_snes_atol 1e-8 & &-damage_snes_atol 1e-8 &
&-damage_pc_type ml & &-damage_pc_type hypre &
&-damage_mg_levels_ksp_type chebyshev &
&-damage_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 &
&-damage_mg_levels_pc_type sor &
&-thermal_snes_type newtonls & &-thermal_snes_type newtonls &
&-thermal_snes_linesearch_type cp & &-thermal_snes_linesearch_type cp &
&-thermal_ksp_type fgmres & &-thermal_ksp_type fgmres &
&-thermal_ksp_max_it 25 &
&-thermal_snes_atol 1e-1 & &-thermal_snes_atol 1e-1 &
&-thermal_pc_type ml & &-thermal_pc_type hypre &
&-thermal_mg_levels_ksp_type chebyshev &
&-thermal_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 &
&-thermal_mg_levels_pc_type sor &
&-vacancy_snes_type newtonls & &-vacancy_snes_type newtonls &
&-vacancy_snes_linesearch_type cp & &-vacancy_snes_linesearch_type cp &
&-vacancy_ksp_type fgmres &
&-vacancy_snes_atol 1e-9 & &-vacancy_snes_atol 1e-9 &
&-vacancy_ksp_type fgmres &
&-vacancy_ksp_max_it 25 &
&-vacancy_pc_type ml & &-vacancy_pc_type ml &
&-vacancy_mg_levels_ksp_type chebyshev & &-vacancy_mg_levels_ksp_type chebyshev &
&-vacancy_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 & &-vacancy_mg_levels_pc_type sor &
&-vacancy_mg_levels_pc_type sor ' &-porosity_snes_type newtonls &
integer(pInt), protected, public :: & &-porosity_snes_linesearch_type cp &
itmaxFEM = 25_pInt, & !< maximum number of iterations &-porosity_ksp_type fgmres &
itminFEM = 1_pInt, & !< minimum number of iterations &-porosity_ksp_max_it 25 &
stagItMax = 10_pInt, & !< max number of field level staggered iterations &-porosity_snes_atol 1e-8 &
maxCutBackFEM = 3_pInt, & !< max number of cut backs &-porosity_pc_type hypre &
integrationOrder = 2_pInt, & &-hydrogen_snes_type newtonls &
structOrder = 2_pInt, & &-hydrogen_snes_linesearch_type cp &
thermalOrder = 2_pInt, & &-hydrogen_snes_atol 1e-9 &
damageOrder = 2_pInt, & &-hydrogen_ksp_type fgmres &
vacancyDiffusionOrder = 2_pInt &-hydrogen_ksp_max_it 25 &
logical, protected, public :: & &-hydrogen_pc_type ml &
BBarStabilisation = .false. &-hydrogen_mg_levels_ksp_type chebyshev &
&-hydrogen_mg_levels_pc_type sor '
#endif #endif
public :: numerics_init public :: numerics_init
@ -350,6 +368,49 @@ subroutine numerics_init
case ('residualstiffness') case ('residualstiffness')
residualStiffness = IO_floatValue(line,positions,2_pInt) residualStiffness = IO_floatValue(line,positions,2_pInt)
!--------------------------------------------------------------------------------------------------
! field parameters
case ('err_struct_tolabs')
err_struct_tolAbs = IO_floatValue(line,positions,2_pInt)
case ('err_struct_tolrel')
err_struct_tolRel = IO_floatValue(line,positions,2_pInt)
case ('err_thermal_tolabs')
err_thermal_tolabs = IO_floatValue(line,positions,2_pInt)
case ('err_thermal_tolrel')
err_thermal_tolrel = IO_floatValue(line,positions,2_pInt)
case ('err_damage_tolabs')
err_damage_tolabs = IO_floatValue(line,positions,2_pInt)
case ('err_damage_tolrel')
err_damage_tolrel = IO_floatValue(line,positions,2_pInt)
case ('err_vacancyflux_tolabs')
err_vacancyflux_tolabs = IO_floatValue(line,positions,2_pInt)
case ('err_vacancyflux_tolrel')
err_vacancyflux_tolrel = IO_floatValue(line,positions,2_pInt)
case ('err_porosity_tolabs')
err_porosity_tolabs = IO_floatValue(line,positions,2_pInt)
case ('err_porosity_tolrel')
err_porosity_tolrel = IO_floatValue(line,positions,2_pInt)
case ('err_hydrogenflux_tolabs')
err_hydrogenflux_tolabs = IO_floatValue(line,positions,2_pInt)
case ('err_hydrogenflux_tolrel')
err_hydrogenflux_tolrel = IO_floatValue(line,positions,2_pInt)
case ('vacancyboundpenalty')
vacancyBoundPenalty = IO_floatValue(line,positions,2_pInt)
case ('hydrogenboundpenalty')
hydrogenBoundPenalty = IO_floatValue(line,positions,2_pInt)
case ('itmax')
itmax = IO_intValue(line,positions,2_pInt)
case ('itmin')
itmin = IO_intValue(line,positions,2_pInt)
case ('maxcutback')
maxCutBack = IO_intValue(line,positions,2_pInt)
case ('maxstaggerediter')
stagItMax = IO_intValue(line,positions,2_pInt)
case ('vacancypolyorder')
vacancyPolyOrder = IO_intValue(line,positions,2_pInt)
case ('hydrogenpolyorder')
hydrogenPolyOrder = IO_intValue(line,positions,2_pInt)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! spectral parameters ! spectral parameters
#ifdef Spectral #ifdef Spectral
@ -361,12 +422,6 @@ subroutine numerics_init
err_stress_tolrel = IO_floatValue(line,positions,2_pInt) err_stress_tolrel = IO_floatValue(line,positions,2_pInt)
case ('err_stress_tolabs') case ('err_stress_tolabs')
err_stress_tolabs = IO_floatValue(line,positions,2_pInt) err_stress_tolabs = IO_floatValue(line,positions,2_pInt)
case ('itmax')
itmax = IO_intValue(line,positions,2_pInt)
case ('itmin')
itmin = IO_intValue(line,positions,2_pInt)
case ('maxcutback')
maxCutBack = IO_intValue(line,positions,2_pInt)
case ('continuecalculation') case ('continuecalculation')
continueCalculation = IO_intValue(line,positions,2_pInt) continueCalculation = IO_intValue(line,positions,2_pInt)
case ('memory_efficient') case ('memory_efficient')
@ -395,36 +450,16 @@ subroutine numerics_init
polarBeta = IO_floatValue(line,positions,2_pInt) polarBeta = IO_floatValue(line,positions,2_pInt)
#else #else
case ('err_div_tolabs','err_div_tolrel','err_stress_tolrel','err_stress_tolabs',& ! found spectral parameter for FEM build case ('err_div_tolabs','err_div_tolrel','err_stress_tolrel','err_stress_tolabs',& ! found spectral parameter for FEM build
'itmax', 'itmin','memory_efficient','fftw_timelimit','fftw_plan_mode', & 'memory_efficient','fftw_timelimit','fftw_plan_mode', &
'divergence_correction','update_gamma','spectralfilter','myfilter', & 'divergence_correction','update_gamma','spectralfilter','myfilter', &
'err_curl_tolabs','err_curl_tolrel', & 'err_curl_tolabs','err_curl_tolrel', &
'maxcutback','polaralpha','polarbeta') 'polaralpha','polarbeta')
call IO_warning(40_pInt,ext_msg=tag) call IO_warning(40_pInt,ext_msg=tag)
#endif #endif
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! FEM parameters ! FEM parameters
#ifdef FEM #ifdef FEM
case ('err_struct_tolabs')
err_struct_tolAbs = IO_floatValue(line,positions,2_pInt)
case ('err_struct_tolrel')
err_struct_tolRel = IO_floatValue(line,positions,2_pInt)
case ('err_thermal_tol')
err_thermal_tol = IO_floatValue(line,positions,2_pInt)
case ('err_damage_tol')
err_damage_tol = IO_floatValue(line,positions,2_pInt)
case ('err_vacancydiffusion_tol')
err_vacancyDiffusion_tol = IO_floatValue(line,positions,2_pInt)
case ('vacancyboundpenalty')
vacancyBoundPenalty = IO_floatValue(line,positions,2_pInt)
case ('itmaxfem')
itmaxFEM = IO_intValue(line,positions,2_pInt)
case ('itminfem')
itminFEM = IO_intValue(line,positions,2_pInt)
case ('maxcutbackfem')
maxCutBackFEM = IO_intValue(line,positions,2_pInt)
case ('maxstaggerediter')
stagItMax = IO_intValue(line,positions,2_pInt)
case ('integrationorder') case ('integrationorder')
integrationorder = IO_intValue(line,positions,2_pInt) integrationorder = IO_intValue(line,positions,2_pInt)
case ('structorder') case ('structorder')
@ -433,16 +468,19 @@ subroutine numerics_init
thermalorder = IO_intValue(line,positions,2_pInt) thermalorder = IO_intValue(line,positions,2_pInt)
case ('damageorder') case ('damageorder')
damageorder = IO_intValue(line,positions,2_pInt) damageorder = IO_intValue(line,positions,2_pInt)
case ('vacancydiffusionorder') case ('vacancyfluxorder')
vacancyDiffusionOrder = IO_intValue(line,positions,2_pInt) vacancyfluxOrder = IO_intValue(line,positions,2_pInt)
case ('porosityorder')
porosityOrder = IO_intValue(line,positions,2_pInt)
case ('hydrogenfluxorder')
hydrogenfluxOrder = IO_intValue(line,positions,2_pInt)
case ('petsc_optionsfem') case ('petsc_optionsfem')
petsc_optionsFEM = trim(line(positions(4):)) petsc_optionsFEM = trim(line(positions(4):))
case ('bbarstabilisation') case ('bbarstabilisation')
BBarStabilisation = IO_intValue(line,positions,2_pInt) > 0_pInt BBarStabilisation = IO_intValue(line,positions,2_pInt) > 0_pInt
#else #else
case ('err_struct_tolabs','err_struct_tolrel','err_thermal_tol','err_damage_tol','err_vacancydiffusion_tol',& ! found FEM parameter for spectral/Abaqus/Marc build case ('integrationorder','structorder','thermalorder', 'damageorder','vacancyfluxorder', &
'vacancyboundpenalty','itmaxfem', 'itminfem','maxcutbackfem','maxstaggerediter','integrationorder',& 'porosityorder','hydrogenfluxorder','petsc_optionsfem','bbarstabilisation')
'structorder','thermalorder', 'damageorder','petsc_optionsfem','bbarstabilisation')
call IO_warning(40_pInt,ext_msg=tag) call IO_warning(40_pInt,ext_msg=tag)
#endif #endif
case default ! found unknown keyword case default ! found unknown keyword
@ -541,11 +579,31 @@ subroutine numerics_init
!$ write(6,'(a24,1x,i8,/)') ' number of threads: ',DAMASK_NumThreadsInt !$ write(6,'(a24,1x,i8,/)') ' number of threads: ',DAMASK_NumThreadsInt
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! spectral parameters ! field parameters
#ifdef Spectral
write(6,'(a24,1x,i8)') ' itmax: ',itmax write(6,'(a24,1x,i8)') ' itmax: ',itmax
write(6,'(a24,1x,i8)') ' itmin: ',itmin write(6,'(a24,1x,i8)') ' itmin: ',itmin
write(6,'(a24,1x,i8)') ' maxCutBack: ',maxCutBack write(6,'(a24,1x,i8)') ' maxCutBack: ',maxCutBack
write(6,'(a24,1x,i8)') ' maxStaggeredIter: ',stagItMax
write(6,'(a24,1x,i8)') ' vacancyPolyOrder: ',vacancyPolyOrder
write(6,'(a24,1x,i8)') ' hydrogenPolyOrder: ',hydrogenPolyOrder
write(6,'(a24,1x,es8.1)') ' err_struct_tolAbs: ',err_struct_tolAbs
write(6,'(a24,1x,es8.1)') ' err_struct_tolRel: ',err_struct_tolRel
write(6,'(a24,1x,es8.1)') ' err_thermal_tolabs: ',err_thermal_tolabs
write(6,'(a24,1x,es8.1)') ' err_thermal_tolrel: ',err_thermal_tolrel
write(6,'(a24,1x,es8.1)') ' err_damage_tolabs: ',err_damage_tolabs
write(6,'(a24,1x,es8.1)') ' err_damage_tolrel: ',err_damage_tolrel
write(6,'(a24,1x,es8.1)') ' err_vacancyflux_tolabs: ',err_vacancyflux_tolabs
write(6,'(a24,1x,es8.1)') ' err_vacancyflux_tolrel: ',err_vacancyflux_tolrel
write(6,'(a24,1x,es8.1)') ' err_porosity_tolabs: ',err_porosity_tolabs
write(6,'(a24,1x,es8.1)') ' err_porosity_tolrel: ',err_porosity_tolrel
write(6,'(a24,1x,es8.1)') ' err_hydrogenflux_tolabs:',err_hydrogenflux_tolabs
write(6,'(a24,1x,es8.1)') ' err_hydrogenflux_tolrel:',err_hydrogenflux_tolrel
write(6,'(a24,1x,es8.1)') ' vacancyBoundPenalty: ',vacancyBoundPenalty
write(6,'(a24,1x,es8.1)') ' hydrogenBoundPenalty: ',hydrogenBoundPenalty
!--------------------------------------------------------------------------------------------------
! spectral parameters
#ifdef Spectral
write(6,'(a24,1x,i8)') ' continueCalculation: ',continueCalculation write(6,'(a24,1x,i8)') ' continueCalculation: ',continueCalculation
write(6,'(a24,1x,L8)') ' memory_efficient: ',memory_efficient write(6,'(a24,1x,L8)') ' memory_efficient: ',memory_efficient
write(6,'(a24,1x,i8)') ' divergence_correction: ',divergence_correction write(6,'(a24,1x,i8)') ' divergence_correction: ',divergence_correction
@ -573,21 +631,13 @@ subroutine numerics_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! spectral parameters ! spectral parameters
#ifdef FEM #ifdef FEM
write(6,'(a24,1x,i8)') ' itmaxFEM: ',itmaxFEM
write(6,'(a24,1x,i8)') ' itminFEM: ',itminFEM
write(6,'(a24,1x,i8)') ' maxCutBackFEM: ',maxCutBackFEM
write(6,'(a24,1x,i8)') ' maxStaggeredIter: ',stagItMax
write(6,'(a24,1x,i8)') ' integrationOrder: ',integrationOrder write(6,'(a24,1x,i8)') ' integrationOrder: ',integrationOrder
write(6,'(a24,1x,i8)') ' structOrder: ',structOrder write(6,'(a24,1x,i8)') ' structOrder: ',structOrder
write(6,'(a24,1x,i8)') ' thermalOrder: ',thermalOrder write(6,'(a24,1x,i8)') ' thermalOrder: ',thermalOrder
write(6,'(a24,1x,i8)') ' damageOrder: ',damageOrder write(6,'(a24,1x,i8)') ' damageOrder: ',damageOrder
write(6,'(a24,1x,i8)') ' vacancyDiffusionOrder: ',vacancyDiffusionOrder write(6,'(a24,1x,i8)') ' vacancyfluxOrder: ',vacancyfluxOrder
write(6,'(a24,1x,es8.1)') ' err_struct_tolAbs: ',err_struct_tolAbs write(6,'(a24,1x,i8)') ' porosityOrder: ',porosityOrder
write(6,'(a24,1x,es8.1)') ' err_struct_tolRel: ',err_struct_tolRel write(6,'(a24,1x,i8)') ' hydrogenfluxOrder: ',hydrogenfluxOrder
write(6,'(a24,1x,es8.1)') ' err_thermal_tol: ',err_thermal_tol
write(6,'(a24,1x,es8.1)') ' err_damage_tol: ',err_damage_tol
write(6,'(a24,1x,es8.1)') ' err_vacancyDiff_tol: ',err_vacancyDiffusion_tol
write(6,'(a24,1x,es8.1)') ' vacancyBoundPenalty: ',vacancyBoundPenalty
write(6,'(a24,1x,a)') ' PETSc_optionsFEM: ',trim(petsc_optionsFEM) write(6,'(a24,1x,a)') ' PETSc_optionsFEM: ',trim(petsc_optionsFEM)
write(6,'(a24,1x,L8)') ' B-Bar stabilisation: ',BBarStabilisation write(6,'(a24,1x,L8)') ' B-Bar stabilisation: ',BBarStabilisation
#endif #endif
@ -634,14 +684,28 @@ subroutine numerics_init
if (volDiscrMod_RGC < 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrMod_RGC') if (volDiscrMod_RGC < 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrMod_RGC')
if (volDiscrPow_RGC <= 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrPw_RGC') if (volDiscrPow_RGC <= 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrPw_RGC')
if (residualStiffness <= 0.0_pReal) call IO_error(301_pInt,ext_msg='residualStiffness') if (residualStiffness <= 0.0_pReal) call IO_error(301_pInt,ext_msg='residualStiffness')
#ifdef Spectral
if (itmax <= 1_pInt) call IO_error(301_pInt,ext_msg='itmax') if (itmax <= 1_pInt) call IO_error(301_pInt,ext_msg='itmax')
if (itmin > itmax .or. itmin < 1_pInt) call IO_error(301_pInt,ext_msg='itmin') if (itmin > itmax .or. itmin < 1_pInt) call IO_error(301_pInt,ext_msg='itmin')
if (maxCutBack < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBack')
if (stagItMax < 0_pInt) call IO_error(301_pInt,ext_msg='maxStaggeredIter')
if (vacancyPolyOrder < 0_pInt) call IO_error(301_pInt,ext_msg='vacancyPolyOrder')
if (err_struct_tolRel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolRel')
if (err_struct_tolAbs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolAbs')
if (err_thermal_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tolabs')
if (err_thermal_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tolrel')
if (err_damage_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tolabs')
if (err_damage_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tolrel')
if (err_vacancyflux_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_vacancyflux_tolabs')
if (err_vacancyflux_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_vacancyflux_tolrel')
if (err_porosity_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_porosity_tolabs')
if (err_porosity_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_porosity_tolrel')
if (err_hydrogenflux_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_hydrogenflux_tolabs')
if (err_hydrogenflux_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_hydrogenflux_tolrel')
#ifdef Spectral
if (continueCalculation /= 0_pInt .and. & if (continueCalculation /= 0_pInt .and. &
continueCalculation /= 1_pInt) call IO_error(301_pInt,ext_msg='continueCalculation') continueCalculation /= 1_pInt) call IO_error(301_pInt,ext_msg='continueCalculation')
if (divergence_correction < 0_pInt .or. & if (divergence_correction < 0_pInt .or. &
divergence_correction > 2_pInt) call IO_error(301_pInt,ext_msg='divergence_correction') divergence_correction > 2_pInt) call IO_error(301_pInt,ext_msg='divergence_correction')
if (maxCutBack < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBack')
if (update_gamma .and. & if (update_gamma .and. &
.not. memory_efficient) call IO_error(error_ID = 847_pInt) .not. memory_efficient) call IO_error(error_ID = 847_pInt)
if (err_stress_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_stress_tolRel') if (err_stress_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_stress_tolRel')
@ -655,18 +719,6 @@ subroutine numerics_init
if (polarBeta < 0.0_pReal .or. & if (polarBeta < 0.0_pReal .or. &
polarBeta > 2.0_pReal) call IO_error(301_pInt,ext_msg='polarBeta') polarBeta > 2.0_pReal) call IO_error(301_pInt,ext_msg='polarBeta')
#endif #endif
#ifdef FEM
if (itmaxFEM <= 1_pInt) call IO_error(301_pInt,ext_msg='itmaxFEM')
if (itminFEM > itmaxFEM .or. &
itminFEM < 0_pInt) call IO_error(301_pInt,ext_msg='itminFEM')
if (maxCutBackFEM < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBackFEM')
if (stagItMax < 0_pInt) call IO_error(301_pInt,ext_msg='maxStaggeredIter')
if (err_struct_tolRel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolRel')
if (err_struct_tolAbs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolAbs')
if (err_thermal_tol <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tol')
if (err_damage_tol <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tol')
if (err_vacancyDiffusion_tol <= 0.0_pReal)call IO_error(301_pInt,ext_msg='err_vacancydiffusion_tol')
#endif
end subroutine numerics_init end subroutine numerics_init

62
code/porosity_none.f90 Normal file
View File

@ -0,0 +1,62 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for constant porosity
!--------------------------------------------------------------------------------------------------
module porosity_none
implicit none
private
public :: &
porosity_none_init
contains
!--------------------------------------------------------------------------------------------------
!> @brief allocates all neccessary fields, reads information from material configuration file
!--------------------------------------------------------------------------------------------------
subroutine porosity_none_init()
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use prec, only: &
pReal, &
pInt
use IO, only: &
IO_timeStamp
use material
use numerics, only: &
worldrank
implicit none
integer(pInt) :: &
homog, &
NofMyHomog
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- porosity_'//POROSITY_none_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
initializeInstances: do homog = 1_pInt, material_Nhomogenization
myhomog: if (porosity_type(homog) == POROSITY_none_ID) then
NofMyHomog = count(material_homog == homog)
porosityState(homog)%sizeState = 0_pInt
porosityState(homog)%sizePostResults = 0_pInt
allocate(porosityState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal)
allocate(porosityState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal)
allocate(porosityState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal)
deallocate(porosity(homog)%p)
allocate (porosity(homog)%p(1), source=1.0_pReal)
endif myhomog
enddo initializeInstances
end subroutine porosity_none_init
end module porosity_none

View File

@ -0,0 +1,488 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for phase field modelling of pore nucleation and growth
!> @details phase field model for pore nucleation and growth based on vacancy clustering
!--------------------------------------------------------------------------------------------------
module porosity_phasefield
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
porosity_phasefield_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
porosity_phasefield_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
porosity_phasefield_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
porosity_phasefield_Noutput !< number of outputs per instance of this porosity
real(pReal), dimension(:), allocatable, private :: &
porosity_phasefield_specificFormationEnergy, &
porosity_phasefield_surfaceEnergy
enum, bind(c)
enumerator :: undefined_ID, &
porosity_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
porosity_phasefield_outputID !< ID of each post result output
public :: &
porosity_phasefield_init, &
porosity_phasefield_getFormationEnergy, &
porosity_phasefield_getSurfaceEnergy, &
porosity_phasefield_getSourceAndItsTangent, &
porosity_phasefield_getDiffusion33, &
porosity_phasefield_getMobility, &
porosity_phasefield_putPorosity, &
porosity_phasefield_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine porosity_phasefield_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, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use lattice, only: &
lattice_vacancyVol
use material, only: &
porosity_type, &
porosity_typeInstance, &
homogenization_Noutput, &
POROSITY_phasefield_label, &
POROSITY_phasefield_ID, &
material_homog, &
material_Nphase, &
mappingHomogenization, &
porosityState, &
porosityMapping, &
porosity, &
material_partHomogenization, &
material_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- porosity_'//POROSITY_phasefield_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(porosity_type == POROSITY_phasefield_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(porosity_phasefield_sizePostResults(maxNinstance), source=0_pInt)
allocate(porosity_phasefield_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(porosity_phasefield_output (maxval(homogenization_Noutput),maxNinstance))
porosity_phasefield_output = ''
allocate(porosity_phasefield_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(porosity_phasefield_Noutput (maxNinstance), source=0_pInt)
allocate(porosity_phasefield_specificFormationEnergy(material_Nphase), source=0.0_pReal)
allocate(porosity_phasefield_surfaceEnergy (material_Nphase), source=0.0_pReal)
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (porosity_type(section) == POROSITY_phasefield_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = porosity_typeInstance(section) ! which instance of my porosity is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('porosity')
porosity_phasefield_Noutput(instance) = porosity_phasefield_Noutput(instance) + 1_pInt
porosity_phasefield_outputID(porosity_phasefield_Noutput(instance),instance) = porosity_ID
porosity_phasefield_output(porosity_phasefield_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingHomog
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (porosity_type(section) == POROSITY_phasefield_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('vacancyformationenergy')
porosity_phasefield_specificFormationEnergy(section) = IO_floatValue(line,positions,2_pInt)/&
lattice_vacancyVol(section)
case ('voidsurfaceenergy')
porosity_phasefield_surfaceEnergy(section) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingPhase
initializeInstances: do section = 1_pInt, size(porosity_type)
if (porosity_type(section) == POROSITY_phasefield_ID) then
NofMyHomog=count(material_homog==section)
instance = porosity_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,porosity_phasefield_Noutput(instance)
select case(porosity_phasefield_outputID(o,instance))
case(porosity_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
porosity_phasefield_sizePostResult(o,instance) = mySize
porosity_phasefield_sizePostResults(instance) = porosity_phasefield_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 0_pInt
porosityState(section)%sizeState = sizeState
porosityState(section)%sizePostResults = porosity_phasefield_sizePostResults(instance)
allocate(porosityState(section)%state0 (sizeState,NofMyHomog))
allocate(porosityState(section)%subState0(sizeState,NofMyHomog))
allocate(porosityState(section)%state (sizeState,NofMyHomog))
nullify(porosityMapping(section)%p)
porosityMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(porosity(section)%p)
allocate(porosity(section)%p(NofMyHomog), source=1.0_pReal)
endif
enddo initializeInstances
end subroutine porosity_phasefield_init
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized vacancy formation energy
!--------------------------------------------------------------------------------------------------
function porosity_phasefield_getFormationEnergy(ip,el)
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
porosity_phasefield_getFormationEnergy
integer(pInt) :: &
grain
porosity_phasefield_getFormationEnergy = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
porosity_phasefield_getFormationEnergy = porosity_phasefield_getFormationEnergy + &
porosity_phasefield_specificFormationEnergy(material_phase(grain,ip,el))
enddo
porosity_phasefield_getFormationEnergy = &
porosity_phasefield_getFormationEnergy/ &
homogenization_Ngrains(mesh_element(3,el))
end function porosity_phasefield_getFormationEnergy
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized pore surface energy (normalized by characteristic length)
!--------------------------------------------------------------------------------------------------
function porosity_phasefield_getSurfaceEnergy(ip,el)
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
porosity_phasefield_getSurfaceEnergy
integer(pInt) :: &
grain
porosity_phasefield_getSurfaceEnergy = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
porosity_phasefield_getSurfaceEnergy = porosity_phasefield_getSurfaceEnergy + &
porosity_phasefield_surfaceEnergy(material_phase(grain,ip,el))
enddo
porosity_phasefield_getSurfaceEnergy = &
porosity_phasefield_getSurfaceEnergy/ &
homogenization_Ngrains(mesh_element(3,el))
end function porosity_phasefield_getSurfaceEnergy
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized local driving force for pore nucleation and growth
!--------------------------------------------------------------------------------------------------
subroutine porosity_phasefield_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el)
use math, only : &
math_mul33x33, &
math_mul66x6, &
math_Mandel33to6, &
math_transpose33, &
math_I3
use material, only: &
homogenization_Ngrains, &
material_homog, &
material_phase, &
phase_NstiffnessDegradations, &
phase_stiffnessDegradation, &
vacancyConc, &
vacancyfluxMapping, &
damage, &
damageMapping, &
STIFFNESS_DEGRADATION_damage_ID
use crystallite, only: &
crystallite_Fe
use constitutive, only: &
constitutive_homogenizedC
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer(pInt) :: &
phase, &
grain, &
homog, &
mech
real(pReal) :: &
phiDot, dPhiDot_dPhi, Cv, W_e, strain(6), C(6,6)
homog = material_homog(ip,el)
Cv = vacancyConc(homog)%p(vacancyfluxMapping(homog)%p(ip,el))
W_e = 0.0_pReal
do grain = 1, homogenization_Ngrains(homog)
phase = material_phase(grain,ip,el)
strain = math_Mandel33to6(math_mul33x33(math_transpose33(crystallite_Fe(1:3,1:3,grain,ip,el)), &
crystallite_Fe(1:3,1:3,grain,ip,el)) - math_I3)/2.0_pReal
C = constitutive_homogenizedC(grain,ip,el)
do mech = 1_pInt, phase_NstiffnessDegradations(phase)
select case(phase_stiffnessDegradation(mech,phase))
case (STIFFNESS_DEGRADATION_damage_ID)
C = damage(homog)%p(damageMapping(homog)%p(ip,el))* &
damage(homog)%p(damageMapping(homog)%p(ip,el))* &
C
end select
enddo
W_e = W_e + sum(abs(strain*math_mul66x6(C,strain)))
enddo
W_e = W_e/homogenization_Ngrains(homog)
phiDot = 2.0_pReal*(1.0_pReal - phi)*(1.0_pReal - Cv)*(1.0_pReal - Cv) - &
2.0_pReal*phi*(W_e + Cv*porosity_phasefield_getFormationEnergy(ip,el))/ &
porosity_phasefield_getSurfaceEnergy (ip,el)
dPhiDot_dPhi = - 2.0_pReal*(1.0_pReal - Cv)*(1.0_pReal - Cv) &
- 2.0_pReal*(W_e + Cv*porosity_phasefield_getFormationEnergy(ip,el))/ &
porosity_phasefield_getSurfaceEnergy (ip,el)
end subroutine porosity_phasefield_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized nonlocal diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function porosity_phasefield_getDiffusion33(ip,el)
use lattice, only: &
lattice_PorosityDiffusion33
use material, only: &
homogenization_Ngrains, &
material_phase, &
mappingHomogenization
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
porosity_phasefield_getDiffusion33
integer(pInt) :: &
homog, &
grain
homog = mappingHomogenization(2,ip,el)
porosity_phasefield_getDiffusion33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(homog)
porosity_phasefield_getDiffusion33 = porosity_phasefield_getDiffusion33 + &
crystallite_push33ToRef(grain,ip,el,lattice_PorosityDiffusion33(1:3,1:3,material_phase(grain,ip,el)))
enddo
porosity_phasefield_getDiffusion33 = &
porosity_phasefield_getDiffusion33/ &
homogenization_Ngrains(homog)
end function porosity_phasefield_getDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief Returns homogenized phase field mobility
!--------------------------------------------------------------------------------------------------
real(pReal) function porosity_phasefield_getMobility(ip,el)
use mesh, only: &
mesh_element
use lattice, only: &
lattice_PorosityMobility
use material, only: &
material_phase, &
homogenization_Ngrains
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
integer(pInt) :: &
ipc
porosity_phasefield_getMobility = 0.0_pReal
do ipc = 1, homogenization_Ngrains(mesh_element(3,el))
porosity_phasefield_getMobility = porosity_phasefield_getMobility + lattice_PorosityMobility(material_phase(ipc,ip,el))
enddo
porosity_phasefield_getMobility = porosity_phasefield_getMobility/homogenization_Ngrains(mesh_element(3,el))
end function porosity_phasefield_getMobility
!--------------------------------------------------------------------------------------------------
!> @brief updates porosity with solution from phasefield PDE
!--------------------------------------------------------------------------------------------------
subroutine porosity_phasefield_putPorosity(phi,ip,el)
use material, only: &
material_homog, &
porosityMapping, &
porosity
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer(pInt) :: &
homog, &
offset
homog = material_homog(ip,el)
offset = porosityMapping(homog)%p(ip,el)
porosity(homog)%p(offset) = phi
end subroutine porosity_phasefield_putPorosity
!--------------------------------------------------------------------------------------------------
!> @brief return array of porosity results
!--------------------------------------------------------------------------------------------------
function porosity_phasefield_postResults(ip,el)
use material, only: &
mappingHomogenization, &
porosity_typeInstance, &
porosity
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(porosity_phasefield_sizePostResults(porosity_typeInstance(mappingHomogenization(2,ip,el)))) :: &
porosity_phasefield_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = mappingHomogenization(1,ip,el)
instance = porosity_typeInstance(homog)
c = 0_pInt
porosity_phasefield_postResults = 0.0_pReal
do o = 1_pInt,porosity_phasefield_Noutput(instance)
select case(porosity_phasefield_outputID(o,instance))
case (porosity_ID)
porosity_phasefield_postResults(c+1_pInt) = porosity(homog)%p(offset)
c = c + 1
end select
enddo
end function porosity_phasefield_postResults
end module porosity_phasefield

View File

@ -58,11 +58,11 @@ use ifport
real(pReal), parameter, public :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation) real(pReal), parameter, public :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation)
type, public :: p_vec !< variable length datatype used for storage of state type, public :: p_vec !< variable length datatype used for storage of state
real(pReal), dimension(:), allocatable :: p real(pReal), dimension(:), pointer :: p
end type p_vec end type p_vec
type, public :: p_intvec type, public :: p_intvec
integer(pInt), dimension(:), allocatable :: p integer(pInt), dimension(:), pointer :: p
end type p_intvec end type p_intvec
!http://stackoverflow.com/questions/3948210/can-i-have-a-pointer-to-an-item-in-an-allocatable-array !http://stackoverflow.com/questions/3948210/can-i-have-a-pointer-to-an-item-in-an-allocatable-array
@ -71,14 +71,11 @@ type, public :: p_intvec
sizeState = 0_pInt , & !< size of state sizeState = 0_pInt , & !< size of state
sizeDotState = 0_pInt, & !< size of dot state, i.e. parts of the state that are integrated sizeDotState = 0_pInt, & !< size of dot state, i.e. parts of the state that are integrated
sizePostResults = 0_pInt !< size of output data sizePostResults = 0_pInt !< size of output data
logical :: &
nonlocal = .false. !< absolute tolerance for state integration
real(pReal), allocatable, dimension(:) :: & real(pReal), allocatable, dimension(:) :: &
atolState atolState
real(pReal), pointer, dimension(:,:), contiguous :: & ! a pointer is needed here because we might point to state/doState. However, they will never point to something, but are rather allocated and, hence, contiguous real(pReal), pointer, dimension(:,:), contiguous :: & ! a pointer is needed here because we might point to state/doState. However, they will never point to something, but are rather allocated and, hence, contiguous
state, & !< state state, & !< state
dotState !< state rate dotState, & !< state rate
real(pReal), allocatable, dimension(:,:) :: &
state0, & state0, &
partionedState0, & partionedState0, &
subState0, & subState0, &
@ -97,17 +94,23 @@ type, public :: p_intvec
nSlip = 0_pInt , & nSlip = 0_pInt , &
nTwin = 0_pInt, & nTwin = 0_pInt, &
nTrans = 0_pInt nTrans = 0_pInt
logical :: &
nonlocal = .false. !< absolute tolerance for state integration
real(pReal), pointer, dimension(:,:), contiguous :: & real(pReal), pointer, dimension(:,:), contiguous :: &
slipRate, & !< slip rate slipRate, & !< slip rate
accumulatedSlip !< accumulated plastic slip accumulatedSlip !< accumulated plastic slip
end type end type
type, public :: tFieldData type, public :: tSourceState
integer(pInt) :: & type(tState), dimension(:), allocatable :: p !< tState for each active source mechanism in a phase
sizeField = 0_pInt , & end type
sizePostResults = 0_pInt
real(pReal), allocatable, dimension(:,:) :: & type, public :: tHomogMapping
field !< field data integer(pInt), pointer, dimension(:,:) :: p
end type
type, public :: tPhaseMapping
integer(pInt), pointer, dimension(:,:,:) :: p
end type end type
#ifdef FEM #ifdef FEM

View File

@ -0,0 +1,423 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @brief material subroutine incorporating anisotropic brittle damage source mechanism
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_damage_anisoBrittle
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_damage_anisoBrittle_sizePostResults, & !< cumulative size of post results
source_damage_anisoBrittle_offset, & !< which source is my current source mechanism?
source_damage_anisoBrittle_instance !< instance of source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_damage_anisoBrittle_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_damage_anisoBrittle_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_damage_anisoBrittle_Noutput !< number of outputs per instance of this source
integer(pInt), dimension(:), allocatable, private :: &
source_damage_anisoBrittle_totalNcleavage !< total number of cleavage systems
integer(pInt), dimension(:,:), allocatable, private :: &
source_damage_anisoBrittle_Ncleavage !< number of cleavage systems per family
real(pReal), dimension(:), allocatable, private :: &
source_damage_anisoBrittle_aTol, &
source_damage_anisoBrittle_sdot_0, &
source_damage_anisoBrittle_N
real(pReal), dimension(:,:), allocatable, private :: &
source_damage_anisoBrittle_critDisp, &
source_damage_anisoBrittle_critLoad
enum, bind(c)
enumerator :: undefined_ID, &
damage_drivingforce_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
source_damage_anisoBrittle_outputID !< ID of each post result output
public :: &
source_damage_anisoBrittle_init, &
source_damage_anisoBrittle_dotState, &
source_damage_anisobrittle_getRateAndItsTangent, &
source_damage_anisoBrittle_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisoBrittle_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_damage_anisoBrittle_label, &
SOURCE_damage_anisoBrittle_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
use lattice, only: &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_anisoBrittle_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_damage_anisoBrittle_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_damage_anisoBrittle_offset(material_Nphase), source=0_pInt)
allocate(source_damage_anisoBrittle_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_damage_anisoBrittle_instance(phase) = count(phase_source(:,1:phase) == source_damage_anisoBrittle_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_damage_anisoBrittle_ID) &
source_damage_anisoBrittle_offset(phase) = source
enddo
enddo
allocate(source_damage_anisoBrittle_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_damage_anisoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt)
allocate(source_damage_anisoBrittle_output(maxval(phase_Noutput),maxNinstance))
source_damage_anisoBrittle_output = ''
allocate(source_damage_anisoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(source_damage_anisoBrittle_Noutput(maxNinstance), source=0_pInt)
allocate(source_damage_anisoBrittle_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoBrittle_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoBrittle_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt)
allocate(source_damage_anisoBrittle_totalNcleavage(maxNinstance), source=0_pInt)
allocate(source_damage_anisoBrittle_aTol(maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoBrittle_sdot_0(maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoBrittle_N(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_damage_anisoBrittle_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('anisobrittle_drivingforce')
source_damage_anisoBrittle_Noutput(instance) = source_damage_anisoBrittle_Noutput(instance) + 1_pInt
source_damage_anisoBrittle_outputID(source_damage_anisoBrittle_Noutput(instance),instance) = damage_drivingforce_ID
source_damage_anisoBrittle_output(source_damage_anisoBrittle_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('anisobrittle_atol')
source_damage_anisoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisobrittle_sdot0')
source_damage_anisoBrittle_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisobrittle_ratesensitivity')
source_damage_anisoBrittle_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('ncleavage') !
Nchunks_CleavageFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_CleavageFamilies
source_damage_anisoBrittle_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('anisobrittle_criticaldisplacement')
do j = 1_pInt, Nchunks_CleavageFamilies
source_damage_anisoBrittle_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('anisobrittle_criticalload')
do j = 1_pInt, Nchunks_CleavageFamilies
source_damage_anisoBrittle_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, material_Nphase
myPhase: if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then
instance = source_damage_anisoBrittle_instance(phase)
source_damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance) = &
min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested
source_damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance))
source_damage_anisoBrittle_totalNcleavage(instance) = sum(source_damage_anisoBrittle_Ncleavage(:,instance)) ! how many cleavage systems altogether
if (source_damage_anisoBrittle_aTol(instance) < 0.0_pReal) &
source_damage_anisoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (source_damage_anisoBrittle_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//SOURCE_damage_anisoBrittle_LABEL//')')
if (any(source_damage_anisoBrittle_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//SOURCE_damage_anisoBrittle_LABEL//')')
if (any(source_damage_anisoBrittle_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//SOURCE_damage_anisoBrittle_LABEL//')')
if (source_damage_anisoBrittle_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//SOURCE_damage_anisoBrittle_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_damage_anisoBrittle_instance(phase)
sourceOffset = source_damage_anisoBrittle_offset(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,source_damage_anisoBrittle_Noutput(instance)
select case(source_damage_anisoBrittle_outputID(o,instance))
case(damage_drivingforce_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
source_damage_anisoBrittle_sizePostResult(o,instance) = mySize
source_damage_anisoBrittle_sizePostResults(instance) = source_damage_anisoBrittle_sizePostResults(instance) + mySize
endif
enddo outputsLoop
!--------------------------------------------------------------------------------------------------
! Determine size of state array
sizeDotState = 1_pInt
sizeState = 1_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_anisoBrittle_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), &
source=source_damage_anisoBrittle_aTol(instance))
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_damage_anisoBrittle_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisoBrittle_dotState(Tstar_v, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState, &
material_homog, &
damage, &
damageMapping
use lattice, only: &
lattice_Scleavage_v, &
lattice_maxNcleavageFamily, &
lattice_NcleavageSystem
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel)
integer(pInt) :: &
phase, &
constituent, &
instance, &
sourceOffset, &
damageOffset, &
homog, &
f, i, index_myFamily
real(pReal) :: &
traction_d, traction_t, traction_n, traction_crit
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_anisoBrittle_instance(phase)
sourceOffset = source_damage_anisoBrittle_offset(phase)
homog = material_homog(ip,el)
damageOffset = damageMapping(homog)%p(ip,el)
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = 0.0_pReal
do f = 1_pInt,lattice_maxNcleavageFamily
index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family
do i = 1_pInt,source_damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family
traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase))
traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase))
traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase))
traction_crit = source_damage_anisoBrittle_critLoad(f,instance)* &
damage(homog)%p(damageOffset)
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = &
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) + &
source_damage_anisoBrittle_sdot_0(instance)* &
((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance) + &
(max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance) + &
(max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance))/ &
source_damage_anisoBrittle_critDisp(f,instance)
enddo
enddo
end subroutine source_damage_anisoBrittle_dotState
!--------------------------------------------------------------------------------------------------
!> @brief returns local part of nonlocal damage driving force
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
phi
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
integer(pInt) :: &
phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_damage_anisoBrittle_offset(phase)
localphiDot = 1.0_pReal - &
max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* &
phi
dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))
end subroutine source_damage_anisobrittle_getRateAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of local damage results
!--------------------------------------------------------------------------------------------------
function source_damage_anisoBrittle_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(source_damage_anisoBrittle_sizePostResults( &
source_damage_anisoBrittle_instance(mappingConstitutive(2,ipc,ip,el)))) :: &
source_damage_anisoBrittle_postResults
integer(pInt) :: &
instance, phase, constituent, sourceOffset, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_anisoBrittle_instance(phase)
sourceOffset = source_damage_anisoBrittle_offset(phase)
c = 0_pInt
source_damage_anisoBrittle_postResults = 0.0_pReal
do o = 1_pInt,source_damage_anisoBrittle_Noutput(instance)
select case(source_damage_anisoBrittle_outputID(o,instance))
case (damage_drivingforce_ID)
source_damage_anisoBrittle_postResults(c+1_pInt) = &
sourceState(phase)%p(sourceOffset)%state(1,constituent)
c = c + 1_pInt
end select
enddo
end function source_damage_anisoBrittle_postResults
end module source_damage_anisoBrittle

View File

@ -0,0 +1,412 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incorporating anisotropic ductile damage source mechanism
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_damage_anisoDuctile
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_damage_anisoDuctile_sizePostResults, & !< cumulative size of post results
source_damage_anisoDuctile_offset, & !< which source is my current damage mechanism?
source_damage_anisoDuctile_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_damage_anisoDuctile_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_damage_anisoDuctile_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_damage_anisoDuctile_Noutput !< number of outputs per instance of this damage
integer(pInt), dimension(:), allocatable, private :: &
source_damage_anisoDuctile_totalNslip !< total number of slip systems
integer(pInt), dimension(:,:), allocatable, private :: &
source_damage_anisoDuctile_Nslip !< number of slip systems per family
real(pReal), dimension(:), allocatable, private :: &
source_damage_anisoDuctile_aTol
real(pReal), dimension(:,:), allocatable, private :: &
source_damage_anisoDuctile_critPlasticStrain
real(pReal), dimension(:), allocatable, private :: &
source_damage_anisoDuctile_sdot_0, &
source_damage_anisoDuctile_N
real(pReal), dimension(:,:), allocatable, private :: &
source_damage_anisoDuctile_critLoad
enum, bind(c)
enumerator :: undefined_ID, &
damage_drivingforce_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
source_damage_anisoDuctile_outputID !< ID of each post result output
public :: &
source_damage_anisoDuctile_init, &
source_damage_anisoDuctile_dotState, &
source_damage_anisoDuctile_getRateAndItsTangent, &
source_damage_anisoDuctile_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisoDuctile_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_damage_anisoDuctile_label, &
SOURCE_damage_anisoDuctile_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
use lattice, only: &
lattice_maxNslipFamily, &
lattice_NslipSystem
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_anisoDuctile_LABEL//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_damage_anisoDuctile_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_damage_anisoDuctile_offset(material_Nphase), source=0_pInt)
allocate(source_damage_anisoDuctile_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_damage_anisoDuctile_instance(phase) = count(phase_source(:,1:phase) == source_damage_anisoDuctile_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_damage_anisoDuctile_ID) &
source_damage_anisoDuctile_offset(phase) = source
enddo
enddo
allocate(source_damage_anisoDuctile_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_damage_anisoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_damage_anisoDuctile_output(maxval(phase_Noutput),maxNinstance))
source_damage_anisoDuctile_output = ''
allocate(source_damage_anisoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(source_damage_anisoDuctile_Noutput(maxNinstance), source=0_pInt)
allocate(source_damage_anisoDuctile_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoDuctile_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal)
allocate(source_damage_anisoDuctile_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt)
allocate(source_damage_anisoDuctile_totalNslip(maxNinstance), source=0_pInt)
allocate(source_damage_anisoDuctile_N(maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoDuctile_sdot_0(maxNinstance), source=0.0_pReal)
allocate(source_damage_anisoDuctile_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_damage_anisoDuctile_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('anisoductile_drivingforce')
source_damage_anisoDuctile_Noutput(instance) = source_damage_anisoDuctile_Noutput(instance) + 1_pInt
source_damage_anisoDuctile_outputID(source_damage_anisoDuctile_Noutput(instance),instance) = damage_drivingforce_ID
source_damage_anisoDuctile_output(source_damage_anisoDuctile_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('anisoductile_atol')
source_damage_anisoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt)
case ('nslip') !
Nchunks_SlipFamilies = positions(1) - 1_pInt
do j = 1_pInt, Nchunks_SlipFamilies
source_damage_anisoDuctile_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j)
enddo
case ('anisoductile_sdot0')
source_damage_anisoDuctile_sdot_0(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisoductile_criticalplasticstrain')
do j = 1_pInt, Nchunks_SlipFamilies
source_damage_anisoDuctile_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
case ('anisoductile_ratesensitivity')
source_damage_anisoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('anisoductile_criticalload')
do j = 1_pInt, Nchunks_SlipFamilies
source_damage_anisoDuctile_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j)
enddo
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, size(phase_source)
myPhase: if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then
instance = source_damage_anisoDuctile_instance(phase)
source_damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance) = &
min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested
source_damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance))
source_damage_anisoDuctile_totalNslip(instance) = sum(source_damage_anisoDuctile_Nslip(:,instance))
if (source_damage_anisoDuctile_aTol(instance) < 0.0_pReal) &
source_damage_anisoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (source_damage_anisoDuctile_sdot_0(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//SOURCE_damage_anisoDuctile_LABEL//')')
if (any(source_damage_anisoDuctile_critPlasticStrain(:,instance) < 0.0_pReal)) &
call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//SOURCE_damage_anisoDuctile_LABEL//')')
if (source_damage_anisoDuctile_N(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//SOURCE_damage_anisoDuctile_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_damage_anisoDuctile_instance(phase)
sourceOffset = source_damage_anisoDuctile_offset(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,source_damage_anisoDuctile_Noutput(instance)
select case(source_damage_anisoDuctile_outputID(o,instance))
case(damage_drivingforce_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
source_damage_anisoDuctile_sizePostResult(o,instance) = mySize
source_damage_anisoDuctile_sizePostResults(instance) = source_damage_anisoDuctile_sizePostResults(instance) + mySize
endif
enddo outputsLoop
!--------------------------------------------------------------------------------------------------
! Determine size of state array
sizeDotState = 1_pInt
sizeState = 1_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_anisoDuctile_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), &
source=source_damage_anisoDuctile_aTol(instance))
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_damage_anisoDuctile_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisoDuctile_dotState(ipc, ip, el)
use material, only: &
mappingConstitutive, &
plasticState, &
sourceState, &
material_homog, &
damage, &
damageMapping
use lattice, only: &
lattice_maxNslipFamily
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
integer(pInt) :: &
phase, &
constituent, &
sourceOffset, &
homog, damageOffset, &
instance, &
index, f, i
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_anisoDuctile_instance(phase)
sourceOffset = source_damage_anisoDuctile_offset(phase)
homog = material_homog(ip,el)
damageOffset = damageMapping(homog)%p(ip,el)
index = 1_pInt
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = 0.0_pReal
do f = 1_pInt,lattice_maxNslipFamily
do i = 1_pInt,source_damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = &
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) + &
plasticState(phase)%slipRate(index,constituent)/ &
((damage(homog)%p(damageOffset))**source_damage_anisoDuctile_N(instance))/ &
source_damage_anisoDuctile_critPlasticStrain(f,instance)
index = index + 1_pInt
enddo
enddo
end subroutine source_damage_anisoDuctile_dotState
!--------------------------------------------------------------------------------------------------
!> @brief returns local part of nonlocal damage driving force
!--------------------------------------------------------------------------------------------------
subroutine source_damage_anisoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
phi
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
integer(pInt) :: &
phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_damage_anisoDuctile_offset(phase)
localphiDot = 1.0_pReal - &
max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* &
phi
dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))
end subroutine source_damage_anisoDuctile_getRateAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of local damage results
!--------------------------------------------------------------------------------------------------
function source_damage_anisoDuctile_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(source_damage_anisoDuctile_sizePostResults( &
source_damage_anisoDuctile_instance(mappingConstitutive(2,ipc,ip,el)))) :: &
source_damage_anisoDuctile_postResults
integer(pInt) :: &
instance, phase, constituent, sourceOffset, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_anisoDuctile_instance(phase)
sourceOffset = source_damage_anisoDuctile_offset(phase)
c = 0_pInt
source_damage_anisoDuctile_postResults = 0.0_pReal
do o = 1_pInt,source_damage_anisoDuctile_Noutput(instance)
select case(source_damage_anisoDuctile_outputID(o,instance))
case (damage_drivingforce_ID)
source_damage_anisoDuctile_postResults(c+1_pInt) = &
sourceState(phase)%p(sourceOffset)%state(1,constituent)
c = c + 1_pInt
end select
enddo
end function source_damage_anisoDuctile_postResults
end module source_damage_anisoDuctile

View File

@ -0,0 +1,362 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incoprorating isotropic brittle damage source mechanism
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_damage_isoBrittle
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_damage_isoBrittle_sizePostResults, & !< cumulative size of post results
source_damage_isoBrittle_offset, & !< which source is my current damage mechanism?
source_damage_isoBrittle_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_damage_isoBrittle_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_damage_isoBrittle_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_damage_isoBrittle_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
source_damage_isoBrittle_aTol, &
source_damage_isoBrittle_critStrainEnergy
enum, bind(c)
enumerator :: undefined_ID, &
damage_drivingforce_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
source_damage_isoBrittle_outputID !< ID of each post result output
public :: &
source_damage_isoBrittle_init, &
source_damage_isoBrittle_deltaState, &
source_damage_isoBrittle_getRateAndItsTangent, &
source_damage_isoBrittle_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoBrittle_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_damage_isoBrittle_label, &
SOURCE_damage_isoBrittle_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_isoBrittle_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_damage_isoBrittle_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_damage_isoBrittle_offset(material_Nphase), source=0_pInt)
allocate(source_damage_isoBrittle_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_damage_isoBrittle_instance(phase) = count(phase_source(:,1:phase) == source_damage_isoBrittle_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_damage_isoBrittle_ID) &
source_damage_isoBrittle_offset(phase) = source
enddo
enddo
allocate(source_damage_isoBrittle_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_damage_isoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_damage_isoBrittle_output(maxval(phase_Noutput),maxNinstance))
source_damage_isoBrittle_output = ''
allocate(source_damage_isoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(source_damage_isoBrittle_Noutput(maxNinstance), source=0_pInt)
allocate(source_damage_isoBrittle_critStrainEnergy(maxNinstance), source=0.0_pReal)
allocate(source_damage_isoBrittle_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_damage_isoBrittle_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('isobrittle_drivingforce')
source_damage_isoBrittle_Noutput(instance) = source_damage_isoBrittle_Noutput(instance) + 1_pInt
source_damage_isoBrittle_outputID(source_damage_isoBrittle_Noutput(instance),instance) = damage_drivingforce_ID
source_damage_isoBrittle_output(source_damage_isoBrittle_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('isobrittle_criticalstrainenergy')
source_damage_isoBrittle_critStrainEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('isobrittle_atol')
source_damage_isoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, material_Nphase
myPhase: if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then
instance = source_damage_isoBrittle_instance(phase)
if (source_damage_isoBrittle_aTol(instance) < 0.0_pReal) &
source_damage_isoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (source_damage_isoBrittle_critStrainEnergy(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='criticalStrainEnergy ('//SOURCE_damage_isoBrittle_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_damage_isoBrittle_instance(phase)
sourceOffset = source_damage_isoBrittle_offset(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,source_damage_isoBrittle_Noutput(instance)
select case(source_damage_isoBrittle_outputID(o,instance))
case(damage_drivingforce_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
source_damage_isoBrittle_sizePostResult(o,instance) = mySize
source_damage_isoBrittle_sizePostResults(instance) = source_damage_isoBrittle_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 1_pInt
sizeState = 1_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_isoBrittle_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), &
source=source_damage_isoBrittle_aTol(instance))
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_damage_isoBrittle_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoBrittle_deltaState(C, Fe, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState, &
material_homog, &
phase_NstiffnessDegradations, &
phase_stiffnessDegradation, &
porosity, &
porosityMapping, &
STIFFNESS_DEGRADATION_porosity_ID
use math, only : &
math_mul33x33, &
math_mul66x6, &
math_Mandel33to6, &
math_transpose33, &
math_I3
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in), dimension(3,3) :: &
Fe
integer(pInt) :: &
phase, constituent, instance, sourceOffset, mech
real(pReal) :: &
strain(6), &
C(6,6)
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_isoBrittle_instance(phase)
sourceOffset = source_damage_isoBrittle_offset(phase)
do mech = 1_pInt, phase_NstiffnessDegradations(phase)
select case(phase_stiffnessDegradation(mech,phase))
case (STIFFNESS_DEGRADATION_porosity_ID)
C = porosity(material_homog(ip,el))%p(porosityMapping(material_homog(ip,el))%p(ip,el))* &
porosity(material_homog(ip,el))%p(porosityMapping(material_homog(ip,el))%p(ip,el))* &
C
end select
enddo
strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3)
sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = &
2.0_pReal*sum(strain*math_mul66x6(C,strain))/source_damage_isoBrittle_critStrainEnergy(instance) - &
sourceState(phase)%p(sourceOffset)%state(1,constituent)
end subroutine source_damage_isoBrittle_deltaState
!--------------------------------------------------------------------------------------------------
!> @brief returns local part of nonlocal damage driving force
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoBrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
phi
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
integer(pInt) :: &
phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_damage_isoBrittle_offset(phase)
localphiDot = 1.0_pReal - &
max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* &
phi
dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))
end subroutine source_damage_isoBrittle_getRateAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of local damage results
!--------------------------------------------------------------------------------------------------
function source_damage_isoBrittle_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(source_damage_isoBrittle_sizePostResults( &
source_damage_isoBrittle_instance(mappingConstitutive(2,ipc,ip,el)))) :: &
source_damage_isoBrittle_postResults
integer(pInt) :: &
instance, phase, constituent, sourceOffset, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_isoBrittle_instance(phase)
sourceOffset = source_damage_isoBrittle_offset(phase)
c = 0_pInt
source_damage_isoBrittle_postResults = 0.0_pReal
do o = 1_pInt,source_damage_isoBrittle_Noutput(instance)
select case(source_damage_isoBrittle_outputID(o,instance))
case (damage_drivingforce_ID)
source_damage_isoBrittle_postResults(c+1_pInt) = sourceState(phase)%p(sourceOffset)%state(1,constituent)
c = c + 1
end select
enddo
end function source_damage_isoBrittle_postResults
end module source_damage_isoBrittle

View File

@ -0,0 +1,347 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH
!> @brief material subroutine incoprorating isotropic ductile damage source mechanism
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_damage_isoDuctile
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_damage_isoDuctile_sizePostResults, & !< cumulative size of post results
source_damage_isoDuctile_offset, & !< which source is my current damage mechanism?
source_damage_isoDuctile_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_damage_isoDuctile_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_damage_isoDuctile_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_damage_isoDuctile_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
source_damage_isoDuctile_aTol, &
source_damage_isoDuctile_critPlasticStrain, &
source_damage_isoDuctile_N
enum, bind(c)
enumerator :: undefined_ID, &
damage_drivingforce_ID
end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
source_damage_isoDuctile_outputID !< ID of each post result output
public :: &
source_damage_isoDuctile_init, &
source_damage_isoDuctile_dotState, &
source_damage_isoDuctile_getRateAndItsTangent, &
source_damage_isoDuctile_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoDuctile_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_damage_isoDuctile_label, &
SOURCE_damage_isoDuctile_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_isoDuctile_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_damage_isoDuctile_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_damage_isoDuctile_offset(material_Nphase), source=0_pInt)
allocate(source_damage_isoDuctile_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_damage_isoDuctile_instance(phase) = count(phase_source(:,1:phase) == source_damage_isoDuctile_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_damage_isoDuctile_ID) &
source_damage_isoDuctile_offset(phase) = source
enddo
enddo
allocate(source_damage_isoDuctile_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_damage_isoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_damage_isoDuctile_output(maxval(phase_Noutput),maxNinstance))
source_damage_isoDuctile_output = ''
allocate(source_damage_isoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(source_damage_isoDuctile_Noutput(maxNinstance), source=0_pInt)
allocate(source_damage_isoDuctile_critPlasticStrain(maxNinstance), source=0.0_pReal)
allocate(source_damage_isoDuctile_N(maxNinstance), source=0.0_pReal)
allocate(source_damage_isoDuctile_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_damage_isoDuctile_instance(phase) ! which instance of my damage is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('isoductile_drivingforce')
source_damage_isoDuctile_Noutput(instance) = source_damage_isoDuctile_Noutput(instance) + 1_pInt
source_damage_isoDuctile_outputID(source_damage_isoDuctile_Noutput(instance),instance) = damage_drivingforce_ID
source_damage_isoDuctile_output(source_damage_isoDuctile_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('isoductile_criticalplasticstrain')
source_damage_isoDuctile_critPlasticStrain(instance) = IO_floatValue(line,positions,2_pInt)
case ('isoductile_ratesensitivity')
source_damage_isoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt)
case ('isoductile_atol')
source_damage_isoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
!--------------------------------------------------------------------------------------------------
! sanity checks
sanityChecks: do phase = 1_pInt, material_Nphase
myPhase: if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then
instance = source_damage_isoDuctile_instance(phase)
if (source_damage_isoDuctile_aTol(instance) < 0.0_pReal) &
source_damage_isoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3
if (source_damage_isoDuctile_critPlasticStrain(instance) <= 0.0_pReal) &
call IO_error(211_pInt,el=instance,ext_msg='critical plastic strain ('//SOURCE_damage_isoDuctile_LABEL//')')
endif myPhase
enddo sanityChecks
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_damage_isoDuctile_instance(phase)
sourceOffset = source_damage_isoDuctile_offset(phase)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,source_damage_isoDuctile_Noutput(instance)
select case(source_damage_isoDuctile_outputID(o,instance))
case(damage_drivingforce_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
source_damage_isoDuctile_sizePostResult(o,instance) = mySize
source_damage_isoDuctile_sizePostResults(instance) = source_damage_isoDuctile_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 1_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_isoDuctile_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), &
source=source_damage_isoDuctile_aTol(instance))
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_damage_isoDuctile_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoDuctile_dotState(ipc, ip, el)
use material, only: &
mappingConstitutive, &
plasticState, &
sourceState, &
material_homog, &
damage, &
damageMapping
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
integer(pInt) :: &
phase, constituent, instance, homog, sourceOffset, damageOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_isoDuctile_instance(phase)
sourceOffset = source_damage_isoDuctile_offset(phase)
homog = material_homog(ip,el)
damageOffset = damageMapping(homog)%p(ip,el)
sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = &
sum(plasticState(phase)%slipRate(:,constituent))/ &
((damage(homog)%p(damageOffset))**source_damage_isoDuctile_N(instance))/ &
source_damage_isoDuctile_critPlasticStrain(instance)
end subroutine source_damage_isoDuctile_dotState
!--------------------------------------------------------------------------------------------------
!> @brief returns local part of nonlocal damage driving force
!--------------------------------------------------------------------------------------------------
subroutine source_damage_isoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
phi
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
integer(pInt) :: &
phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_damage_isoDuctile_offset(phase)
localphiDot = 1.0_pReal - &
max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* &
phi
dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))
end subroutine source_damage_isoDuctile_getRateAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of local damage results
!--------------------------------------------------------------------------------------------------
function source_damage_isoDuctile_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(source_damage_isoDuctile_sizePostResults( &
source_damage_isoDuctile_instance(mappingConstitutive(2,ipc,ip,el)))) :: &
source_damage_isoDuctile_postResults
integer(pInt) :: &
instance, phase, constituent, sourceOffset, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_damage_isoDuctile_instance(phase)
sourceOffset = source_damage_isoDuctile_offset(phase)
c = 0_pInt
source_damage_isoDuctile_postResults = 0.0_pReal
do o = 1_pInt,source_damage_isoDuctile_Noutput(instance)
select case(source_damage_isoDuctile_outputID(o,instance))
case (damage_drivingforce_ID)
source_damage_isoDuctile_postResults(c+1_pInt) = sourceState(phase)%p(sourceOffset)%state(1,constituent)
c = c + 1
end select
enddo
end function source_damage_isoDuctile_postResults
end module source_damage_isoDuctile

View File

@ -0,0 +1,217 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for thermal source due to plastic dissipation
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_thermal_dissipation
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_thermal_dissipation_sizePostResults, & !< cumulative size of post results
source_thermal_dissipation_offset, & !< which source is my current thermal dissipation mechanism?
source_thermal_dissipation_instance !< instance of thermal dissipation source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_thermal_dissipation_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_thermal_dissipation_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_thermal_dissipation_Noutput !< number of outputs per instance of this source
real(pReal), dimension(:), allocatable, private :: &
source_thermal_dissipation_coldworkCoeff
public :: &
source_thermal_dissipation_init, &
source_thermal_dissipation_getRateAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_thermal_dissipation_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_thermal_dissipation_label, &
SOURCE_thermal_dissipation_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_dissipation_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_thermal_dissipation_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_thermal_dissipation_offset(material_Nphase), source=0_pInt)
allocate(source_thermal_dissipation_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_thermal_dissipation_instance(phase) = count(phase_source(:,1:phase) == SOURCE_thermal_dissipation_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == SOURCE_thermal_dissipation_ID) &
source_thermal_dissipation_offset(phase) = source
enddo
enddo
allocate(source_thermal_dissipation_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_thermal_dissipation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_thermal_dissipation_output (maxval(phase_Noutput),maxNinstance))
source_thermal_dissipation_output = ''
allocate(source_thermal_dissipation_Noutput(maxNinstance), source=0_pInt)
allocate(source_thermal_dissipation_coldworkCoeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_thermal_dissipation_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_thermal_dissipation_instance(phase) ! which instance of my source is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('dissipation_coldworkcoeff')
source_thermal_dissipation_coldworkCoeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_thermal_dissipation_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_thermal_dissipation_instance(phase)
sourceOffset = source_thermal_dissipation_offset(phase)
sizeDotState = 0_pInt
sizeState = 0_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_thermal_dissipation_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_thermal_dissipation_init
!--------------------------------------------------------------------------------------------------
!> @brief returns local vacancy generation rate
!--------------------------------------------------------------------------------------------------
subroutine source_thermal_dissipation_getRateAndItsTangent(TDot, dTDOT_dT, Tstar_v, Lp, ipc, ip, el)
use math, only: &
math_Mandel6to33
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel)
real(pReal), intent(in), dimension(3,3) :: &
Lp
real(pReal), intent(out) :: &
TDot, &
dTDOT_dT
integer(pInt) :: &
instance, phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_thermal_dissipation_instance(phase)
TDot = source_thermal_dissipation_coldworkCoeff(instance)* &
sum(abs(math_Mandel6to33(Tstar_v)*Lp))
dTDOT_dT = 0.0_pReal
end subroutine source_thermal_dissipation_getRateAndItsTangent
end module source_thermal_dissipation

View File

@ -0,0 +1,250 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for vacancy generation due to irradiation
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_vacancy_irradiation
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_vacancy_irradiation_sizePostResults, & !< cumulative size of post results
source_vacancy_irradiation_offset, & !< which source is my current damage mechanism?
source_vacancy_irradiation_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_vacancy_irradiation_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_vacancy_irradiation_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_vacancy_irradiation_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
source_vacancy_irradiation_cascadeProb, &
source_vacancy_irradiation_cascadeVolume
public :: &
source_vacancy_irradiation_init, &
source_vacancy_irradiation_deltaState, &
source_vacancy_irradiation_getRateAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_irradiation_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_vacancy_irradiation_label, &
SOURCE_vacancy_irradiation_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_irradiation_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_vacancy_irradiation_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_vacancy_irradiation_offset(material_Nphase), source=0_pInt)
allocate(source_vacancy_irradiation_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_vacancy_irradiation_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_irradiation_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_vacancy_irradiation_ID) &
source_vacancy_irradiation_offset(phase) = source
enddo
enddo
allocate(source_vacancy_irradiation_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_vacancy_irradiation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_vacancy_irradiation_output(maxval(phase_Noutput),maxNinstance))
source_vacancy_irradiation_output = ''
allocate(source_vacancy_irradiation_Noutput(maxNinstance), source=0_pInt)
allocate(source_vacancy_irradiation_cascadeProb(maxNinstance), source=0.0_pReal)
allocate(source_vacancy_irradiation_cascadeVolume(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_irradiation_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_vacancy_irradiation_instance(phase) ! which instance of my vacancy is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('irradiation_cascadeprobability')
source_vacancy_irradiation_cascadeProb(instance) = IO_floatValue(line,positions,2_pInt)
case ('irradiation_cascadevolume')
source_vacancy_irradiation_cascadeVolume(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_vacancy_irradiation_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_vacancy_irradiation_instance(phase)
sourceOffset = source_vacancy_irradiation_offset(phase)
sizeDotState = 2_pInt
sizeState = 2_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_irradiation_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.1_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_vacancy_irradiation_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_irradiation_deltaState(ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
integer(pInt) :: &
phase, constituent, sourceOffset
real(pReal) :: &
randNo
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_vacancy_irradiation_offset(phase)
call random_number(randNo)
sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = &
randNo - sourceState(phase)%p(sourceOffset)%state(1,constituent)
call random_number(randNo)
sourceState(phase)%p(sourceOffset)%deltaState(2,constituent) = &
randNo - sourceState(phase)%p(sourceOffset)%state(2,constituent)
end subroutine source_vacancy_irradiation_deltaState
!--------------------------------------------------------------------------------------------------
!> @brief returns local vacancy generation rate
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_irradiation_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out) :: &
CvDot, dCvDot_dCv
integer(pInt) :: &
instance, phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_vacancy_irradiation_instance(phase)
sourceOffset = source_vacancy_irradiation_offset(phase)
CvDot = 0.0_pReal
dCvDot_dCv = 0.0_pReal
if (sourceState(phase)%p(sourceOffset)%state0(1,constituent) < source_vacancy_irradiation_cascadeProb(instance)) &
CvDot = sourceState(phase)%p(sourceOffset)%state0(2,constituent)*source_vacancy_irradiation_cascadeVolume(instance)
end subroutine source_vacancy_irradiation_getRateAndItsTangent
end module source_vacancy_irradiation

View File

@ -0,0 +1,212 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for vacancy generation due to plasticity
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_vacancy_phenoplasticity
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_vacancy_phenoplasticity_sizePostResults, & !< cumulative size of post results
source_vacancy_phenoplasticity_offset, & !< which source is my current damage mechanism?
source_vacancy_phenoplasticity_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_vacancy_phenoplasticity_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_vacancy_phenoplasticity_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_vacancy_phenoplasticity_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
source_vacancy_phenoplasticity_rateCoeff
public :: &
source_vacancy_phenoplasticity_init, &
source_vacancy_phenoplasticity_getRateAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_phenoplasticity_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_vacancy_phenoplasticity_label, &
SOURCE_vacancy_phenoplasticity_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_phenoplasticity_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_vacancy_phenoplasticity_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_vacancy_phenoplasticity_offset(material_Nphase), source=0_pInt)
allocate(source_vacancy_phenoplasticity_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_vacancy_phenoplasticity_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_phenoplasticity_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_vacancy_phenoplasticity_ID) &
source_vacancy_phenoplasticity_offset(phase) = source
enddo
enddo
allocate(source_vacancy_phenoplasticity_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_vacancy_phenoplasticity_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_vacancy_phenoplasticity_output(maxval(phase_Noutput),maxNinstance))
source_vacancy_phenoplasticity_output = ''
allocate(source_vacancy_phenoplasticity_Noutput(maxNinstance), source=0_pInt)
allocate(source_vacancy_phenoplasticity_rateCoeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_phenoplasticity_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_vacancy_phenoplasticity_instance(phase) ! which instance of my vacancy is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('phenoplasticity_ratecoeff')
source_vacancy_phenoplasticity_rateCoeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_vacancy_phenoplasticity_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_vacancy_phenoplasticity_instance(phase)
sourceOffset = source_vacancy_phenoplasticity_offset(phase)
sizeDotState = 0_pInt
sizeState = 0_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_phenoplasticity_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_vacancy_phenoplasticity_init
!--------------------------------------------------------------------------------------------------
!> @brief returns local vacancy generation rate
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_phenoplasticity_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el)
use material, only: &
mappingConstitutive, &
plasticState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out) :: &
CvDot, dCvDot_dCv
integer(pInt) :: &
instance, phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_vacancy_phenoplasticity_instance(phase)
CvDot = &
source_vacancy_phenoplasticity_rateCoeff(instance)* &
sum(plasticState(phase)%slipRate(:,constituent))
dCvDot_dCv = 0.0_pReal
end subroutine source_vacancy_phenoplasticity_getRateAndItsTangent
end module source_vacancy_phenoplasticity

View File

@ -0,0 +1,240 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for vacancy generation due to thermal fluctuations
!> @details to be done
!--------------------------------------------------------------------------------------------------
module source_vacancy_thermalfluc
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
source_vacancy_thermalfluc_sizePostResults, & !< cumulative size of post results
source_vacancy_thermalfluc_offset, & !< which source is my current damage mechanism?
source_vacancy_thermalfluc_instance !< instance of damage source mechanism
integer(pInt), dimension(:,:), allocatable, target, public :: &
source_vacancy_thermalfluc_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
source_vacancy_thermalfluc_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
source_vacancy_thermalfluc_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
source_vacancy_thermalfluc_amplitude
public :: &
source_vacancy_thermalfluc_init, &
source_vacancy_thermalfluc_deltaState, &
source_vacancy_thermalfluc_getRateAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_thermalfluc_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
phase_source, &
phase_Nsources, &
phase_Noutput, &
SOURCE_vacancy_thermalfluc_label, &
SOURCE_vacancy_thermalfluc_ID, &
material_Nphase, &
material_phase, &
sourceState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_thermalfluc_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_source == SOURCE_vacancy_thermalfluc_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(source_vacancy_thermalfluc_offset(material_Nphase), source=0_pInt)
allocate(source_vacancy_thermalfluc_instance(material_Nphase), source=0_pInt)
do phase = 1, material_Nphase
source_vacancy_thermalfluc_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_thermalfluc_ID)
do source = 1, phase_Nsources(phase)
if (phase_source(source,phase) == source_vacancy_thermalfluc_ID) &
source_vacancy_thermalfluc_offset(phase) = source
enddo
enddo
allocate(source_vacancy_thermalfluc_sizePostResults(maxNinstance), source=0_pInt)
allocate(source_vacancy_thermalfluc_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(source_vacancy_thermalfluc_output(maxval(phase_Noutput),maxNinstance))
source_vacancy_thermalfluc_output = ''
allocate(source_vacancy_thermalfluc_Noutput(maxNinstance), source=0_pInt)
allocate(source_vacancy_thermalfluc_amplitude(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_thermalfluc_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = source_vacancy_thermalfluc_instance(phase) ! which instance of my vacancy is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('thermalfluctuation_amplitude')
source_vacancy_thermalfluc_amplitude(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, material_Nphase
if (any(phase_source(:,phase) == SOURCE_vacancy_thermalfluc_ID)) then
NofMyPhase=count(material_phase==phase)
instance = source_vacancy_thermalfluc_instance(phase)
sourceOffset = source_vacancy_thermalfluc_offset(phase)
sizeDotState = 1_pInt
sizeState = 1_pInt
sourceState(phase)%p(sourceOffset)%sizeState = sizeState
sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState
sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_thermalfluc_sizePostResults(instance)
allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
endif
enddo initializeInstances
end subroutine source_vacancy_thermalfluc_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_thermalfluc_deltaState(ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
integer(pInt) :: &
phase, constituent, sourceOffset
real(pReal) :: &
randNo
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
sourceOffset = source_vacancy_thermalfluc_offset(phase)
call random_number(randNo)
sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = &
randNo - sourceState(phase)%p(sourceOffset)%state(1,constituent)
end subroutine source_vacancy_thermalfluc_deltaState
!--------------------------------------------------------------------------------------------------
!> @brief returns local vacancy generation rate
!--------------------------------------------------------------------------------------------------
subroutine source_vacancy_thermalfluc_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el)
use material, only: &
mappingConstitutive, &
sourceState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(out) :: &
CvDot, dCvDot_dCv
integer(pInt) :: &
instance, phase, constituent, sourceOffset
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = source_vacancy_thermalfluc_instance(phase)
sourceOffset = source_vacancy_thermalfluc_offset(phase)
CvDot = source_vacancy_thermalfluc_amplitude(instance)*(sourceState(phase)%p(sourceOffset)%state0(2,constituent) - 0.5_pReal)
dCvDot_dCv = 0.0_pReal
end subroutine source_vacancy_thermalfluc_getRateAndItsTangent
end module source_vacancy_thermalfluc

View File

@ -2,7 +2,7 @@
! $Id$ ! $Id$
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine incoprorating local heat generation due to plastic dissipation !> @brief material subroutine for adiabatic temperature evolution
!> @details to be done !> @details to be done
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module thermal_adiabatic module thermal_adiabatic
@ -22,10 +22,7 @@ module thermal_adiabatic
thermal_adiabatic_output !< name of each post result output thermal_adiabatic_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: & integer(pInt), dimension(:), allocatable, target, public :: &
thermal_adiabatic_Noutput !< number of outputs per instance of this damage thermal_adiabatic_Noutput !< number of outputs per instance of this thermal model
real(pReal), dimension(:), allocatable, public :: &
thermal_adiabatic_aTol
enum, bind(c) enum, bind(c)
enumerator :: undefined_ID, & enumerator :: undefined_ID, &
@ -37,14 +34,10 @@ module thermal_adiabatic
public :: & public :: &
thermal_adiabatic_init, & thermal_adiabatic_init, &
thermal_adiabatic_stateInit, & thermal_adiabatic_updateState, &
thermal_adiabatic_aTolState, & thermal_adiabatic_getSourceAndItsTangent, &
thermal_adiabatic_microstructure, & thermal_adiabatic_getSpecificHeat, &
thermal_adiabatic_LTAndItsTangent, & thermal_adiabatic_getMassDensity, &
thermal_adiabatic_getTemperature, &
thermal_adiabatic_getLocalTemperature, &
thermal_adiabatic_putLocalTemperature, &
thermal_adiabatic_getHeatGeneration, &
thermal_adiabatic_postResults thermal_adiabatic_postResults
contains contains
@ -56,10 +49,6 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_init(fileUnit,temperature_init) subroutine thermal_adiabatic_init(fileUnit,temperature_init)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use IO, only: & use IO, only: &
IO_read, & IO_read, &
IO_lc, & IO_lc, &
@ -74,17 +63,20 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init)
IO_timeStamp, & IO_timeStamp, &
IO_EOF IO_EOF
use material, only: & use material, only: &
phase_thermal, & thermal_type, &
phase_thermalInstance, & thermal_typeInstance, &
phase_Noutput, & homogenization_Noutput, &
LOCAL_THERMAL_ADIABATIC_label, & THERMAL_ADIABATIC_label, &
LOCAL_THERMAL_adiabatic_ID, & THERMAL_adiabatic_ID, &
material_phase, & material_homog, &
mappingHomogenization, &
thermalState, & thermalState, &
MATERIAL_partPhase thermalMapping, &
temperature, &
temperatureRate, &
material_partHomogenization
use numerics,only: & use numerics,only: &
worldrank, & worldrank
numerics_integrator
implicit none implicit none
real(pReal), intent(in) :: temperature_init !< initial temperature real(pReal), intent(in) :: temperature_init !< initial temperature
@ -92,54 +84,51 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init)
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState, sizeDotState integer(pInt) :: sizeState
integer(pInt) :: NofMyPhase integer(pInt) :: NofMyHomog
character(len=65536) :: & character(len=65536) :: &
tag = '', & tag = '', &
line = '' line = ''
mainProcess: if (worldrank == 0) then mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- thermal_'//LOCAL_THERMAL_ADIABATIC_label//' init -+>>>' write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_ADIABATIC_label//' init -+>>>'
write(6,'(a)') ' $Id$' write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp() write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90" #include "compilation_info.f90"
endif mainProcess endif mainProcess
maxNinstance = int(count(phase_thermal == LOCAL_THERMAL_adiabatic_ID),pInt) maxNinstance = int(count(thermal_type == THERMAL_adiabatic_ID),pInt)
if (maxNinstance == 0_pInt) return if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(thermal_adiabatic_sizePostResults(maxNinstance), source=0_pInt) allocate(thermal_adiabatic_sizePostResults(maxNinstance), source=0_pInt)
allocate(thermal_adiabatic_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) allocate(thermal_adiabatic_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(thermal_adiabatic_output(maxval(phase_Noutput),maxNinstance)) allocate(thermal_adiabatic_output (maxval(homogenization_Noutput),maxNinstance))
thermal_adiabatic_output = '' thermal_adiabatic_output = ''
allocate(thermal_adiabatic_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) allocate(thermal_adiabatic_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(thermal_adiabatic_Noutput(maxNinstance), source=0_pInt) allocate(thermal_adiabatic_Noutput (maxNinstance), source=0_pInt)
allocate(thermal_adiabatic_aTol(maxNinstance), source=0.0_pReal)
rewind(fileUnit) rewind(fileUnit)
phase = 0_pInt section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase> do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit) line = IO_read(fileUnit)
enddo enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part
line = IO_read(fileUnit) line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read line = IO_read(fileUnit, .true.) ! reset IO_read
exit exit
endif endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section if (IO_getTag(line,'[',']') /= '') then ! next homog section
phase = phase + 1_pInt ! advance phase section counter section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line cycle ! skip to next line
endif endif
if (phase > 0_pInt ) then; if (phase_thermal(phase) == LOCAL_THERMAL_adiabatic_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran if (section > 0_pInt ) then; if (thermal_type(section) == THERMAL_adiabatic_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_thermalInstance(phase) ! which instance of my thermal is present phase instance = thermal_typeInstance(section) ! which instance of my thermal is present homog
positions = IO_stringPos(line,MAXNCHUNKS) positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag) select case(tag)
@ -152,17 +141,14 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init)
IO_lc(IO_stringValue(line,positions,2_pInt)) IO_lc(IO_stringValue(line,positions,2_pInt))
end select end select
case ('atol_adiabatic')
thermal_adiabatic_aTol(instance) = IO_floatValue(line,positions,2_pInt)
end select end select
endif; endif endif; endif
enddo parsingFile enddo parsingFile
initializeInstances: do phase = 1_pInt, size(phase_thermal) initializeInstances: do section = 1_pInt, size(thermal_type)
if (phase_thermal(phase) == LOCAL_THERMAL_adiabatic_ID) then if (thermal_type(section) == THERMAL_adiabatic_ID) then
NofMyPhase=count(material_phase==phase) NofMyHomog=count(material_homog==section)
instance = phase_thermalInstance(phase) instance = thermal_typeInstance(section)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! Determine size of postResults array ! Determine size of postResults array
@ -177,280 +163,243 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init)
thermal_adiabatic_sizePostResults(instance) = thermal_adiabatic_sizePostResults(instance) + mySize thermal_adiabatic_sizePostResults(instance) = thermal_adiabatic_sizePostResults(instance) + mySize
endif endif
enddo outputsLoop enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 1_pInt
thermalState(phase)%sizeState = sizeState
thermalState(phase)%sizeDotState = sizeDotState
thermalState(phase)%sizePostResults = thermal_adiabatic_sizePostResults(instance)
allocate(thermalState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(thermalState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(thermalState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(thermalState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(thermalState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(thermalState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(thermalState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) ! allocate state arrays
allocate(thermalState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) sizeState = 1_pInt
allocate(thermalState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) thermalState(section)%sizeState = sizeState
if (any(numerics_integrator == 1_pInt)) then thermalState(section)%sizePostResults = thermal_adiabatic_sizePostResults(instance)
allocate(thermalState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) allocate(thermalState(section)%state0 (sizeState,NofMyHomog), source=temperature_init)
allocate(thermalState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) allocate(thermalState(section)%subState0(sizeState,NofMyHomog), source=temperature_init)
endif allocate(thermalState(section)%state (sizeState,NofMyHomog), source=temperature_init)
if (any(numerics_integrator == 4_pInt)) &
allocate(thermalState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) nullify(thermalMapping(section)%p)
if (any(numerics_integrator == 5_pInt)) & thermalMapping(section)%p => mappingHomogenization(1,:,:)
allocate(thermalState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) deallocate(temperature(section)%p)
temperature(section)%p => thermalState(section)%state(1,:)
deallocate(temperatureRate(section)%p)
allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal)
call thermal_adiabatic_stateInit(phase,temperature_init)
call thermal_adiabatic_aTolState(phase,instance)
endif endif
enddo initializeInstances enddo initializeInstances
end subroutine thermal_adiabatic_init end subroutine thermal_adiabatic_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief sets the relevant NEW state values for a given instance of this thermal !> @brief calculates adiabatic change in temperature based on local heat generation model
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_stateInit(phase,temperature_init) function thermal_adiabatic_updateState(subdt, ip, el)
use material, only: & use numerics, only: &
thermalState err_thermal_tolAbs, &
err_thermal_tolRel
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the thermal
real(pReal), intent(in) :: temperature_init !< initial temperature
real(pReal), dimension(thermalState(phase)%sizeState) :: tempState
tempState(1) = temperature_init
thermalState(phase)%state = spread(tempState,2,size(thermalState(phase)%state(1,:)))
thermalState(phase)%state0 = thermalState(phase)%state
thermalState(phase)%partionedState0 = thermalState(phase)%state
end subroutine thermal_adiabatic_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this thermal
!--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_aTolState(phase,instance)
use material, only: &
thermalState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the thermal
real(pReal), dimension(thermalState(phase)%sizeState) :: tempTol
tempTol = thermal_adiabatic_aTol(instance)
thermalState(phase)%aTolState = tempTol
end subroutine thermal_adiabatic_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_microstructure(Tstar_v, Lp, subdt, ipc, ip, el)
use lattice, only: &
lattice_massDensity, &
lattice_specificHeat
use material, only: &
mappingConstitutive, &
thermalState
use math, only: &
math_Mandel6to33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(in), dimension(3,3) :: &
Lp !< plastic velocity gradient
real(pReal), intent(in) :: &
subdt
integer(pInt) :: &
phase, &
constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
thermalState(phase)%state(1,constituent) = &
thermalState(phase)%subState0(1,constituent) + &
subdt* &
0.95_pReal*sum(abs(math_Mandel6to33(Tstar_v))*Lp)/ &
(lattice_massDensity(phase)*lattice_specificHeat(phase))
end subroutine thermal_adiabatic_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief contains the constitutive equation for calculating the velocity gradient
!--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_LTAndItsTangent(LT, dLT_dTstar3333, Tstar_v, Lp, ipc, ip, el)
use lattice, only: &
lattice_massDensity, &
lattice_specificHeat, &
lattice_thermalExpansion33
use material, only: &
mappingConstitutive
use math, only: &
math_Plain3333to99, &
math_Mandel6to33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in), dimension(6) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress
real(pReal), intent(in), dimension(3,3) :: &
Lp !< plastic velocity gradient
real(pReal), intent(out), dimension(3,3) :: &
LT !< thermal velocity gradient
real(pReal), intent(out), dimension(3,3,3,3) :: &
dLT_dTstar3333 !< derivative of LT with respect to Tstar (4th-order tensor)
integer(pInt) :: &
phase, &
constituent, &
i, j, k, l
real(pReal) :: &
Tdot
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
Tdot = 0.95_pReal &
* sum(abs(math_Mandel6to33(Tstar_v))*Lp) &
/ (lattice_massDensity(phase)*lattice_specificHeat(phase))
LT = Tdot*lattice_thermalExpansion33(1:3,1:3,phase)
dLT_dTstar3333 = 0.0_pReal
forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) &
dLT_dTstar3333(i,j,k,l) = Lp(k,l)*lattice_thermalExpansion33(i,j,phase)
dLT_dTstar3333 = 0.95_pReal*dLT_dTstar3333/(lattice_massDensity(phase)*lattice_specificHeat(phase))
end subroutine thermal_adiabatic_LTAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
pure function thermal_adiabatic_getTemperature(ipc, ip, el)
use material, only: & use material, only: &
mappingHomogenization, & mappingHomogenization, &
fieldThermal, & thermalState, &
field_thermal_type, & temperature, &
FIELD_THERMAL_nonlocal_ID, & temperatureRate, &
material_homog, & thermalMapping
mappingConstitutive, &
thermalState
implicit none implicit none
integer(pInt), intent(in) :: & integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: thermal_adiabatic_getTemperature
select case(field_thermal_type(material_homog(ip,el)))
case (FIELD_THERMAL_nonlocal_ID)
thermal_adiabatic_getTemperature = fieldThermal(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
case default
thermal_adiabatic_getTemperature = thermalState(mappingConstitutive(2,ipc,ip,el))% &
state(1,mappingConstitutive(1,ipc,ip,el))
end select
end function thermal_adiabatic_getTemperature
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
pure function thermal_adiabatic_getLocalTemperature(ipc, ip, el)
use material, only: &
mappingConstitutive, &
ThermalState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: &
thermal_adiabatic_getLocalTemperature
thermal_adiabatic_getLocalTemperature = &
thermalState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function thermal_adiabatic_getLocalTemperature
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
subroutine thermal_adiabatic_putLocalTemperature(ipc, ip, el, localTemperature)
use material, only: &
mappingConstitutive, &
ThermalState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number ip, & !< integration point number
el !< element number el !< element number
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
localTemperature subdt
logical, dimension(2) :: &
thermal_adiabatic_updateState
integer(pInt) :: &
homog, &
offset
real(pReal) :: &
T, Tdot, dTdot_dT
thermalState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))= & homog = mappingHomogenization(2,ip,el)
localTemperature offset = mappingHomogenization(1,ip,el)
end subroutine thermal_adiabatic_putLocalTemperature T = thermalState(homog)%subState0(1,offset)
call thermal_adiabatic_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el)
T = T + subdt*thermal_adiabatic_getSpecificHeat(ip,el)*thermal_adiabatic_getMassDensity(ip,el)*Tdot
thermal_adiabatic_updateState = [ abs(T - thermalState(homog)%state(1,offset)) &
<= err_thermal_tolAbs &
.or. abs(T - thermalState(homog)%state(1,offset)) &
<= err_thermal_tolRel*abs(thermalState(homog)%state(1,offset)), &
.true.]
temperature (homog)%p(thermalMapping(homog)%p(ip,el)) = T
temperatureRate(homog)%p(thermalMapping(homog)%p(ip,el)) = &
(thermalState(homog)%state(1,offset) - thermalState(homog)%subState0(1,offset))/subdt
end function thermal_adiabatic_updateState
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief returns heat generation rate !> @brief returns heat generation rate
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
pure function thermal_adiabatic_getHeatGeneration(Tstar_v, Lp) subroutine thermal_adiabatic_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el)
use math, only: & use math, only: &
math_Mandel6to33 math_Mandel6to33
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
thermal_typeInstance, &
phase_Nsources, &
phase_source, &
SOURCE_thermal_dissipation_ID
use source_thermal_dissipation, only: &
source_thermal_dissipation_getRateAndItsTangent
use crystallite, only: &
crystallite_Tstar_v, &
crystallite_Lp
implicit none implicit none
real(pReal), intent(in), dimension(6) :: & integer(pInt), intent(in) :: &
Tstar_v !< 2nd Piola-Kirchhoff stress ip, & !< integration point number
real(pReal), intent(in), dimension(3,3) :: & el !< element number
Lp !< plastic velocity gradient real(pReal), intent(in) :: &
real(pReal) :: thermal_adiabatic_getHeatGeneration T
real(pReal), intent(out) :: &
Tdot, dTdot_dT
real(pReal) :: &
my_Tdot, my_dTdot_dT
integer(pInt) :: &
phase, &
homog, &
offset, &
instance, &
grain, &
source
thermal_adiabatic_getHeatGeneration = 0.95_pReal & homog = mappingHomogenization(2,ip,el)
* sum(abs(math_Mandel6to33(Tstar_v))*Lp) offset = mappingHomogenization(1,ip,el)
instance = thermal_typeInstance(homog)
end function thermal_adiabatic_getHeatGeneration Tdot = 0.0_pReal
dTdot_dT = 0.0_pReal
do grain = 1, homogenization_Ngrains(homog)
phase = mappingConstitutive(2,grain,ip,el)
do source = 1, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_thermal_dissipation_ID)
call source_thermal_dissipation_getRateAndItsTangent(my_Tdot, my_dTdot_dT, &
crystallite_Tstar_v(1:6,grain,ip,el), &
crystallite_Lp(1:3,1:3,grain,ip,el), &
grain, ip, el)
case default
my_Tdot = 0.0_pReal
my_dTdot_dT = 0.0_pReal
end select
Tdot = Tdot + my_Tdot
dTdot_dT = dTdot_dT + my_dTdot_dT
enddo
enddo
Tdot = Tdot/homogenization_Ngrains(homog)
dTdot_dT = dTdot_dT/homogenization_Ngrains(homog)
end subroutine thermal_adiabatic_getSourceAndItsTangent
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results !> @brief returns homogenized specific heat capacity
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function thermal_adiabatic_postResults(ipc,ip,el) function thermal_adiabatic_getSpecificHeat(ip,el)
use lattice, only: &
lattice_specificHeat
use material, only: & use material, only: &
mappingConstitutive, & homogenization_Ngrains, &
phase_thermalInstance, & mappingHomogenization, &
thermalState material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
thermal_adiabatic_getSpecificHeat
integer(pInt) :: &
homog, grain
thermal_adiabatic_getSpecificHeat = 0.0_pReal
homog = mappingHomogenization(2,ip,el)
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
thermal_adiabatic_getSpecificHeat = thermal_adiabatic_getSpecificHeat + &
lattice_specificHeat(material_phase(grain,ip,el))
enddo
thermal_adiabatic_getSpecificHeat = &
thermal_adiabatic_getSpecificHeat/ &
homogenization_Ngrains(mesh_element(3,el))
end function thermal_adiabatic_getSpecificHeat
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized mass density
!--------------------------------------------------------------------------------------------------
function thermal_adiabatic_getMassDensity(ip,el)
use lattice, only: &
lattice_massDensity
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
thermal_adiabatic_getMassDensity
integer(pInt) :: &
homog, grain
thermal_adiabatic_getMassDensity = 0.0_pReal
homog = mappingHomogenization(2,ip,el)
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
thermal_adiabatic_getMassDensity = thermal_adiabatic_getMassDensity + &
lattice_massDensity(material_phase(grain,ip,el))
enddo
thermal_adiabatic_getMassDensity = &
thermal_adiabatic_getMassDensity/ &
homogenization_Ngrains(mesh_element(3,el))
end function thermal_adiabatic_getMassDensity
!--------------------------------------------------------------------------------------------------
!> @brief return array of thermal results
!--------------------------------------------------------------------------------------------------
function thermal_adiabatic_postResults(ip,el)
use material, only: &
mappingHomogenization, &
thermal_typeInstance, &
thermalMapping, &
temperature
implicit none implicit none
integer(pInt), intent(in) :: & integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point ip, & !< integration point
el !< element el !< element
real(pReal), dimension(thermal_adiabatic_sizePostResults(phase_thermalInstance(mappingConstitutive(2,ipc,ip,el)))) :: & real(pReal), dimension(thermal_adiabatic_sizePostResults(thermal_typeInstance(mappingHomogenization(2,ip,el)))) :: &
thermal_adiabatic_postResults thermal_adiabatic_postResults
integer(pInt) :: & integer(pInt) :: &
instance, phase, constituent, o, c instance, homog, offset, o, c
phase = mappingConstitutive(2,ipc,ip,el) homog = mappingHomogenization(2,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el) offset = thermalMapping(homog)%p(ip,el)
instance = phase_thermalInstance(phase) instance = thermal_typeInstance(homog)
c = 0_pInt c = 0_pInt
thermal_adiabatic_postResults = 0.0_pReal thermal_adiabatic_postResults = 0.0_pReal
@ -459,7 +408,7 @@ function thermal_adiabatic_postResults(ipc,ip,el)
select case(thermal_adiabatic_outputID(o,instance)) select case(thermal_adiabatic_outputID(o,instance))
case (temperature_ID) case (temperature_ID)
thermal_adiabatic_postResults(c+1_pInt) = thermalState(phase)%state(1,constituent) thermal_adiabatic_postResults(c+1_pInt) = temperature(homog)%p(offset)
c = c + 1 c = c + 1
end select end select
enddo enddo

439
code/thermal_conduction.f90 Normal file
View File

@ -0,0 +1,439 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for temperature evolution from heat conduction
!> @details to be done
!--------------------------------------------------------------------------------------------------
module thermal_conduction
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
thermal_conduction_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
thermal_conduction_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
thermal_conduction_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
thermal_conduction_Noutput !< number of outputs per instance of this damage
enum, bind(c)
enumerator :: undefined_ID, &
temperature_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
thermal_conduction_outputID !< ID of each post result output
public :: &
thermal_conduction_init, &
thermal_conduction_getSourceAndItsTangent, &
thermal_conduction_getConductivity33, &
thermal_conduction_getSpecificHeat, &
thermal_conduction_getMassDensity, &
thermal_conduction_putTemperatureAndItsRate, &
thermal_conduction_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine thermal_conduction_init(fileUnit,temperature_init)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
thermal_type, &
thermal_typeInstance, &
homogenization_Noutput, &
THERMAL_conduction_label, &
THERMAL_conduction_ID, &
material_homog, &
mappingHomogenization, &
thermalState, &
thermalMapping, &
temperature, &
temperatureRate, &
material_partHomogenization
use numerics,only: &
worldrank
implicit none
real(pReal), intent(in) :: temperature_init !< initial temperature
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_CONDUCTION_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(thermal_type == THERMAL_conduction_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(thermal_conduction_sizePostResults(maxNinstance), source=0_pInt)
allocate(thermal_conduction_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(thermal_conduction_output (maxval(homogenization_Noutput),maxNinstance))
thermal_conduction_output = ''
allocate(thermal_conduction_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(thermal_conduction_Noutput (maxNinstance), source=0_pInt)
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (thermal_type(section) == THERMAL_conduction_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = thermal_typeInstance(section) ! which instance of my thermal is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('temperature')
thermal_conduction_Noutput(instance) = thermal_conduction_Noutput(instance) + 1_pInt
thermal_conduction_outputID(thermal_conduction_Noutput(instance),instance) = temperature_ID
thermal_conduction_output(thermal_conduction_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingFile
initializeInstances: do section = 1_pInt, size(thermal_type)
if (thermal_type(section) == THERMAL_conduction_ID) then
NofMyHomog=count(material_homog==section)
instance = thermal_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,thermal_conduction_Noutput(instance)
select case(thermal_conduction_outputID(o,instance))
case(temperature_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
thermal_conduction_sizePostResult(o,instance) = mySize
thermal_conduction_sizePostResults(instance) = thermal_conduction_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 0_pInt
thermalState(section)%sizeState = sizeState
thermalState(section)%sizePostResults = thermal_conduction_sizePostResults(instance)
allocate(thermalState(section)%state0 (sizeState,NofMyHomog))
allocate(thermalState(section)%subState0(sizeState,NofMyHomog))
allocate(thermalState(section)%state (sizeState,NofMyHomog))
nullify(thermalMapping(section)%p)
thermalMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(temperature (section)%p)
allocate (temperature (section)%p(NofMyHomog), source=temperature_init)
deallocate(temperatureRate(section)%p)
allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal)
endif
enddo initializeInstances
end subroutine thermal_conduction_init
!--------------------------------------------------------------------------------------------------
!> @brief returns heat generation rate
!--------------------------------------------------------------------------------------------------
subroutine thermal_conduction_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el)
use math, only: &
math_Mandel6to33
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
thermal_typeInstance, &
phase_Nsources, &
phase_source, &
SOURCE_thermal_dissipation_ID
use source_thermal_dissipation, only: &
source_thermal_dissipation_getRateAndItsTangent
use crystallite, only: &
crystallite_Tstar_v, &
crystallite_Lp
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
T
real(pReal), intent(out) :: &
Tdot, dTdot_dT
real(pReal) :: &
my_Tdot, my_dTdot_dT
integer(pInt) :: &
phase, &
homog, &
offset, &
instance, &
grain, &
source
homog = mappingHomogenization(2,ip,el)
offset = mappingHomogenization(1,ip,el)
instance = thermal_typeInstance(homog)
Tdot = 0.0_pReal
dTdot_dT = 0.0_pReal
do grain = 1, homogenization_Ngrains(homog)
phase = mappingConstitutive(2,grain,ip,el)
do source = 1, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_thermal_dissipation_ID)
call source_thermal_dissipation_getRateAndItsTangent(my_Tdot, my_dTdot_dT, &
crystallite_Tstar_v(1:6,grain,ip,el), &
crystallite_Lp(1:3,1:3,grain,ip,el), &
grain, ip, el)
case default
my_Tdot = 0.0_pReal
my_dTdot_dT = 0.0_pReal
end select
Tdot = Tdot + my_Tdot
dTdot_dT = dTdot_dT + my_dTdot_dT
enddo
enddo
Tdot = Tdot/homogenization_Ngrains(homog)
dTdot_dT = dTdot_dT/homogenization_Ngrains(homog)
end subroutine thermal_conduction_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized thermal conductivity in reference configuration
!--------------------------------------------------------------------------------------------------
function thermal_conduction_getConductivity33(ip,el)
use lattice, only: &
lattice_thermalConductivity33
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
thermal_conduction_getConductivity33
integer(pInt) :: &
homog, &
grain
homog = mappingHomogenization(2,ip,el)
thermal_conduction_getConductivity33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
thermal_conduction_getConductivity33 = thermal_conduction_getConductivity33 + &
crystallite_push33ToRef(grain,ip,el,lattice_thermalConductivity33(:,:,material_phase(grain,ip,el)))
enddo
thermal_conduction_getConductivity33 = &
thermal_conduction_getConductivity33/ &
homogenization_Ngrains(mesh_element(3,el))
end function thermal_conduction_getConductivity33
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized specific heat capacity
!--------------------------------------------------------------------------------------------------
function thermal_conduction_getSpecificHeat(ip,el)
use lattice, only: &
lattice_specificHeat
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
thermal_conduction_getSpecificHeat
integer(pInt) :: &
homog, grain
thermal_conduction_getSpecificHeat = 0.0_pReal
homog = mappingHomogenization(2,ip,el)
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
thermal_conduction_getSpecificHeat = thermal_conduction_getSpecificHeat + &
lattice_specificHeat(material_phase(grain,ip,el))
enddo
thermal_conduction_getSpecificHeat = &
thermal_conduction_getSpecificHeat/ &
homogenization_Ngrains(mesh_element(3,el))
end function thermal_conduction_getSpecificHeat
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized mass density
!--------------------------------------------------------------------------------------------------
function thermal_conduction_getMassDensity(ip,el)
use lattice, only: &
lattice_massDensity
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
thermal_conduction_getMassDensity
integer(pInt) :: &
homog, grain
thermal_conduction_getMassDensity = 0.0_pReal
homog = mappingHomogenization(2,ip,el)
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
thermal_conduction_getMassDensity = thermal_conduction_getMassDensity + &
lattice_massDensity(material_phase(grain,ip,el))
enddo
thermal_conduction_getMassDensity = &
thermal_conduction_getMassDensity/ &
homogenization_Ngrains(mesh_element(3,el))
end function thermal_conduction_getMassDensity
!--------------------------------------------------------------------------------------------------
!> @brief updates thermal state with solution from heat conduction PDE
!--------------------------------------------------------------------------------------------------
subroutine thermal_conduction_putTemperatureAndItsRate(T,Tdot,ip,el)
use material, only: &
mappingHomogenization, &
temperature, &
temperatureRate, &
thermalMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
T, &
Tdot
integer(pInt) :: &
homog, &
offset
homog = mappingHomogenization(2,ip,el)
offset = thermalMapping(homog)%p(ip,el)
temperature (homog)%p(offset) = T
temperatureRate(homog)%p(offset) = Tdot
end subroutine thermal_conduction_putTemperatureAndItsRate
!--------------------------------------------------------------------------------------------------
!> @brief return array of thermal results
!--------------------------------------------------------------------------------------------------
function thermal_conduction_postResults(ip,el)
use material, only: &
mappingHomogenization, &
thermal_typeInstance, &
temperature, &
thermalMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(thermal_conduction_sizePostResults(thermal_typeInstance(mappingHomogenization(2,ip,el)))) :: &
thermal_conduction_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = thermalMapping(homog)%p(ip,el)
instance = thermal_typeInstance(homog)
c = 0_pInt
thermal_conduction_postResults = 0.0_pReal
do o = 1_pInt,thermal_conduction_Noutput(instance)
select case(thermal_conduction_outputID(o,instance))
case (temperature_ID)
thermal_conduction_postResults(c+1_pInt) = temperature(homog)%p(offset)
c = c + 1
end select
enddo
end function thermal_conduction_postResults
end module thermal_conduction

View File

@ -1,107 +1,66 @@
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! $Id$ ! $Id$
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for isothermal temperature field
!> @brief material subroutine for purely elastic material
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module thermal_isothermal module thermal_isothermal
use prec, only: &
pInt, &
pReal
implicit none implicit none
private private
integer(pInt), dimension(:), allocatable, public, protected :: &
thermal_isothermal_sizePostResults
integer(pInt), dimension(:,:), allocatable, target, public :: &
thermal_isothermal_sizePostResult !< size of each post result output
real(pReal), dimension(:), allocatable, public :: &
thermal_isothermal_temperature
public :: & public :: &
thermal_isothermal_init thermal_isothermal_init
contains contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief module initialization !> @brief allocates all neccessary fields, reads information from material configuration file
!> @details reads in material parameters, allocates arrays, and does sanity checks
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine thermal_isothermal_init(temperature_init) subroutine thermal_isothermal_init(temperature_init)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: & use prec, only: &
debug_level, & pReal, &
debug_constitutive, & pInt
debug_levelBasic
use IO, only: & use IO, only: &
IO_timeStamp IO_timeStamp
use material
use numerics, only: & use numerics, only: &
worldrank, & worldrank
numerics_integrator
use material, only: &
phase_thermal, &
LOCAL_THERMAL_ISOTHERMAL_label, &
LOCAL_THERMAL_ISOTHERMAL_ID, &
material_phase, &
thermalState, &
MATERIAL_partPhase
implicit none implicit none
real(pReal), intent(in) :: temperature_init !< initial temperature real(pReal), intent(in) :: temperature_init !< initial temperature
integer(pInt) :: & integer(pInt) :: &
maxNinstance, & homog, &
phase, & NofMyHomog, &
NofMyPhase, & sizeState
sizeState, &
sizeDotState
mainProcess: if (worldrank == 0) then mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- thermal_'//LOCAL_THERMAL_ISOTHERMAL_label//' init -+>>>' write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_isothermal_label//' init -+>>>'
write(6,'(a)') ' $Id$' write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp() write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90" #include "compilation_info.f90"
endif mainProcess endif mainProcess
maxNinstance = int(count(phase_thermal == LOCAL_THERMAL_ISOTHERMAL_ID),pInt) initializeInstances: do homog = 1_pInt, material_Nhomogenization
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & myhomog: if (thermal_type(homog) == THERMAL_isothermal_ID) then
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance NofMyHomog = count(material_homog == homog)
sizeState = 0_pInt
thermalState(homog)%sizeState = sizeState
thermalState(homog)%sizePostResults = sizeState
allocate(thermalState(homog)%state0 (sizeState,NofMyHomog), source=0.0_pReal)
allocate(thermalState(homog)%subState0(sizeState,NofMyHomog), source=0.0_pReal)
allocate(thermalState(homog)%state (sizeState,NofMyHomog), source=0.0_pReal)
initializeInstances: do phase = 1_pInt, size(phase_thermal) deallocate(temperature (homog)%p)
NofMyPhase=count(material_phase==phase) allocate (temperature (homog)%p(1), source=temperature_init)
deallocate(temperatureRate(homog)%p)
allocate (temperatureRate(homog)%p(1), source=0.0_pReal)
if (phase_thermal(phase) == LOCAL_THERMAL_ISOTHERMAL_ID) then endif myhomog
sizeState = 0_pInt
thermalState(phase)%sizeState = sizeState
sizeDotState = sizeState
thermalState(phase)%sizeDotState = sizeDotState
thermalState(phase)%sizePostResults = 0_pInt
allocate(thermalState(phase)%state0 (sizeState,NofMyPhase))
allocate(thermalState(phase)%partionedState0(sizeState,NofMyPhase))
allocate(thermalState(phase)%subState0 (sizeState,NofMyPhase))
allocate(thermalState(phase)%state (sizeState,NofMyPhase))
allocate(thermalState(phase)%state_backup (sizeState,NofMyPhase))
allocate(thermalState(phase)%aTolState (NofMyPhase))
allocate(thermalState(phase)%dotState (sizeDotState,NofMyPhase))
allocate(thermalState(phase)%dotState_backup(sizeDotState,NofMyPhase))
if (any(numerics_integrator == 1_pInt)) then
allocate(thermalState(phase)%previousDotState (sizeDotState,NofMyPhase))
allocate(thermalState(phase)%previousDotState2 (sizeDotState,NofMyPhase))
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(thermalState(phase)%RK4dotState (sizeDotState,NofMyPhase))
if (any(numerics_integrator == 5_pInt)) &
allocate(thermalState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase))
endif
enddo initializeInstances enddo initializeInstances
allocate(thermal_isothermal_sizePostResults(maxNinstance), source=0_pInt)
allocate(thermal_isothermal_temperature(maxNinstance), source=temperature_init)
end subroutine thermal_isothermal_init end subroutine thermal_isothermal_init

View File

@ -1,101 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for constant vacancy concentration
!--------------------------------------------------------------------------------------------------
module vacancy_constant
use prec, only: &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
vacancy_constant_sizePostResults
integer(pInt), dimension(:,:), allocatable, target, public :: &
vacancy_constant_sizePostResult !< size of each post result output
public :: &
vacancy_constant_init
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine vacancy_constant_init
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level, &
debug_constitutive, &
debug_levelBasic
use IO, only: &
IO_timeStamp
use numerics, only: &
worldrank, &
numerics_integrator
use material, only: &
phase_vacancy, &
LOCAL_VACANCY_CONSTANT_label, &
LOCAL_VACANCY_CONSTANT_ID, &
material_phase, &
vacancyState, &
MATERIAL_partPhase
implicit none
integer(pInt) :: &
maxNinstance, &
phase, &
NofMyPhase, &
sizeState, &
sizeDotState
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- vacancy_'//LOCAL_VACANCY_CONSTANT_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_vacancy == LOCAL_VACANCY_CONSTANT_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
initializeInstances: do phase = 1_pInt, size(phase_vacancy)
NofMyPhase=count(material_phase==phase)
if (phase_vacancy(phase) == LOCAL_VACANCY_CONSTANT_ID) then
sizeState = 0_pInt
vacancyState(phase)%sizeState = sizeState
sizeDotState = sizeState
vacancyState(phase)%sizeDotState = sizeDotState
vacancyState(phase)%sizePostResults = 0_pInt
allocate(vacancyState(phase)%state0 (sizeState,NofMyPhase))
allocate(vacancyState(phase)%partionedState0(sizeState,NofMyPhase))
allocate(vacancyState(phase)%subState0 (sizeState,NofMyPhase))
allocate(vacancyState(phase)%state (sizeState,NofMyPhase))
allocate(vacancyState(phase)%state_backup (sizeState,NofMyPhase))
allocate(vacancyState(phase)%aTolState (NofMyPhase))
allocate(vacancyState(phase)%dotState (sizeDotState,NofMyPhase))
allocate(vacancyState(phase)%dotState_backup(sizeDotState,NofMyPhase))
if (any(numerics_integrator == 1_pInt)) then
allocate(vacancyState(phase)%previousDotState (sizeDotState,NofMyPhase))
allocate(vacancyState(phase)%previousDotState2 (sizeDotState,NofMyPhase))
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(vacancyState(phase)%RK4dotState (sizeDotState,NofMyPhase))
if (any(numerics_integrator == 5_pInt)) &
allocate(vacancyState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase))
endif
enddo initializeInstances
allocate(vacancy_constant_sizePostResults(maxNinstance), source=0_pInt)
end subroutine vacancy_constant_init
end module vacancy_constant

View File

@ -1,534 +0,0 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for plastically generated vacancy concentrations
!> @details to be done
!--------------------------------------------------------------------------------------------------
module vacancy_generation
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
vacancy_generation_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
vacancy_generation_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
vacancy_generation_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
vacancy_generation_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
vacancy_generation_aTol, &
vacancy_generation_freq, &
vacancy_generation_formationEnergy, &
vacancy_generation_specificFormationEnergy, &
vacancy_generation_migrationEnergy, &
vacancy_generation_diffusionCoeff0, & !< the temperature-independent diffusion coefficient D_0
vacancy_generation_atomicVol, &
vacancy_generation_surfaceEnergy, &
vacancy_generation_plasticityCoeff, &
vacancy_generation_kBCoeff
real(pReal), parameter, private :: &
kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin
enum, bind(c)
enumerator :: undefined_ID, &
vacancy_concentration_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
vacancy_generation_outputID !< ID of each post result output
public :: &
vacancy_generation_init, &
vacancy_generation_stateInit, &
vacancy_generation_aTolState, &
vacancy_generation_microstructure, &
vacancy_generation_getLocalConcentration, &
vacancy_generation_putLocalConcentration, &
vacancy_generation_getConcentration, &
vacancy_generation_getVacancyDiffusion33, &
vacancy_generation_getVacancyMobility33, &
vacancy_generation_getVacancyEnergy, &
vacancy_generation_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine vacancy_generation_init(fileUnit)
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use debug, only: &
debug_level,&
debug_constitutive,&
debug_levelBasic
use mesh, only: &
mesh_maxNips, &
mesh_NcpElems
use IO, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
homogenization_maxNgrains, &
phase_vacancy, &
phase_vacancyInstance, &
phase_Noutput, &
LOCAL_VACANCY_GENERATION_label, &
LOCAL_VACANCY_generation_ID, &
material_phase, &
vacancyState, &
MATERIAL_partPhase
use numerics,only: &
worldrank, &
numerics_integrator
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o
integer(pInt) :: sizeState, sizeDotState
integer(pInt) :: NofMyPhase
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- vacancy_'//LOCAL_VACANCY_GENERATION_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(phase_vacancy == LOCAL_VACANCY_generation_ID),pInt)
if (maxNinstance == 0_pInt) return
if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) &
write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance
allocate(vacancy_generation_sizePostResults(maxNinstance), source=0_pInt)
allocate(vacancy_generation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt)
allocate(vacancy_generation_output(maxval(phase_Noutput),maxNinstance))
vacancy_generation_output = ''
allocate(vacancy_generation_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID)
allocate(vacancy_generation_Noutput(maxNinstance), source=0_pInt)
allocate(vacancy_generation_aTol(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_freq(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_formationEnergy(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_specificFormationEnergy(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_migrationEnergy(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_diffusionCoeff0(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_atomicVol(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_surfaceEnergy(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_plasticityCoeff(maxNinstance), source=0.0_pReal)
allocate(vacancy_generation_kBCoeff(maxNinstance), source=0.0_pReal)
rewind(fileUnit)
phase = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to <phase>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part
line = IO_read(fileUnit)
if (IO_isBlank(line)) cycle ! skip empty lines
if (IO_getTag(line,'<','>') /= '') then ! stop at next part
line = IO_read(fileUnit, .true.) ! reset IO_read
exit
endif
if (IO_getTag(line,'[',']') /= '') then ! next phase section
phase = phase + 1_pInt ! advance phase section counter
cycle ! skip to next line
endif
if (phase > 0_pInt ) then; if (phase_vacancy(phase) == LOCAL_VACANCY_generation_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = phase_vacancyInstance(phase) ! which instance of my vacancy is present phase
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('vacancy_concentration')
vacancy_generation_Noutput(instance) = vacancy_generation_Noutput(instance) + 1_pInt
vacancy_generation_outputID(vacancy_generation_Noutput(instance),instance) = vacancy_concentration_ID
vacancy_generation_output(vacancy_generation_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
case ('atolvacancygeneration')
vacancy_generation_aTol(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancyformationfreq')
vacancy_generation_freq(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancyformationenergy')
vacancy_generation_formationEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancymigrationenergy')
vacancy_generation_migrationEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancydiffusioncoeff0')
vacancy_generation_diffusionCoeff0(instance) = IO_floatValue(line,positions,2_pInt)
case ('atomicvolume')
vacancy_generation_atomicVol(instance) = IO_floatValue(line,positions,2_pInt)
case ('surfaceenergy')
vacancy_generation_surfaceEnergy(instance) = IO_floatValue(line,positions,2_pInt)
case ('vacancyplasticitycoeff')
vacancy_generation_plasticityCoeff(instance) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingFile
initializeInstances: do phase = 1_pInt, size(phase_vacancy)
if (phase_vacancy(phase) == LOCAL_VACANCY_generation_ID) then
NofMyPhase=count(material_phase==phase)
instance = phase_vacancyInstance(phase)
!--------------------------------------------------------------------------------------------------
! pre-calculating derived material parameters
vacancy_generation_kBCoeff(instance) = kB/vacancy_generation_atomicVol(instance)
vacancy_generation_specificFormationEnergy(instance) = &
vacancy_generation_formationEnergy(instance)/vacancy_generation_atomicVol(instance)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,vacancy_generation_Noutput(instance)
select case(vacancy_generation_outputID(o,instance))
case(vacancy_concentration_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
vacancy_generation_sizePostResult(o,instance) = mySize
vacancy_generation_sizePostResults(instance) = vacancy_generation_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! Determine size of state array
sizeDotState = 0_pInt
sizeState = 1_pInt
vacancyState(phase)%sizeState = sizeState
vacancyState(phase)%sizeDotState = sizeDotState
vacancyState(phase)%sizePostResults = vacancy_generation_sizePostResults(instance)
allocate(vacancyState(phase)%aTolState (sizeState), source=0.0_pReal)
allocate(vacancyState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 1_pInt)) then
allocate(vacancyState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal)
allocate(vacancyState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal)
endif
if (any(numerics_integrator == 4_pInt)) &
allocate(vacancyState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal)
if (any(numerics_integrator == 5_pInt)) &
allocate(vacancyState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal)
call vacancy_generation_stateInit(phase)
call vacancy_generation_aTolState(phase,instance)
endif
enddo initializeInstances
end subroutine vacancy_generation_init
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant NEW state values for a given instance of this vacancy model
!--------------------------------------------------------------------------------------------------
subroutine vacancy_generation_stateInit(phase)
use material, only: &
vacancyState
use lattice, only: &
lattice_equilibriumVacancyConcentration
implicit none
integer(pInt), intent(in) :: phase !< number specifying the phase of the vacancy
real(pReal), dimension(vacancyState(phase)%sizeState) :: tempState
tempState(1) = lattice_equilibriumVacancyConcentration(phase)
vacancyState(phase)%state0 = spread(tempState,2,size(vacancyState(phase)%state(1,:)))
end subroutine vacancy_generation_stateInit
!--------------------------------------------------------------------------------------------------
!> @brief sets the relevant state values for a given instance of this vacancy model
!--------------------------------------------------------------------------------------------------
subroutine vacancy_generation_aTolState(phase,instance)
use material, only: &
vacancyState
implicit none
integer(pInt), intent(in) :: &
phase, &
instance ! number specifying the current instance of the vacancy
real(pReal), dimension(vacancyState(phase)%sizeState) :: tempTol
tempTol = vacancy_generation_aTol(instance)
vacancyState(phase)%aTolState = tempTol
end subroutine vacancy_generation_aTolState
!--------------------------------------------------------------------------------------------------
!> @brief calculates derived quantities from state
!--------------------------------------------------------------------------------------------------
subroutine vacancy_generation_microstructure(Tstar_v, temperature, damage, subdt, &
ipc, ip, el)
use material, only: &
mappingConstitutive, &
phase_vacancyInstance, &
plasticState, &
vacancyState
use math, only : &
math_Mandel6to33, &
math_trace33
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), intent(in) :: &
Tstar_v(6), &
temperature, & !< 2nd Piola Kirchhoff stress tensor (Mandel)
damage, &
subdt
real(pReal) :: &
pressure, &
stressBarrier
integer(pInt) :: &
instance, phase, constituent
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_vacancyInstance(phase)
pressure = math_trace33(math_Mandel6to33(Tstar_v))/3.0_pReal
stressBarrier = max(0.0_pReal, &
vacancy_generation_specificFormationEnergy(instance) - &
pressure - &
vacancy_generation_plasticityCoeff(instance)* &
sum(plasticState(phase)%accumulatedSlip(:,constituent)))
vacancyState(phase)%state(1,constituent) = &
vacancyState(phase)%subState0(1,constituent) + &
subdt* &
damage*damage* &
vacancy_generation_freq(instance)* &
exp(-stressBarrier/(vacancy_generation_kBCoeff(instance)*temperature))
end subroutine vacancy_generation_microstructure
!--------------------------------------------------------------------------------------------------
!> @brief returns vacancy concentration based on state layout
!--------------------------------------------------------------------------------------------------
pure function vacancy_generation_getLocalConcentration(ipc, ip, el)
use material, only: &
mappingConstitutive, &
vacancyState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: vacancy_generation_getLocalConcentration
vacancy_generation_getLocalConcentration = &
vacancyState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))
end function vacancy_generation_getLocalConcentration
!--------------------------------------------------------------------------------------------------
!> @brief returns temperature based on local damage model state layout
!--------------------------------------------------------------------------------------------------
subroutine vacancy_generation_putLocalConcentration(ipc, ip, el, localVacancyConcentration)
use material, only: &
mappingConstitutive, &
vacancyState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
localVacancyConcentration
vacancyState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))= &
localVacancyConcentration
end subroutine vacancy_generation_putLocalConcentration
!--------------------------------------------------------------------------------------------------
!> @brief returns vacancy concentration based on state layout
!--------------------------------------------------------------------------------------------------
pure function vacancy_generation_getConcentration(ipc, ip, el)
use material, only: &
mappingHomogenization, &
material_phase, &
fieldVacancy, &
field_vacancy_type, &
FIELD_VACANCY_local_ID, &
FIELD_VACANCY_nonlocal_ID, &
material_homog
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal) :: vacancy_generation_getConcentration
select case(field_vacancy_type(material_homog(ip,el)))
case (FIELD_VACANCY_local_ID)
vacancy_generation_getConcentration = vacancy_generation_getLocalConcentration(ipc, ip, el)
case (FIELD_VACANCY_nonlocal_ID)
vacancy_generation_getConcentration = fieldVacancy(material_homog(ip,el))% &
field(1,mappingHomogenization(1,ip,el)) ! Taylor type
end select
end function vacancy_generation_getConcentration
!--------------------------------------------------------------------------------------------------
!> @brief returns generation vacancy diffusion tensor
!--------------------------------------------------------------------------------------------------
pure function vacancy_generation_getVacancyDiffusion33(ipc,ip,el)
use lattice, only: &
lattice_VacancyDiffusion33
use material, only: &
mappingConstitutive
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
vacancy_generation_getVacancyDiffusion33
vacancy_generation_getVacancyDiffusion33 = &
lattice_VacancyDiffusion33(1:3,1:3,mappingConstitutive(2,ipc,ip,el))
end function vacancy_generation_getVacancyDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief returns generation vacancy mobility tensor
!--------------------------------------------------------------------------------------------------
pure function vacancy_generation_getVacancyMobility33(temperature,ipc,ip,el)
use math, only: &
math_I3
use material, only: &
mappingConstitutive, &
phase_vacancyInstance, &
plasticState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
vacancy_generation_getVacancyMobility33
real(pReal), intent(in) :: &
temperature
integer(pInt) :: &
phase, constituent, instance
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_vacancyInstance(phase)
vacancy_generation_getVacancyMobility33 = &
math_I3*(1.0_pReal + sum(plasticState(phase)%accumulatedSlip(:,constituent)))
end function vacancy_generation_getVacancyMobility33
!--------------------------------------------------------------------------------------------------
!> @brief returns generation vacancy mobility tensor
!--------------------------------------------------------------------------------------------------
pure real(pReal) function vacancy_generation_getVacancyEnergy(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_vacancyInstance
implicit none
integer(pInt), intent(in) :: &
ipc, & !< grain number
ip, & !< integration point number
el !< element number
integer(pInt) :: &
instance
instance = phase_vacancyInstance(mappingConstitutive(2,ipc,ip,el))
vacancy_generation_getVacancyEnergy = &
vacancy_generation_specificFormationEnergy(instance)/vacancy_generation_surfaceEnergy(instance)
end function vacancy_generation_getVacancyEnergy
!--------------------------------------------------------------------------------------------------
!> @brief return array of constitutive results
!--------------------------------------------------------------------------------------------------
function vacancy_generation_postResults(ipc,ip,el)
use material, only: &
mappingConstitutive, &
phase_vacancyInstance, &
vacancyState
implicit none
integer(pInt), intent(in) :: &
ipc, & !< component-ID of integration point
ip, & !< integration point
el !< element
real(pReal), dimension(vacancy_generation_sizePostResults(phase_vacancyInstance(mappingConstitutive(2,ipc,ip,el)))) :: &
vacancy_generation_postResults
integer(pInt) :: &
instance, phase, constituent, o, c
phase = mappingConstitutive(2,ipc,ip,el)
constituent = mappingConstitutive(1,ipc,ip,el)
instance = phase_vacancyInstance(phase)
c = 0_pInt
vacancy_generation_postResults = 0.0_pReal
do o = 1_pInt,vacancy_generation_Noutput(instance)
select case(vacancy_generation_outputID(o,instance))
case (vacancy_concentration_ID)
vacancy_generation_postResults(c+1_pInt) = vacancyState(phase)%state(1,constituent)
c = c + 1
end select
enddo
end function vacancy_generation_postResults
end module vacancy_generation

View File

@ -0,0 +1,637 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for conservative transport of vacancy concentration field
!> @details to be done
!--------------------------------------------------------------------------------------------------
module vacancyflux_cahnhilliard
use prec, only: &
pReal, &
pInt, &
p_vec
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
vacancyflux_cahnhilliard_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
vacancyflux_cahnhilliard_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
vacancyflux_cahnhilliard_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
vacancyflux_cahnhilliard_Noutput !< number of outputs per instance of this damage
real(pReal), dimension(:), allocatable, private :: &
vacancyflux_cahnhilliard_formationEnergyCoeff, &
vacancyflux_cahnhilliard_surfaceEnergy, &
vacancyflux_cahnhilliard_kBCoeff
type(p_vec), dimension(:), allocatable, private :: &
vacancyflux_cahnhilliard_thermalFluc
real(pReal), parameter, private :: &
kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin
enum, bind(c)
enumerator :: undefined_ID, &
vacancyConc_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
vacancyflux_cahnhilliard_outputID !< ID of each post result output
public :: &
vacancyflux_cahnhilliard_init, &
vacancyflux_cahnhilliard_getSourceAndItsTangent, &
vacancyflux_cahnhilliard_getMobility33, &
vacancyflux_cahnhilliard_getDiffusion33, &
vacancyflux_cahnhilliard_getChemPotAndItsTangent, &
vacancyflux_cahnhilliard_putVacancyConcAndItsRate, &
vacancyflux_cahnhilliard_postResults
private :: &
vacancyflux_cahnhilliard_getFormationEnergy, &
vacancyflux_cahnhilliard_getEntropicCoeff, &
vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_cahnhilliard_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, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use lattice, only: &
lattice_vacancyVol
use material, only: &
vacancyflux_type, &
vacancyflux_typeInstance, &
homogenization_Noutput, &
VACANCYFLUX_cahnhilliard_label, &
VACANCYFLUX_cahnhilliard_ID, &
material_homog, &
material_Nphase, &
mappingHomogenization, &
vacancyfluxState, &
vacancyfluxMapping, &
vacancyConc, &
vacancyConcRate, &
material_partHomogenization, &
material_partPhase
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o,offset
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_cahnhilliard_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(vacancyflux_type == VACANCYFLUX_cahnhilliard_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(vacancyflux_cahnhilliard_sizePostResults(maxNinstance), source=0_pInt)
allocate(vacancyflux_cahnhilliard_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(vacancyflux_cahnhilliard_output (maxval(homogenization_Noutput),maxNinstance))
vacancyflux_cahnhilliard_output = ''
allocate(vacancyflux_cahnhilliard_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(vacancyflux_cahnhilliard_Noutput (maxNinstance), source=0_pInt)
allocate(vacancyflux_cahnhilliard_formationEnergyCoeff(material_Nphase), source=0.0_pReal)
allocate(vacancyflux_cahnhilliard_kBCoeff (material_Nphase), source=0.0_pReal)
allocate(vacancyflux_cahnhilliard_surfaceEnergy (material_Nphase), source=0.0_pReal)
allocate(vacancyflux_cahnhilliard_thermalFluc(maxNinstance))
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = vacancyflux_typeInstance(section) ! which instance of my vacancyflux is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('vacancyconc')
vacancyflux_cahnhilliard_Noutput(instance) = vacancyflux_cahnhilliard_Noutput(instance) + 1_pInt
vacancyflux_cahnhilliard_outputID(vacancyflux_cahnhilliard_Noutput(instance),instance) = vacancyConc_ID
vacancyflux_cahnhilliard_output(vacancyflux_cahnhilliard_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingHomog
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('vacancyformationenergy')
vacancyflux_cahnhilliard_formationEnergyCoeff(section) = IO_floatValue(line,positions,2_pInt)
case ('voidsurfaceenergy')
vacancyflux_cahnhilliard_surfaceEnergy(section) = IO_floatValue(line,positions,2_pInt)
end select
endif; endif
enddo parsingPhase
initializeInstances: do section = 1_pInt, size(vacancyflux_type)
if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then
NofMyHomog=count(material_homog==section)
instance = vacancyflux_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,vacancyflux_cahnhilliard_Noutput(instance)
select case(vacancyflux_cahnhilliard_outputID(o,instance))
case(vacancyConc_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
vacancyflux_cahnhilliard_sizePostResult(o,instance) = mySize
vacancyflux_cahnhilliard_sizePostResults(instance) = vacancyflux_cahnhilliard_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 0_pInt
vacancyfluxState(section)%sizeState = sizeState
vacancyfluxState(section)%sizePostResults = vacancyflux_cahnhilliard_sizePostResults(instance)
allocate(vacancyfluxState(section)%state0 (sizeState,NofMyHomog))
allocate(vacancyfluxState(section)%subState0(sizeState,NofMyHomog))
allocate(vacancyfluxState(section)%state (sizeState,NofMyHomog))
allocate(vacancyflux_cahnhilliard_thermalFluc(instance)%p(NofMyHomog))
do offset = 1_pInt, NofMyHomog
call random_number(vacancyflux_cahnhilliard_thermalFluc(instance)%p(offset))
enddo
nullify(vacancyfluxMapping(section)%p)
vacancyfluxMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(vacancyConc (section)%p)
allocate (vacancyConc (section)%p(NofMyHomog), source=0.0_pReal)
deallocate(vacancyConcRate(section)%p)
allocate (vacancyConcRate(section)%p(NofMyHomog), source=0.0_pReal)
endif
enddo initializeInstances
initializeParams: do section = 1_pInt, material_Nphase
vacancyflux_cahnhilliard_formationEnergyCoeff(section) = &
vacancyflux_cahnhilliard_formationEnergyCoeff(section)/ &
lattice_vacancyVol(section)/ &
vacancyflux_cahnhilliard_surfaceEnergy(section)
vacancyflux_cahnhilliard_kBCoeff(section) = &
kB/ &
lattice_vacancyVol(section)/ &
vacancyflux_cahnhilliard_surfaceEnergy(section)
enddo initializeParams
end subroutine vacancyflux_cahnhilliard_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized vacancy driving forces
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_cahnhilliard_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el)
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
phase_source, &
phase_Nsources, &
SOURCE_vacancy_phenoplasticity_ID, &
SOURCE_vacancy_irradiation_ID, &
SOURCE_vacancy_thermalfluc_ID
use source_vacancy_phenoplasticity, only: &
source_vacancy_phenoplasticity_getRateAndItsTangent
use source_vacancy_irradiation, only: &
source_vacancy_irradiation_getRateAndItsTangent
use source_vacancy_thermalfluc, only: &
source_vacancy_thermalfluc_getRateAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Cv
integer(pInt) :: &
phase, &
grain, &
source
real(pReal) :: &
CvDot, dCvDot_dCv, localCvDot, dLocalCvDot_dCv
CvDot = 0.0_pReal
dCvDot_dCv = 0.0_pReal
do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el))
phase = mappingConstitutive(2,grain,ip,el)
do source = 1_pInt, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_vacancy_phenoplasticity_ID)
call source_vacancy_phenoplasticity_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el)
case (SOURCE_vacancy_irradiation_ID)
call source_vacancy_irradiation_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el)
case (SOURCE_vacancy_thermalfluc_ID)
call source_vacancy_thermalfluc_getRateAndItsTangent(localCvDot, dLocalCvDot_dCv, grain, ip, el)
end select
CvDot = CvDot + localCvDot
dCvDot_dCv = dCvDot_dCv + dLocalCvDot_dCv
enddo
enddo
CvDot = CvDot/homogenization_Ngrains(mappingHomogenization(2,ip,el))
dCvDot_dCv = dCvDot_dCv/homogenization_Ngrains(mappingHomogenization(2,ip,el))
end subroutine vacancyflux_cahnhilliard_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized vacancy mobility tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function vacancyflux_cahnhilliard_getMobility33(ip,el)
use lattice, only: &
lattice_vacancyfluxMobility33
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
vacancyflux_cahnhilliard_getMobility33
integer(pInt) :: &
grain
vacancyflux_cahnhilliard_getMobility33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
vacancyflux_cahnhilliard_getMobility33 = vacancyflux_cahnhilliard_getMobility33 + &
crystallite_push33ToRef(grain,ip,el,lattice_vacancyfluxMobility33(:,:,material_phase(grain,ip,el)))
enddo
vacancyflux_cahnhilliard_getMobility33 = &
vacancyflux_cahnhilliard_getMobility33/ &
homogenization_Ngrains(mesh_element(3,el))
end function vacancyflux_cahnhilliard_getMobility33
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized vacancy diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function vacancyflux_cahnhilliard_getDiffusion33(ip,el)
use lattice, only: &
lattice_vacancyfluxDiffusion33
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
use crystallite, only: &
crystallite_push33ToRef
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
vacancyflux_cahnhilliard_getDiffusion33
integer(pInt) :: &
grain
vacancyflux_cahnhilliard_getDiffusion33 = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
vacancyflux_cahnhilliard_getDiffusion33 = vacancyflux_cahnhilliard_getDiffusion33 + &
crystallite_push33ToRef(grain,ip,el,lattice_vacancyfluxDiffusion33(:,:,material_phase(grain,ip,el)))
enddo
vacancyflux_cahnhilliard_getDiffusion33 = &
vacancyflux_cahnhilliard_getDiffusion33/ &
homogenization_Ngrains(mesh_element(3,el))
end function vacancyflux_cahnhilliard_getDiffusion33
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized vacancy formation energy
!--------------------------------------------------------------------------------------------------
function vacancyflux_cahnhilliard_getFormationEnergy(ip,el)
use material, only: &
homogenization_Ngrains, &
material_phase
use mesh, only: &
mesh_element
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
vacancyflux_cahnhilliard_getFormationEnergy
integer(pInt) :: &
grain
vacancyflux_cahnhilliard_getFormationEnergy = 0.0_pReal
do grain = 1, homogenization_Ngrains(mesh_element(3,el))
vacancyflux_cahnhilliard_getFormationEnergy = vacancyflux_cahnhilliard_getFormationEnergy + &
vacancyflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el))
enddo
vacancyflux_cahnhilliard_getFormationEnergy = &
vacancyflux_cahnhilliard_getFormationEnergy/ &
homogenization_Ngrains(mesh_element(3,el))
end function vacancyflux_cahnhilliard_getFormationEnergy
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized vacancy entropy coefficient
!--------------------------------------------------------------------------------------------------
function vacancyflux_cahnhilliard_getEntropicCoeff(ip,el)
use material, only: &
homogenization_Ngrains, &
material_homog, &
material_phase, &
temperature, &
thermalMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal) :: &
vacancyflux_cahnhilliard_getEntropicCoeff
integer(pInt) :: &
grain
vacancyflux_cahnhilliard_getEntropicCoeff = 0.0_pReal
do grain = 1, homogenization_Ngrains(material_homog(ip,el))
vacancyflux_cahnhilliard_getEntropicCoeff = vacancyflux_cahnhilliard_getEntropicCoeff + &
vacancyflux_cahnhilliard_kBCoeff(material_phase(grain,ip,el))
enddo
vacancyflux_cahnhilliard_getEntropicCoeff = &
vacancyflux_cahnhilliard_getEntropicCoeff* &
temperature(material_homog(ip,el))%p(thermalMapping(material_homog(ip,el))%p(ip,el))/ &
homogenization_Ngrains(material_homog(ip,el))
end function vacancyflux_cahnhilliard_getEntropicCoeff
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized kinematic contribution to chemical potential
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCv, Cv, ip, el)
use material, only: &
homogenization_Ngrains, &
material_homog, &
phase_kinematics, &
phase_Nkinematics, &
material_phase, &
KINEMATICS_vacancy_strain_ID
use crystallite, only: &
crystallite_Tstar_v, &
crystallite_Fi0, &
crystallite_Fi
use kinematics_vacancy_strain, only: &
kinematics_vacancy_strain_ChemPotAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Cv
real(pReal), intent(out) :: &
KPot, dKPot_dCv
real(pReal) :: &
my_KPot, my_dKPot_dCv
integer(pInt) :: &
grain, kinematics
KPot = 0.0_pReal
dKPot_dCv = 0.0_pReal
do grain = 1_pInt,homogenization_Ngrains(material_homog(ip,el))
do kinematics = 1_pInt, phase_Nkinematics(material_phase(grain,ip,el))
select case (phase_kinematics(kinematics,material_phase(grain,ip,el)))
case (KINEMATICS_vacancy_strain_ID)
call kinematics_vacancy_strain_ChemPotAndItsTangent(my_KPot, my_dKPot_dCv, &
crystallite_Tstar_v(1:6,grain,ip,el), &
crystallite_Fi0(1:3,1:3,grain,ip,el), &
crystallite_Fi (1:3,1:3,grain,ip,el), &
grain,ip, el)
case default
my_KPot = 0.0_pReal
my_dKPot_dCv = 0.0_pReal
end select
KPot = KPot + my_KPot/vacancyflux_cahnhilliard_surfaceEnergy(material_phase(grain,ip,el))
dKPot_dCv = dKPot_dCv + my_dKPot_dCv/vacancyflux_cahnhilliard_surfaceEnergy(material_phase(grain,ip,el))
enddo
enddo
KPot = KPot/homogenization_Ngrains(material_homog(ip,el))
dKPot_dCv = dKPot_dCv/homogenization_Ngrains(material_homog(ip,el))
end subroutine vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized chemical potential and its tangent
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_cahnhilliard_getChemPotAndItsTangent(ChemPot,dChemPot_dCv,Cv,ip,el)
use numerics, only: &
vacancyBoundPenalty, &
vacancyPolyOrder
use material, only: &
mappingHomogenization, &
porosity, &
porosityMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Cv
real(pReal), intent(out) :: &
ChemPot, &
dChemPot_dCv
real(pReal) :: &
VoidPhaseFrac, kBT, KPot, dKPot_dCv
integer(pInt) :: &
homog, o
homog = mappingHomogenization(2,ip,el)
VoidPhaseFrac = porosity(homog)%p(porosityMapping(homog)%p(ip,el))
kBT = vacancyflux_cahnhilliard_getEntropicCoeff(ip,el)
ChemPot = vacancyflux_cahnhilliard_getFormationEnergy(ip,el)
dChemPot_dCv = 0.0_pReal
do o = 1_pInt, vacancyPolyOrder
ChemPot = ChemPot + kBT*((2.0_pReal*Cv - 1.0_pReal)**real(2_pInt*o-1_pInt,pReal))/ &
real(2_pInt*o-1_pInt,pReal)
dChemPot_dCv = dChemPot_dCv + 2.0_pReal*kBT*(2.0_pReal*Cv - 1.0_pReal)**real(2_pInt*o-2_pInt,pReal)
enddo
ChemPot = VoidPhaseFrac*VoidPhaseFrac*ChemPot &
- 2.0_pReal*(1.0_pReal - Cv)*(1.0_pReal - VoidPhaseFrac)*(1.0_pReal - VoidPhaseFrac)
dChemPot_dCv = VoidPhaseFrac*VoidPhaseFrac*dChemPot_dCv &
+ 2.0_pReal*(1.0_pReal - VoidPhaseFrac)*(1.0_pReal - VoidPhaseFrac)
call vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCv, Cv, ip, el)
ChemPot = ChemPot + KPot
dChemPot_dCv = dChemPot_dCv + dKPot_dCv
if (Cv < 0.0_pReal) then
ChemPot = ChemPot - 3.0_pReal*vacancyBoundPenalty*Cv*Cv
dChemPot_dCv = dChemPot_dCv - 6.0_pReal*vacancyBoundPenalty*Cv
elseif (Cv > 1.0_pReal) then
ChemPot = ChemPot + 3.0_pReal*vacancyBoundPenalty*(1.0_pReal - Cv)*(1.0_pReal - Cv)
dChemPot_dCv = dChemPot_dCv - 6.0_pReal*vacancyBoundPenalty*(1.0_pReal - Cv)
endif
end subroutine vacancyflux_cahnhilliard_getChemPotAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief updated vacancy concentration and its rate with solution from transport PDE
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_cahnhilliard_putVacancyConcAndItsRate(Cv,Cvdot,ip,el)
use material, only: &
mappingHomogenization, &
vacancyConc, &
vacancyConcRate, &
vacancyfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Cv, &
Cvdot
integer(pInt) :: &
homog, &
offset
homog = mappingHomogenization(2,ip,el)
offset = vacancyfluxMapping(homog)%p(ip,el)
vacancyConc (homog)%p(offset) = Cv
vacancyConcRate(homog)%p(offset) = Cvdot
end subroutine vacancyflux_cahnhilliard_putVacancyConcAndItsRate
!--------------------------------------------------------------------------------------------------
!> @brief return array of vacancy transport results
!--------------------------------------------------------------------------------------------------
function vacancyflux_cahnhilliard_postResults(ip,el)
use material, only: &
mappingHomogenization, &
vacancyflux_typeInstance, &
vacancyConc, &
vacancyfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(vacancyflux_cahnhilliard_sizePostResults(vacancyflux_typeInstance(mappingHomogenization(2,ip,el)))) :: &
vacancyflux_cahnhilliard_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = vacancyfluxMapping(homog)%p(ip,el)
instance = vacancyflux_typeInstance(homog)
c = 0_pInt
vacancyflux_cahnhilliard_postResults = 0.0_pReal
do o = 1_pInt,vacancyflux_cahnhilliard_Noutput(instance)
select case(vacancyflux_cahnhilliard_outputID(o,instance))
case (vacancyConc_ID)
vacancyflux_cahnhilliard_postResults(c+1_pInt) = vacancyConc(homog)%p(offset)
c = c + 1
end select
enddo
end function vacancyflux_cahnhilliard_postResults
end module vacancyflux_cahnhilliard

View File

@ -0,0 +1,330 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for locally evolving vacancy concentration
!> @details to be done
!--------------------------------------------------------------------------------------------------
module vacancyflux_isochempot
use prec, only: &
pReal, &
pInt
implicit none
private
integer(pInt), dimension(:), allocatable, public, protected :: &
vacancyflux_isochempot_sizePostResults !< cumulative size of post results
integer(pInt), dimension(:,:), allocatable, target, public :: &
vacancyflux_isochempot_sizePostResult !< size of each post result output
character(len=64), dimension(:,:), allocatable, target, public :: &
vacancyflux_isochempot_output !< name of each post result output
integer(pInt), dimension(:), allocatable, target, public :: &
vacancyflux_isochempot_Noutput !< number of outputs per instance of this damage
enum, bind(c)
enumerator :: undefined_ID, &
vacancyconc_ID
end enum
integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: &
vacancyflux_isochempot_outputID !< ID of each post result output
public :: &
vacancyflux_isochempot_init, &
vacancyflux_isochempot_updateState, &
vacancyflux_isochempot_getSourceAndItsTangent, &
vacancyflux_isochempot_postResults
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_isochempot_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, only: &
IO_read, &
IO_lc, &
IO_getTag, &
IO_isBlank, &
IO_stringPos, &
IO_stringValue, &
IO_floatValue, &
IO_intValue, &
IO_warning, &
IO_error, &
IO_timeStamp, &
IO_EOF
use material, only: &
vacancyflux_type, &
vacancyflux_typeInstance, &
homogenization_Noutput, &
VACANCYFLUX_isochempot_label, &
VACANCYFLUX_isochempot_ID, &
material_homog, &
mappingHomogenization, &
vacancyfluxState, &
vacancyfluxMapping, &
vacancyConc, &
vacancyConcRate, &
material_partHomogenization
use numerics,only: &
worldrank
implicit none
integer(pInt), intent(in) :: fileUnit
integer(pInt), parameter :: MAXNCHUNKS = 7_pInt
integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions
integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o
integer(pInt) :: sizeState
integer(pInt) :: NofMyHomog
character(len=65536) :: &
tag = '', &
line = ''
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_isochempot_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
maxNinstance = int(count(vacancyflux_type == VACANCYFLUX_isochempot_ID),pInt)
if (maxNinstance == 0_pInt) return
allocate(vacancyflux_isochempot_sizePostResults(maxNinstance), source=0_pInt)
allocate(vacancyflux_isochempot_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt)
allocate(vacancyflux_isochempot_output (maxval(homogenization_Noutput),maxNinstance))
vacancyflux_isochempot_output = ''
allocate(vacancyflux_isochempot_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID)
allocate(vacancyflux_isochempot_Noutput (maxNinstance), source=0_pInt)
rewind(fileUnit)
section = 0_pInt
do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to <homogenization>
line = IO_read(fileUnit)
enddo
parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog 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 homog section
section = section + 1_pInt ! advance homog section counter
cycle ! skip to next line
endif
if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_isochempot_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran
instance = vacancyflux_typeInstance(section) ! which instance of my vacancyflux is present homog
positions = IO_stringPos(line,MAXNCHUNKS)
tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key
select case(tag)
case ('(output)')
select case(IO_lc(IO_stringValue(line,positions,2_pInt)))
case ('vacancyconc')
vacancyflux_isochempot_Noutput(instance) = vacancyflux_isochempot_Noutput(instance) + 1_pInt
vacancyflux_isochempot_outputID(vacancyflux_isochempot_Noutput(instance),instance) = vacancyconc_ID
vacancyflux_isochempot_output(vacancyflux_isochempot_Noutput(instance),instance) = &
IO_lc(IO_stringValue(line,positions,2_pInt))
end select
end select
endif; endif
enddo parsingFile
initializeInstances: do section = 1_pInt, size(vacancyflux_type)
if (vacancyflux_type(section) == VACANCYFLUX_isochempot_ID) then
NofMyHomog=count(material_homog==section)
instance = vacancyflux_typeInstance(section)
!--------------------------------------------------------------------------------------------------
! Determine size of postResults array
outputsLoop: do o = 1_pInt,vacancyflux_isochempot_Noutput(instance)
select case(vacancyflux_isochempot_outputID(o,instance))
case(vacancyconc_ID)
mySize = 1_pInt
end select
if (mySize > 0_pInt) then ! any meaningful output found
vacancyflux_isochempot_sizePostResult(o,instance) = mySize
vacancyflux_isochempot_sizePostResults(instance) = vacancyflux_isochempot_sizePostResults(instance) + mySize
endif
enddo outputsLoop
! allocate state arrays
sizeState = 1_pInt
vacancyfluxState(section)%sizeState = sizeState
vacancyfluxState(section)%sizePostResults = vacancyflux_isochempot_sizePostResults(instance)
allocate(vacancyfluxState(section)%state0 (sizeState,NofMyHomog), source=0.0_pReal)
allocate(vacancyfluxState(section)%subState0(sizeState,NofMyHomog), source=0.0_pReal)
allocate(vacancyfluxState(section)%state (sizeState,NofMyHomog), source=0.0_pReal)
nullify(vacancyfluxMapping(section)%p)
vacancyfluxMapping(section)%p => mappingHomogenization(1,:,:)
deallocate(vacancyConc(section)%p)
vacancyConc(section)%p => vacancyfluxState(section)%state(1,:)
deallocate(vacancyConcRate(section)%p)
allocate(vacancyConcRate(section)%p(NofMyHomog), source=0.0_pReal)
endif
enddo initializeInstances
end subroutine vacancyflux_isochempot_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates change in vacancy concentration based on local vacancy generation model
!--------------------------------------------------------------------------------------------------
function vacancyflux_isochempot_updateState(subdt, ip, el)
use numerics, only: &
err_vacancyflux_tolAbs, &
err_vacancyflux_tolRel
use material, only: &
mappingHomogenization, &
vacancyflux_typeInstance, &
vacancyfluxState, &
vacancyConc, &
vacancyConcRate, &
vacancyfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
subdt
logical, dimension(2) :: &
vacancyflux_isochempot_updateState
integer(pInt) :: &
homog, &
offset, &
instance
real(pReal) :: &
Cv, Cvdot, dCvDot_dCv
homog = mappingHomogenization(2,ip,el)
offset = mappingHomogenization(1,ip,el)
instance = vacancyflux_typeInstance(homog)
Cv = vacancyfluxState(homog)%subState0(1,offset)
call vacancyflux_isochempot_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el)
Cv = Cv + subdt*Cvdot
vacancyflux_isochempot_updateState = [ abs(Cv - vacancyfluxState(homog)%state(1,offset)) &
<= err_vacancyflux_tolAbs &
.or. abs(Cv - vacancyfluxState(homog)%state(1,offset)) &
<= err_vacancyflux_tolRel*abs(vacancyfluxState(homog)%state(1,offset)), &
.true.]
vacancyConc (homog)%p(vacancyfluxMapping(homog)%p(ip,el)) = Cv
vacancyConcRate(homog)%p(vacancyfluxMapping(homog)%p(ip,el)) = &
(vacancyfluxState(homog)%state(1,offset) - vacancyfluxState(homog)%subState0(1,offset))/subdt
end function vacancyflux_isochempot_updateState
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized vacancy driving forces
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_isochempot_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el)
use material, only: &
homogenization_Ngrains, &
mappingHomogenization, &
mappingConstitutive, &
phase_source, &
phase_Nsources, &
SOURCE_vacancy_phenoplasticity_ID, &
SOURCE_vacancy_irradiation_ID, &
SOURCE_vacancy_thermalfluc_ID
use source_vacancy_phenoplasticity, only: &
source_vacancy_phenoplasticity_getRateAndItsTangent
use source_vacancy_irradiation, only: &
source_vacancy_irradiation_getRateAndItsTangent
use source_vacancy_thermalfluc, only: &
source_vacancy_thermalfluc_getRateAndItsTangent
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
Cv
integer(pInt) :: &
phase, &
grain, &
source
real(pReal) :: &
CvDot, dCvDot_dCv, localCvDot, dLocalCvDot_dCv
CvDot = 0.0_pReal
dCvDot_dCv = 0.0_pReal
do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el))
phase = mappingConstitutive(2,grain,ip,el)
do source = 1_pInt, phase_Nsources(phase)
select case(phase_source(source,phase))
case (SOURCE_vacancy_phenoplasticity_ID)
call source_vacancy_phenoplasticity_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el)
case (SOURCE_vacancy_irradiation_ID)
call source_vacancy_irradiation_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el)
case (SOURCE_vacancy_thermalfluc_ID)
call source_vacancy_thermalfluc_getRateAndItsTangent(localCvDot, dLocalCvDot_dCv, grain, ip, el)
end select
CvDot = CvDot + localCvDot
dCvDot_dCv = dCvDot_dCv + dLocalCvDot_dCv
enddo
enddo
CvDot = CvDot/homogenization_Ngrains(mappingHomogenization(2,ip,el))
dCvDot_dCv = dCvDot_dCv/homogenization_Ngrains(mappingHomogenization(2,ip,el))
end subroutine vacancyflux_isochempot_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief return array of vacancy transport results
!--------------------------------------------------------------------------------------------------
function vacancyflux_isochempot_postResults(ip,el)
use material, only: &
mappingHomogenization, &
vacancyflux_typeInstance, &
vacancyConc, &
vacancyfluxMapping
implicit none
integer(pInt), intent(in) :: &
ip, & !< integration point
el !< element
real(pReal), dimension(vacancyflux_isochempot_sizePostResults(vacancyflux_typeInstance(mappingHomogenization(2,ip,el)))) :: &
vacancyflux_isochempot_postResults
integer(pInt) :: &
instance, homog, offset, o, c
homog = mappingHomogenization(2,ip,el)
offset = vacancyfluxMapping(homog)%p(ip,el)
instance = vacancyflux_typeInstance(homog)
c = 0_pInt
vacancyflux_isochempot_postResults = 0.0_pReal
do o = 1_pInt,vacancyflux_isochempot_Noutput(instance)
select case(vacancyflux_isochempot_outputID(o,instance))
case (vacancyconc_ID)
vacancyflux_isochempot_postResults(c+1_pInt) = vacancyConc(homog)%p(offset)
c = c + 1
end select
enddo
end function vacancyflux_isochempot_postResults
end module vacancyflux_isochempot

View File

@ -0,0 +1,64 @@
!--------------------------------------------------------------------------------------------------
! $Id$
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for constant vacancy concentration
!--------------------------------------------------------------------------------------------------
module vacancyflux_isoconc
implicit none
private
public :: &
vacancyflux_isoconc_init
contains
!--------------------------------------------------------------------------------------------------
!> @brief allocates all neccessary fields, reads information from material configuration file
!--------------------------------------------------------------------------------------------------
subroutine vacancyflux_isoconc_init()
use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment)
use prec, only: &
pReal, &
pInt
use IO, only: &
IO_timeStamp
use material
use numerics, only: &
worldrank
implicit none
integer(pInt) :: &
homog, &
NofMyHomog
mainProcess: if (worldrank == 0) then
write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_isoconc_label//' init -+>>>'
write(6,'(a)') ' $Id$'
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
#include "compilation_info.f90"
endif mainProcess
initializeInstances: do homog = 1_pInt, material_Nhomogenization
myhomog: if (vacancyflux_type(homog) == VACANCYFLUX_isoconc_ID) then
NofMyHomog = count(material_homog == homog)
vacancyfluxState(homog)%sizeState = 0_pInt
vacancyfluxState(homog)%sizePostResults = 0_pInt
allocate(vacancyfluxState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal)
allocate(vacancyfluxState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal)
allocate(vacancyfluxState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal)
deallocate(vacancyConc (homog)%p)
allocate (vacancyConc (homog)%p(1), source=0.0_pReal)
deallocate(vacancyConcRate(homog)%p)
allocate (vacancyConcRate(homog)%p(1), source=0.0_pReal)
endif myhomog
enddo initializeInstances
end subroutine vacancyflux_isoconc_init
end module vacancyflux_isoconc