DAMASK with grid solvers  Revision: v2.0.3-2204-gdb1f2151
The Düsseldorf Advanced Material Simulation Kit with Grid Solvers
constitutive_plastic_dislotwin.f90
Go to the documentation of this file.
1 # 1 "/home/damask_user/GitLabCI_Pipeline_4301/DAMASK/src/constitutive_plastic_dislotwin.f90"
2 # 1 "<built-in>"
3 # 1 "<command-line>"
4 # 1 "/home/damask_user/GitLabCI_Pipeline_4301/DAMASK/src/constitutive_plastic_dislotwin.f90"
5 !--------------------------------------------------------------------------------------------------
13 !--------------------------------------------------------------------------------------------------
14 submodule(constitutive) plastic_dislotwin
15 
16  real(pReal), parameter :: &
17  kB = 1.38e-23_preal
18 
19  type :: tparameters
20  real(pReal) :: &
21  mu = 1.0_preal, &
22  nu = 1.0_preal, &
23  d0 = 1.0_preal, &
24  qsd = 1.0_preal, &
25  omega = 1.0_preal, &
26  d = 1.0_preal, &
27  p_sb = 1.0_preal, &
28  q_sb = 1.0_preal, &
29  cedgedipmindistance = 1.0_preal, &
30  i_tw = 1.0_preal, &
31  tau_0 = 1.0_preal, &
32  l_tw = 1.0_preal, &
33  l_tr = 1.0_preal, &
34  xc_twin = 1.0_preal, &
35  xc_trans = 1.0_preal, &
36  v_cs = 1.0_preal, &
37  sbresistance = 1.0_preal, &
38  sbvelocity = 1.0_preal, &
39  e_sb = 1.0_preal, &
40  sfe_0k = 1.0_preal, &
41  dsfe_dt = 1.0_preal, &
42  gamma_fcc_hex = 1.0_preal, &
43  i_tr = 1.0_preal, &
44  h = 1.0_preal
45  real(pReal), allocatable, dimension(:) :: &
46  b_sl, & !< absolute length of burgers vector [m] for each slip system
47  b_tw, & !< absolute length of burgers vector [m] for each twin system
48  b_tr, & !< absolute length of burgers vector [m] for each transformation system
49  Delta_F,& !< activation energy for glide [J] for each slip system
50  v0, & !< dislocation velocity prefactor [m/s] for each slip system
51  dot_N_0_tw, & !< twin nucleation rate [1/mÂs] for each twin system dot_N_0_tr, & !< trans nucleation rate [1/m³s] for each trans system t_tw, & !< twin thickness [m] for each twin system CLambdaSlip, & !< Adj. parameter for distance between 2 forest dislocations for each slip system t_tr, & !< martensite lamellar thickness [m] for each trans system and instance p, & !< p-exponent in glide velocity q, & !< q-exponent in glide velocity r, & !< r-exponent in twin nucleation rate s, & !< s-exponent in trans nucleation rate gamma_char, & !< characteristic shear for twins B !< drag coefficient real(pReal), allocatable, dimension(:,:) :: & h_sl_sl, & !< h_sl_tw, & !< h_tw_tw, & !< h_sl_tr, & !< h_tr_tr, & !< n0_sl, & !< slip system normal forestProjection, & C66 real(pReal), allocatable, dimension(:,:,:) :: & P_sl, & P_tw, & P_tr, & C66_tw, & C66_tr integer :: & sum_N_sl, & !< total number of active slip system sum_N_tw, & !< total number of active twin system sum_N_tr !< total number of active transformation system integer, allocatable, dimension(:,:) :: & fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans character(len=pStringLen), allocatable, dimension(:) :: & output logical :: & ExtendedDislocations, & !< consider split into partials for climb calculation fccTwinTransNucleation, & !< twinning and transformation models are for fcc dipoleFormation !< flag indicating consideration of dipole formation end type !< container type for internal constitutive parameters type :: tDislotwinState real(pReal), dimension(:,:), pointer :: & rho_mob, & rho_dip, & gamma_sl, & f_tw, & f_tr end type tDislotwinState type :: tDislotwinMicrostructure real(pReal), dimension(:,:), allocatable :: & Lambda_sl, & !< mean free path between 2 obstacles seen by a moving dislocation Lambda_tw, & !< mean free path between 2 obstacles seen by a growing twin Lambda_tr, & !< mean free path between 2 obstacles seen by a growing martensite tau_pass, & tau_hat_tw, & tau_hat_tr, & V_tw, & !< volume of a new twin V_tr, & !< volume of a new martensite disc tau_r_tw, & !< stress to bring partials close together (twin) tau_r_tr !< stress to bring partials close together (trans) end type tDislotwinMicrostructure !-------------------------------------------------------------------------------------------------- ! containers for parameters and state type(tParameters), allocatable, dimension(:) :: param type(tDislotwinState), allocatable, dimension(:) :: & dotState, & state type(tDislotwinMicrostructure), allocatable, dimension(:) :: dependentState contains !-------------------------------------------------------------------------------------------------- !> @brief Perform module initialization. !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_init integer :: & Ninstance, & p, i, & NipcMyPhase, & sizeState, sizeDotState, & startIndex, endIndex integer, dimension(:), allocatable :: & N_sl, N_tw, N_tr real(pReal), allocatable, dimension(:) :: & rho_mob_0, & !< initial unipolar dislocation density per slip system rho_dip_0 !< initial dipole dislocation density per slip system character(len=pStringLen) :: & extmsg = '' write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Ma and Roters, Acta Materialia 52(12):3603–3612, 2004' write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2004.04.012' write(6,'(/,a)') ' Roters et al., Computational Materials Science 39:91–95, 2007' write(6,'(a)') ' https://doi.org/10.1016/j.commatsci.2006.04.014' write(6,'(/,a)') ' Wong et al., Acta Materialia 118:140–151, 2016' write(6,'(a,/)') ' https://doi.org/10.1016/j.actamat.2016.07.032' Ninstance = count(phase_plasticity == PLASTICITY_DISLOTWIN_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) allocate(dependentState(Ninstance)) do p = 1, size(phase_plasticity) if (phase_plasticity(p) /= PLASTICITY_DISLOTWIN_ID) cycle associate(prm => param(phase_plasticityInstance(p)), & dot => dotState(phase_plasticityInstance(p)), & stt => state(phase_plasticityInstance(p)), & dst => dependentState(phase_plasticityInstance(p)), & config => config_phase(p)) prm%output = config%getStrings('(output)', defaultVal=emptyStringArray) ! This data is read in already in lattice prm%mu = lattice_mu(p) prm%nu = lattice_nu(p) prm%C66 = lattice_C66(1:6,1:6,p) !-------------------------------------------------------------------------------------------------- ! slip related parameters N_sl = config%getInts('nslip',defaultVal=emptyIntArray) prm%sum_N_sl = sum(abs(N_sl)) slipActive: if (prm%sum_N_sl > 0) then prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%forestProjection = transpose(prm%forestProjection) prm%n0_sl = lattice_slip_normal(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%fccTwinTransNucleation = merge(.true., .false., lattice_structure(p) == lattice_FCC_ID) & .and. (N_sl(1) == 12) if(prm%fccTwinTransNucleation) prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl)) rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(N_sl)) prm%v0 = config%getFloats('v0', requiredSize=size(N_sl)) prm%b_sl = config%getFloats('slipburgers',requiredSize=size(N_sl)) prm%Delta_F = config%getFloats('qedge', requiredSize=size(N_sl)) prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(N_sl)) prm%p = config%getFloats('p_slip', requiredSize=size(N_sl)) prm%q = config%getFloats('q_slip', requiredSize=size(N_sl)) prm%B = config%getFloats('b', requiredSize=size(N_sl), & defaultVal=[(0.0_pReal, i=1,size(N_sl))]) prm%tau_0 = config%getFloat('solidsolutionstrength') prm%CEdgeDipMinDistance = config%getFloat('cedgedipmindistance') prm%D0 = config%getFloat('d0') prm%Qsd = config%getFloat('qsd') prm%ExtendedDislocations = config%keyExists('/extend_dislocations/') if (prm%ExtendedDislocations) then prm%SFE_0K = config%getFloat('sfe_0k') prm%dSFE_dT = config%getFloat('dsfe_dt') endif prm%dipoleformation = .not. config%keyExists('/nodipoleformation/') ! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex) ! details: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) & * merge(12.0_pReal,8.0_pReal,any(lattice_structure(p) == [lattice_FCC_ID,lattice_HEX_ID])) ! expand: family => system rho_mob_0 = math_expand(rho_mob_0, N_sl) rho_dip_0 = math_expand(rho_dip_0, N_sl) prm%v0 = math_expand(prm%v0, N_sl) prm%b_sl = math_expand(prm%b_sl, N_sl) prm%Delta_F = math_expand(prm%Delta_F, N_sl) prm%CLambdaSlip = math_expand(prm%CLambdaSlip, N_sl) prm%p = math_expand(prm%p, N_sl) prm%q = math_expand(prm%q, N_sl) prm%B = math_expand(prm%B, N_sl) ! sanity checks if ( prm%D0 <= 0.0_pReal) extmsg = trim(extmsg)//' D0' if ( prm%Qsd <= 0.0_pReal) extmsg = trim(extmsg)//' Qsd' if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0' if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0' if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0' if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl' if (any(prm%Delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' Delta_F' if (any(prm%CLambdaSlip <= 0.0_pReal)) extmsg = trim(extmsg)//' CLambdaSlip' if (any(prm%B < 0.0_pReal)) extmsg = trim(extmsg)//' B' if (any(prm%p<=0.0_pReal .or. prm%p>1.0_pReal)) extmsg = trim(extmsg)//' p' if (any(prm%q< 1.0_pReal .or. prm%q>2.0_pReal)) extmsg = trim(extmsg)//' q' else slipActive rho_mob_0 = emptyRealArray; rho_dip_0 = emptyRealArray allocate(prm%b_sl,prm%Delta_F,prm%v0,prm%CLambdaSlip,prm%p,prm%q,prm%B,source=emptyRealArray) allocate(prm%forestProjection(0,0),prm%h_sl_sl(0,0)) endif slipActive !-------------------------------------------------------------------------------------------------- ! twin related parameters N_tw = config%getInts('ntwin', defaultVal=emptyIntArray) prm%sum_N_tw = sum(abs(N_tw)) twinActive: if (prm%sum_N_tw > 0) then prm%P_tw = lattice_SchmidMatrix_twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%h_tw_tw = lattice_interaction_TwinByTwin(N_tw,& config%getFloats('interaction_twintwin'), & config%getString('lattice_structure')) prm%b_tw = config%getFloats('twinburgers', requiredSize=size(N_tw)) prm%t_tw = config%getFloats('twinsize', requiredSize=size(N_tw)) prm%r = config%getFloats('r_twin', requiredSize=size(N_tw)) prm%xc_twin = config%getFloat('xc_twin') prm%L_tw = config%getFloat('l0_twin') prm%i_tw = config%getFloat('cmfptwin') prm%gamma_char= lattice_characteristicShear_Twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%C66_tw = lattice_C66_twin(N_tw,prm%C66,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) if (.not. prm%fccTwinTransNucleation) then prm%dot_N_0_tw = config%getFloats('ndot0_twin') prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,N_tw) endif ! expand: family => system prm%b_tw = math_expand(prm%b_tw,N_tw) prm%t_tw = math_expand(prm%t_tw,N_tw) prm%r = math_expand(prm%r,N_tw) ! sanity checks if ( prm%xc_twin < 0.0_pReal) extmsg = trim(extmsg)//' xc_twin' if ( prm%L_tw < 0.0_pReal) extmsg = trim(extmsg)//' L_tw' if ( prm%i_tw < 0.0_pReal) extmsg = trim(extmsg)//' i_tw' if (any(prm%b_tw < 0.0_pReal)) extmsg = trim(extmsg)//' b_tw' if (any(prm%t_tw < 0.0_pReal)) extmsg = trim(extmsg)//' t_tw' if (any(prm%r < 0.0_pReal)) extmsg = trim(extmsg)//' r' if (.not. prm%fccTwinTransNucleation) then if (any(prm%dot_N_0_tw < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tw' endif else twinActive allocate(prm%gamma_char,prm%b_tw,prm%dot_N_0_tw,prm%t_tw,prm%r,source=emptyRealArray) allocate(prm%h_tw_tw(0,0)) endif twinActive !-------------------------------------------------------------------------------------------------- ! transformation related parameters N_tr = config%getInts('ntrans', defaultVal=emptyIntArray) prm%sum_N_tr = sum(abs(N_tr)) transActive: if (prm%sum_N_tr > 0) then prm%b_tr = config%getFloats('transburgers') prm%b_tr = math_expand(prm%b_tr,N_tr) prm%h = config%getFloat('transstackheight', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%i_tr = config%getFloat('cmfptrans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%gamma_fcc_hex = config%getFloat('deltag') prm%xc_trans = config%getFloat('xc_trans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%L_tr = config%getFloat('l0_trans') prm%h_tr_tr = lattice_interaction_TransByTrans(N_tr,config%getFloats('interaction_transtrans'), & config%getString('lattice_structure')) prm%C66_tr = lattice_C66_trans(N_tr,prm%C66,config%getString('trans_lattice_structure'), & 0.0_pReal, & config%getFloat('a_bcc', defaultVal=0.0_pReal), & config%getFloat('a_fcc', defaultVal=0.0_pReal)) prm%P_tr = lattice_SchmidMatrix_trans(N_tr,config%getString('trans_lattice_structure'), & 0.0_pReal, & config%getFloat('a_bcc', defaultVal=0.0_pReal), & config%getFloat('a_fcc', defaultVal=0.0_pReal)) if (lattice_structure(p) /= lattice_FCC_ID) then prm%dot_N_0_tr = config%getFloats('ndot0_trans') prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,N_tr) endif prm%t_tr = config%getFloats('lamellarsize') prm%t_tr = math_expand(prm%t_tr,N_tr) prm%s = config%getFloats('s_trans',defaultVal=[0.0_pReal]) prm%s = math_expand(prm%s,N_tr) ! sanity checks if ( prm%xc_trans < 0.0_pReal) extmsg = trim(extmsg)//' xc_trans' if ( prm%L_tr < 0.0_pReal) extmsg = trim(extmsg)//' L_tr' if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr' if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr' if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' s' if (lattice_structure(p) /= lattice_FCC_ID) then if (any(prm%dot_N_0_tr < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tr' endif else transActive allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyRealArray) allocate(prm%h_tr_tr(0,0)) endif transActive !-------------------------------------------------------------------------------------------------- ! shearband related parameters prm%sbVelocity = config%getFloat('shearbandvelocity',defaultVal=0.0_pReal) if (prm%sbVelocity > 0.0_pReal) then prm%sbResistance = config%getFloat('shearbandresistance') prm%E_sb = config%getFloat('qedgepersbsystem') prm%p_sb = config%getFloat('p_shearband') prm%q_sb = config%getFloat('q_shearband') ! sanity checks if (prm%sbResistance < 0.0_pReal) extmsg = trim(extmsg)//' shearbandresistance' if (prm%E_sb < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem' if (prm%p_sb <= 0.0_pReal) extmsg = trim(extmsg)//' p_shearband' if (prm%q_sb <= 0.0_pReal) extmsg = trim(extmsg)//' q_shearband' endif !-------------------------------------------------------------------------------------------------- ! parameters required for several mechanisms and their interactions if(prm%sum_N_sl + prm%sum_N_tw + prm%sum_N_tw > 0) & prm%D = config%getFloat('grainsize') twinOrSlipActive: if (prm%sum_N_tw + prm%sum_N_tr > 0) then prm%SFE_0K = config%getFloat('sfe_0k') prm%dSFE_dT = config%getFloat('dsfe_dt') prm%V_cs = config%getFloat('vcrossslip') endif twinOrSlipActive slipAndTwinActive: if (prm%sum_N_sl * prm%sum_N_tw > 0) then prm%h_sl_tw = lattice_interaction_SlipByTwin(N_sl,N_tw,& config%getFloats('interaction_sliptwin'), & config%getString('lattice_structure')) if (prm%fccTwinTransNucleation .and. size(N_tw) /= 1) extmsg = trim(extmsg)//' interaction_sliptwin' endif slipAndTwinActive slipAndTransActive: if (prm%sum_N_sl * prm%sum_N_tr > 0) then prm%h_sl_tr = lattice_interaction_SlipByTrans(N_sl,N_tr,& config%getFloats('interaction_sliptrans'), & config%getString('lattice_structure')) if (prm%fccTwinTransNucleation .and. size(N_tr) /= 1) extmsg = trim(extmsg)//' interaction_sliptrans' endif slipAndTransActive !-------------------------------------------------------------------------------------------------- ! allocate state arrays NipcMyPhase = count(material_phaseAt == p) * discretization_nIP sizeDotState = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl & + size(['f_tw']) * prm%sum_N_tw & + size(['f_tr']) * prm%sum_N_tr sizeState = sizeDotState call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and atol startIndex = 1 endIndex = prm%sum_N_sl stt%rho_mob=>plasticState(p)%state(startIndex:endIndex,:) stt%rho_mob= spread(rho_mob_0,2,NipcMyPhase) dot%rho_mob=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%rho_dip=>plasticState(p)%state(startIndex:endIndex,:) stt%rho_dip= spread(rho_dip_0,2,NipcMyPhase) dot%rho_dip=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%gamma_sl=>plasticState(p)%state(startIndex:endIndex,:) dot%gamma_sl=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal ! global alias plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_tw stt%f_tw=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tw=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_twin',defaultVal=1.0e-7_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_twin' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_tr stt%f_tr=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tr=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_trans',defaultVal=1.0e-6_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_trans' allocate(dst%Lambda_sl (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_pass (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) allocate(dst%Lambda_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_hat_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_r_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%V_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%Lambda_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_hat_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_r_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%V_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally end associate !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOTWIN_LABEL//')') enddo end subroutine plastic_dislotwin_init !-------------------------------------------------------------------------------------------------- !> @brief Return the homogenized elasticity matrix. !-------------------------------------------------------------------------------------------------- module function plastic_dislotwin_homogenizedC(ipc,ip,el) result(homogenizedC) real(pReal), dimension(6,6) :: & homogenizedC integer, intent(in) :: & ipc, & !< component-ID of integration point ip, & !< integration point el !< element integer :: i, & of real(pReal) :: f_unrotated of = material_phasememberAt(ipc,ip,el) associate(prm => param(phase_plasticityInstance(material_phaseAt(ipc,el))),& stt => state(phase_plasticityInstance(material_phaseAT(ipc,el)))) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) homogenizedC = f_unrotated * prm%C66 do i=1,prm%sum_N_tw homogenizedC = homogenizedC & + stt%f_tw(i,of)*prm%C66_tw(1:6,1:6,i) enddo do i=1,prm%sum_N_tr homogenizedC = homogenizedC & + stt%f_tr(i,of)*prm%C66_tr(1:6,1:6,i) enddo end associate end function plastic_dislotwin_homogenizedC !-------------------------------------------------------------------------------------------------- !> @brief Calculate plastic velocity gradient and its tangent. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of) real(pReal), dimension(3,3), intent(out) :: Lp real(pReal), dimension(3,3,3,3), intent(out) :: dLp_dMp real(pReal), dimension(3,3), intent(in) :: Mp integer, intent(in) :: instance,of real(pReal), intent(in) :: T integer :: i,k,l,m,n real(pReal) :: & f_unrotated,StressRatio_p,& BoltzmannRatio, & ddot_gamma_dtau, & tau real(pReal), dimension(param(instance)%sum_N_sl) :: & dot_gamma_sl,ddot_gamma_dtau_slip real(pReal), dimension(param(instance)%sum_N_tw) :: & dot_gamma_twin,ddot_gamma_dtau_twin real(pReal), dimension(param(instance)%sum_N_tr) :: & dot_gamma_tr,ddot_gamma_dtau_trans real(pReal):: dot_gamma_sb real(pReal), dimension(3,3) :: eigVectors, P_sb real(pReal), dimension(3) :: eigValues real(pReal), dimension(3,6), parameter :: & sb_sComposition = & reshape(real([& 1, 0, 1, & 1, 0,-1, & 1, 1, 0, & 1,-1, 0, & 0, 1, 1, & 0, 1,-1 & ],pReal),[ 3,6]), & sb_mComposition = & reshape(real([& 1, 0,-1, & 1, 0,+1, & 1,-1, 0, & 1, 1, 0, & 0, 1,-1, & 0, 1, 1 & ],pReal),[ 3,6]) associate(prm => param(instance), stt => state(instance)) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) Lp = 0.0_pReal dLp_dMp = 0.0_pReal call kinetics_slip(Mp,T,instance,of,dot_gamma_sl,ddot_gamma_dtau_slip) slipContribution: do i = 1, prm%sum_N_sl Lp = Lp + dot_gamma_sl(i)*prm%P_sl(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_slip(i) * prm%P_sl(k,l,i) * prm%P_sl(m,n,i) enddo slipContribution !ToDo: Why do this before shear banding? Lp = Lp * f_unrotated dLp_dMp = dLp_dMp * f_unrotated shearBandingContribution: if(dNeq0(prm%sbVelocity)) then BoltzmannRatio = prm%E_sb/(kB*T) call math_eigh33(Mp,eigValues,eigVectors) ! is Mp symmetric by design? do i = 1,6 P_sb = 0.5_pReal * math_outer(matmul(eigVectors,sb_sComposition(1:3,i)),& matmul(eigVectors,sb_mComposition(1:3,i))) tau = math_tensordot(Mp,P_sb) significantShearBandStress: if (abs(tau) > tol_math_check) then StressRatio_p = (abs(tau)/prm%sbResistance)**prm%p_sb dot_gamma_sb = sign(prm%sbVelocity*exp(-BoltzmannRatio*(1-StressRatio_p)**prm%q_sb), tau) ddot_gamma_dtau = abs(dot_gamma_sb)*BoltzmannRatio* prm%p_sb*prm%q_sb/ prm%sbResistance & * (abs(tau)/prm%sbResistance)**(prm%p_sb-1.0_pReal) & * (1.0_pReal-StressRatio_p)**(prm%q_sb-1.0_pReal) Lp = Lp + dot_gamma_sb * P_sb forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau * P_sb(k,l) * P_sb(m,n) endif significantShearBandStress enddo endif shearBandingContribution call kinetics_twin(Mp,T,dot_gamma_sl,instance,of,dot_gamma_twin,ddot_gamma_dtau_twin) twinContibution: do i = 1, prm%sum_N_tw Lp = Lp + dot_gamma_twin(i)*prm%P_tw(1:3,1:3,i) * f_unrotated forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_twin(i)* prm%P_tw(k,l,i)*prm%P_tw(m,n,i) * f_unrotated enddo twinContibution call kinetics_trans(Mp,T,dot_gamma_sl,instance,of,dot_gamma_tr,ddot_gamma_dtau_trans) transContibution: do i = 1, prm%sum_N_tr Lp = Lp + dot_gamma_tr(i)*prm%P_tr(1:3,1:3,i) * f_unrotated forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_trans(i)* prm%P_tr(k,l,i)*prm%P_tr(m,n,i) * f_unrotated enddo transContibution end associate end subroutine plastic_dislotwin_LpAndItsTangent !-------------------------------------------------------------------------------------------------- !> @brief Calculate the rate of change of microstructure. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_dotState(Mp,T,instance,of) real(pReal), dimension(3,3), intent(in):: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature at integration point integer, intent(in) :: & instance, & of integer :: i real(pReal) :: & f_unrotated, & rho_dip_distance, & v_cl, & !< climb velocity Gamma, & !< stacking fault energy tau, & sigma_cl, & !< climb stress b_d !< ratio of burgers vector to stacking fault width real(pReal), dimension(param(instance)%sum_N_sl) :: & dot_rho_dip_formation, & dot_rho_dip_climb, & rho_dip_distance_min, & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tw) :: & dot_gamma_twin real(pReal), dimension(param(instance)%sum_N_tr) :: & dot_gamma_tr associate(prm => param(instance), stt => state(instance), & dot => dotState(instance), dst => dependentState(instance)) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) call kinetics_slip(Mp,T,instance,of,dot_gamma_sl) dot%gamma_sl(:,of) = abs(dot_gamma_sl) rho_dip_distance_min = prm%CEdgeDipMinDistance*prm%b_sl slipState: do i = 1, prm%sum_N_sl tau = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) significantSlipStress: if (dEq0(tau)) then dot_rho_dip_formation(i) = 0.0_pReal dot_rho_dip_climb(i) = 0.0_pReal else significantSlipStress rho_dip_distance = 3.0_pReal*prm%mu*prm%b_sl(i)/(16.0_pReal*PI*abs(tau)) rho_dip_distance = math_clip(rho_dip_distance, right = dst%Lambda_sl(i,of)) rho_dip_distance = math_clip(rho_dip_distance, left = rho_dip_distance_min(i)) if (prm%dipoleFormation) then dot_rho_dip_formation(i) = 2.0_pReal*(rho_dip_distance-rho_dip_distance_min(i))/prm%b_sl(i) & * stt%rho_mob(i,of)*abs(dot_gamma_sl(i)) else dot_rho_dip_formation(i) = 0.0_pReal endif if (dEq(rho_dip_distance,rho_dip_distance_min(i))) then dot_rho_dip_climb(i) = 0.0_pReal else !@details: Refer: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 sigma_cl = dot_product(prm%n0_sl(1:3,i),matmul(Mp,prm%n0_sl(1:3,i))) if (prm%ExtendedDislocations) then Gamma = prm%SFE_0K + prm%dSFE_dT * T b_d = 24.0_pReal*PI*(1.0_pReal - prm%nu)/(2.0_pReal + prm%nu)* Gamma/(prm%mu*prm%b_sl(i)) else b_d = 1.0_pReal endif v_cl = 2.0_pReal*prm%omega*b_d**2.0_pReal*exp(-prm%Qsd/(kB*T)) & * (exp(abs(sigma_cl)*prm%b_sl(i)**3.0_pReal/(kB*T)) - 1.0_pReal) dot_rho_dip_climb(i) = 4.0_pReal*v_cl*stt%rho_dip(i,of) & / (rho_dip_distance-rho_dip_distance_min(i)) endif endif significantSlipStress enddo slipState dot%rho_mob(:,of) = abs(dot_gamma_sl)/(prm%b_sl*dst%Lambda_sl(:,of)) & - dot_rho_dip_formation & - 2.0_pReal*rho_dip_distance_min/prm%b_sl * stt%rho_mob(:,of)*abs(dot_gamma_sl) dot%rho_dip(:,of) = dot_rho_dip_formation & - 2.0_pReal*rho_dip_distance_min/prm%b_sl * stt%rho_dip(:,of)*abs(dot_gamma_sl) & - dot_rho_dip_climb call kinetics_twin(Mp,T,dot_gamma_sl,instance,of,dot_gamma_twin) dot%f_tw(:,of) = f_unrotated*dot_gamma_twin/prm%gamma_char call kinetics_trans(Mp,T,dot_gamma_sl,instance,of,dot_gamma_tr) dot%f_tr(:,of) = f_unrotated*dot_gamma_tr end associate end subroutine plastic_dislotwin_dotState !-------------------------------------------------------------------------------------------------- !> @brief Calculate derived quantities from state. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_dependentState(T,instance,of) integer, intent(in) :: & instance, & of real(pReal), intent(in) :: & T real(pReal) :: & sumf_twin,Gamma,sumf_trans real(pReal), dimension(param(instance)%sum_N_sl) :: & inv_lambda_sl_sl, & !< 1/mean free distance between 2 forest dislocations seen by a moving dislocation inv_lambda_sl_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a moving dislocation inv_lambda_sl_tr !< 1/mean free distance between 2 martensite lamellar from different systems seen by a moving dislocation real(pReal), dimension(param(instance)%sum_N_tw) :: & inv_lambda_tw_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a growing twin f_over_t_tw real(pReal), dimension(param(instance)%sum_N_tr) :: & inv_lambda_tr_tr, & !< 1/mean free distance between 2 martensite stacks from different systems seen by a growing martensite f_over_t_tr real(pReal), dimension(:), allocatable :: & x0 associate(prm => param(instance),& stt => state(instance),& dst => dependentState(instance)) sumf_twin = sum(stt%f_tw(1:prm%sum_N_tw,of)) sumf_trans = sum(stt%f_tr(1:prm%sum_N_tr,of)) Gamma = prm%SFE_0K + prm%dSFE_dT * T !* rescaled volume fraction for topology f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,of)/prm%t_tw ! this is per system ... f_over_t_tr = sumf_trans/prm%t_tr ! but this not ! ToDo ...Physically correct, but naming could be adjusted inv_lambda_sl_sl = sqrt(matmul(prm%forestProjection, & stt%rho_mob(:,of)+stt%rho_dip(:,of)))/prm%CLambdaSlip if (prm%sum_N_tw > 0 .and. prm%sum_N_sl > 0) & inv_lambda_sl_tw = matmul(prm%h_sl_tw,f_over_t_tw)/(1.0_pReal-sumf_twin) inv_lambda_tw_tw = matmul(prm%h_tw_tw,f_over_t_tw)/(1.0_pReal-sumf_twin) if (prm%sum_N_tr > 0 .and. prm%sum_N_sl > 0) & inv_lambda_sl_tr = matmul(prm%h_sl_tr,f_over_t_tr)/(1.0_pReal-sumf_trans) inv_lambda_tr_tr = matmul(prm%h_tr_tr,f_over_t_tr)/(1.0_pReal-sumf_trans) if ((prm%sum_N_tw > 0) .or. (prm%sum_N_tr > 0)) then ! ToDo: better logic needed here dst%Lambda_sl(:,of) = prm%D & / (1.0_pReal+prm%D*(inv_lambda_sl_sl + inv_lambda_sl_tw + inv_lambda_sl_tr)) else dst%Lambda_sl(:,of) = prm%D & / (1.0_pReal+prm%D*inv_lambda_sl_sl) !!!!!! correct? endif dst%Lambda_tw(:,of) = prm%i_tw*prm%D/(1.0_pReal+prm%D*inv_lambda_tw_tw) dst%Lambda_tr(:,of) = prm%i_tr*prm%D/(1.0_pReal+prm%D*inv_lambda_tr_tr) !* threshold stress for dislocation motion dst%tau_pass(:,of) = prm%mu*prm%b_sl* sqrt(matmul(prm%h_sl_sl,stt%rho_mob(:,of)+stt%rho_dip(:,of))) !* threshold stress for growing twin/martensite if(prm%sum_N_tw == prm%sum_N_sl) & dst%tau_hat_tw(:,of) = Gamma/(3.0_pReal*prm%b_tw) & + 3.0_pReal*prm%b_tw*prm%mu/(prm%L_tw*prm%b_sl) ! slip burgers here correct? if(prm%sum_N_tr == prm%sum_N_sl) & dst%tau_hat_tr(:,of) = Gamma/(3.0_pReal*prm%b_tr) & + 3.0_pReal*prm%b_tr*prm%mu/(prm%L_tr*prm%b_sl) & ! slip burgers here correct? + prm%h*prm%gamma_fcc_hex/ (3.0_pReal*prm%b_tr) dst%V_tw(:,of) = (PI/4.0_pReal)*prm%t_tw*dst%Lambda_tw(:,of)**2.0_pReal dst%V_tr(:,of) = (PI/4.0_pReal)*prm%t_tr*dst%Lambda_tr(:,of)**2.0_pReal x0 = prm%mu*prm%b_tw**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip and is the same for twin and trans dst%tau_r_tw(:,of) = prm%mu*prm%b_tw/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_twin)+cos(pi/3.0_pReal)/x0) x0 = prm%mu*prm%b_tr**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip dst%tau_r_tr(:,of) = prm%mu*prm%b_tr/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_trans)+cos(pi/3.0_pReal)/x0) end associate end subroutine plastic_dislotwin_dependentState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_results(instance,group) integer, intent(in) :: instance character(len=*), intent(in) :: group integer :: o associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) case('rho_mob') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_mob,'rho_mob',& 'mobile dislocation density','1/m²') case('rho_dip') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip,'rho_dip',& 'dislocation dipole density''1/m²') case('gamma_sl') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'gamma_sl',& 'plastic shear','1') case('lambda_sl') if(prm%sum_N_sl>0) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',& 'mean free path for slip','m') case('tau_pass') if(prm%sum_N_sl>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',& 'passing stress for slip','Pa') case('f_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,stt%f_tw,'f_tw',& 'twinned volume fraction','m³/m³') case('lambda_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,dst%Lambda_tw,'Lambda_tw',& 'mean free path for twinning','m') case('tau_hat_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,dst%tau_hat_tw,'tau_hat_tw',& 'threshold stress for twinning','Pa') case('f_tr') if(prm%sum_N_tr>0) call results_writeDataset(group,stt%f_tr,'f_tr',& 'martensite volume fraction','m³/m³') end select enddo outputsLoop end associate end subroutine plastic_dislotwin_results !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved ! stress, and the resolved stress. !> @details Derivatives and resolved stress are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_slip(Mp,T,instance,of, & dot_gamma_sl,ddot_gamma_dtau_slip,tau_slip) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(out) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_sl), optional, intent(out) :: & ddot_gamma_dtau_slip, & tau_slip real(pReal), dimension(param(instance)%sum_N_sl) :: & ddot_gamma_dtau real(pReal), dimension(param(instance)%sum_N_sl) :: & tau, & stressRatio, & StressRatio_p, & BoltzmannRatio, & v_wait_inverse, & !< inverse of the effective velocity of a dislocation waiting at obstacles (unsigned) v_run_inverse, & !< inverse of the velocity of a free moving dislocation (unsigned) dV_wait_inverse_dTau, & dV_run_inverse_dTau, & dV_dTau, & tau_eff !< effective resolved stress integer :: i associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_sl tau(i) = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) enddo tau_eff = abs(tau)-dst%tau_pass(:,of) significantStress: where(tau_eff > tol_math_check) stressRatio = tau_eff/prm%tau_0 StressRatio_p = stressRatio** prm%p BoltzmannRatio = prm%Delta_F/(kB*T) v_wait_inverse = prm%v0**(-1.0_pReal) * exp(BoltzmannRatio*(1.0_pReal-StressRatio_p)** prm%q) v_run_inverse = prm%B/(tau_eff*prm%b_sl) dot_gamma_sl = sign(stt%rho_mob(:,of)*prm%b_sl/(v_wait_inverse+v_run_inverse),tau) dV_wait_inverse_dTau = -1.0_pReal * v_wait_inverse * prm%p * prm%q * BoltzmannRatio & * (stressRatio**(prm%p-1.0_pReal)) & * (1.0_pReal-StressRatio_p)**(prm%q-1.0_pReal) & / prm%tau_0 dV_run_inverse_dTau = -1.0_pReal * v_run_inverse/tau_eff dV_dTau = -1.0_pReal * (dV_wait_inverse_dTau+dV_run_inverse_dTau) & / (v_wait_inverse+v_run_inverse)**2.0_pReal ddot_gamma_dtau = dV_dTau*stt%rho_mob(:,of)*prm%b_sl else where significantStress dot_gamma_sl = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_slip)) ddot_gamma_dtau_slip = ddot_gamma_dtau if(present(tau_slip)) tau_slip = tau end subroutine kinetics_slip !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved ! stress. !> @details Derivatives are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,& dot_gamma_twin,ddot_gamma_dtau_twin) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tw), intent(out) :: & dot_gamma_twin real(pReal), dimension(param(instance)%sum_N_tw), optional, intent(out) :: & ddot_gamma_dtau_twin real, dimension(param(instance)%sum_N_tw) :: & tau, & Ndot0, & stressRatio_r, & ddot_gamma_dtau integer :: i,s1,s2 associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tw tau(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) if (tau(i) < dst%tau_r_tw(i,of)) then ! ToDo: correct? Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+& abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state (prm%L_tw*prm%b_sl(i))*& (1.0_pReal-exp(-prm%V_cs/(kB*T)*(dst%tau_r_tw(i,of)-tau(i)))) ! P_ncs else Ndot0=0.0_pReal end if else isFCC Ndot0=prm%dot_N_0_tw(i) endif isFCC enddo significantStress: where(tau > tol_math_check) StressRatio_r = (dst%tau_hat_tw(:,of)/tau)**prm%r dot_gamma_twin = prm%gamma_char * dst%V_tw(:,of) * Ndot0*exp(-StressRatio_r) ddot_gamma_dtau = (dot_gamma_twin*prm%r/tau)*StressRatio_r else where significantStress dot_gamma_twin = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_twin)) ddot_gamma_dtau_twin = ddot_gamma_dtau end subroutine kinetics_twin !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on transformation systems and their derivatives with respect to ! resolved stress. !> @details Derivatives are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,& dot_gamma_tr,ddot_gamma_dtau_trans) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tr), intent(out) :: & dot_gamma_tr real(pReal), dimension(param(instance)%sum_N_tr), optional, intent(out) :: & ddot_gamma_dtau_trans real, dimension(param(instance)%sum_N_tr) :: & tau, & Ndot0, & stressRatio_s, & ddot_gamma_dtau integer :: i,s1,s2 associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tr tau(i) = math_tensordot(Mp,prm%P_tr(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) if (tau(i) < dst%tau_r_tr(i,of)) then ! ToDo: correct? Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+& abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state (prm%L_tr*prm%b_sl(i))*& (1.0_pReal-exp(-prm%V_cs/(kB*T)*(dst%tau_r_tr(i,of)-tau(i)))) ! P_ncs else Ndot0=0.0_pReal end if else isFCC Ndot0=prm%dot_N_0_tr(i) endif isFCC enddo significantStress: where(tau > tol_math_check) StressRatio_s = (dst%tau_hat_tr(:,of)/tau)**prm%s dot_gamma_tr = dst%V_tr(:,of) * Ndot0*exp(-StressRatio_s) ddot_gamma_dtau = (dot_gamma_tr*prm%s/tau)*StressRatio_s else where significantStress dot_gamma_tr = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_trans)) ddot_gamma_dtau_trans = ddot_gamma_dtau end subroutine kinetics_trans end submodule plastic_dislotwin ³s] for each twin system
52  dot_N_0_tr, & !< trans nucleation rate [1/mÂs] for each trans system t_tw, & !< twin thickness [m] for each twin system CLambdaSlip, & !< Adj. parameter for distance between 2 forest dislocations for each slip system t_tr, & !< martensite lamellar thickness [m] for each trans system and instance p, & !< p-exponent in glide velocity q, & !< q-exponent in glide velocity r, & !< r-exponent in twin nucleation rate s, & !< s-exponent in trans nucleation rate gamma_char, & !< characteristic shear for twins B !< drag coefficient real(pReal), allocatable, dimension(:,:) :: & h_sl_sl, & !< h_sl_tw, & !< h_tw_tw, & !< h_sl_tr, & !< h_tr_tr, & !< n0_sl, & !< slip system normal forestProjection, & C66 real(pReal), allocatable, dimension(:,:,:) :: & P_sl, & P_tw, & P_tr, & C66_tw, & C66_tr integer :: & sum_N_sl, & !< total number of active slip system sum_N_tw, & !< total number of active twin system sum_N_tr !< total number of active transformation system integer, allocatable, dimension(:,:) :: & fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans character(len=pStringLen), allocatable, dimension(:) :: & output logical :: & ExtendedDislocations, & !< consider split into partials for climb calculation fccTwinTransNucleation, & !< twinning and transformation models are for fcc dipoleFormation !< flag indicating consideration of dipole formation end type !< container type for internal constitutive parameters type :: tDislotwinState real(pReal), dimension(:,:), pointer :: & rho_mob, & rho_dip, & gamma_sl, & f_tw, & f_tr end type tDislotwinState type :: tDislotwinMicrostructure real(pReal), dimension(:,:), allocatable :: & Lambda_sl, & !< mean free path between 2 obstacles seen by a moving dislocation Lambda_tw, & !< mean free path between 2 obstacles seen by a growing twin Lambda_tr, & !< mean free path between 2 obstacles seen by a growing martensite tau_pass, & tau_hat_tw, & tau_hat_tr, & V_tw, & !< volume of a new twin V_tr, & !< volume of a new martensite disc tau_r_tw, & !< stress to bring partials close together (twin) tau_r_tr !< stress to bring partials close together (trans) end type tDislotwinMicrostructure !-------------------------------------------------------------------------------------------------- ! containers for parameters and state type(tParameters), allocatable, dimension(:) :: param type(tDislotwinState), allocatable, dimension(:) :: & dotState, & state type(tDislotwinMicrostructure), allocatable, dimension(:) :: dependentState contains !-------------------------------------------------------------------------------------------------- !> @brief Perform module initialization. !> @details reads in material parameters, allocates arrays, and does sanity checks !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_init integer :: & Ninstance, & p, i, & NipcMyPhase, & sizeState, sizeDotState, & startIndex, endIndex integer, dimension(:), allocatable :: & N_sl, N_tw, N_tr real(pReal), allocatable, dimension(:) :: & rho_mob_0, & !< initial unipolar dislocation density per slip system rho_dip_0 !< initial dipole dislocation density per slip system character(len=pStringLen) :: & extmsg = '' write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Ma and Roters, Acta Materialia 52(12):3603–3612, 2004' write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2004.04.012' write(6,'(/,a)') ' Roters et al., Computational Materials Science 39:91–95, 2007' write(6,'(a)') ' https://doi.org/10.1016/j.commatsci.2006.04.014' write(6,'(/,a)') ' Wong et al., Acta Materialia 118:140–151, 2016' write(6,'(a,/)') ' https://doi.org/10.1016/j.actamat.2016.07.032' Ninstance = count(phase_plasticity == PLASTICITY_DISLOTWIN_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) allocate(dependentState(Ninstance)) do p = 1, size(phase_plasticity) if (phase_plasticity(p) /= PLASTICITY_DISLOTWIN_ID) cycle associate(prm => param(phase_plasticityInstance(p)), & dot => dotState(phase_plasticityInstance(p)), & stt => state(phase_plasticityInstance(p)), & dst => dependentState(phase_plasticityInstance(p)), & config => config_phase(p)) prm%output = config%getStrings('(output)', defaultVal=emptyStringArray) ! This data is read in already in lattice prm%mu = lattice_mu(p) prm%nu = lattice_nu(p) prm%C66 = lattice_C66(1:6,1:6,p) !-------------------------------------------------------------------------------------------------- ! slip related parameters N_sl = config%getInts('nslip',defaultVal=emptyIntArray) prm%sum_N_sl = sum(abs(N_sl)) slipActive: if (prm%sum_N_sl > 0) then prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%forestProjection = transpose(prm%forestProjection) prm%n0_sl = lattice_slip_normal(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%fccTwinTransNucleation = merge(.true., .false., lattice_structure(p) == lattice_FCC_ID) & .and. (N_sl(1) == 12) if(prm%fccTwinTransNucleation) prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl)) rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(N_sl)) prm%v0 = config%getFloats('v0', requiredSize=size(N_sl)) prm%b_sl = config%getFloats('slipburgers',requiredSize=size(N_sl)) prm%Delta_F = config%getFloats('qedge', requiredSize=size(N_sl)) prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(N_sl)) prm%p = config%getFloats('p_slip', requiredSize=size(N_sl)) prm%q = config%getFloats('q_slip', requiredSize=size(N_sl)) prm%B = config%getFloats('b', requiredSize=size(N_sl), & defaultVal=[(0.0_pReal, i=1,size(N_sl))]) prm%tau_0 = config%getFloat('solidsolutionstrength') prm%CEdgeDipMinDistance = config%getFloat('cedgedipmindistance') prm%D0 = config%getFloat('d0') prm%Qsd = config%getFloat('qsd') prm%ExtendedDislocations = config%keyExists('/extend_dislocations/') if (prm%ExtendedDislocations) then prm%SFE_0K = config%getFloat('sfe_0k') prm%dSFE_dT = config%getFloat('dsfe_dt') endif prm%dipoleformation = .not. config%keyExists('/nodipoleformation/') ! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex) ! details: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) & * merge(12.0_pReal,8.0_pReal,any(lattice_structure(p) == [lattice_FCC_ID,lattice_HEX_ID])) ! expand: family => system rho_mob_0 = math_expand(rho_mob_0, N_sl) rho_dip_0 = math_expand(rho_dip_0, N_sl) prm%v0 = math_expand(prm%v0, N_sl) prm%b_sl = math_expand(prm%b_sl, N_sl) prm%Delta_F = math_expand(prm%Delta_F, N_sl) prm%CLambdaSlip = math_expand(prm%CLambdaSlip, N_sl) prm%p = math_expand(prm%p, N_sl) prm%q = math_expand(prm%q, N_sl) prm%B = math_expand(prm%B, N_sl) ! sanity checks if ( prm%D0 <= 0.0_pReal) extmsg = trim(extmsg)//' D0' if ( prm%Qsd <= 0.0_pReal) extmsg = trim(extmsg)//' Qsd' if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0' if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0' if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0' if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl' if (any(prm%Delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' Delta_F' if (any(prm%CLambdaSlip <= 0.0_pReal)) extmsg = trim(extmsg)//' CLambdaSlip' if (any(prm%B < 0.0_pReal)) extmsg = trim(extmsg)//' B' if (any(prm%p<=0.0_pReal .or. prm%p>1.0_pReal)) extmsg = trim(extmsg)//' p' if (any(prm%q< 1.0_pReal .or. prm%q>2.0_pReal)) extmsg = trim(extmsg)//' q' else slipActive rho_mob_0 = emptyRealArray; rho_dip_0 = emptyRealArray allocate(prm%b_sl,prm%Delta_F,prm%v0,prm%CLambdaSlip,prm%p,prm%q,prm%B,source=emptyRealArray) allocate(prm%forestProjection(0,0),prm%h_sl_sl(0,0)) endif slipActive !-------------------------------------------------------------------------------------------------- ! twin related parameters N_tw = config%getInts('ntwin', defaultVal=emptyIntArray) prm%sum_N_tw = sum(abs(N_tw)) twinActive: if (prm%sum_N_tw > 0) then prm%P_tw = lattice_SchmidMatrix_twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%h_tw_tw = lattice_interaction_TwinByTwin(N_tw,& config%getFloats('interaction_twintwin'), & config%getString('lattice_structure')) prm%b_tw = config%getFloats('twinburgers', requiredSize=size(N_tw)) prm%t_tw = config%getFloats('twinsize', requiredSize=size(N_tw)) prm%r = config%getFloats('r_twin', requiredSize=size(N_tw)) prm%xc_twin = config%getFloat('xc_twin') prm%L_tw = config%getFloat('l0_twin') prm%i_tw = config%getFloat('cmfptwin') prm%gamma_char= lattice_characteristicShear_Twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) prm%C66_tw = lattice_C66_twin(N_tw,prm%C66,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) if (.not. prm%fccTwinTransNucleation) then prm%dot_N_0_tw = config%getFloats('ndot0_twin') prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,N_tw) endif ! expand: family => system prm%b_tw = math_expand(prm%b_tw,N_tw) prm%t_tw = math_expand(prm%t_tw,N_tw) prm%r = math_expand(prm%r,N_tw) ! sanity checks if ( prm%xc_twin < 0.0_pReal) extmsg = trim(extmsg)//' xc_twin' if ( prm%L_tw < 0.0_pReal) extmsg = trim(extmsg)//' L_tw' if ( prm%i_tw < 0.0_pReal) extmsg = trim(extmsg)//' i_tw' if (any(prm%b_tw < 0.0_pReal)) extmsg = trim(extmsg)//' b_tw' if (any(prm%t_tw < 0.0_pReal)) extmsg = trim(extmsg)//' t_tw' if (any(prm%r < 0.0_pReal)) extmsg = trim(extmsg)//' r' if (.not. prm%fccTwinTransNucleation) then if (any(prm%dot_N_0_tw < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tw' endif else twinActive allocate(prm%gamma_char,prm%b_tw,prm%dot_N_0_tw,prm%t_tw,prm%r,source=emptyRealArray) allocate(prm%h_tw_tw(0,0)) endif twinActive !-------------------------------------------------------------------------------------------------- ! transformation related parameters N_tr = config%getInts('ntrans', defaultVal=emptyIntArray) prm%sum_N_tr = sum(abs(N_tr)) transActive: if (prm%sum_N_tr > 0) then prm%b_tr = config%getFloats('transburgers') prm%b_tr = math_expand(prm%b_tr,N_tr) prm%h = config%getFloat('transstackheight', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%i_tr = config%getFloat('cmfptrans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%gamma_fcc_hex = config%getFloat('deltag') prm%xc_trans = config%getFloat('xc_trans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%L_tr = config%getFloat('l0_trans') prm%h_tr_tr = lattice_interaction_TransByTrans(N_tr,config%getFloats('interaction_transtrans'), & config%getString('lattice_structure')) prm%C66_tr = lattice_C66_trans(N_tr,prm%C66,config%getString('trans_lattice_structure'), & 0.0_pReal, & config%getFloat('a_bcc', defaultVal=0.0_pReal), & config%getFloat('a_fcc', defaultVal=0.0_pReal)) prm%P_tr = lattice_SchmidMatrix_trans(N_tr,config%getString('trans_lattice_structure'), & 0.0_pReal, & config%getFloat('a_bcc', defaultVal=0.0_pReal), & config%getFloat('a_fcc', defaultVal=0.0_pReal)) if (lattice_structure(p) /= lattice_FCC_ID) then prm%dot_N_0_tr = config%getFloats('ndot0_trans') prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,N_tr) endif prm%t_tr = config%getFloats('lamellarsize') prm%t_tr = math_expand(prm%t_tr,N_tr) prm%s = config%getFloats('s_trans',defaultVal=[0.0_pReal]) prm%s = math_expand(prm%s,N_tr) ! sanity checks if ( prm%xc_trans < 0.0_pReal) extmsg = trim(extmsg)//' xc_trans' if ( prm%L_tr < 0.0_pReal) extmsg = trim(extmsg)//' L_tr' if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr' if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr' if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' s' if (lattice_structure(p) /= lattice_FCC_ID) then if (any(prm%dot_N_0_tr < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tr' endif else transActive allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyRealArray) allocate(prm%h_tr_tr(0,0)) endif transActive !-------------------------------------------------------------------------------------------------- ! shearband related parameters prm%sbVelocity = config%getFloat('shearbandvelocity',defaultVal=0.0_pReal) if (prm%sbVelocity > 0.0_pReal) then prm%sbResistance = config%getFloat('shearbandresistance') prm%E_sb = config%getFloat('qedgepersbsystem') prm%p_sb = config%getFloat('p_shearband') prm%q_sb = config%getFloat('q_shearband') ! sanity checks if (prm%sbResistance < 0.0_pReal) extmsg = trim(extmsg)//' shearbandresistance' if (prm%E_sb < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem' if (prm%p_sb <= 0.0_pReal) extmsg = trim(extmsg)//' p_shearband' if (prm%q_sb <= 0.0_pReal) extmsg = trim(extmsg)//' q_shearband' endif !-------------------------------------------------------------------------------------------------- ! parameters required for several mechanisms and their interactions if(prm%sum_N_sl + prm%sum_N_tw + prm%sum_N_tw > 0) & prm%D = config%getFloat('grainsize') twinOrSlipActive: if (prm%sum_N_tw + prm%sum_N_tr > 0) then prm%SFE_0K = config%getFloat('sfe_0k') prm%dSFE_dT = config%getFloat('dsfe_dt') prm%V_cs = config%getFloat('vcrossslip') endif twinOrSlipActive slipAndTwinActive: if (prm%sum_N_sl * prm%sum_N_tw > 0) then prm%h_sl_tw = lattice_interaction_SlipByTwin(N_sl,N_tw,& config%getFloats('interaction_sliptwin'), & config%getString('lattice_structure')) if (prm%fccTwinTransNucleation .and. size(N_tw) /= 1) extmsg = trim(extmsg)//' interaction_sliptwin' endif slipAndTwinActive slipAndTransActive: if (prm%sum_N_sl * prm%sum_N_tr > 0) then prm%h_sl_tr = lattice_interaction_SlipByTrans(N_sl,N_tr,& config%getFloats('interaction_sliptrans'), & config%getString('lattice_structure')) if (prm%fccTwinTransNucleation .and. size(N_tr) /= 1) extmsg = trim(extmsg)//' interaction_sliptrans' endif slipAndTransActive !-------------------------------------------------------------------------------------------------- ! allocate state arrays NipcMyPhase = count(material_phaseAt == p) * discretization_nIP sizeDotState = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl & + size(['f_tw']) * prm%sum_N_tw & + size(['f_tr']) * prm%sum_N_tr sizeState = sizeDotState call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and atol startIndex = 1 endIndex = prm%sum_N_sl stt%rho_mob=>plasticState(p)%state(startIndex:endIndex,:) stt%rho_mob= spread(rho_mob_0,2,NipcMyPhase) dot%rho_mob=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%rho_dip=>plasticState(p)%state(startIndex:endIndex,:) stt%rho_dip= spread(rho_dip_0,2,NipcMyPhase) dot%rho_dip=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%gamma_sl=>plasticState(p)%state(startIndex:endIndex,:) dot%gamma_sl=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal ! global alias plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_tw stt%f_tw=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tw=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_twin',defaultVal=1.0e-7_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_twin' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_tr stt%f_tr=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tr=>plasticState(p)%dotState(startIndex:endIndex,:) plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_trans',defaultVal=1.0e-6_pReal) if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_trans' allocate(dst%Lambda_sl (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_pass (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) allocate(dst%Lambda_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_hat_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_r_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%V_tw (prm%sum_N_tw,NipcMyPhase),source=0.0_pReal) allocate(dst%Lambda_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_hat_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_r_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%V_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally end associate !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOTWIN_LABEL//')') enddo end subroutine plastic_dislotwin_init !-------------------------------------------------------------------------------------------------- !> @brief Return the homogenized elasticity matrix. !-------------------------------------------------------------------------------------------------- module function plastic_dislotwin_homogenizedC(ipc,ip,el) result(homogenizedC) real(pReal), dimension(6,6) :: & homogenizedC integer, intent(in) :: & ipc, & !< component-ID of integration point ip, & !< integration point el !< element integer :: i, & of real(pReal) :: f_unrotated of = material_phasememberAt(ipc,ip,el) associate(prm => param(phase_plasticityInstance(material_phaseAt(ipc,el))),& stt => state(phase_plasticityInstance(material_phaseAT(ipc,el)))) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) homogenizedC = f_unrotated * prm%C66 do i=1,prm%sum_N_tw homogenizedC = homogenizedC & + stt%f_tw(i,of)*prm%C66_tw(1:6,1:6,i) enddo do i=1,prm%sum_N_tr homogenizedC = homogenizedC & + stt%f_tr(i,of)*prm%C66_tr(1:6,1:6,i) enddo end associate end function plastic_dislotwin_homogenizedC !-------------------------------------------------------------------------------------------------- !> @brief Calculate plastic velocity gradient and its tangent. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of) real(pReal), dimension(3,3), intent(out) :: Lp real(pReal), dimension(3,3,3,3), intent(out) :: dLp_dMp real(pReal), dimension(3,3), intent(in) :: Mp integer, intent(in) :: instance,of real(pReal), intent(in) :: T integer :: i,k,l,m,n real(pReal) :: & f_unrotated,StressRatio_p,& BoltzmannRatio, & ddot_gamma_dtau, & tau real(pReal), dimension(param(instance)%sum_N_sl) :: & dot_gamma_sl,ddot_gamma_dtau_slip real(pReal), dimension(param(instance)%sum_N_tw) :: & dot_gamma_twin,ddot_gamma_dtau_twin real(pReal), dimension(param(instance)%sum_N_tr) :: & dot_gamma_tr,ddot_gamma_dtau_trans real(pReal):: dot_gamma_sb real(pReal), dimension(3,3) :: eigVectors, P_sb real(pReal), dimension(3) :: eigValues real(pReal), dimension(3,6), parameter :: & sb_sComposition = & reshape(real([& 1, 0, 1, & 1, 0,-1, & 1, 1, 0, & 1,-1, 0, & 0, 1, 1, & 0, 1,-1 & ],pReal),[ 3,6]), & sb_mComposition = & reshape(real([& 1, 0,-1, & 1, 0,+1, & 1,-1, 0, & 1, 1, 0, & 0, 1,-1, & 0, 1, 1 & ],pReal),[ 3,6]) associate(prm => param(instance), stt => state(instance)) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) Lp = 0.0_pReal dLp_dMp = 0.0_pReal call kinetics_slip(Mp,T,instance,of,dot_gamma_sl,ddot_gamma_dtau_slip) slipContribution: do i = 1, prm%sum_N_sl Lp = Lp + dot_gamma_sl(i)*prm%P_sl(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_slip(i) * prm%P_sl(k,l,i) * prm%P_sl(m,n,i) enddo slipContribution !ToDo: Why do this before shear banding? Lp = Lp * f_unrotated dLp_dMp = dLp_dMp * f_unrotated shearBandingContribution: if(dNeq0(prm%sbVelocity)) then BoltzmannRatio = prm%E_sb/(kB*T) call math_eigh33(Mp,eigValues,eigVectors) ! is Mp symmetric by design? do i = 1,6 P_sb = 0.5_pReal * math_outer(matmul(eigVectors,sb_sComposition(1:3,i)),& matmul(eigVectors,sb_mComposition(1:3,i))) tau = math_tensordot(Mp,P_sb) significantShearBandStress: if (abs(tau) > tol_math_check) then StressRatio_p = (abs(tau)/prm%sbResistance)**prm%p_sb dot_gamma_sb = sign(prm%sbVelocity*exp(-BoltzmannRatio*(1-StressRatio_p)**prm%q_sb), tau) ddot_gamma_dtau = abs(dot_gamma_sb)*BoltzmannRatio* prm%p_sb*prm%q_sb/ prm%sbResistance & * (abs(tau)/prm%sbResistance)**(prm%p_sb-1.0_pReal) & * (1.0_pReal-StressRatio_p)**(prm%q_sb-1.0_pReal) Lp = Lp + dot_gamma_sb * P_sb forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau * P_sb(k,l) * P_sb(m,n) endif significantShearBandStress enddo endif shearBandingContribution call kinetics_twin(Mp,T,dot_gamma_sl,instance,of,dot_gamma_twin,ddot_gamma_dtau_twin) twinContibution: do i = 1, prm%sum_N_tw Lp = Lp + dot_gamma_twin(i)*prm%P_tw(1:3,1:3,i) * f_unrotated forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_twin(i)* prm%P_tw(k,l,i)*prm%P_tw(m,n,i) * f_unrotated enddo twinContibution call kinetics_trans(Mp,T,dot_gamma_sl,instance,of,dot_gamma_tr,ddot_gamma_dtau_trans) transContibution: do i = 1, prm%sum_N_tr Lp = Lp + dot_gamma_tr(i)*prm%P_tr(1:3,1:3,i) * f_unrotated forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & + ddot_gamma_dtau_trans(i)* prm%P_tr(k,l,i)*prm%P_tr(m,n,i) * f_unrotated enddo transContibution end associate end subroutine plastic_dislotwin_LpAndItsTangent !-------------------------------------------------------------------------------------------------- !> @brief Calculate the rate of change of microstructure. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_dotState(Mp,T,instance,of) real(pReal), dimension(3,3), intent(in):: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature at integration point integer, intent(in) :: & instance, & of integer :: i real(pReal) :: & f_unrotated, & rho_dip_distance, & v_cl, & !< climb velocity Gamma, & !< stacking fault energy tau, & sigma_cl, & !< climb stress b_d !< ratio of burgers vector to stacking fault width real(pReal), dimension(param(instance)%sum_N_sl) :: & dot_rho_dip_formation, & dot_rho_dip_climb, & rho_dip_distance_min, & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tw) :: & dot_gamma_twin real(pReal), dimension(param(instance)%sum_N_tr) :: & dot_gamma_tr associate(prm => param(instance), stt => state(instance), & dot => dotState(instance), dst => dependentState(instance)) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) call kinetics_slip(Mp,T,instance,of,dot_gamma_sl) dot%gamma_sl(:,of) = abs(dot_gamma_sl) rho_dip_distance_min = prm%CEdgeDipMinDistance*prm%b_sl slipState: do i = 1, prm%sum_N_sl tau = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) significantSlipStress: if (dEq0(tau)) then dot_rho_dip_formation(i) = 0.0_pReal dot_rho_dip_climb(i) = 0.0_pReal else significantSlipStress rho_dip_distance = 3.0_pReal*prm%mu*prm%b_sl(i)/(16.0_pReal*PI*abs(tau)) rho_dip_distance = math_clip(rho_dip_distance, right = dst%Lambda_sl(i,of)) rho_dip_distance = math_clip(rho_dip_distance, left = rho_dip_distance_min(i)) if (prm%dipoleFormation) then dot_rho_dip_formation(i) = 2.0_pReal*(rho_dip_distance-rho_dip_distance_min(i))/prm%b_sl(i) & * stt%rho_mob(i,of)*abs(dot_gamma_sl(i)) else dot_rho_dip_formation(i) = 0.0_pReal endif if (dEq(rho_dip_distance,rho_dip_distance_min(i))) then dot_rho_dip_climb(i) = 0.0_pReal else !@details: Refer: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 sigma_cl = dot_product(prm%n0_sl(1:3,i),matmul(Mp,prm%n0_sl(1:3,i))) if (prm%ExtendedDislocations) then Gamma = prm%SFE_0K + prm%dSFE_dT * T b_d = 24.0_pReal*PI*(1.0_pReal - prm%nu)/(2.0_pReal + prm%nu)* Gamma/(prm%mu*prm%b_sl(i)) else b_d = 1.0_pReal endif v_cl = 2.0_pReal*prm%omega*b_d**2.0_pReal*exp(-prm%Qsd/(kB*T)) & * (exp(abs(sigma_cl)*prm%b_sl(i)**3.0_pReal/(kB*T)) - 1.0_pReal) dot_rho_dip_climb(i) = 4.0_pReal*v_cl*stt%rho_dip(i,of) & / (rho_dip_distance-rho_dip_distance_min(i)) endif endif significantSlipStress enddo slipState dot%rho_mob(:,of) = abs(dot_gamma_sl)/(prm%b_sl*dst%Lambda_sl(:,of)) & - dot_rho_dip_formation & - 2.0_pReal*rho_dip_distance_min/prm%b_sl * stt%rho_mob(:,of)*abs(dot_gamma_sl) dot%rho_dip(:,of) = dot_rho_dip_formation & - 2.0_pReal*rho_dip_distance_min/prm%b_sl * stt%rho_dip(:,of)*abs(dot_gamma_sl) & - dot_rho_dip_climb call kinetics_twin(Mp,T,dot_gamma_sl,instance,of,dot_gamma_twin) dot%f_tw(:,of) = f_unrotated*dot_gamma_twin/prm%gamma_char call kinetics_trans(Mp,T,dot_gamma_sl,instance,of,dot_gamma_tr) dot%f_tr(:,of) = f_unrotated*dot_gamma_tr end associate end subroutine plastic_dislotwin_dotState !-------------------------------------------------------------------------------------------------- !> @brief Calculate derived quantities from state. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_dependentState(T,instance,of) integer, intent(in) :: & instance, & of real(pReal), intent(in) :: & T real(pReal) :: & sumf_twin,Gamma,sumf_trans real(pReal), dimension(param(instance)%sum_N_sl) :: & inv_lambda_sl_sl, & !< 1/mean free distance between 2 forest dislocations seen by a moving dislocation inv_lambda_sl_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a moving dislocation inv_lambda_sl_tr !< 1/mean free distance between 2 martensite lamellar from different systems seen by a moving dislocation real(pReal), dimension(param(instance)%sum_N_tw) :: & inv_lambda_tw_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a growing twin f_over_t_tw real(pReal), dimension(param(instance)%sum_N_tr) :: & inv_lambda_tr_tr, & !< 1/mean free distance between 2 martensite stacks from different systems seen by a growing martensite f_over_t_tr real(pReal), dimension(:), allocatable :: & x0 associate(prm => param(instance),& stt => state(instance),& dst => dependentState(instance)) sumf_twin = sum(stt%f_tw(1:prm%sum_N_tw,of)) sumf_trans = sum(stt%f_tr(1:prm%sum_N_tr,of)) Gamma = prm%SFE_0K + prm%dSFE_dT * T !* rescaled volume fraction for topology f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,of)/prm%t_tw ! this is per system ... f_over_t_tr = sumf_trans/prm%t_tr ! but this not ! ToDo ...Physically correct, but naming could be adjusted inv_lambda_sl_sl = sqrt(matmul(prm%forestProjection, & stt%rho_mob(:,of)+stt%rho_dip(:,of)))/prm%CLambdaSlip if (prm%sum_N_tw > 0 .and. prm%sum_N_sl > 0) & inv_lambda_sl_tw = matmul(prm%h_sl_tw,f_over_t_tw)/(1.0_pReal-sumf_twin) inv_lambda_tw_tw = matmul(prm%h_tw_tw,f_over_t_tw)/(1.0_pReal-sumf_twin) if (prm%sum_N_tr > 0 .and. prm%sum_N_sl > 0) & inv_lambda_sl_tr = matmul(prm%h_sl_tr,f_over_t_tr)/(1.0_pReal-sumf_trans) inv_lambda_tr_tr = matmul(prm%h_tr_tr,f_over_t_tr)/(1.0_pReal-sumf_trans) if ((prm%sum_N_tw > 0) .or. (prm%sum_N_tr > 0)) then ! ToDo: better logic needed here dst%Lambda_sl(:,of) = prm%D & / (1.0_pReal+prm%D*(inv_lambda_sl_sl + inv_lambda_sl_tw + inv_lambda_sl_tr)) else dst%Lambda_sl(:,of) = prm%D & / (1.0_pReal+prm%D*inv_lambda_sl_sl) !!!!!! correct? endif dst%Lambda_tw(:,of) = prm%i_tw*prm%D/(1.0_pReal+prm%D*inv_lambda_tw_tw) dst%Lambda_tr(:,of) = prm%i_tr*prm%D/(1.0_pReal+prm%D*inv_lambda_tr_tr) !* threshold stress for dislocation motion dst%tau_pass(:,of) = prm%mu*prm%b_sl* sqrt(matmul(prm%h_sl_sl,stt%rho_mob(:,of)+stt%rho_dip(:,of))) !* threshold stress for growing twin/martensite if(prm%sum_N_tw == prm%sum_N_sl) & dst%tau_hat_tw(:,of) = Gamma/(3.0_pReal*prm%b_tw) & + 3.0_pReal*prm%b_tw*prm%mu/(prm%L_tw*prm%b_sl) ! slip burgers here correct? if(prm%sum_N_tr == prm%sum_N_sl) & dst%tau_hat_tr(:,of) = Gamma/(3.0_pReal*prm%b_tr) & + 3.0_pReal*prm%b_tr*prm%mu/(prm%L_tr*prm%b_sl) & ! slip burgers here correct? + prm%h*prm%gamma_fcc_hex/ (3.0_pReal*prm%b_tr) dst%V_tw(:,of) = (PI/4.0_pReal)*prm%t_tw*dst%Lambda_tw(:,of)**2.0_pReal dst%V_tr(:,of) = (PI/4.0_pReal)*prm%t_tr*dst%Lambda_tr(:,of)**2.0_pReal x0 = prm%mu*prm%b_tw**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip and is the same for twin and trans dst%tau_r_tw(:,of) = prm%mu*prm%b_tw/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_twin)+cos(pi/3.0_pReal)/x0) x0 = prm%mu*prm%b_tr**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip dst%tau_r_tr(:,of) = prm%mu*prm%b_tr/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_trans)+cos(pi/3.0_pReal)/x0) end associate end subroutine plastic_dislotwin_dependentState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- module subroutine plastic_dislotwin_results(instance,group) integer, intent(in) :: instance character(len=*), intent(in) :: group integer :: o associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) case('rho_mob') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_mob,'rho_mob',& 'mobile dislocation density','1/m²') case('rho_dip') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip,'rho_dip',& 'dislocation dipole density''1/m²') case('gamma_sl') if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'gamma_sl',& 'plastic shear','1') case('lambda_sl') if(prm%sum_N_sl>0) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',& 'mean free path for slip','m') case('tau_pass') if(prm%sum_N_sl>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',& 'passing stress for slip','Pa') case('f_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,stt%f_tw,'f_tw',& 'twinned volume fraction','m³/m³') case('lambda_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,dst%Lambda_tw,'Lambda_tw',& 'mean free path for twinning','m') case('tau_hat_tw') if(prm%sum_N_tw>0) call results_writeDataset(group,dst%tau_hat_tw,'tau_hat_tw',& 'threshold stress for twinning','Pa') case('f_tr') if(prm%sum_N_tr>0) call results_writeDataset(group,stt%f_tr,'f_tr',& 'martensite volume fraction','m³/m³') end select enddo outputsLoop end associate end subroutine plastic_dislotwin_results !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved ! stress, and the resolved stress. !> @details Derivatives and resolved stress are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_slip(Mp,T,instance,of, & dot_gamma_sl,ddot_gamma_dtau_slip,tau_slip) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(out) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_sl), optional, intent(out) :: & ddot_gamma_dtau_slip, & tau_slip real(pReal), dimension(param(instance)%sum_N_sl) :: & ddot_gamma_dtau real(pReal), dimension(param(instance)%sum_N_sl) :: & tau, & stressRatio, & StressRatio_p, & BoltzmannRatio, & v_wait_inverse, & !< inverse of the effective velocity of a dislocation waiting at obstacles (unsigned) v_run_inverse, & !< inverse of the velocity of a free moving dislocation (unsigned) dV_wait_inverse_dTau, & dV_run_inverse_dTau, & dV_dTau, & tau_eff !< effective resolved stress integer :: i associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_sl tau(i) = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) enddo tau_eff = abs(tau)-dst%tau_pass(:,of) significantStress: where(tau_eff > tol_math_check) stressRatio = tau_eff/prm%tau_0 StressRatio_p = stressRatio** prm%p BoltzmannRatio = prm%Delta_F/(kB*T) v_wait_inverse = prm%v0**(-1.0_pReal) * exp(BoltzmannRatio*(1.0_pReal-StressRatio_p)** prm%q) v_run_inverse = prm%B/(tau_eff*prm%b_sl) dot_gamma_sl = sign(stt%rho_mob(:,of)*prm%b_sl/(v_wait_inverse+v_run_inverse),tau) dV_wait_inverse_dTau = -1.0_pReal * v_wait_inverse * prm%p * prm%q * BoltzmannRatio & * (stressRatio**(prm%p-1.0_pReal)) & * (1.0_pReal-StressRatio_p)**(prm%q-1.0_pReal) & / prm%tau_0 dV_run_inverse_dTau = -1.0_pReal * v_run_inverse/tau_eff dV_dTau = -1.0_pReal * (dV_wait_inverse_dTau+dV_run_inverse_dTau) & / (v_wait_inverse+v_run_inverse)**2.0_pReal ddot_gamma_dtau = dV_dTau*stt%rho_mob(:,of)*prm%b_sl else where significantStress dot_gamma_sl = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_slip)) ddot_gamma_dtau_slip = ddot_gamma_dtau if(present(tau_slip)) tau_slip = tau end subroutine kinetics_slip !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved ! stress. !> @details Derivatives are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,& dot_gamma_twin,ddot_gamma_dtau_twin) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tw), intent(out) :: & dot_gamma_twin real(pReal), dimension(param(instance)%sum_N_tw), optional, intent(out) :: & ddot_gamma_dtau_twin real, dimension(param(instance)%sum_N_tw) :: & tau, & Ndot0, & stressRatio_r, & ddot_gamma_dtau integer :: i,s1,s2 associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tw tau(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) if (tau(i) < dst%tau_r_tw(i,of)) then ! ToDo: correct? Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+& abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state (prm%L_tw*prm%b_sl(i))*& (1.0_pReal-exp(-prm%V_cs/(kB*T)*(dst%tau_r_tw(i,of)-tau(i)))) ! P_ncs else Ndot0=0.0_pReal end if else isFCC Ndot0=prm%dot_N_0_tw(i) endif isFCC enddo significantStress: where(tau > tol_math_check) StressRatio_r = (dst%tau_hat_tw(:,of)/tau)**prm%r dot_gamma_twin = prm%gamma_char * dst%V_tw(:,of) * Ndot0*exp(-StressRatio_r) ddot_gamma_dtau = (dot_gamma_twin*prm%r/tau)*StressRatio_r else where significantStress dot_gamma_twin = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_twin)) ddot_gamma_dtau_twin = ddot_gamma_dtau end subroutine kinetics_twin !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on transformation systems and their derivatives with respect to ! resolved stress. !> @details Derivatives are calculated only optionally. ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to ! have the optional arguments at the end. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,& dot_gamma_tr,ddot_gamma_dtau_trans) real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & T !< temperature integer, intent(in) :: & instance, & of real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: & dot_gamma_sl real(pReal), dimension(param(instance)%sum_N_tr), intent(out) :: & dot_gamma_tr real(pReal), dimension(param(instance)%sum_N_tr), optional, intent(out) :: & ddot_gamma_dtau_trans real, dimension(param(instance)%sum_N_tr) :: & tau, & Ndot0, & stressRatio_s, & ddot_gamma_dtau integer :: i,s1,s2 associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tr tau(i) = math_tensordot(Mp,prm%P_tr(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) if (tau(i) < dst%tau_r_tr(i,of)) then ! ToDo: correct? Ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+& abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state (prm%L_tr*prm%b_sl(i))*& (1.0_pReal-exp(-prm%V_cs/(kB*T)*(dst%tau_r_tr(i,of)-tau(i)))) ! P_ncs else Ndot0=0.0_pReal end if else isFCC Ndot0=prm%dot_N_0_tr(i) endif isFCC enddo significantStress: where(tau > tol_math_check) StressRatio_s = (dst%tau_hat_tr(:,of)/tau)**prm%s dot_gamma_tr = dst%V_tr(:,of) * Ndot0*exp(-StressRatio_s) ddot_gamma_dtau = (dot_gamma_tr*prm%s/tau)*StressRatio_s else where significantStress dot_gamma_tr = 0.0_pReal ddot_gamma_dtau = 0.0_pReal end where significantStress end associate if(present(ddot_gamma_dtau_trans)) ddot_gamma_dtau_trans = ddot_gamma_dtau end subroutine kinetics_trans end submodule plastic_dislotwin ³s] for each trans system
53  t_tw, & !< twin thickness [m] for each twin system
54  CLambdaSlip, & !< Adj. parameter for distance between 2 forest dislocations for each slip system
55  t_tr, & !< martensite lamellar thickness [m] for each trans system and instance
56  p, & !< p-exponent in glide velocity
57  q, & !< q-exponent in glide velocity
58  r, & !< r-exponent in twin nucleation rate
59  s, & !< s-exponent in trans nucleation rate
60  gamma_char, & !< characteristic shear for twins
61  B
62  real(pReal), allocatable, dimension(:,:) :: &
63  h_sl_sl, & !<
64  h_sl_tw, & !<
65  h_tw_tw, & !<
66  h_sl_tr, & !<
67  h_tr_tr, & !<
68  n0_sl, & !< slip system normal
69  forestProjection, &
70  C66
71  real(pReal), allocatable, dimension(:,:,:) :: &
72  P_sl, &
73  P_tw, &
74  P_tr, &
75  C66_tw, &
76  C66_tr
77  integer :: &
78  sum_N_sl, & !< total number of active slip system
79  sum_N_tw, & !< total number of active twin system
80  sum_N_tr
81  integer, allocatable, dimension(:,:) :: &
82  fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans
83  character(len=pStringLen), allocatable, dimension(:) :: &
84  output
85  logical :: &
86  ExtendedDislocations, & !< consider split into partials for climb calculation
87  fccTwinTransNucleation, & !< twinning and transformation models are for fcc
88  dipoleFormation
89  end type
90 
91  type :: tdislotwinstate
92  real(pReal), dimension(:,:), pointer :: &
93  rho_mob, &
94  rho_dip, &
95  gamma_sl, &
96  f_tw, &
97  f_tr
98  end type tdislotwinstate
99 
100  type :: tdislotwinmicrostructure
101  real(pReal), dimension(:,:), allocatable :: &
102  Lambda_sl, & !< mean free path between 2 obstacles seen by a moving dislocation
103  Lambda_tw, & !< mean free path between 2 obstacles seen by a growing twin
104  Lambda_tr, & !< mean free path between 2 obstacles seen by a growing martensite
105  tau_pass, &
106  tau_hat_tw, &
107  tau_hat_tr, &
108  V_tw, & !< volume of a new twin
109  V_tr, & !< volume of a new martensite disc
110  tau_r_tw, & !< stress to bring partials close together (twin)
111  tau_r_tr
112  end type tdislotwinmicrostructure
113 
114 !--------------------------------------------------------------------------------------------------
115 ! containers for parameters and state
116  type(tParameters), allocatable, dimension(:) :: param
117  type(tDislotwinState), allocatable, dimension(:) :: &
118  dotState, &
119  state
120  type(tDislotwinMicrostructure), allocatable, dimension(:) :: dependentState
121 
122 contains
123 
124 
125 !--------------------------------------------------------------------------------------------------
128 !--------------------------------------------------------------------------------------------------
129 module subroutine plastic_dislotwin_init
130 
131  integer :: &
132  Ninstance, &
133  p, i, &
134  NipcMyPhase, &
135  sizeState, sizeDotState, &
136  startIndex, endIndex
137  integer, dimension(:), allocatable :: &
138  N_sl, N_tw, N_tr
139  real(pReal), allocatable, dimension(:) :: &
140  rho_mob_0, & !< initial unipolar dislocation density per slip system
141  rho_dip_0
142  character(len=pStringLen) :: &
143  extmsg = ''
144 
145  write(6,'(/,a)') ' <<<+- constitutive_'//plasticity_dislotwin_label//' init -+>>>'; flush(6)
146 
147  write(6,'(/,a)') ' Ma and Roters, Acta Materialia 52(12):3603–3612, 2004'
148  write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2004.04.012'
149 
150  write(6,'(/,a)') ' Roters et al., Computational Materials Science 39:91–95, 2007'
151  write(6,'(a)') ' https://doi.org/10.1016/j.commatsci.2006.04.014'
152 
153  write(6,'(/,a)') ' Wong et al., Acta Materialia 118:140–151, 2016'
154  write(6,'(a,/)') ' https://doi.org/10.1016/j.actamat.2016.07.032'
155 
156  ninstance = count(phase_plasticity == plasticity_dislotwin_id)
157 
158  if (iand(debug_level(debug_constitutive),debug_levelbasic) /= 0) &
159  write(6,'(a16,1x,i5,/)') '# instances:',ninstance
160 
161  allocate(param(ninstance))
162  allocate(state(ninstance))
163  allocate(dotstate(ninstance))
164  allocate(dependentstate(ninstance))
165 
166  do p = 1, size(phase_plasticity)
167  if (phase_plasticity(p) /= plasticity_dislotwin_id) cycle
168  associate(prm => param(phase_plasticityinstance(p)), &
169  dot => dotstate(phase_plasticityinstance(p)), &
170  stt => state(phase_plasticityinstance(p)), &
171  dst => dependentstate(phase_plasticityinstance(p)), &
172  config => config_phase(p))
173 
174  prm%output = config%getStrings('(output)', defaultval=emptystringarray)
175 
176  ! This data is read in already in lattice
177  prm%mu = lattice_mu(p)
178  prm%nu = lattice_nu(p)
179  prm%C66 = lattice_c66(1:6,1:6,p)
180 
181 !--------------------------------------------------------------------------------------------------
182 ! slip related parameters
183  n_sl = config%getInts('nslip',defaultval=emptyintarray)
184  prm%sum_N_sl = sum(abs(n_sl))
185  slipactive: if (prm%sum_N_sl > 0) then
186  prm%P_sl = lattice_schmidmatrix_slip(n_sl,config%getString('lattice_structure'),&
187  config%getFloat('c/a',defaultval=0.0_preal))
188  prm%h_sl_sl = lattice_interaction_slipbyslip(n_sl,config%getFloats('interaction_slipslip'), &
189  config%getString('lattice_structure'))
190  prm%forestProjection = lattice_forestprojection_edge(n_sl,config%getString('lattice_structure'),&
191  config%getFloat('c/a',defaultval=0.0_preal))
192  prm%forestProjection = transpose(prm%forestProjection)
193 
194  prm%n0_sl = lattice_slip_normal(n_sl,config%getString('lattice_structure'),&
195  config%getFloat('c/a',defaultval=0.0_preal))
196  prm%fccTwinTransNucleation = merge(.true., .false., lattice_structure(p) == lattice_fcc_id) &
197  .and. (n_sl(1) == 12)
198  if(prm%fccTwinTransNucleation) prm%fcc_twinNucleationSlipPair = lattice_fcc_twinnucleationslippair
199 
200  rho_mob_0 = config%getFloats('rhoedge0', requiredsize=size(n_sl))
201  rho_dip_0 = config%getFloats('rhoedgedip0',requiredsize=size(n_sl))
202  prm%v0 = config%getFloats('v0', requiredsize=size(n_sl))
203  prm%b_sl = config%getFloats('slipburgers',requiredsize=size(n_sl))
204  prm%Delta_F = config%getFloats('qedge', requiredsize=size(n_sl))
205  prm%CLambdaSlip = config%getFloats('clambdaslip',requiredsize=size(n_sl))
206  prm%p = config%getFloats('p_slip', requiredsize=size(n_sl))
207  prm%q = config%getFloats('q_slip', requiredsize=size(n_sl))
208  prm%B = config%getFloats('b', requiredsize=size(n_sl), &
209  defaultval=[(0.0_preal, i=1,size(n_sl))])
210 
211  prm%tau_0 = config%getFloat('solidsolutionstrength')
212  prm%CEdgeDipMinDistance = config%getFloat('cedgedipmindistance')
213  prm%D0 = config%getFloat('d0')
214  prm%Qsd = config%getFloat('qsd')
215  prm%ExtendedDislocations = config%keyExists('/extend_dislocations/')
216  if (prm%ExtendedDislocations) then
217  prm%SFE_0K = config%getFloat('sfe_0k')
218  prm%dSFE_dT = config%getFloat('dsfe_dt')
219  endif
220 
221  prm%dipoleformation = .not. config%keyExists('/nodipoleformation/')
222 
223  ! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex)
224  ! details: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
225  prm%omega = config%getFloat('omega', defaultval = 1000.0_preal) &
226  * merge(12.0_preal,8.0_preal,any(lattice_structure(p) == [lattice_fcc_id,lattice_hex_id]))
227 
228  ! expand: family => system
229  rho_mob_0 = math_expand(rho_mob_0, n_sl)
230  rho_dip_0 = math_expand(rho_dip_0, n_sl)
231  prm%v0 = math_expand(prm%v0, n_sl)
232  prm%b_sl = math_expand(prm%b_sl, n_sl)
233  prm%Delta_F = math_expand(prm%Delta_F, n_sl)
234  prm%CLambdaSlip = math_expand(prm%CLambdaSlip, n_sl)
235  prm%p = math_expand(prm%p, n_sl)
236  prm%q = math_expand(prm%q, n_sl)
237  prm%B = math_expand(prm%B, n_sl)
238 
239  ! sanity checks
240  if ( prm%D0 <= 0.0_preal) extmsg = trim(extmsg)//' D0'
241  if ( prm%Qsd <= 0.0_preal) extmsg = trim(extmsg)//' Qsd'
242  if (any(rho_mob_0 < 0.0_preal)) extmsg = trim(extmsg)//' rho_mob_0'
243  if (any(rho_dip_0 < 0.0_preal)) extmsg = trim(extmsg)//' rho_dip_0'
244  if (any(prm%v0 < 0.0_preal)) extmsg = trim(extmsg)//' v0'
245  if (any(prm%b_sl <= 0.0_preal)) extmsg = trim(extmsg)//' b_sl'
246  if (any(prm%Delta_F <= 0.0_preal)) extmsg = trim(extmsg)//' Delta_F'
247  if (any(prm%CLambdaSlip <= 0.0_preal)) extmsg = trim(extmsg)//' CLambdaSlip'
248  if (any(prm%B < 0.0_preal)) extmsg = trim(extmsg)//' B'
249  if (any(prm%p<=0.0_preal .or. prm%p>1.0_preal)) extmsg = trim(extmsg)//' p'
250  if (any(prm%q< 1.0_preal .or. prm%q>2.0_preal)) extmsg = trim(extmsg)//' q'
251  else slipactive
252  rho_mob_0 = emptyrealarray; rho_dip_0 = emptyrealarray
253  allocate(prm%b_sl,prm%Delta_F,prm%v0,prm%CLambdaSlip,prm%p,prm%q,prm%B,source=emptyrealarray)
254  allocate(prm%forestProjection(0,0),prm%h_sl_sl(0,0))
255  endif slipactive
256 
257 !--------------------------------------------------------------------------------------------------
258 ! twin related parameters
259  n_tw = config%getInts('ntwin', defaultval=emptyintarray)
260  prm%sum_N_tw = sum(abs(n_tw))
261  twinactive: if (prm%sum_N_tw > 0) then
262  prm%P_tw = lattice_schmidmatrix_twin(n_tw,config%getString('lattice_structure'),&
263  config%getFloat('c/a',defaultval=0.0_preal))
264  prm%h_tw_tw = lattice_interaction_twinbytwin(n_tw,&
265  config%getFloats('interaction_twintwin'), &
266  config%getString('lattice_structure'))
267 
268  prm%b_tw = config%getFloats('twinburgers', requiredsize=size(n_tw))
269  prm%t_tw = config%getFloats('twinsize', requiredsize=size(n_tw))
270  prm%r = config%getFloats('r_twin', requiredsize=size(n_tw))
271 
272  prm%xc_twin = config%getFloat('xc_twin')
273  prm%L_tw = config%getFloat('l0_twin')
274  prm%i_tw = config%getFloat('cmfptwin')
275 
276  prm%gamma_char= lattice_characteristicshear_twin(n_tw,config%getString('lattice_structure'),&
277  config%getFloat('c/a',defaultval=0.0_preal))
278 
279  prm%C66_tw = lattice_c66_twin(n_tw,prm%C66,config%getString('lattice_structure'),&
280  config%getFloat('c/a',defaultval=0.0_preal))
281 
282  if (.not. prm%fccTwinTransNucleation) then
283  prm%dot_N_0_tw = config%getFloats('ndot0_twin')
284  prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,n_tw)
285  endif
286 
287  ! expand: family => system
288  prm%b_tw = math_expand(prm%b_tw,n_tw)
289  prm%t_tw = math_expand(prm%t_tw,n_tw)
290  prm%r = math_expand(prm%r,n_tw)
291 
292  ! sanity checks
293  if ( prm%xc_twin < 0.0_preal) extmsg = trim(extmsg)//' xc_twin'
294  if ( prm%L_tw < 0.0_preal) extmsg = trim(extmsg)//' L_tw'
295  if ( prm%i_tw < 0.0_preal) extmsg = trim(extmsg)//' i_tw'
296  if (any(prm%b_tw < 0.0_preal)) extmsg = trim(extmsg)//' b_tw'
297  if (any(prm%t_tw < 0.0_preal)) extmsg = trim(extmsg)//' t_tw'
298  if (any(prm%r < 0.0_preal)) extmsg = trim(extmsg)//' r'
299  if (.not. prm%fccTwinTransNucleation) then
300  if (any(prm%dot_N_0_tw < 0.0_preal)) extmsg = trim(extmsg)//' dot_N_0_tw'
301  endif
302  else twinactive
303  allocate(prm%gamma_char,prm%b_tw,prm%dot_N_0_tw,prm%t_tw,prm%r,source=emptyrealarray)
304  allocate(prm%h_tw_tw(0,0))
305  endif twinactive
306 
307 !--------------------------------------------------------------------------------------------------
308 ! transformation related parameters
309  n_tr = config%getInts('ntrans', defaultval=emptyintarray)
310  prm%sum_N_tr = sum(abs(n_tr))
311  transactive: if (prm%sum_N_tr > 0) then
312  prm%b_tr = config%getFloats('transburgers')
313  prm%b_tr = math_expand(prm%b_tr,n_tr)
314 
315  prm%h = config%getFloat('transstackheight', defaultval=0.0_preal) ! ToDo: How to handle that???
316  prm%i_tr = config%getFloat('cmfptrans', defaultval=0.0_preal) ! ToDo: How to handle that???
317  prm%gamma_fcc_hex = config%getFloat('deltag')
318  prm%xc_trans = config%getFloat('xc_trans', defaultval=0.0_preal) ! ToDo: How to handle that???
319  prm%L_tr = config%getFloat('l0_trans')
320 
321  prm%h_tr_tr = lattice_interaction_transbytrans(n_tr,config%getFloats('interaction_transtrans'), &
322  config%getString('lattice_structure'))
323 
324  prm%C66_tr = lattice_c66_trans(n_tr,prm%C66,config%getString('trans_lattice_structure'), &
325  0.0_preal, &
326  config%getFloat('a_bcc', defaultval=0.0_preal), &
327  config%getFloat('a_fcc', defaultval=0.0_preal))
328 
329  prm%P_tr = lattice_schmidmatrix_trans(n_tr,config%getString('trans_lattice_structure'), &
330  0.0_preal, &
331  config%getFloat('a_bcc', defaultval=0.0_preal), &
332  config%getFloat('a_fcc', defaultval=0.0_preal))
333 
334  if (lattice_structure(p) /= lattice_fcc_id) then
335  prm%dot_N_0_tr = config%getFloats('ndot0_trans')
336  prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,n_tr)
337  endif
338  prm%t_tr = config%getFloats('lamellarsize')
339  prm%t_tr = math_expand(prm%t_tr,n_tr)
340  prm%s = config%getFloats('s_trans',defaultval=[0.0_preal])
341  prm%s = math_expand(prm%s,n_tr)
342 
343  ! sanity checks
344  if ( prm%xc_trans < 0.0_preal) extmsg = trim(extmsg)//' xc_trans'
345  if ( prm%L_tr < 0.0_preal) extmsg = trim(extmsg)//' L_tr'
346  if ( prm%i_tr < 0.0_preal) extmsg = trim(extmsg)//' i_tr'
347  if (any(prm%t_tr < 0.0_preal)) extmsg = trim(extmsg)//' t_tr'
348  if (any(prm%s < 0.0_preal)) extmsg = trim(extmsg)//' s'
349  if (lattice_structure(p) /= lattice_fcc_id) then
350  if (any(prm%dot_N_0_tr < 0.0_preal)) extmsg = trim(extmsg)//' dot_N_0_tr'
351  endif
352  else transactive
353  allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyrealarray)
354  allocate(prm%h_tr_tr(0,0))
355  endif transactive
356 
357 !--------------------------------------------------------------------------------------------------
358 ! shearband related parameters
359  prm%sbVelocity = config%getFloat('shearbandvelocity',defaultval=0.0_preal)
360  if (prm%sbVelocity > 0.0_preal) then
361  prm%sbResistance = config%getFloat('shearbandresistance')
362  prm%E_sb = config%getFloat('qedgepersbsystem')
363  prm%p_sb = config%getFloat('p_shearband')
364  prm%q_sb = config%getFloat('q_shearband')
365 
366  ! sanity checks
367  if (prm%sbResistance < 0.0_preal) extmsg = trim(extmsg)//' shearbandresistance'
368  if (prm%E_sb < 0.0_preal) extmsg = trim(extmsg)//' qedgepersbsystem'
369  if (prm%p_sb <= 0.0_preal) extmsg = trim(extmsg)//' p_shearband'
370  if (prm%q_sb <= 0.0_preal) extmsg = trim(extmsg)//' q_shearband'
371  endif
372 
373 !--------------------------------------------------------------------------------------------------
374 ! parameters required for several mechanisms and their interactions
375  if(prm%sum_N_sl + prm%sum_N_tw + prm%sum_N_tw > 0) &
376  prm%D = config%getFloat('grainsize')
377 
378  twinorslipactive: if (prm%sum_N_tw + prm%sum_N_tr > 0) then
379  prm%SFE_0K = config%getFloat('sfe_0k')
380  prm%dSFE_dT = config%getFloat('dsfe_dt')
381  prm%V_cs = config%getFloat('vcrossslip')
382  endif twinorslipactive
383 
384  slipandtwinactive: if (prm%sum_N_sl * prm%sum_N_tw > 0) then
385  prm%h_sl_tw = lattice_interaction_slipbytwin(n_sl,n_tw,&
386  config%getFloats('interaction_sliptwin'), &
387  config%getString('lattice_structure'))
388  if (prm%fccTwinTransNucleation .and. size(n_tw) /= 1) extmsg = trim(extmsg)//' interaction_sliptwin'
389  endif slipandtwinactive
390 
391  slipandtransactive: if (prm%sum_N_sl * prm%sum_N_tr > 0) then
392  prm%h_sl_tr = lattice_interaction_slipbytrans(n_sl,n_tr,&
393  config%getFloats('interaction_sliptrans'), &
394  config%getString('lattice_structure'))
395  if (prm%fccTwinTransNucleation .and. size(n_tr) /= 1) extmsg = trim(extmsg)//' interaction_sliptrans'
396  endif slipandtransactive
397 
398 !--------------------------------------------------------------------------------------------------
399 ! allocate state arrays
400  nipcmyphase = count(material_phaseat == p) * discretization_nip
401  sizedotstate = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl &
402  + size(['f_tw']) * prm%sum_N_tw &
403  + size(['f_tr']) * prm%sum_N_tr
404  sizestate = sizedotstate
405 
406  call material_allocateplasticstate(p,nipcmyphase,sizestate,sizedotstate,0)
407 
408 !--------------------------------------------------------------------------------------------------
409 ! locally defined state aliases and initialization of state0 and atol
410  startindex = 1
411  endindex = prm%sum_N_sl
412  stt%rho_mob=>plasticstate(p)%state(startindex:endindex,:)
413  stt%rho_mob= spread(rho_mob_0,2,nipcmyphase)
414  dot%rho_mob=>plasticstate(p)%dotState(startindex:endindex,:)
415  plasticstate(p)%atol(startindex:endindex) = config%getFloat('atol_rho',defaultval=1.0_preal)
416  if (any(plasticstate(p)%atol(startindex:endindex) < 0.0_preal)) extmsg = trim(extmsg)//' atol_rho'
417 
418  startindex = endindex + 1
419  endindex = endindex + prm%sum_N_sl
420  stt%rho_dip=>plasticstate(p)%state(startindex:endindex,:)
421  stt%rho_dip= spread(rho_dip_0,2,nipcmyphase)
422  dot%rho_dip=>plasticstate(p)%dotState(startindex:endindex,:)
423  plasticstate(p)%atol(startindex:endindex) = config%getFloat('atol_rho',defaultval=1.0_preal)
424 
425  startindex = endindex + 1
426  endindex = endindex + prm%sum_N_sl
427  stt%gamma_sl=>plasticstate(p)%state(startindex:endindex,:)
428  dot%gamma_sl=>plasticstate(p)%dotState(startindex:endindex,:)
429  plasticstate(p)%atol(startindex:endindex) = 1.0e-2_preal
430  ! global alias
431  plasticstate(p)%slipRate => plasticstate(p)%dotState(startindex:endindex,:)
432 
433  startindex = endindex + 1
434  endindex = endindex + prm%sum_N_tw
435  stt%f_tw=>plasticstate(p)%state(startindex:endindex,:)
436  dot%f_tw=>plasticstate(p)%dotState(startindex:endindex,:)
437  plasticstate(p)%atol(startindex:endindex) = config%getFloat('f_twin',defaultval=1.0e-7_preal)
438  if (any(plasticstate(p)%atol(startindex:endindex) < 0.0_preal)) extmsg = trim(extmsg)//' f_twin'
439 
440  startindex = endindex + 1
441  endindex = endindex + prm%sum_N_tr
442  stt%f_tr=>plasticstate(p)%state(startindex:endindex,:)
443  dot%f_tr=>plasticstate(p)%dotState(startindex:endindex,:)
444  plasticstate(p)%atol(startindex:endindex) = config%getFloat('f_trans',defaultval=1.0e-6_preal)
445  if (any(plasticstate(p)%atol(startindex:endindex) < 0.0_preal)) extmsg = trim(extmsg)//' f_trans'
446 
447  allocate(dst%Lambda_sl (prm%sum_N_sl,nipcmyphase),source=0.0_preal)
448  allocate(dst%tau_pass (prm%sum_N_sl,nipcmyphase),source=0.0_preal)
449 
450  allocate(dst%Lambda_tw (prm%sum_N_tw,nipcmyphase),source=0.0_preal)
451  allocate(dst%tau_hat_tw (prm%sum_N_tw,nipcmyphase),source=0.0_preal)
452  allocate(dst%tau_r_tw (prm%sum_N_tw,nipcmyphase),source=0.0_preal)
453  allocate(dst%V_tw (prm%sum_N_tw,nipcmyphase),source=0.0_preal)
454 
455  allocate(dst%Lambda_tr (prm%sum_N_tr,nipcmyphase),source=0.0_preal)
456  allocate(dst%tau_hat_tr (prm%sum_N_tr,nipcmyphase),source=0.0_preal)
457  allocate(dst%tau_r_tr (prm%sum_N_tr,nipcmyphase),source=0.0_preal)
458  allocate(dst%V_tr (prm%sum_N_tr,nipcmyphase),source=0.0_preal)
459 
460  plasticstate(p)%state0 = plasticstate(p)%state ! ToDo: this could be done centrally
461 
462  end associate
463 
464 !--------------------------------------------------------------------------------------------------
465 ! exit if any parameter is out of range
466  if (extmsg /= '') call io_error(211,ext_msg=trim(extmsg)//'('//plasticity_dislotwin_label//')')
467 
468  enddo
469 
470 end subroutine plastic_dislotwin_init
471 
472 
473 !--------------------------------------------------------------------------------------------------
475 !--------------------------------------------------------------------------------------------------
476 module function plastic_dislotwin_homogenizedc(ipc,ip,el) result(homogenizedc)
477 
478  real(pReal), dimension(6,6) :: &
479  homogenizedC
480  integer, intent(in) :: &
481  ipc, & !< component-ID of integration point
482  ip, & !< integration point
483  el
484 
485  integer :: i, &
486  of
487  real(pReal) :: f_unrotated
488 
489  of = material_phasememberat(ipc,ip,el)
490  associate(prm => param(phase_plasticityinstance(material_phaseat(ipc,el))),&
491  stt => state(phase_plasticityinstance(material_phaseat(ipc,el))))
492 
493  f_unrotated = 1.0_preal &
494  - sum(stt%f_tw(1:prm%sum_N_tw,of)) &
495  - sum(stt%f_tr(1:prm%sum_N_tr,of))
496 
497  homogenizedc = f_unrotated * prm%C66
498  do i=1,prm%sum_N_tw
499  homogenizedc = homogenizedc &
500  + stt%f_tw(i,of)*prm%C66_tw(1:6,1:6,i)
501  enddo
502  do i=1,prm%sum_N_tr
503  homogenizedc = homogenizedc &
504  + stt%f_tr(i,of)*prm%C66_tr(1:6,1:6,i)
505  enddo
506 
507  end associate
508 
509 end function plastic_dislotwin_homogenizedc
510 
511 
512 !--------------------------------------------------------------------------------------------------
514 !--------------------------------------------------------------------------------------------------
515 module subroutine plastic_dislotwin_lpanditstangent(lp,dlp_dmp,mp,t,instance,of)
516 
517  real(pReal), dimension(3,3), intent(out) :: Lp
518  real(pReal), dimension(3,3,3,3), intent(out) :: dLp_dMp
519  real(pReal), dimension(3,3), intent(in) :: Mp
520  integer, intent(in) :: instance,of
521  real(pReal), intent(in) :: T
522 
523  integer :: i,k,l,m,n
524  real(pReal) :: &
525  f_unrotated,StressRatio_p,&
526  BoltzmannRatio, &
527  ddot_gamma_dtau, &
528  tau
529  real(pReal), dimension(param(instance)%sum_N_sl) :: &
530  dot_gamma_sl,ddot_gamma_dtau_slip
531  real(pReal), dimension(param(instance)%sum_N_tw) :: &
532  dot_gamma_twin,ddot_gamma_dtau_twin
533  real(pReal), dimension(param(instance)%sum_N_tr) :: &
534  dot_gamma_tr,ddot_gamma_dtau_trans
535  real(pReal):: dot_gamma_sb
536  real(pReal), dimension(3,3) :: eigVectors, P_sb
537  real(pReal), dimension(3) :: eigValues
538  real(pReal), dimension(3,6), parameter :: &
539  sb_sComposition = &
540  reshape(real([&
541  1, 0, 1, &
542  1, 0,-1, &
543  1, 1, 0, &
544  1,-1, 0, &
545  0, 1, 1, &
546  0, 1,-1 &
547  ],preal),[ 3,6]), &
548  sb_mcomposition = &
549  reshape(real([&
550  1, 0,-1, &
551  1, 0,+1, &
552  1,-1, 0, &
553  1, 1, 0, &
554  0, 1,-1, &
555  0, 1, 1 &
556  ],preal),[ 3,6])
557 
558  associate(prm => param(instance), stt => state(instance))
559 
560  f_unrotated = 1.0_preal &
561  - sum(stt%f_tw(1:prm%sum_N_tw,of)) &
562  - sum(stt%f_tr(1:prm%sum_N_tr,of))
563 
564  lp = 0.0_preal
565  dlp_dmp = 0.0_preal
566 
567  call kinetics_slip(mp,t,instance,of,dot_gamma_sl,ddot_gamma_dtau_slip)
568  slipcontribution: do i = 1, prm%sum_N_sl
569  lp = lp + dot_gamma_sl(i)*prm%P_sl(1:3,1:3,i)
570  forall (k=1:3,l=1:3,m=1:3,n=1:3) &
571  dlp_dmp(k,l,m,n) = dlp_dmp(k,l,m,n) &
572  + ddot_gamma_dtau_slip(i) * prm%P_sl(k,l,i) * prm%P_sl(m,n,i)
573  enddo slipcontribution
574 
575  !ToDo: Why do this before shear banding?
576  lp = lp * f_unrotated
577  dlp_dmp = dlp_dmp * f_unrotated
578 
579  shearbandingcontribution: if(dneq0(prm%sbVelocity)) then
580 
581  boltzmannratio = prm%E_sb/(kb*t)
582  call math_eigh33(mp,eigvalues,eigvectors) ! is Mp symmetric by design?
583 
584  do i = 1,6
585  p_sb = 0.5_preal * math_outer(matmul(eigvectors,sb_scomposition(1:3,i)),&
586  matmul(eigvectors,sb_mcomposition(1:3,i)))
587  tau = math_tensordot(mp,p_sb)
588 
589  significantshearbandstress: if (abs(tau) > tol_math_check) then
590  stressratio_p = (abs(tau)/prm%sbResistance)**prm%p_sb
591  dot_gamma_sb = sign(prm%sbVelocity*exp(-boltzmannratio*(1-stressratio_p)**prm%q_sb), tau)
592  ddot_gamma_dtau = abs(dot_gamma_sb)*boltzmannratio* prm%p_sb*prm%q_sb/ prm%sbResistance &
593  * (abs(tau)/prm%sbResistance)**(prm%p_sb-1.0_preal) &
594  * (1.0_preal-stressratio_p)**(prm%q_sb-1.0_preal)
595 
596  lp = lp + dot_gamma_sb * p_sb
597  forall (k=1:3,l=1:3,m=1:3,n=1:3) &
598  dlp_dmp(k,l,m,n) = dlp_dmp(k,l,m,n) &
599  + ddot_gamma_dtau * p_sb(k,l) * p_sb(m,n)
600  endif significantshearbandstress
601  enddo
602 
603  endif shearbandingcontribution
604 
605  call kinetics_twin(mp,t,dot_gamma_sl,instance,of,dot_gamma_twin,ddot_gamma_dtau_twin)
606  twincontibution: do i = 1, prm%sum_N_tw
607  lp = lp + dot_gamma_twin(i)*prm%P_tw(1:3,1:3,i) * f_unrotated
608  forall (k=1:3,l=1:3,m=1:3,n=1:3) &
609  dlp_dmp(k,l,m,n) = dlp_dmp(k,l,m,n) &
610  + ddot_gamma_dtau_twin(i)* prm%P_tw(k,l,i)*prm%P_tw(m,n,i) * f_unrotated
611  enddo twincontibution
612 
613  call kinetics_trans(mp,t,dot_gamma_sl,instance,of,dot_gamma_tr,ddot_gamma_dtau_trans)
614  transcontibution: do i = 1, prm%sum_N_tr
615  lp = lp + dot_gamma_tr(i)*prm%P_tr(1:3,1:3,i) * f_unrotated
616  forall (k=1:3,l=1:3,m=1:3,n=1:3) &
617  dlp_dmp(k,l,m,n) = dlp_dmp(k,l,m,n) &
618  + ddot_gamma_dtau_trans(i)* prm%P_tr(k,l,i)*prm%P_tr(m,n,i) * f_unrotated
619  enddo transcontibution
620 
621 
622  end associate
623 
624 end subroutine plastic_dislotwin_lpanditstangent
625 
626 
627 !--------------------------------------------------------------------------------------------------
629 !--------------------------------------------------------------------------------------------------
630 module subroutine plastic_dislotwin_dotstate(mp,t,instance,of)
631 
632  real(pReal), dimension(3,3), intent(in):: &
633  Mp
634  real(pReal), intent(in) :: &
635  T
636  integer, intent(in) :: &
637  instance, &
638  of
639 
640  integer :: i
641  real(pReal) :: &
642  f_unrotated, &
643  rho_dip_distance, &
644  v_cl, & !< climb velocity
645  Gamma, & !< stacking fault energy
646  tau, &
647  sigma_cl, & !< climb stress
648  b_d
649  real(pReal), dimension(param(instance)%sum_N_sl) :: &
650  dot_rho_dip_formation, &
651  dot_rho_dip_climb, &
652  rho_dip_distance_min, &
653  dot_gamma_sl
654  real(pReal), dimension(param(instance)%sum_N_tw) :: &
655  dot_gamma_twin
656  real(pReal), dimension(param(instance)%sum_N_tr) :: &
657  dot_gamma_tr
658 
659  associate(prm => param(instance), stt => state(instance), &
660  dot => dotstate(instance), dst => dependentstate(instance))
661 
662  f_unrotated = 1.0_preal &
663  - sum(stt%f_tw(1:prm%sum_N_tw,of)) &
664  - sum(stt%f_tr(1:prm%sum_N_tr,of))
665 
666  call kinetics_slip(mp,t,instance,of,dot_gamma_sl)
667  dot%gamma_sl(:,of) = abs(dot_gamma_sl)
668 
669  rho_dip_distance_min = prm%CEdgeDipMinDistance*prm%b_sl
670 
671  slipstate: do i = 1, prm%sum_N_sl
672  tau = math_tensordot(mp,prm%P_sl(1:3,1:3,i))
673 
674  significantslipstress: if (deq0(tau)) then
675  dot_rho_dip_formation(i) = 0.0_preal
676  dot_rho_dip_climb(i) = 0.0_preal
677  else significantslipstress
678  rho_dip_distance = 3.0_preal*prm%mu*prm%b_sl(i)/(16.0_preal*pi*abs(tau))
679  rho_dip_distance = math_clip(rho_dip_distance, right = dst%Lambda_sl(i,of))
680  rho_dip_distance = math_clip(rho_dip_distance, left = rho_dip_distance_min(i))
681 
682  if (prm%dipoleFormation) then
683  dot_rho_dip_formation(i) = 2.0_preal*(rho_dip_distance-rho_dip_distance_min(i))/prm%b_sl(i) &
684  * stt%rho_mob(i,of)*abs(dot_gamma_sl(i))
685  else
686  dot_rho_dip_formation(i) = 0.0_preal
687  endif
688 
689  if (deq(rho_dip_distance,rho_dip_distance_min(i))) then
690  dot_rho_dip_climb(i) = 0.0_preal
691  else
692  !@details: Refer: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981
693  sigma_cl = dot_product(prm%n0_sl(1:3,i),matmul(mp,prm%n0_sl(1:3,i)))
694  if (prm%ExtendedDislocations) then
695  gamma = prm%SFE_0K + prm%dSFE_dT * t
696  b_d = 24.0_preal*pi*(1.0_preal - prm%nu)/(2.0_preal + prm%nu)* gamma/(prm%mu*prm%b_sl(i))
697  else
698  b_d = 1.0_preal
699  endif
700  v_cl = 2.0_preal*prm%omega*b_d**2.0_preal*exp(-prm%Qsd/(kb*t)) &
701  * (exp(abs(sigma_cl)*prm%b_sl(i)**3.0_preal/(kb*t)) - 1.0_preal)
702 
703  dot_rho_dip_climb(i) = 4.0_preal*v_cl*stt%rho_dip(i,of) &
704  / (rho_dip_distance-rho_dip_distance_min(i))
705  endif
706  endif significantslipstress
707  enddo slipstate
708 
709  dot%rho_mob(:,of) = abs(dot_gamma_sl)/(prm%b_sl*dst%Lambda_sl(:,of)) &
710  - dot_rho_dip_formation &
711  - 2.0_preal*rho_dip_distance_min/prm%b_sl * stt%rho_mob(:,of)*abs(dot_gamma_sl)
712 
713  dot%rho_dip(:,of) = dot_rho_dip_formation &
714  - 2.0_preal*rho_dip_distance_min/prm%b_sl * stt%rho_dip(:,of)*abs(dot_gamma_sl) &
715  - dot_rho_dip_climb
716 
717  call kinetics_twin(mp,t,dot_gamma_sl,instance,of,dot_gamma_twin)
718  dot%f_tw(:,of) = f_unrotated*dot_gamma_twin/prm%gamma_char
719 
720  call kinetics_trans(mp,t,dot_gamma_sl,instance,of,dot_gamma_tr)
721  dot%f_tr(:,of) = f_unrotated*dot_gamma_tr
722 
723  end associate
724 
725 end subroutine plastic_dislotwin_dotstate
726 
727 
728 !--------------------------------------------------------------------------------------------------
730 !--------------------------------------------------------------------------------------------------
731 module subroutine plastic_dislotwin_dependentstate(t,instance,of)
732 
733  integer, intent(in) :: &
734  instance, &
735  of
736  real(pReal), intent(in) :: &
737  T
738 
739  real(pReal) :: &
740  sumf_twin,Gamma,sumf_trans
741  real(pReal), dimension(param(instance)%sum_N_sl) :: &
742  inv_lambda_sl_sl, & !< 1/mean free distance between 2 forest dislocations seen by a moving dislocation
743  inv_lambda_sl_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a moving dislocation
744  inv_lambda_sl_tr
745  real(pReal), dimension(param(instance)%sum_N_tw) :: &
746  inv_lambda_tw_tw, & !< 1/mean free distance between 2 twin stacks from different systems seen by a growing twin
747  f_over_t_tw
748  real(pReal), dimension(param(instance)%sum_N_tr) :: &
749  inv_lambda_tr_tr, & !< 1/mean free distance between 2 martensite stacks from different systems seen by a growing martensite
750  f_over_t_tr
751  real(pReal), dimension(:), allocatable :: &
752  x0
753 
754 
755  associate(prm => param(instance),&
756  stt => state(instance),&
757  dst => dependentstate(instance))
758 
759  sumf_twin = sum(stt%f_tw(1:prm%sum_N_tw,of))
760  sumf_trans = sum(stt%f_tr(1:prm%sum_N_tr,of))
761 
762  gamma = prm%SFE_0K + prm%dSFE_dT * t
763 
764  !* rescaled volume fraction for topology
765  f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,of)/prm%t_tw ! this is per system ...
766  f_over_t_tr = sumf_trans/prm%t_tr ! but this not
767  ! ToDo ...Physically correct, but naming could be adjusted
768 
769  inv_lambda_sl_sl = sqrt(matmul(prm%forestProjection, &
770  stt%rho_mob(:,of)+stt%rho_dip(:,of)))/prm%CLambdaSlip
771 
772  if (prm%sum_N_tw > 0 .and. prm%sum_N_sl > 0) &
773  inv_lambda_sl_tw = matmul(prm%h_sl_tw,f_over_t_tw)/(1.0_preal-sumf_twin)
774 
775  inv_lambda_tw_tw = matmul(prm%h_tw_tw,f_over_t_tw)/(1.0_preal-sumf_twin)
776 
777  if (prm%sum_N_tr > 0 .and. prm%sum_N_sl > 0) &
778  inv_lambda_sl_tr = matmul(prm%h_sl_tr,f_over_t_tr)/(1.0_preal-sumf_trans)
779 
780  inv_lambda_tr_tr = matmul(prm%h_tr_tr,f_over_t_tr)/(1.0_preal-sumf_trans)
781 
782  if ((prm%sum_N_tw > 0) .or. (prm%sum_N_tr > 0)) then ! ToDo: better logic needed here
783  dst%Lambda_sl(:,of) = prm%D &
784  / (1.0_preal+prm%D*(inv_lambda_sl_sl + inv_lambda_sl_tw + inv_lambda_sl_tr))
785  else
786  dst%Lambda_sl(:,of) = prm%D &
787  / (1.0_preal+prm%D*inv_lambda_sl_sl) !!!!!! correct?
788  endif
789 
790  dst%Lambda_tw(:,of) = prm%i_tw*prm%D/(1.0_preal+prm%D*inv_lambda_tw_tw)
791  dst%Lambda_tr(:,of) = prm%i_tr*prm%D/(1.0_preal+prm%D*inv_lambda_tr_tr)
792 
793  !* threshold stress for dislocation motion
794  dst%tau_pass(:,of) = prm%mu*prm%b_sl* sqrt(matmul(prm%h_sl_sl,stt%rho_mob(:,of)+stt%rho_dip(:,of)))
795 
796  !* threshold stress for growing twin/martensite
797  if(prm%sum_N_tw == prm%sum_N_sl) &
798  dst%tau_hat_tw(:,of) = gamma/(3.0_preal*prm%b_tw) &
799  + 3.0_preal*prm%b_tw*prm%mu/(prm%L_tw*prm%b_sl) ! slip burgers here correct?
800  if(prm%sum_N_tr == prm%sum_N_sl) &
801  dst%tau_hat_tr(:,of) = gamma/(3.0_preal*prm%b_tr) &
802  + 3.0_preal*prm%b_tr*prm%mu/(prm%L_tr*prm%b_sl) & ! slip burgers here correct?
803  + prm%h*prm%gamma_fcc_hex/ (3.0_preal*prm%b_tr)
804 
805  dst%V_tw(:,of) = (pi/4.0_preal)*prm%t_tw*dst%Lambda_tw(:,of)**2.0_preal
806  dst%V_tr(:,of) = (pi/4.0_preal)*prm%t_tr*dst%Lambda_tr(:,of)**2.0_preal
807 
808 
809  x0 = prm%mu*prm%b_tw**2.0_preal/(gamma*8.0_preal*pi)*(2.0_preal+prm%nu)/(1.0_preal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip and is the same for twin and trans
810  dst%tau_r_tw(:,of) = prm%mu*prm%b_tw/(2.0_preal*pi)*(1.0_preal/(x0+prm%xc_twin)+cos(pi/3.0_preal)/x0)
811 
812  x0 = prm%mu*prm%b_tr**2.0_preal/(gamma*8.0_preal*pi)*(2.0_preal+prm%nu)/(1.0_preal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip
813  dst%tau_r_tr(:,of) = prm%mu*prm%b_tr/(2.0_preal*pi)*(1.0_preal/(x0+prm%xc_trans)+cos(pi/3.0_preal)/x0)
814 
815  end associate
816 
817 end subroutine plastic_dislotwin_dependentstate
818 
819 
820 !--------------------------------------------------------------------------------------------------
822 !--------------------------------------------------------------------------------------------------
823 module subroutine plastic_dislotwin_results(instance,group)
824 
825  integer, intent(in) :: instance
826  character(len=*), intent(in) :: group
827 
828  integer :: o
829 
830  associate(prm => param(instance), stt => state(instance), dst => dependentstate(instance))
831  outputsloop: do o = 1,size(prm%output)
832  select case(trim(prm%output(o)))
833 
834  case('rho_mob')
835  if(prm%sum_N_sl>0) call results_writedataset(group,stt%rho_mob,'rho_mob',&
836  'mobile dislocation density','1/m²')
837  case('rho_dip')
838  if(prm%sum_N_sl>0) call results_writedataset(group,stt%rho_dip,'rho_dip',&
839  'dislocation dipole density''1/m²')
840  case('gamma_sl')
841  if(prm%sum_N_sl>0) call results_writedataset(group,stt%gamma_sl,'gamma_sl',&
842  'plastic shear','1')
843  case('lambda_sl')
844  if(prm%sum_N_sl>0) call results_writedataset(group,dst%Lambda_sl,'Lambda_sl',&
845  'mean free path for slip','m')
846  case('tau_pass')
847  if(prm%sum_N_sl>0) call results_writedataset(group,dst%tau_pass,'tau_pass',&
848  'passing stress for slip','Pa')
849 
850  case('f_tw')
851  if(prm%sum_N_tw>0) call results_writedataset(group,stt%f_tw,'f_tw',&
852  'twinned volume fraction','m³/m³')
853  case('lambda_tw')
854  if(prm%sum_N_tw>0) call results_writedataset(group,dst%Lambda_tw,'Lambda_tw',&
855  'mean free path for twinning','m')
856  case('tau_hat_tw')
857  if(prm%sum_N_tw>0) call results_writedataset(group,dst%tau_hat_tw,'tau_hat_tw',&
858  'threshold stress for twinning','Pa')
859 
860  case('f_tr')
861  if(prm%sum_N_tr>0) call results_writedataset(group,stt%f_tr,'f_tr',&
862  'martensite volume fraction','m³/m³')
863 
864  end select
865  enddo outputsloop
866  end associate
867 
868 end subroutine plastic_dislotwin_results
869 
870 
871 !--------------------------------------------------------------------------------------------------
873 ! stress, and the resolved stress.
875 ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
876 ! have the optional arguments at the end
877 !--------------------------------------------------------------------------------------------------
878 pure subroutine kinetics_slip(Mp,T,instance,of, &
879  dot_gamma_sl,ddot_gamma_dtau_slip,tau_slip)
880 
881  real(pReal), dimension(3,3), intent(in) :: &
882  Mp
883  real(pReal), intent(in) :: &
884  T
885  integer, intent(in) :: &
886  instance, &
887  of
888 
889  real(pReal), dimension(param(instance)%sum_N_sl), intent(out) :: &
890  dot_gamma_sl
891  real(pReal), dimension(param(instance)%sum_N_sl), optional, intent(out) :: &
892  ddot_gamma_dtau_slip, &
893  tau_slip
894  real(pReal), dimension(param(instance)%sum_N_sl) :: &
895  ddot_gamma_dtau
896 
897  real(pReal), dimension(param(instance)%sum_N_sl) :: &
898  tau, &
899  stressRatio, &
900  StressRatio_p, &
901  BoltzmannRatio, &
902  v_wait_inverse, & !< inverse of the effective velocity of a dislocation waiting at obstacles (unsigned)
903  v_run_inverse, & !< inverse of the velocity of a free moving dislocation (unsigned)
904  dV_wait_inverse_dTau, &
905  dV_run_inverse_dTau, &
906  dV_dTau, &
907  tau_eff
908  integer :: i
909 
910  associate(prm => param(instance), stt => state(instance), dst => dependentstate(instance))
911 
912  do i = 1, prm%sum_N_sl
913  tau(i) = math_tensordot(mp,prm%P_sl(1:3,1:3,i))
914  enddo
915 
916  tau_eff = abs(tau)-dst%tau_pass(:,of)
917 
918  significantstress: where(tau_eff > tol_math_check)
919  stressratio = tau_eff/prm%tau_0
920  stressratio_p = stressratio** prm%p
921  boltzmannratio = prm%Delta_F/(kb*t)
922  v_wait_inverse = prm%v0**(-1.0_preal) * exp(boltzmannratio*(1.0_preal-stressratio_p)** prm%q)
923  v_run_inverse = prm%B/(tau_eff*prm%b_sl)
924 
925  dot_gamma_sl = sign(stt%rho_mob(:,of)*prm%b_sl/(v_wait_inverse+v_run_inverse),tau)
926 
927  dv_wait_inverse_dtau = -1.0_preal * v_wait_inverse * prm%p * prm%q * boltzmannratio &
928  * (stressratio**(prm%p-1.0_preal)) &
929  * (1.0_preal-stressratio_p)**(prm%q-1.0_preal) &
930  / prm%tau_0
931  dv_run_inverse_dtau = -1.0_preal * v_run_inverse/tau_eff
932  dv_dtau = -1.0_preal * (dv_wait_inverse_dtau+dv_run_inverse_dtau) &
933  / (v_wait_inverse+v_run_inverse)**2.0_preal
934  ddot_gamma_dtau = dv_dtau*stt%rho_mob(:,of)*prm%b_sl
935  else where significantstress
936  dot_gamma_sl = 0.0_preal
937  ddot_gamma_dtau = 0.0_preal
938  end where significantstress
939 
940  end associate
941 
942  if(present(ddot_gamma_dtau_slip)) ddot_gamma_dtau_slip = ddot_gamma_dtau
943  if(present(tau_slip)) tau_slip = tau
944 
945 end subroutine kinetics_slip
946 
947 
948 !--------------------------------------------------------------------------------------------------
950 ! stress.
952 ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
953 ! have the optional arguments at the end.
954 !--------------------------------------------------------------------------------------------------
955 pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,&
956  dot_gamma_twin,ddot_gamma_dtau_twin)
957 
958  real(pReal), dimension(3,3), intent(in) :: &
959  Mp
960  real(pReal), intent(in) :: &
961  T
962  integer, intent(in) :: &
963  instance, &
964  of
965  real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: &
966  dot_gamma_sl
967 
968  real(pReal), dimension(param(instance)%sum_N_tw), intent(out) :: &
969  dot_gamma_twin
970  real(pReal), dimension(param(instance)%sum_N_tw), optional, intent(out) :: &
971  ddot_gamma_dtau_twin
972 
973  real, dimension(param(instance)%sum_N_tw) :: &
974  tau, &
975  Ndot0, &
976  stressRatio_r, &
977  ddot_gamma_dtau
978 
979  integer :: i,s1,s2
980 
981  associate(prm => param(instance), stt => state(instance), dst => dependentstate(instance))
982 
983  do i = 1, prm%sum_N_tw
984  tau(i) = math_tensordot(mp,prm%P_tw(1:3,1:3,i))
985  isfcc: if (prm%fccTwinTransNucleation) then
986  s1=prm%fcc_twinNucleationSlipPair(1,i)
987  s2=prm%fcc_twinNucleationSlipPair(2,i)
988  if (tau(i) < dst%tau_r_tw(i,of)) then ! ToDo: correct?
989  ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+&
990  abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state
991  (prm%L_tw*prm%b_sl(i))*&
992  (1.0_preal-exp(-prm%V_cs/(kb*t)*(dst%tau_r_tw(i,of)-tau(i)))) ! P_ncs
993  else
994  ndot0=0.0_preal
995  end if
996  else isfcc
997  ndot0=prm%dot_N_0_tw(i)
998  endif isfcc
999  enddo
1000 
1001  significantstress: where(tau > tol_math_check)
1002  stressratio_r = (dst%tau_hat_tw(:,of)/tau)**prm%r
1003  dot_gamma_twin = prm%gamma_char * dst%V_tw(:,of) * ndot0*exp(-stressratio_r)
1004  ddot_gamma_dtau = (dot_gamma_twin*prm%r/tau)*stressratio_r
1005  else where significantstress
1006  dot_gamma_twin = 0.0_preal
1007  ddot_gamma_dtau = 0.0_preal
1008  end where significantstress
1009 
1010  end associate
1011 
1012  if(present(ddot_gamma_dtau_twin)) ddot_gamma_dtau_twin = ddot_gamma_dtau
1013 
1014 end subroutine kinetics_twin
1015 
1016 
1017 !--------------------------------------------------------------------------------------------------
1019 ! resolved stress.
1021 ! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to
1022 ! have the optional arguments at the end.
1023 !--------------------------------------------------------------------------------------------------
1024 pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,&
1025  dot_gamma_tr,ddot_gamma_dtau_trans)
1026 
1027  real(pReal), dimension(3,3), intent(in) :: &
1028  Mp
1029  real(pReal), intent(in) :: &
1030  T
1031  integer, intent(in) :: &
1032  instance, &
1033  of
1034  real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: &
1035  dot_gamma_sl
1036 
1037  real(pReal), dimension(param(instance)%sum_N_tr), intent(out) :: &
1038  dot_gamma_tr
1039  real(pReal), dimension(param(instance)%sum_N_tr), optional, intent(out) :: &
1040  ddot_gamma_dtau_trans
1041 
1042  real, dimension(param(instance)%sum_N_tr) :: &
1043  tau, &
1044  Ndot0, &
1045  stressRatio_s, &
1046  ddot_gamma_dtau
1047 
1048  integer :: i,s1,s2
1049  associate(prm => param(instance), stt => state(instance), dst => dependentstate(instance))
1050 
1051  do i = 1, prm%sum_N_tr
1052  tau(i) = math_tensordot(mp,prm%P_tr(1:3,1:3,i))
1053  isfcc: if (prm%fccTwinTransNucleation) then
1054  s1=prm%fcc_twinNucleationSlipPair(1,i)
1055  s2=prm%fcc_twinNucleationSlipPair(2,i)
1056  if (tau(i) < dst%tau_r_tr(i,of)) then ! ToDo: correct?
1057  ndot0=(abs(dot_gamma_sl(s1))*(stt%rho_mob(s2,of)+stt%rho_dip(s2,of))+&
1058  abs(dot_gamma_sl(s2))*(stt%rho_mob(s1,of)+stt%rho_dip(s1,of)))/& ! ToDo: MD: it would be more consistent to use shearrates from state
1059  (prm%L_tr*prm%b_sl(i))*&
1060  (1.0_preal-exp(-prm%V_cs/(kb*t)*(dst%tau_r_tr(i,of)-tau(i)))) ! P_ncs
1061  else
1062  ndot0=0.0_preal
1063  end if
1064  else isfcc
1065  ndot0=prm%dot_N_0_tr(i)
1066  endif isfcc
1067  enddo
1068 
1069  significantstress: where(tau > tol_math_check)
1070  stressratio_s = (dst%tau_hat_tr(:,of)/tau)**prm%s
1071  dot_gamma_tr = dst%V_tr(:,of) * ndot0*exp(-stressratio_s)
1072  ddot_gamma_dtau = (dot_gamma_tr*prm%s/tau)*stressratio_s
1073  else where significantstress
1074  dot_gamma_tr = 0.0_preal
1075  ddot_gamma_dtau = 0.0_preal
1076  end where significantstress
1077 
1078  end associate
1079 
1080  if(present(ddot_gamma_dtau_trans)) ddot_gamma_dtau_trans = ddot_gamma_dtau
1081 
1082 end subroutine kinetics_trans
1083 
1084 end submodule plastic_dislotwin
config
Reads in the material configuration from file.
Definition: config.f90:13
constitutive
elasticity, plasticity, internal microstructure state
Definition: constitutive.f90:10