From 1657e0f7ba2769fa47414c0a03ae979ec2fa1ba4 Mon Sep 17 00:00:00 2001 From: Luv Sharma Date: Fri, 10 Oct 2014 12:42:12 +0000 Subject: [PATCH] started implementing a void fraction based ductile damage model. --- code/DAMASK_abaqus_exp.f | 1 + code/DAMASK_abaqus_std.f | 1 + code/DAMASK_marc.f90 | 1 + code/DAMASK_spectral_interface.f90 | 2 +- code/Makefile | 5 +- code/constitutive.f90 | 86 ++++-- code/damage_gurson.f90 | 410 +++++++++++++++++++++++++++++ code/material.f90 | 13 +- 8 files changed, 489 insertions(+), 30 deletions(-) create mode 100644 code/damage_gurson.f90 diff --git a/code/DAMASK_abaqus_exp.f b/code/DAMASK_abaqus_exp.f index c5e665444..37c9e5c17 100644 --- a/code/DAMASK_abaqus_exp.f +++ b/code/DAMASK_abaqus_exp.f @@ -85,6 +85,7 @@ end module DAMASK_interface #include "damage_none.f90" #include "damage_brittle.f90" #include "damage_ductile.f90" +#include "damage_gurson.f90" #include "thermal_isothermal.f90" #include "thermal_adiabatic.f90" #include "constitutive_none.f90" diff --git a/code/DAMASK_abaqus_std.f b/code/DAMASK_abaqus_std.f index 587ef46bc..a87e95f2f 100644 --- a/code/DAMASK_abaqus_std.f +++ b/code/DAMASK_abaqus_std.f @@ -85,6 +85,7 @@ end module DAMASK_interface #include "damage_none.f90" #include "damage_brittle.f90" #include "damage_ductile.f90" +#include "damage_gurson.f90" #include "thermal_isothermal.f90" #include "thermal_adiabatic.f90" #include "constitutive_none.f90" diff --git a/code/DAMASK_marc.f90 b/code/DAMASK_marc.f90 index 59ce0da40..5924547b8 100644 --- a/code/DAMASK_marc.f90 +++ b/code/DAMASK_marc.f90 @@ -114,6 +114,7 @@ end module DAMASK_interface #include "damage_none.f90" #include "damage_brittle.f90" #include "damage_ductile.f90" +#include "damage_gurson.f90" #include "thermal_isothermal.f90" #include "thermal_adiabatic.f90" #include "constitutive_none.f90" diff --git a/code/DAMASK_spectral_interface.f90 b/code/DAMASK_spectral_interface.f90 index e4bfec60e..782f5eca3 100644 --- a/code/DAMASK_spectral_interface.f90 +++ b/code/DAMASK_spectral_interface.f90 @@ -9,7 +9,7 @@ !> by DAMASK. Interpretating the command line arguments or, in case of called from f2py, !> the arguments parsed to the init routine to get load case, geometry file, working !> directory, etc. -!-------------------------------------------------------------------------------------------------- +!-----------------------------------------------------------`--------------------------------------- module DAMASK_interface use prec, only: & pInt diff --git a/code/Makefile b/code/Makefile index 5d28db6bf..5ee266fd9 100644 --- a/code/Makefile +++ b/code/Makefile @@ -326,7 +326,7 @@ COMPILE =$(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATI COMPILE_MAXOPTI =$(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90)) ################################################################################################### DAMAGE_FILES = \ - damage_none.o damage_brittle.o damage_ductile.o + damage_none.o damage_brittle.o damage_ductile.o damage_gurson.o THERMAL_FILES = \ thermal_isothermal.o thermal_adiabatic.o @@ -482,6 +482,9 @@ damage_brittle.o: damage_brittle.f90 \ damage_ductile.o: damage_ductile.f90 \ lattice.o + +damage_gurson.o: damage_gurson.f90 \ + lattice.o thermal_isothermal.o: thermal_isothermal.f90 \ lattice.o diff --git a/code/constitutive.f90 b/code/constitutive.f90 index 882e52e96..4e24bec64 100644 --- a/code/constitutive.f90 +++ b/code/constitutive.f90 @@ -112,13 +112,15 @@ subroutine constitutive_init LOCAL_DAMAGE_none_ID, & LOCAL_DAMAGE_brittle_ID, & LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID, & LOCAL_THERMAL_isothermal_ID, & LOCAL_THERMAL_adiabatic_ID, & LOCAL_DAMAGE_NONE_label, & - LOCAL_DAMAGE_BRITTLE_label, & - LOCAL_DAMAGE_DUCTILE_label, & - LOCAL_THERMAL_ISOTHERMAL_label, & - LOCAL_THERMAL_ADIABATIC_label, & + LOCAL_DAMAGE_brittle_label, & + LOCAL_DAMAGE_ductile_label, & + LOCAL_DAMAGE_gurson_label, & + LOCAL_THERMAL_isothermal_label, & + LOCAL_THERMAL_adiabatic_label, & plasticState, & damageState, & thermalState, & @@ -135,6 +137,7 @@ subroutine constitutive_init use damage_none use damage_brittle use damage_ductile + use damage_gurson use thermal_isothermal use thermal_adiabatic implicit none @@ -171,9 +174,10 @@ subroutine constitutive_init ! parse damage from config file if (.not. IO_open_jobFile_stat(FILEUNIT,material_localFileExt)) & ! no local material configuration present... call IO_open_file(FILEUNIT,material_configFile) ! ... open material.config file - if (any(phase_damage == LOCAL_DAMAGE_NONE_ID)) call damage_none_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_BRITTLE_ID)) call damage_brittle_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_DUCTILE_ID)) call damage_ductile_init(FILEUNIT) + if (any(phase_damage == LOCAL_DAMAGE_none_ID)) call damage_none_init(FILEUNIT) + if (any(phase_damage == LOCAL_DAMAGE_brittle_ID)) call damage_brittle_init(FILEUNIT) + if (any(phase_damage == LOCAL_DAMAGE_ductile_ID)) call damage_ductile_init(FILEUNIT) + if (any(phase_damage == LOCAL_DAMAGE_gurson_ID)) call damage_gurson_init(FILEUNIT) close(FILEUNIT) !-------------------------------------------------------------------------------------------------- @@ -258,16 +262,21 @@ subroutine constitutive_init thisNoutput => null() thisOutput => null() thisSize => null() - case (LOCAL_DAMAGE_BRITTLE_ID) + case (LOCAL_DAMAGE_brittle_ID) outputName = LOCAL_DAMAGE_BRITTLE_label thisNoutput => damage_brittle_Noutput thisOutput => damage_brittle_output thisSize => damage_brittle_sizePostResult - case (LOCAL_DAMAGE_DUCTILE_ID) + case (LOCAL_DAMAGE_ductile_ID) outputName = LOCAL_DAMAGE_DUCTILE_label thisNoutput => damage_ductile_Noutput thisOutput => damage_ductile_output thisSize => damage_ductile_sizePostResult + case (LOCAL_DAMAGE_gurson_ID) + outputName = LOCAL_DAMAGE_gurson_label + thisNoutput => damage_gurson_Noutput + thisOutput => damage_gurson_output + thisSize => damage_gurson_sizePostResult case default knownDamage = .false. end select @@ -425,12 +434,13 @@ subroutine constitutive_microstructure(Tstar_v, Fe, Fp, ipc, ip, el) phase_plasticity, & phase_damage, & material_phase, & - PLASTICITY_DISLOTWIN_ID, & - PLASTICITY_DISLOKMC_ID, & - PLASTICITY_TITANMOD_ID, & - PLASTICITY_NONLOCAL_ID, & - LOCAL_DAMAGE_BRITTLE_ID, & - LOCAL_DAMAGE_DUCTILE_ID + PLASTICITY_dislotwin_ID, & + PLASTICITY_dislokmc_ID, & + PLASTICITY_titanmod_ID, & + PLASTICITY_nonlocal_ID, & + LOCAL_DAMAGE_brittle_ID, & + LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID use constitutive_titanmod, only: & constitutive_titanmod_microstructure @@ -444,6 +454,8 @@ subroutine constitutive_microstructure(Tstar_v, Fe, Fp, ipc, ip, el) damage_brittle_microstructure use damage_ductile, only: & damage_ductile_microstructure + use damage_gurson, only: & + damage_gurson_microstructure implicit none integer(pInt), intent(in) :: & @@ -473,12 +485,17 @@ subroutine constitutive_microstructure(Tstar_v, Fe, Fp, ipc, ip, el) end select select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_BRITTLE_ID) + case (LOCAL_DAMAGE_brittle_ID) + damage = constitutive_getDamage(ipc,ip,el) + Tstar_v_effective = Tstar_v/(damage*damage) damage = constitutive_getDamage(ipc,ip,el) Tstar_v_effective = Tstar_v/(damage*damage) call damage_brittle_microstructure(Tstar_v_effective, Fe, ipc, ip, el) - case (LOCAL_DAMAGE_DUCTILE_ID) + case (LOCAL_DAMAGE_ductile_ID) call damage_ductile_microstructure(ipc, ip, el) + case (LOCAL_DAMAGE_gurson_ID) + call damage_gurson_microstructure(ipc, ip, el) + end select @@ -667,6 +684,7 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su PLASTICITY_nonlocal_ID, & LOCAL_DAMAGE_brittle_ID, & LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID, & LOCAL_THERMAL_adiabatic_ID use constitutive_j2, only: & constitutive_j2_dotState @@ -684,6 +702,8 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su damage_brittle_dotState use damage_ductile, only: & damage_ductile_dotState + use damage_gurson, only: & + damage_gurson_dotState use thermal_adiabatic, only: & thermal_adiabatic_dotState @@ -728,11 +748,12 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su end select select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_BRITTLE_ID) + case (LOCAL_DAMAGE_brittle_ID) call damage_brittle_dotState(ipc, ip, el) - case (LOCAL_DAMAGE_DUCTILE_ID) + case (LOCAL_DAMAGE_ductile_ID) call damage_ductile_dotState(Lp, ipc, ip, el) - + case (LOCAL_DAMAGE_gurson_ID) + call damage_gurson_dotState(Lp, ipc, ip, el) end select select case (phase_thermal(material_phase(ipc,ip,el))) @@ -821,13 +842,16 @@ function constitutive_getLocalDamage(ipc, ip, el) use material, only: & material_phase, & LOCAL_DAMAGE_none_ID, & - LOCAL_DAMAGE_BRITTLE_ID, & - LOCAL_DAMAGE_DUCTILE_ID, & + LOCAL_DAMAGE_brittle_ID, & + LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID, & phase_damage use damage_brittle, only: & constitutive_brittle_getDamage use damage_ductile, only: & constitutive_ductile_getDamage + use damage_gurson, only: & + constitutive_gurson_getDamage implicit none integer(pInt), intent(in) :: & @@ -840,11 +864,14 @@ function constitutive_getLocalDamage(ipc, ip, el) case (LOCAL_DAMAGE_none_ID) constitutive_getLocalDamage = 1.0_pReal - case (LOCAL_DAMAGE_BRITTLE_ID) + case (LOCAL_DAMAGE_brittle_ID) constitutive_getLocalDamage = constitutive_brittle_getDamage(ipc, ip, el) - case (LOCAL_DAMAGE_DUCTILE_ID) + case (LOCAL_DAMAGE_ductile_ID) constitutive_getLocalDamage = constitutive_ductile_getDamage(ipc, ip, el) + + case (LOCAL_DAMAGE_gurson_ID) + constitutive_getLocalDamage = constitutive_gurson_getDamage(ipc, ip, el) end select end function constitutive_getLocalDamage @@ -859,11 +886,14 @@ subroutine constitutive_putLocalDamage(ipc, ip, el, localDamage) material_phase, & LOCAL_DAMAGE_BRITTLE_ID, & LOCAL_DAMAGE_DUCTILE_ID, & + LOCAL_DAMAGE_gurson_ID, & phase_damage use damage_brittle, only: & constitutive_brittle_putDamage use damage_ductile, only: & constitutive_ductile_putDamage + use damage_gurson, only: & + constitutive_gurson_putDamage implicit none integer(pInt), intent(in) :: & @@ -879,6 +909,9 @@ subroutine constitutive_putLocalDamage(ipc, ip, el, localDamage) case (LOCAL_DAMAGE_DUCTILE_ID) call constitutive_ductile_putDamage(ipc, ip, el, localDamage) + + case (LOCAL_DAMAGE_gurson_ID) + call constitutive_gurson_putDamage(ipc, ip, el, localDamage) end select @@ -1041,6 +1074,7 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) PLASTICITY_NONLOCAL_ID, & LOCAL_DAMAGE_BRITTLE_ID, & LOCAL_DAMAGE_DUCTILE_ID, & + LOCAL_DAMAGE_gurson_ID, & LOCAL_THERMAL_ADIABATIC_ID use constitutive_j2, only: & #ifdef HDF @@ -1062,6 +1096,8 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) damage_brittle_postResults use damage_ductile, only: & damage_ductile_postResults + use damage_gurson, only: & + damage_gurson_postResults use thermal_adiabatic, only: & thermal_adiabatic_postResults #endif @@ -1121,6 +1157,8 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) constitutive_postResults(startPos:endPos) = damage_brittle_postResults(ipc, ip, el) case (LOCAL_DAMAGE_DUCTILE_ID) constitutive_postResults(startPos:endPos) = damage_ductile_postResults(ipc, ip, el) + case (LOCAL_DAMAGE_gurson_ID) + constitutive_postResults(startPos:endPos) = damage_gurson_postResults(ipc, ip, el) end select startPos = endPos + 1_pInt diff --git a/code/damage_gurson.f90 b/code/damage_gurson.f90 new file mode 100644 index 000000000..d0257b1b8 --- /dev/null +++ b/code/damage_gurson.f90 @@ -0,0 +1,410 @@ +!-------------------------------------------------------------------------------------------------- +! $Id: damage_gurson.f90 3210 2014-06-17 15:24:44Z MPIE\m.diehl $ +!-------------------------------------------------------------------------------------------------- +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incoprorating gurson damage +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module damage_gurson + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + damage_gurson_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + damage_gurson_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + damage_gurson_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + damage_gurson_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + damage_gurson_aTol, & + damage_gurson_critpStrain + + enum, bind(c) + enumerator :: undefined_ID, & + local_damage_ID + end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + damage_gurson_outputID !< ID of each post result output + + + public :: & + damage_gurson_init, & + damage_gurson_stateInit, & + damage_gurson_aTolState, & + damage_gurson_dotState, & + damage_gurson_microstructure, & + constitutive_gurson_getDamage, & + constitutive_gurson_putDamage, & + damage_gurson_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine damage_gurson_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use mesh, only: & + mesh_maxNips, & + mesh_NcpElems + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + homogenization_maxNgrains, & + phase_damage, & + phase_damageInstance, & + phase_Noutput, & + LOCAL_DAMAGE_gurson_label, & + LOCAL_DAMAGE_gurson_ID, & + material_phase, & + damageState, & + MATERIAL_partPhase + use numerics,only: & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + write(6,'(/,a)') ' <<<+- damage_'//LOCAL_DAMAGE_gurson_LABEL//' init -+>>>' + write(6,'(a)') ' $Id: damage_gurson.f90 3210 2014-06-17 15:24:44Z MPIE\m.diehl $' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + + maxNinstance = int(count(phase_damage == LOCAL_DAMAGE_gurson_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(damage_gurson_sizePostResults(maxNinstance), source=0_pInt) + allocate(damage_gurson_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(damage_gurson_output(maxval(phase_Noutput),maxNinstance)) + damage_gurson_output = '' + allocate(damage_gurson_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) + allocate(damage_gurson_Noutput(maxNinstance), source=0_pInt) + allocate(damage_gurson_critpStrain(maxNinstance), source=0.0_pReal) + allocate(damage_gurson_aTol(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = phase_damageInstance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('local_damage') + damage_gurson_Noutput(instance) = damage_gurson_Noutput(instance) + 1_pInt + damage_gurson_outputID(damage_gurson_Noutput(instance),instance) = local_damage_ID + damage_gurson_output(damage_gurson_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + case ('critical_plastic_strain') + damage_gurson_critpStrain(instance) = IO_floatValue(line,positions,2_pInt) + + case ('atol_damage') + damage_gurson_aTol(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + initializeInstances: do phase = 1_pInt, size(phase_damage) + if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then + NofMyPhase=count(material_phase==phase) + instance = phase_damageInstance(phase) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,damage_gurson_Noutput(instance) + select case(damage_gurson_outputID(o,instance)) + case(local_damage_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + damage_gurson_sizePostResult(o,instance) = mySize + damage_gurson_sizePostResults(instance) = damage_gurson_sizePostResults(instance) + mySize + endif + enddo outputsLoop +! Determine size of state array + sizeDotState = 4_pInt + sizeState = 6_pInt + + damageState(phase)%sizeState = sizeState + damageState(phase)%sizeDotState = sizeDotState + damageState(phase)%sizePostResults = damage_gurson_sizePostResults(instance) + allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) + allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + call damage_gurson_stateInit(phase,instance) + call damage_gurson_aTolState(phase,instance) + endif + + enddo initializeInstances +end subroutine damage_gurson_init + +!-------------------------------------------------------------------------------------------------- +!> @brief sets the relevant NEW state values for a given instance of this damage +!-------------------------------------------------------------------------------------------------- +subroutine damage_gurson_stateInit(phase,instance) + use material, only: & + damageState + + implicit none + integer(pInt), intent(in) :: instance !< number specifying the instance of the damage + integer(pInt), intent(in) :: phase !< number specifying the phase of the damage + + real(pReal), dimension(damageState(phase)%sizeState) :: tempState + + tempState(1) = 1.0_pReal + tempState(2) = 0.0_pReal + tempState(3) = 1.0_pReal + + damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:))) + damageState(phase)%state0 = damageState(phase)%state + damageState(phase)%partionedState0 = damageState(phase)%state +end subroutine damage_gurson_stateInit + +!-------------------------------------------------------------------------------------------------- +!> @brief sets the relevant state values for a given instance of this damage +!-------------------------------------------------------------------------------------------------- +subroutine damage_gurson_aTolState(phase,instance) + use material, only: & + damageState + + implicit none + integer(pInt), intent(in) :: & + phase, & + instance ! number specifying the current instance of the damage + real(pReal), dimension(damageState(phase)%sizeState) :: tempTol + + tempTol = damage_gurson_aTol(instance) + damageState(phase)%aTolState = tempTol +end subroutine damage_gurson_aTolState + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine damage_gurson_dotState(Lp, ipc, ip, el) + use material, only: & + mappingConstitutive, & + damageState + use math, only: & + math_equivStrain33, & + math_trace33 + use lattice, only: & + lattice_DamageMobility + + implicit none + real(pReal), intent(in), dimension(3,3) :: & + Lp + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, constituent + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + + damageState(phase)%dotState(1,constituent) = & + (1.0_pReal/lattice_DamageMobility(phase))* & + (damageState(phase)%state(6,constituent) - & + damageState(phase)%state(1,constituent)) + + damageState(phase)%dotState(2,constituent) = & + damageState(phase)%dotState(3,constituent) + & + damageState(phase)%dotState(4,constituent) ! total rate of void fraction evolution + + damageState(phase)%dotState(3,constituent) = & + damageState(phase)%state(6,constituent) + & + damageState(phase)%dotState(4,constituent) ! void nucleation rate + + damageState(phase)%dotState(4,constituent) = & + (1_pReal - damageState(phase)%state(3,constituent)) * & + math_trace33(Lp) ! void growth rate( proportional to hydrostatic part of Lp ) + +end subroutine damage_gurson_dotState + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine damage_gurson_microstructure(ipc, ip, el) + use material, only: & + mappingConstitutive, & + phase_damageInstance, & + damageState + use math, only: & + math_Mandel6to33, & + math_mul33x33, & + math_transpose33, & + math_I3, & + math_norm33 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, constituent + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + + damageState(phase)%state(5,constituent) = 0.0_pReal !< a statistical measure of aeformation hetrogeneity + damageState(phase)%state(6,constituent) = min(damageState(phase)%state(6,constituent), & + damage_gurson_critpStrain(phase)/ & + damageState(phase)%state(2,constituent)) !< akin to damage surface + +end subroutine damage_gurson_microstructure + +!-------------------------------------------------------------------------------------------------- +!> @brief returns temperature based on local damage model state layout +!-------------------------------------------------------------------------------------------------- +function constitutive_gurson_getDamage(ipc, ip, el) + use material, only: & + mappingConstitutive, & + damageState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal) :: constitutive_gurson_getDamage + + constitutive_gurson_getDamage = & + damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) + +end function constitutive_gurson_getDamage + +!-------------------------------------------------------------------------------------------------- +!> @brief returns damage value based on local damage +!-------------------------------------------------------------------------------------------------- +subroutine constitutive_gurson_putDamage(ipc, ip, el, localDamage) + use material, only: & + mappingConstitutive, & + damageState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: localDamage + + damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & + localDamage + +end subroutine constitutive_gurson_putDamage + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of constitutive results +!-------------------------------------------------------------------------------------------------- +function damage_gurson_postResults(ipc,ip,el) + use material, only: & + mappingConstitutive, & + phase_damageInstance,& + damageState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), dimension(damage_gurson_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & + damage_gurson_postResults + + integer(pInt) :: & + instance, phase, constituent, o, c + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = phase_damageInstance(phase) + + c = 0_pInt + damage_gurson_postResults = 0.0_pReal + + do o = 1_pInt,damage_gurson_Noutput(instance) + select case(damage_gurson_outputID(o,instance)) + case (local_damage_ID) + damage_gurson_postResults(c+1_pInt) = damageState(phase)%state(1,constituent) + c = c + 1 + + end select + enddo +end function damage_gurson_postResults + +end module damage_gurson diff --git a/code/material.f90 b/code/material.f90 index 778b64e2b..6bc0d5651 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -30,6 +30,7 @@ module material LOCAL_DAMAGE_none_label = 'none', & LOCAL_DAMAGE_brittle_label = 'brittle', & LOCAL_DAMAGE_ductile_label = 'ductile', & + LOCAL_DAMAGE_gurson_label = 'gurson', & LOCAL_THERMAL_isothermal_label = 'isothermal', & LOCAL_THERMAL_adiabatic_label = 'adiabatic', & FIELD_DAMAGE_local_label = 'local', & @@ -60,7 +61,8 @@ module material enum, bind(c) enumerator :: LOCAL_DAMAGE_none_ID, & LOCAL_DAMAGE_brittle_ID, & - LOCAL_DAMAGE_ductile_ID + LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID end enum enum, bind(c) @@ -216,6 +218,7 @@ module material LOCAL_DAMAGE_none_ID, & LOCAL_DAMAGE_brittle_ID, & LOCAL_DAMAGE_ductile_ID, & + LOCAL_DAMAGE_gurson_ID, & LOCAL_THERMAL_isothermal_ID, & LOCAL_THERMAL_adiabatic_ID, & FIELD_DAMAGE_local_ID, & @@ -789,12 +792,14 @@ subroutine material_parsePhase(fileUnit,myPart) phase_plasticityInstance(section) = count(phase_plasticity(1:section) == phase_plasticity(section)) ! count instances case ('damage') select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case (LOCAL_DAMAGE_NONE_label) + case (LOCAL_DAMAGE_none_label) phase_damage(section) = LOCAL_DAMAGE_none_ID - case (LOCAL_DAMAGE_BRITTLE_label) + case (LOCAL_DAMAGE_brittle_label) phase_damage(section) = LOCAL_DAMAGE_BRITTLE_ID - case (LOCAL_DAMAGE_DUCTILE_label) + case (LOCAL_DAMAGE_ductile_label) phase_damage(section) = LOCAL_DAMAGE_DUCTILE_ID + case (LOCAL_DAMAGE_gurson_label) + phase_damage(section) = LOCAL_DAMAGE_gurson_ID case default call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) end select