diff --git a/code/CPFEM.f90 b/code/CPFEM.f90 index 034d08a39..6713ae113 100644 --- a/code/CPFEM.f90 +++ b/code/CPFEM.f90 @@ -45,7 +45,7 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief call (thread safe) all module initializations !-------------------------------------------------------------------------------------------------- -subroutine CPFEM_initAll(temperature,el,ip) +subroutine CPFEM_initAll(temperature_inp,el,ip) use prec, only: & prec_init use numerics, only: & @@ -79,7 +79,7 @@ subroutine CPFEM_initAll(temperature,el,ip) implicit none integer(pInt), intent(in) :: el, & !< FE el number ip !< FE integration point number - real(pReal), intent(in) :: temperature !< temperature + real(pReal), intent(in) :: temperature_inp !< temperature !$OMP CRITICAL (init) if (.not. CPFEM_init_done) then @@ -97,10 +97,10 @@ subroutine CPFEM_initAll(temperature,el,ip) call FE_init call mesh_init(ip, el) ! pass on coordinates to alter calcMode of first ip call lattice_init - call material_init(temperature) - call constitutive_init(temperature) + call material_init + call constitutive_init call crystallite_init - call homogenization_init + call homogenization_init(temperature_inp) call CPFEM_init #if defined(Marc4DAMASK) || defined(Abaqus) call DAMASK_interface_init ! Spectral solver and FEM init is already done @@ -262,9 +262,9 @@ end subroutine CPFEM_init !> @brief perform initialization at first call, update variables and call the actual material model !-------------------------------------------------------------------------------------------------- #if defined(Marc4DAMASK) || defined(Abaqus) -subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature, dt, elFE, ip, cauchyStress, jacobian) +subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyStress, jacobian) #else -subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) +subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip) #endif use numerics, only: & defgradTolerance, & @@ -316,13 +316,19 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) use material, only: & microstructure_elemhomo, & plasticState, & - damageState, & + sourceState, & homogState, & thermalState, & - vacancyState,& + damageState, & + vacancyfluxState, & + hydrogenfluxState, & mappingConstitutive, & material_phase, & phase_plasticity, & + temperature, & + thermalMapping, & + phase_Nsources, & + material_homog, & material_Nhomogenization use crystallite, only: & crystallite_partionedF,& @@ -349,8 +355,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) materialpoint_sizeResults, & #endif materialpoint_stressAndItsTangent, & - materialpoint_postResults, & - field_putFieldTemperature + materialpoint_postResults use IO, only: & IO_write_jobRealFile, & IO_warning @@ -359,7 +364,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) implicit none integer(pInt), intent(in) :: elFE, & !< FE element number ip !< integration point number - real(pReal), intent(in) :: temperature !< temperature + real(pReal), intent(in) :: temperature_inp !< temperature real(pReal), intent(in) :: dt !< time increment real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0 ffn1 !< deformation gradient for t=t1 @@ -381,7 +386,7 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) #endif integer(pInt) elCP, & ! crystal plasticity element number - i, j, k, l, m, n, ph, homog + i, j, k, l, m, n, ph, homog, mySource logical updateJaco ! flag indicating if JAcobian has to be updated character(len=1024) :: rankStr @@ -427,10 +432,11 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) crystallite_dPdF0 = crystallite_dPdF ! crystallite stiffness crystallite_Tstar0_v = crystallite_Tstar_v ! crystallite 2nd Piola Kirchhoff stress - forall ( i = 1:size(plasticState)) plasticState(i)%state0= plasticState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array - forall ( i = 1:size(damageState)) damageState(i)%state0 = damageState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array - forall ( i = 1:size(thermalState)) thermalState(i)%state0= thermalState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array - forall ( i = 1:size(vacancyState)) vacancyState(i)%state0= vacancyState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array + forall ( i = 1:size(plasticState )) plasticState(i)%state0 = plasticState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array + do i = 1, size(sourceState) + do mySource = 1,phase_Nsources(i) + sourceState(i)%p(mySource)%state0 = sourceState(i)%p(mySource)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array + enddo; enddo if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then write(6,'(a)') '<< CPFEM >> aging states' if (debug_e <= mesh_NcpElems .and. debug_i <= mesh_maxNips) then @@ -441,7 +447,11 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) endif do homog = 1_pInt, material_Nhomogenization - homogState(homog)%state0 = homogState(homog)%state + homogState (homog)%state0 = homogState (homog)%state + thermalState (homog)%state0 = thermalState (homog)%state + damageState (homog)%state0 = damageState (homog)%state + vacancyfluxState (homog)%state0 = vacancyfluxState (homog)%state + hydrogenfluxState(homog)%state0 = hydrogenfluxState(homog)%state enddo @@ -523,7 +533,8 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) if (.not. parallelExecution) then #if defined(Marc4DAMASK) || defined(Abaqus) - call field_putFieldTemperature(ip,elCP,temperature) + temperature(material_homog(ip,elCP))%p(thermalMapping(material_homog(ip,elCP))%p(ip,elCP)) = & + temperature_inp #endif materialpoint_F0(1:3,1:3,ip,elCP) = ffn materialpoint_F(1:3,1:3,ip,elCP) = ffn1 @@ -536,7 +547,8 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature, dt, elFE, ip) CPFEM_dcsde(1:6,1:6,ip,elCP) = CPFEM_odd_jacobian * math_identity2nd(6) #endif #if defined(Marc4DAMASK) || defined(Abaqus) - call field_putFieldTemperature(ip,elCP,temperature) + temperature(material_homog(ip,elCP))%p(thermalMapping(material_homog(ip,elCP))%p(ip,elCP)) = & + temperature_inp #endif materialpoint_F0(1:3,1:3,ip,elCP) = ffn materialpoint_F(1:3,1:3,ip,elCP) = ffn1 diff --git a/code/DAMASK_spectral_driver.f90 b/code/DAMASK_spectral_driver.f90 index 83b52deee..e7f8b301c 100644 --- a/code/DAMASK_spectral_driver.f90 +++ b/code/DAMASK_spectral_driver.f90 @@ -140,7 +140,7 @@ program DAMASK_spectral_Driver external :: quit !-------------------------------------------------------------------------------------------------- ! init DAMASK (all modules) - call CPFEM_initAll(temperature = 300.0_pReal, el = 1_pInt, ip = 1_pInt) + call CPFEM_initAll(temperature_inp = 300.0_pReal, el = 1_pInt, ip = 1_pInt) mainProcess: if (worldrank == 0) then write(6,'(/,a)') ' <<<+- DAMASK_spectral_driver init -+>>>' write(6,'(a)') ' $Id$' diff --git a/code/DAMASK_spectral_solverBasicPETSc.f90 b/code/DAMASK_spectral_solverBasicPETSc.f90 index 14cbd66ee..bb76b80b0 100644 --- a/code/DAMASK_spectral_solverBasicPETSc.f90 +++ b/code/DAMASK_spectral_solverBasicPETSc.f90 @@ -205,7 +205,7 @@ subroutine basicPETSc_init(temperature) call Utilities_updateIPcoords(F) call Utilities_constitutiveResponse(F_lastInc, F, & temperature, & - 0.0_pReal, & + 1.0_pReal, & P, & C_volAvg,C_minMaxAvg, & ! global average of stiffness and (min+max)/2 temp33_Real, & diff --git a/code/DAMASK_spectral_utilities.f90 b/code/DAMASK_spectral_utilities.f90 index 0ee3ce5e3..30169b9bf 100644 --- a/code/DAMASK_spectral_utilities.f90 +++ b/code/DAMASK_spectral_utilities.f90 @@ -395,10 +395,13 @@ subroutine utilities_FFTforward() use numerics, only: & worldrank use mesh, only: & - gridOffset, & gridLocal implicit none + external :: & + MPI_Bcast, & + MPI_reduce + integer(pInt) :: row, column ! if debug FFTW, compare 3D array field of row and column real(pReal), dimension(2) :: myRand, maxScalarField ! random numbers integer(pInt) :: i, j, k @@ -433,7 +436,7 @@ subroutine utilities_FFTforward() field_fourierMPI(row,column,1:grid1Red,1:gridLocal(2),1:gridLocal(3)))/& scalarField_fourierMPI(1:grid1Red,1:gridLocal(2),1:gridLocal(3)) else where - scalarField_realMPI = cmplx(0.0,0.0,pReal) + scalarField_fourierMPI = cmplx(0.0,0.0,pReal) end where maxScalarField(1) = maxval(real (scalarField_fourierMPI(1:grid1Red,1:gridLocal(2), & 1:gridLocal(3)))) @@ -451,7 +454,7 @@ subroutine utilities_FFTforward() !-------------------------------------------------------------------------------------------------- ! applying filter do k = 1_pInt, gridLocal(3); do j = 1_pInt, gridLocal(2); do i = 1_pInt,grid1Red - field_fourierMPI(1:3,1:3,i,j,k) = utilities_getFilter(xi(1:3,i,j,k))* & + field_fourierMPI(1:3,1:3,i,j,k) = cmplx(utilities_getFilter(xi(1:3,i,j,k)),0.0,pReal)* & field_fourierMPI(1:3,1:3,i,j,k) enddo; enddo; enddo @@ -473,6 +476,10 @@ subroutine utilities_FFTbackward() gridLocal implicit none + external :: & + MPI_Bcast, & + MPI_reduce + integer(pInt) :: row, column !< if debug FFTW, compare 3D array field of row and column real(pReal), dimension(2) :: myRand real(pReal) :: maxScalarField @@ -506,7 +513,7 @@ subroutine utilities_FFTbackward() - field_realMPI (row,column,1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)))/ & scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)) else where - scalarField_realMPI = cmplx(0.0,0.0,pReal) + scalarField_realMPI = 0.0_pReal end where maxScalarField = maxval(real (scalarField_realMPI(1:gridLocal(1),1:gridLocal(2),1:gridLocal(3)))) call MPI_reduce(MPI_IN_PLACE,maxScalarField,1,MPI_DOUBLE,MPI_MAX,0,PETSC_COMM_WORLD,ierr) @@ -627,6 +634,10 @@ real(pReal) function utilities_divergenceRMS() gridGlobal implicit none + external :: & + MPI_reduce, & + MPI_Allreduce + integer(pInt) :: i, j, k real(pReal) :: & err_real_div_RMS, & !< RMS of divergence in real space @@ -714,6 +725,9 @@ real(pReal) function utilities_curlRMS() gridGlobal implicit none + external :: & + MPI_Allreduce + integer(pInt) :: i, j, k, l complex(pReal), dimension(3,3) :: curl_fourier PetscErrorCode :: ierr @@ -898,10 +912,14 @@ subroutine utilities_constitutiveResponse(F_lastInc,F,temperature,timeinc,& materialpoint_F, & materialpoint_P, & materialpoint_dPdF - use thermal_isothermal, only: & - thermal_isothermal_temperature +! use thermal_isothermal, only: & +! thermal_isothermal_temperature implicit none + external :: & + MPI_reduce, & + MPI_Allreduce + real(pReal), intent(in) :: temperature !< temperature (no field) real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: & F_lastInc, & !< target deformation gradient @@ -937,7 +955,7 @@ subroutine utilities_constitutiveResponse(F_lastInc,F,temperature,timeinc,& call CPFEM_general(CPFEM_COLLECT,F_lastInc(1:3,1:3,1,1,1),F(1:3,1:3,1,1,1), & temperature,timeinc,1_pInt,1_pInt) - thermal_isothermal_temperature(:) = temperature +! thermal_isothermal_temperature(:) = temperature materialpoint_F = reshape(F,[3,3,1,product(gridLocal)]) call debug_reset() @@ -1044,6 +1062,9 @@ function utilities_forwardField(timeinc,field_lastInc,rate,aim) gridLocal implicit none + external :: & + MPI_Allreduce + real(pReal), intent(in) :: & timeinc !< timeinc of current step real(pReal), intent(in), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)) :: & @@ -1143,6 +1164,8 @@ subroutine utilities_updateIPcoords(F) geomSizeGlobal, & mesh_ipCoordinates implicit none + external :: & + MPI_Bcast real(pReal), dimension(3,3,gridLocal(1),gridLocal(2),gridLocal(3)), intent(in) :: F integer(pInt) :: i, j, k, m diff --git a/code/Makefile b/code/Makefile index 3bf916c0e..af7b8d2d8 100644 --- a/code/Makefile +++ b/code/Makefile @@ -187,7 +187,8 @@ COMPILE_OPTIONS_gfortran +=-ffree-line-length-132\ -Wsuggest-attribute=pure\ -Wsuggest-attribute=noreturn\ -Wconversion-extra\ - -Wimplicit-procedure + -Wimplicit-procedure\ + -Wno-unused-parameter endif ################################################################################################### #COMPILE SWITCHES @@ -305,22 +306,37 @@ PRECISION_gfortran :=-fdefault-real-8 -fdefault-double-8 -DFLOAT=8 -DINT=4 COMPILE =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(OPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90)) COMPILE_MAXOPTI =$(OPENMP_FLAG_$(F90)) $(COMPILE_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) $(INCLUDE_DIRS) $(PRECISION_$(F90)) ################################################################################################### -DAMAGE_FILES = \ - damage_none.o damage_isoBrittle.o damage_isoDuctile.o damage_gurson.o damage_anisoBrittle.o damage_anisoDuctile.o damage_phaseField.o - -THERMAL_FILES = \ - thermal_isothermal.o thermal_adiabatic.o - -VACANCY_FILES = \ - vacancy_constant.o vacancy_generation.o - +SOURCE_FILES = \ + source_thermal_dissipation.o \ + source_damage_isoBrittle.o source_damage_isoDuctile.o source_damage_anisoBrittle.o source_damage_anisoDuctile.o \ + source_vacancy_phenoplasticity.o source_vacancy_irradiation.o source_vacancy_thermalfluc.o + +KINEMATICS_FILES = \ + kinematics_cleavage_opening.o kinematics_slipplane_opening.o \ + kinematics_thermal_expansion.o \ + kinematics_vacancy_strain.o kinematics_hydrogen_strain.o + PLASTIC_FILES = \ plastic_dislotwin.o plastic_disloUCLA.o plastic_disloKMC.o plastic_j2.o plastic_phenopowerlaw.o \ - plastic_titanmod.o plastic_nonlocal.o plastic_none.o + plastic_titanmod.o plastic_nonlocal.o plastic_none.o +THERMAL_FILES = \ + thermal_isothermal.o thermal_adiabatic.o thermal_conduction.o + +DAMAGE_FILES = \ + damage_none.o damage_local.o damage_nonlocal.o + +VACANCYFLUX_FILES = \ + vacancyflux_isoconc.o vacancyflux_isochempot.o vacancyflux_cahnhilliard.o + +POROSITY_FILES = \ + porosity_none.o porosity_phasefield.o + +HYDROGENFLUX_FILES = \ + hydrogenflux_isoconc.o hydrogenflux_cahnhilliard.o HOMOGENIZATION_FILES = \ - homogenization_RGC.o homogenization_isostrain.o homogenization_none.o homogenization.o + homogenization_RGC.o homogenization_isostrain.o homogenization_none.o ##################### # Spectral Solver @@ -332,12 +348,17 @@ DAMASK_spectral.exe: MESHNAME := mesh.f90 DAMASK_spectral.exe: INTERFACENAME := DAMASK_spectral_interface.f90 +SPECTRAL_SOLVER_FILES = DAMASK_spectral_solverAL.o DAMASK_spectral_solverBasicPETSc.o DAMASK_spectral_solverPolarisation.o + SPECTRAL_FILES = prec.o DAMASK_interface.o IO.o libs.o numerics.o debug.o math.o \ - FEsolving.o mesh.o material.o lattice.o constitutive.o \ - $(DAMAGE_FILES) $(THERMAL_FILES) $(VACANCY_FILES) $(PLASTIC_FILES) \ - crystallite.o $(HOMOGENIZATION_FILES) CPFEM.o \ + FEsolving.o mesh.o material.o lattice.o \ + $(SOURCE_FILES) $(KINEMATICS_FILES) $(PLASTIC_FILES) constitutive.o \ + crystallite.o \ + $(THERMAL_FILES) $(DAMAGE_FILES) $(VACANCYFLUX_FILES) $(HYDROGENFLUX_FILES) $(POROSITY_FILES) \ + $(HOMOGENIZATION_FILES) homogenization.o \ + CPFEM.o \ DAMASK_spectral_utilities.o \ - DAMASK_spectral_solverAL.o DAMASK_spectral_solverBasicPETSc.o DAMASK_spectral_solverPolarisation.o + $(SPECTRAL_SOLVER_FILES) DAMASK_spectral.exe: DAMASK_spectral_driver.o $(PREFIX) $(LINKERNAME) $(OPENMP_FLAG_$(F90)) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \ @@ -346,9 +367,7 @@ DAMASK_spectral.exe: DAMASK_spectral_driver.o DAMASK_spectral_driver.o: DAMASK_spectral_driver.f90 \ - DAMASK_spectral_solverAL.o \ - DAMASK_spectral_solverBasicPETSc.o \ - DAMASK_spectral_solverPolarisation.o + $(SPECTRAL_SOLVER_FILES) $(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c DAMASK_spectral_driver.f90 $(SUFFIX) DAMASK_spectral_solverAL.o: DAMASK_spectral_solverAL.f90 \ @@ -373,18 +392,23 @@ DAMASK_FEM.exe: MESHNAME := ../private/FEM/code/meshFEM.f90 DAMASK_FEM.exe: INTERFACENAME := ../private/FEM/code/DAMASK_FEM_interface.f90 DAMASK_FEM.exe: INCLUDE_DIRS += -I./ +FEM_SOLVER_FILES = FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyflux.o FEM_porosity.o FEM_hydrogenflux.o + FEM_FILES = prec.o DAMASK_interface.o FEZoo.o IO.o libs.o numerics.o debug.o math.o \ FEsolving.o mesh.o material.o lattice.o \ - $(DAMAGE_FILES) $(THERMAL_FILES) $(VACANCY_FILES) $(PLASTIC_FILES) \ - crystallite.o $(HOMOGENIZATION_FILES) CPFEM.o \ - FEM_utilities.o FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyDiffusion.o + $(SOURCE_FILES) $(KINEMATICS_FILES) $(PLASTIC_FILES) constitutive.o \ + crystallite.o \ + $(THERMAL_FILES) $(DAMAGE_FILES) $(VACANCYFLUX_FILES) $(HYDROGENFLUX_FILES) $(POROSITY_FILES) \ + $(HOMOGENIZATION_FILES) homogenization.o \ + CPFEM.o \ + FEM_utilities.o $(FEM_SOLVER_FILES) DAMASK_FEM.exe: DAMASK_FEM_driver.o - $(PREFIX) $(LINKERNAME) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \ + $(PREFIX) $(LINKERNAME) $(OPENMP_FLAG_$(F90)) $(LINK_OPTIONS_$(F90)) $(STANDARD_CHECK_$(F90)) $(OPTIMIZATION_$(MAXOPTI)_$(F90)) \ -o DAMASK_FEM.exe DAMASK_FEM_driver.o \ $(FEM_FILES) $(LIBRARIES) $(SUFFIX) -DAMASK_FEM_driver.o: DAMASK_FEM_driver.f90 FEM_mech.o FEM_thermal.o FEM_damage.o FEM_vacancyDiffusion.o +DAMASK_FEM_driver.o: DAMASK_FEM_driver.f90 $(FEM_SOLVER_FILES) $(PREFIX) $(COMPILERNAME) $(COMPILE_MAXOPTI) -c ../private/FEM/code/DAMASK_FEM_driver.f90 $(SUFFIX) FEM_mech.o: FEM_mech.f90 \ @@ -396,7 +420,13 @@ FEM_thermal.o: FEM_thermal.f90 \ FEM_damage.o: FEM_damage.f90 \ FEM_utilities.o -FEM_vacancyDiffusion.o: FEM_vacancyDiffusion.f90 \ +FEM_vacancyflux.o: FEM_vacancyflux.f90 \ + FEM_utilities.o + +FEM_porosity.o: FEM_porosity.f90 \ + FEM_utilities.o + +FEM_hydrogenflux.o: FEM_hydrogenflux.f90 \ FEM_utilities.o FEM_utilities.o: FEM_utilities.f90 \ @@ -411,9 +441,54 @@ CPFEM.o: CPFEM.f90\ homogenization.o homogenization.o: homogenization.f90\ - homogenization_none.o \ - homogenization_RGC.o \ - homogenization_isostrain.o + $(THERMAL_FILES) \ + $(DAMAGE_FILES) \ + $(VACANCYFLUX_FILES) \ + $(POROSITY_FILES) \ + $(HYDROGENFLUX_FILES) \ + $(HOMOGENIZATION_FILES) + +thermal_isothermal.o: thermal_isothermal.f90 \ + crystallite.o + +thermal_adiabatic.o: thermal_adiabatic.f90 \ + crystallite.o + +thermal_conduction.o: thermal_conduction.f90 \ + crystallite.o + +damage_none.o: damage_none.f90 \ + crystallite.o + +damage_local.o: damage_local.f90 \ + crystallite.o + +damage_nonlocal.o: damage_nonlocal.f90 \ + crystallite.o + +thermal_conduction.o: thermal_conduction.f90 \ + crystallite.o + +vacancyflux_isoconc.o: vacancyflux_isoconc.f90 \ + crystallite.o + +vacancyflux_isochempot.o: vacancyflux_isochempot.f90 \ + crystallite.o + +vacancyflux_cahnhilliard.o: vacancyflux_cahnhilliard.f90 \ + crystallite.o + +porosity_none.o: porosity_none.f90 \ + crystallite.o + +porosity_phasefield.o: porosity_phasefield.f90 \ + crystallite.o + +hydrogenflux_isoconc.o: hydrogenflux_isoconc.f90 \ + crystallite.o + +hydrogenflux_cahnhilliard.o: hydrogenflux_cahnhilliard.f90 \ + crystallite.o homogenization_RGC.o: homogenization_RGC.f90 \ crystallite.o @@ -428,11 +503,49 @@ crystallite.o: crystallite.f90 \ constitutive.o constitutive.o: constitutive.f90 \ - $(PLASTIC_FILES) \ - $(DAMAGE_FILES) \ - $(THERMAL_FILES) \ - $(VACANCY_FILES) + $(SOURCE_FILES) \ + $(KINEMATICS_FILES) \ + $(PLASTIC_FILES) +source_thermal_dissipation.o: source_thermal_dissipation.f90 \ + lattice.o + +source_damage_isoBrittle.o: source_damage_isoBrittle.f90 \ + lattice.o + +source_damage_isoDuctile.o: source_damage_isoDuctile.f90 \ + lattice.o + +source_damage_anisoBrittle.o: source_damage_anisoBrittle.f90 \ + lattice.o + +source_damage_anisoDuctile.o: source_damage_anisoDuctile.f90 \ + lattice.o + +source_vacancy_phenoplasticity.o: source_vacancy_phenoplasticity.f90 \ + lattice.o + +source_vacancy_irradiation.o: source_vacancy_irradiation.f90 \ + lattice.o + +source_vacancy_thermalfluc.o: source_vacancy_thermalfluc.f90 \ + lattice.o + +kinematics_cleavage_opening.o: kinematics_cleavage_opening.f90 \ + lattice.o + +kinematics_slipplane_opening.o: kinematics_slipplane_opening.f90 \ + lattice.o + +kinematics_thermal_expansion.o: kinematics_thermal_expansion.f90 \ + lattice.o + +kinematics_vacancy_strain.o: kinematics_vacancy_strain.f90 \ + lattice.o + +kinematics_hydrogen_strain.o: kinematics_hydrogen_strain.f90 \ + lattice.o + plastic_nonlocal.o: plastic_nonlocal.f90 \ lattice.o @@ -457,39 +570,6 @@ plastic_j2.o: plastic_j2.f90 \ plastic_none.o: plastic_none.f90 \ lattice.o -damage_none.o: damage_none.f90 \ - lattice.o - -damage_isoBrittle.o: damage_isoBrittle.f90 \ - lattice.o - -damage_isoDuctile.o: damage_isoDuctile.f90 \ - lattice.o - -damage_anisoBrittle.o: damage_anisoBrittle.f90 \ - lattice.o - -damage_anisoDuctile.o: damage_anisoDuctile.f90 \ - lattice.o - -damage_phaseField.o: damage_phaseField.f90 \ - lattice.o - -damage_gurson.o: damage_gurson.f90 \ - lattice.o - -thermal_isothermal.o: thermal_isothermal.f90 \ - lattice.o - -thermal_adiabatic.o: thermal_adiabatic.f90 \ - lattice.o - -vacancy_constant.o: vacancy_constant.f90 \ - lattice.o - -vacancy_generation.o: vacancy_generation.f90 \ - lattice.o - lattice.o: lattice.f90 \ material.o diff --git a/code/commercialFEM_fileList.f90 b/code/commercialFEM_fileList.f90 index 608096309..ffdb0015c 100644 --- a/code/commercialFEM_fileList.f90 +++ b/code/commercialFEM_fileList.f90 @@ -1,5 +1,5 @@ !-------------------------------------------------------------------------------------------------- -! $Id: libs.f90 3413 2014-08-24 22:07:53Z MPIE\m.diehl $ +! $Id$ !-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief all DAMASK files without solver @@ -14,17 +14,19 @@ #include "mesh.f90" #include "material.f90" #include "lattice.f90" -#include "damage_none.f90" -#include "damage_isoBrittle.f90" -#include "damage_isoDuctile.f90" -#include "damage_anisoBrittle.f90" -#include "damage_anisoDuctile.f90" -#include "damage_gurson.f90" -#include "damage_phaseField.f90" -#include "thermal_isothermal.f90" -#include "thermal_adiabatic.f90" -#include "vacancy_constant.f90" -#include "vacancy_generation.f90" +#include "source_thermal_dissipation.f90" +#include "source_damage_isoBrittle.f90" +#include "source_damage_isoDuctile.f90" +#include "source_damage_anisoBrittle.f90" +#include "source_damage_anisoDuctile.f90" +#include "source_vacancy_phenoplasticity.f90" +#include "source_vacancy_irradiation.f90" +#include "source_vacancy_thermalfluc.f90" +#include "kinematics_cleavage_opening.f90" +#include "kinematics_slipplane_opening.f90" +#include "kinematics_thermal_expansion.f90" +#include "kinematics_vacancy_strain.f90" +#include "kinematics_hydrogen_strain.f90" #include "plastic_none.f90" #include "plastic_j2.f90" #include "plastic_phenopowerlaw.f90" @@ -38,5 +40,18 @@ #include "homogenization_none.f90" #include "homogenization_isostrain.f90" #include "homogenization_RGC.f90" +#include "thermal_isothermal.f90" +#include "thermal_adiabatic.f90" +#include "thermal_conduction.f90" +#include "damage_none.f90" +#include "damage_local.f90" +#include "damage_nonlocal.f90" +#include "vacancyflux_isoconc.f90" +#include "vacancyflux_isochempot.f90" +#include "vacancyflux_cahnhilliard.f90" +#include "porosity_none.f90" +#include "porosity_phasefield.f90" +#include "hydrogenflux_isoconc.f90" +#include "hydrogenflux_cahnhilliard.f90" #include "homogenization.f90" #include "CPFEM.f90" diff --git a/code/config/Homogenization_Damage_NonLocal.config b/code/config/Homogenization_Damage_NonLocal.config new file mode 100644 index 000000000..1b6bcfc16 --- /dev/null +++ b/code/config/Homogenization_Damage_NonLocal.config @@ -0,0 +1,3 @@ +### $Id$ ### +damage nonlocal +(output) damage diff --git a/code/config/Homogenization_HydrogenFlux_CahnHilliard.config b/code/config/Homogenization_HydrogenFlux_CahnHilliard.config new file mode 100644 index 000000000..73705d846 --- /dev/null +++ b/code/config/Homogenization_HydrogenFlux_CahnHilliard.config @@ -0,0 +1,3 @@ +### $Id$ ### +hydrogenflux cahnhilliard +(output) hydrogenconc diff --git a/code/config/Homogenization_Porosity_PhaseField.config b/code/config/Homogenization_Porosity_PhaseField.config new file mode 100644 index 000000000..38a618ceb --- /dev/null +++ b/code/config/Homogenization_Porosity_PhaseField.config @@ -0,0 +1,3 @@ +### $Id$ ### +porosity phasefield +(output) porosity diff --git a/code/config/Homogenization_Thermal_Conduction.config b/code/config/Homogenization_Thermal_Conduction.config new file mode 100644 index 000000000..f761ce0b3 --- /dev/null +++ b/code/config/Homogenization_Thermal_Conduction.config @@ -0,0 +1,3 @@ +### $Id$ ### +thermal conduction +(output) temperature diff --git a/code/config/Homogenization_VacancyFlux_CahnHilliard.config b/code/config/Homogenization_VacancyFlux_CahnHilliard.config new file mode 100644 index 000000000..00f5399f2 --- /dev/null +++ b/code/config/Homogenization_VacancyFlux_CahnHilliard.config @@ -0,0 +1,3 @@ +### $Id$ ### +vacancyflux cahnhilliard +(output) vacancyconc diff --git a/code/config/Homogenization_multiField.config b/code/config/Homogenization_multiField.config new file mode 100644 index 000000000..926737ff9 --- /dev/null +++ b/code/config/Homogenization_multiField.config @@ -0,0 +1,9 @@ +### $Id$ ### +[SX] +type isostrain +Ngrains 1 +{./Homogenization_Damage_NonLocal.config} +{./Homogenization_Thermal_Conduction.config} +{./Homogenization_VacancyFlux_CahnHilliard.config} +{./Homogenization_Porosity_PhaseField.config} +{./Homogenization_HydrogenFlux_CahnHilliard.config} diff --git a/code/config/Kinematics_Hydrogen_Strain.config b/code/config/Kinematics_Hydrogen_Strain.config new file mode 100644 index 000000000..f4a999038 --- /dev/null +++ b/code/config/Kinematics_Hydrogen_Strain.config @@ -0,0 +1,3 @@ +### $Id$ ### +(kinematics) vacancy_strain +vacancy_strain_coeff 0.006 diff --git a/code/config/Kinematics_Thermal_Expansion.config b/code/config/Kinematics_Thermal_Expansion.config new file mode 100644 index 000000000..408c489e2 --- /dev/null +++ b/code/config/Kinematics_Thermal_Expansion.config @@ -0,0 +1,3 @@ +### $Id$ ### +(kinematics) thermal_expansion +thermal_expansion_coeff 0.00231 diff --git a/code/config/Kinematics_Vacancy_Strain.config b/code/config/Kinematics_Vacancy_Strain.config new file mode 100644 index 000000000..cfb75ed0d --- /dev/null +++ b/code/config/Kinematics_Vacancy_Strain.config @@ -0,0 +1,3 @@ +### $Id$ ### +(kinematics) hydrogen_strain +hydrogen_strain_coeff 0.06 diff --git a/code/config/Phase_Damage.config b/code/config/Phase_Damage.config new file mode 100644 index 000000000..67c70a987 --- /dev/null +++ b/code/config/Phase_Damage.config @@ -0,0 +1,3 @@ +### $Id$ ### +damage_diffusion11 1.0 +damage_mobility 0.001 diff --git a/code/config/Phase_Hydrogen.config b/code/config/Phase_Hydrogen.config new file mode 100644 index 000000000..e3797df52 --- /dev/null +++ b/code/config/Phase_Hydrogen.config @@ -0,0 +1,4 @@ +### $Id$ ### +hydrogenflux_diffusion11 1.0 +hydrogenflux_mobility11 1.0 +hydrogenVolume 1e-28 diff --git a/code/config/Phase_Phenopowerlaw_multiField.config b/code/config/Phase_Phenopowerlaw_multiField.config new file mode 100644 index 000000000..3de057f3f --- /dev/null +++ b/code/config/Phase_Phenopowerlaw_multiField.config @@ -0,0 +1,62 @@ +### $Id$ ### +[Aluminum] +elasticity hooke +plasticity phenopowerlaw + +(output) resistance_slip +(output) shearrate_slip +(output) resolvedstress_slip +(output) accumulated_shear_slip +(output) totalshear +(output) resistance_twin +(output) shearrate_twin +(output) resolvedstress_twin +(output) accumulated_shear_twin +(output) totalvolfrac_twin + +lattice_structure fcc +Nslip 12 # per family +Ntwin 0 # per family + +c11 106.75e9 +c12 60.41e9 +c44 28.34e9 + +gdot0_slip 0.001 +n_slip 20 +tau0_slip 31e6 # per family +tausat_slip 63e6 # per family +a_slip 2.25 +gdot0_twin 0.001 +n_twin 20 +tau0_twin 31e6 # per family +s_pr 0 # push-up factor for slip saturation due to twinning +twin_b 0 +twin_c 0 +twin_d 0 +twin_e 0 +h0_slipslip 75e6 +h0_twinslip 0 +h0_twintwin 0 +interaction_slipslip 1 1 1.4 1.4 1.4 1.4 +interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +atol_resistance 1 + +(stiffness_degradation) damage +(stiffness_degradation) porosity +{./Phase_Damage.config} +{./Phase_Thermal.config} +{./Phase_Vacancy.config} +{./Phase_Porosity.config} +{./Phase_Hydrogen.config} +{./Source_Damage_IsoBrittle.config} +{./Source_Thermal_Dissipation.config} +{./Source_Vacancy_PhenoPlasticity.config} +{./Source_Vacancy_Irradiation.config} +{./Kinematics_Thermal_Expansion.config} +{./Kinematics_Vacancy_Strain.config} +{./Kinematics_Hydrogen_Strain.config} + + diff --git a/code/config/Phase_Porosity.config b/code/config/Phase_Porosity.config new file mode 100644 index 000000000..3f1ba52ce --- /dev/null +++ b/code/config/Phase_Porosity.config @@ -0,0 +1,3 @@ +### $Id$ ### +porosity_diffusion11 1.0 +porosity_mobility 0.001 diff --git a/code/config/Phase_Thermal.config b/code/config/Phase_Thermal.config new file mode 100644 index 000000000..5b6cb94d1 --- /dev/null +++ b/code/config/Phase_Thermal.config @@ -0,0 +1,5 @@ +### $Id$ ### +thermal_conductivity11 237.0 +specific_heat 910.0 +mass_density 2700.0 +reference_temperature 300.0 diff --git a/code/config/Phase_Vacancy.config b/code/config/Phase_Vacancy.config new file mode 100644 index 000000000..2905913f6 --- /dev/null +++ b/code/config/Phase_Vacancy.config @@ -0,0 +1,6 @@ +### $Id$ ### +vacancyflux_diffusion11 1.0 +vacancyflux_mobility11 1.0 +vacancyFormationEnergy 1e-19 +voidSurfaceEnergy 1e+10 +vacancyVolume 1e-28 diff --git a/code/config/Source_Damage_IsoBrittle.config b/code/config/Source_Damage_IsoBrittle.config new file mode 100644 index 000000000..3def4c13a --- /dev/null +++ b/code/config/Source_Damage_IsoBrittle.config @@ -0,0 +1,5 @@ +### $Id$ ### +(source) damage_isoBrittle +isobrittle_criticalStrainEnergy 1400000.0 +isobrittle_atol 0.01 +(output) isoBrittle_DrivingForce \ No newline at end of file diff --git a/code/config/Source_Thermal_Dissipation.config b/code/config/Source_Thermal_Dissipation.config new file mode 100644 index 000000000..218c5a4b5 --- /dev/null +++ b/code/config/Source_Thermal_Dissipation.config @@ -0,0 +1,3 @@ +### $Id$ ### +(source) thermal_dissipation +dissipation_ColdWorkCoeff 0.95 diff --git a/code/config/Source_Vacancy_Irradiation.config b/code/config/Source_Vacancy_Irradiation.config new file mode 100644 index 000000000..a346d73d4 --- /dev/null +++ b/code/config/Source_Vacancy_Irradiation.config @@ -0,0 +1,4 @@ +### $Id$ ### +(source) vacancy_irradiation +irradiation_cascadeprobability 0.00001 +irradiation_cascadevolume 1000.0 diff --git a/code/config/Source_Vacancy_PhenoPlasticity.config b/code/config/Source_Vacancy_PhenoPlasticity.config new file mode 100644 index 000000000..634b39134 --- /dev/null +++ b/code/config/Source_Vacancy_PhenoPlasticity.config @@ -0,0 +1,3 @@ +### $Id$ ### +(source) vacancy_phenoplasticity +phenoplasticity_ratecoeff 0.01 diff --git a/code/constitutive.f90 b/code/constitutive.f90 index 163759bb5..00a74ef5b 100644 --- a/code/constitutive.f90 +++ b/code/constitutive.f90 @@ -12,39 +12,20 @@ module constitutive implicit none private integer(pInt), public, protected :: & - constitutive_maxSizePostResults, & - constitutive_maxSizeDotState, & - constitutive_damage_maxSizePostResults, & - constitutive_damage_maxSizeDotState, & - constitutive_thermal_maxSizePostResults, & - constitutive_thermal_maxSizeDotState, & - constitutive_vacancy_maxSizePostResults, & - constitutive_vacancy_maxSizeDotState + constitutive_plasticity_maxSizePostResults, & + constitutive_plasticity_maxSizeDotState, & + constitutive_source_maxSizePostResults, & + constitutive_source_maxSizeDotState public :: & constitutive_init, & constitutive_homogenizedC, & - constitutive_damagedC, & constitutive_microstructure, & constitutive_LpAndItsTangent, & constitutive_LiAndItsTangent, & constitutive_TandItsTangent, & constitutive_collectDotState, & constitutive_collectDeltaState, & - constitutive_getLocalDamage, & - constitutive_putLocalDamage, & - constitutive_getDamage, & - constitutive_getDamageDiffusion33, & - constitutive_getAdiabaticTemperature, & - constitutive_putAdiabaticTemperature, & - constitutive_getTemperature, & - constitutive_getHeatGeneration, & - constitutive_getLocalVacancyConcentration, & - constitutive_putLocalVacancyConcentration, & - constitutive_getVacancyConcentration, & - constitutive_getVacancyDiffusion33, & - constitutive_getVacancyMobility33, & - constitutive_getVacancyEnergy, & constitutive_postResults private :: & @@ -56,7 +37,7 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief allocates arrays pointing to array of the various constitutive modules !-------------------------------------------------------------------------------------------------- -subroutine constitutive_init(temperature_init) +subroutine constitutive_init() #ifdef HDF use hdf5, only: & HID_T @@ -89,12 +70,9 @@ subroutine constitutive_init(temperature_init) phase_name, & phase_plasticity, & phase_plasticityInstance, & - phase_damage, & - phase_damageInstance, & - phase_thermal, & - phase_thermalInstance, & - phase_vacancy, & - phase_vacancyInstance, & + phase_Nsources, & + phase_source, & + phase_kinematics, & ELASTICITY_hooke_ID, & PLASTICITY_none_ID, & PLASTICITY_j2_ID, & @@ -104,6 +82,19 @@ subroutine constitutive_init(temperature_init) PLASTICITY_disloucla_ID, & PLASTICITY_titanmod_ID, & PLASTICITY_nonlocal_ID ,& + SOURCE_thermal_dissipation_ID, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID, & + SOURCE_vacancy_phenoplasticity_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID, & + KINEMATICS_cleavage_opening_ID, & + KINEMATICS_slipplane_opening_ID, & + KINEMATICS_thermal_expansion_ID, & + KINEMATICS_vacancy_strain_ID, & + KINEMATICS_hydrogen_strain_ID, & ELASTICITY_HOOKE_label, & PLASTICITY_NONE_label, & PLASTICITY_J2_label, & @@ -113,32 +104,16 @@ subroutine constitutive_init(temperature_init) PLASTICITY_DISLOUCLA_label, & PLASTICITY_TITANMOD_label, & PLASTICITY_NONLOCAL_label, & - LOCAL_DAMAGE_none_ID, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID, & - LOCAL_THERMAL_isothermal_ID, & - LOCAL_THERMAL_adiabatic_ID, & - LOCAL_VACANCY_constant_ID, & - LOCAL_VACANCY_generation_ID, & - LOCAL_DAMAGE_none_LABEL, & - LOCAL_DAMAGE_isoBrittle_LABEL, & - LOCAL_DAMAGE_isoDuctile_LABEL, & - LOCAL_DAMAGE_anisoBrittle_LABEL, & - LOCAL_DAMAGE_anisoDuctile_LABEL, & - LOCAL_DAMAGE_gurson_LABEL, & - LOCAL_DAMAGE_phaseField_label, & - LOCAL_THERMAL_isothermal_label, & - LOCAL_THERMAL_adiabatic_label, & - LOCAL_VACANCY_constant_label, & - LOCAL_VACANCY_generation_label, & + SOURCE_thermal_dissipation_label, & + SOURCE_damage_isoBrittle_label, & + SOURCE_damage_isoDuctile_label, & + SOURCE_damage_anisoBrittle_label, & + SOURCE_damage_anisoDuctile_label, & + SOURCE_vacancy_phenoplasticity_label, & + SOURCE_vacancy_irradiation_label, & + SOURCE_vacancy_thermalfluc_label, & plasticState, & - damageState, & - thermalState, & - vacancyState + sourceState use plastic_none use plastic_j2 @@ -148,31 +123,33 @@ subroutine constitutive_init(temperature_init) use plastic_disloucla use plastic_titanmod use plastic_nonlocal - use damage_none - use damage_isoBrittle - use damage_isoDuctile - use damage_anisoDuctile - use damage_anisoBrittle - use damage_gurson - use damage_phaseField - use thermal_isothermal - use thermal_adiabatic - use vacancy_constant - use vacancy_generation + use source_thermal_dissipation + use source_damage_isoBrittle + use source_damage_isoDuctile + use source_damage_anisoBrittle + use source_damage_anisoDuctile + use source_vacancy_phenoplasticity + use source_vacancy_irradiation + use source_vacancy_thermalfluc + use kinematics_cleavage_opening + use kinematics_slipplane_opening + use kinematics_thermal_expansion + use kinematics_vacancy_strain + use kinematics_hydrogen_strain implicit none - real(pReal), intent(in) :: temperature_init !< initial temperature integer(pInt), parameter :: FILEUNIT = 200_pInt integer(pInt) :: & e, & !< maximum number of elements phase, & + mySource, & instance integer(pInt), dimension(:,:), pointer :: thisSize integer(pInt), dimension(:) , pointer :: thisNoutput character(len=64), dimension(:,:), pointer :: thisOutput character(len=32) :: outputName !< name of output, intermediate fix until HDF5 output is ready - logical :: knownPlasticity, knownDamage, knownThermal, knownVacancy, nonlocalConstitutionPresent + logical :: knownPlasticity, knownSource, nonlocalConstitutionPresent nonlocalConstitutionPresent = .false. !-------------------------------------------------------------------------------------------------- @@ -193,32 +170,28 @@ subroutine constitutive_init(temperature_init) close(FILEUNIT) !-------------------------------------------------------------------------------------------------- -! parse damage from config file +! parse source mechanisms 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 - if (any(phase_damage == LOCAL_DAMAGE_isoBrittle_ID)) call damage_isoBrittle_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_isoductile_ID)) call damage_isoDuctile_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_anisoBrittle_ID)) call damage_anisoBrittle_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_anisoductile_ID)) call damage_anisoDuctile_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_gurson_ID)) call damage_gurson_init(FILEUNIT) - if (any(phase_damage == LOCAL_DAMAGE_phaseField_ID)) call damage_phaseField_init(FILEUNIT) + if (any(phase_source == SOURCE_thermal_dissipation_ID)) call source_thermal_dissipation_init(FILEUNIT) + if (any(phase_source == SOURCE_damage_isoBrittle_ID)) call source_damage_isoBrittle_init(FILEUNIT) + if (any(phase_source == SOURCE_damage_isoDuctile_ID)) call source_damage_isoDuctile_init(FILEUNIT) + if (any(phase_source == SOURCE_damage_anisoBrittle_ID)) call source_damage_anisoBrittle_init(FILEUNIT) + if (any(phase_source == SOURCE_damage_anisoDuctile_ID)) call source_damage_anisoDuctile_init(FILEUNIT) + if (any(phase_source == SOURCE_vacancy_phenoplasticity_ID)) call source_vacancy_phenoplasticity_init(FILEUNIT) + if (any(phase_source == SOURCE_vacancy_irradiation_ID)) call source_vacancy_irradiation_init(FILEUNIT) + if (any(phase_source == SOURCE_vacancy_thermalfluc_ID)) call source_vacancy_thermalfluc_init(FILEUNIT) close(FILEUNIT) !-------------------------------------------------------------------------------------------------- -! parse thermal from config file +! parse kinematic mechanisms 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_thermal == LOCAL_THERMAL_isothermal_ID)) call thermal_isothermal_init(temperature_init) - if (any(phase_thermal == LOCAL_THERMAL_adiabatic_ID)) call thermal_adiabatic_init(FILEUNIT,temperature_init) - close(FILEUNIT) - -!-------------------------------------------------------------------------------------------------- -! parse vacancy model 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_vacancy == LOCAL_VACANCY_constant_ID)) call vacancy_constant_init - if (any(phase_vacancy == LOCAL_VACANCY_generation_ID)) call vacancy_generation_init(FILEUNIT) + if (any(phase_kinematics == KINEMATICS_cleavage_opening_ID)) call kinematics_cleavage_opening_init(FILEUNIT) + if (any(phase_kinematics == KINEMATICS_slipplane_opening_ID)) call kinematics_slipplane_opening_init(FILEUNIT) + if (any(phase_kinematics == KINEMATICS_thermal_expansion_ID)) call kinematics_thermal_expansion_init(FILEUNIT) + if (any(phase_kinematics == KINEMATICS_vacancy_strain_ID)) call kinematics_vacancy_strain_init(FILEUNIT) + if (any(phase_kinematics == KINEMATICS_hydrogen_strain_ID)) call kinematics_hydrogen_strain_init(FILEUNIT) close(FILEUNIT) mainProcess: if (worldrank == 0) then @@ -289,134 +262,93 @@ subroutine constitutive_init(temperature_init) enddo endif endif - instance = phase_damageInstance(phase) ! which instance of a plasticity is present phase - knownDamage = .true. - select case(phase_damage(phase)) ! split per constititution - case (LOCAL_DAMAGE_none_ID) - outputName = LOCAL_DAMAGE_NONE_label - thisNoutput => null() - thisOutput => null() - thisSize => null() - case (LOCAL_DAMAGE_isoBrittle_ID) - outputName = LOCAL_DAMAGE_isoBrittle_LABEL - thisNoutput => damage_isoBrittle_Noutput - thisOutput => damage_isoBrittle_output - thisSize => damage_isoBrittle_sizePostResult - case (LOCAL_DAMAGE_isoDuctile_ID) - outputName = LOCAL_DAMAGE_isoDuctile_LABEL - thisNoutput => damage_isoDuctile_Noutput - thisOutput => damage_isoDuctile_output - thisSize => damage_isoDuctile_sizePostResult - case (LOCAL_DAMAGE_anisoBrittle_ID) - outputName = LOCAL_DAMAGE_anisoBrittle_label - thisNoutput => damage_anisoBrittle_Noutput - thisOutput => damage_anisoBrittle_output - thisSize => damage_anisoBrittle_sizePostResult - case (LOCAL_DAMAGE_anisoDuctile_ID) - outputName = LOCAL_DAMAGE_anisoDuctile_LABEL - thisNoutput => damage_anisoDuctile_Noutput - thisOutput => damage_anisoDuctile_output - thisSize => damage_anisoDuctile_sizePostResult - case (LOCAL_DAMAGE_gurson_ID) - outputName = LOCAL_DAMAGE_gurson_label - thisNoutput => damage_gurson_Noutput - thisOutput => damage_gurson_output - thisSize => damage_gurson_sizePostResult - case (LOCAL_DAMAGE_phaseField_ID) - outputName = LOCAL_DAMAGE_phaseField_label - thisNoutput => damage_phaseField_Noutput - thisOutput => damage_phaseField_output - thisSize => damage_phaseField_sizePostResult - case default - knownDamage = .false. - end select - if (knownDamage) then - write(FILEUNIT,'(a)') '(damage)'//char(9)//trim(outputName) - if (phase_damage(phase) /= LOCAL_DAMAGE_none_ID) then + do mySource = 1_pInt, phase_Nsources(phase) + knownSource = .true. + select case (phase_source(mySource,phase)) + case (SOURCE_thermal_dissipation_ID) + instance = source_thermal_dissipation_instance(phase) + outputName = SOURCE_thermal_dissipation_label + thisNoutput => source_thermal_dissipation_Noutput + thisOutput => source_thermal_dissipation_output + thisSize => source_thermal_dissipation_sizePostResult + case (SOURCE_damage_isoBrittle_ID) + instance = source_damage_isoBrittle_instance(phase) + outputName = SOURCE_damage_isoBrittle_label + thisNoutput => source_damage_isoBrittle_Noutput + thisOutput => source_damage_isoBrittle_output + thisSize => source_damage_isoBrittle_sizePostResult + case (SOURCE_damage_isoDuctile_ID) + instance = source_damage_isoDuctile_instance(phase) + outputName = SOURCE_damage_isoDuctile_label + thisNoutput => source_damage_isoDuctile_Noutput + thisOutput => source_damage_isoDuctile_output + thisSize => source_damage_isoDuctile_sizePostResult + case (SOURCE_damage_anisoBrittle_ID) + instance = source_damage_anisoBrittle_instance(phase) + outputName = SOURCE_damage_anisoBrittle_label + thisNoutput => source_damage_anisoBrittle_Noutput + thisOutput => source_damage_anisoBrittle_output + thisSize => source_damage_anisoBrittle_sizePostResult + case (SOURCE_damage_anisoDuctile_ID) + instance = source_damage_anisoDuctile_instance(phase) + outputName = SOURCE_damage_anisoDuctile_label + thisNoutput => source_damage_anisoDuctile_Noutput + thisOutput => source_damage_anisoDuctile_output + thisSize => source_damage_anisoDuctile_sizePostResult + case (SOURCE_vacancy_phenoplasticity_ID) + instance = source_vacancy_phenoplasticity_instance(phase) + outputName = SOURCE_vacancy_phenoplasticity_label + thisNoutput => source_vacancy_phenoplasticity_Noutput + thisOutput => source_vacancy_phenoplasticity_output + thisSize => source_vacancy_phenoplasticity_sizePostResult + case (SOURCE_vacancy_irradiation_ID) + instance = source_vacancy_irradiation_instance(phase) + outputName = SOURCE_vacancy_irradiation_label + thisNoutput => source_vacancy_irradiation_Noutput + thisOutput => source_vacancy_irradiation_output + thisSize => source_vacancy_irradiation_sizePostResult + case (SOURCE_vacancy_thermalfluc_ID) + instance = source_vacancy_thermalfluc_instance(phase) + outputName = SOURCE_vacancy_thermalfluc_label + thisNoutput => source_vacancy_thermalfluc_Noutput + thisOutput => source_vacancy_thermalfluc_output + thisSize => source_vacancy_thermalfluc_sizePostResult + case default + knownSource = .false. + end select + if (knownSource) then + write(FILEUNIT,'(a)') '(source)'//char(9)//trim(outputName) do e = 1_pInt,thisNoutput(instance) write(FILEUNIT,'(a,i4)') trim(thisOutput(e,instance))//char(9),thisSize(e,instance) enddo endif - endif - instance = phase_thermalInstance(phase) ! which instance is present phase - knownThermal = .true. - select case(phase_thermal(phase)) ! split per constititution - case (LOCAL_THERMAL_isothermal_ID) - outputName = LOCAL_THERMAL_ISOTHERMAL_label - thisNoutput => null() - thisOutput => null() - thisSize => null() - case (LOCAL_THERMAL_adiabatic_ID) - outputName = LOCAL_THERMAL_ADIABATIC_label - thisNoutput => thermal_adiabatic_Noutput - thisOutput => thermal_adiabatic_output - thisSize => thermal_adiabatic_sizePostResult - case default - knownThermal = .false. - end select - if (knownThermal) then - write(FILEUNIT,'(a)') '(thermal)'//char(9)//trim(outputName) - if (phase_thermal(phase) /= LOCAL_THERMAL_isothermal_ID) then - do e = 1_pInt,thisNoutput(instance) - write(FILEUNIT,'(a,i4)') trim(thisOutput(e,instance))//char(9),thisSize(e,instance) - enddo - endif - endif - instance = phase_vacancyInstance(phase) ! which instance is present phase - knownVacancy = .true. - select case(phase_vacancy(phase)) ! split per constititution - case (LOCAL_VACANCY_constant_ID) - outputName = LOCAL_VACANCY_constant_label - thisNoutput => null() - thisOutput => null() - thisSize => null() - case (LOCAL_VACANCY_generation_ID) - outputName = LOCAL_VACANCY_generation_label - thisNoutput => vacancy_generation_Noutput - thisOutput => vacancy_generation_output - thisSize => vacancy_generation_sizePostResult - case default - knownVacancy = .false. - end select - if (knownVacancy) then - write(FILEUNIT,'(a)') '(vacancy)'//char(9)//trim(outputName) - if (phase_vacancy(phase) /= LOCAL_VACANCY_constant_ID) then - do e = 1_pInt,thisNoutput(instance) - write(FILEUNIT,'(a,i4)') trim(thisOutput(e,instance))//char(9),thisSize(e,instance) - enddo - endif - endif + enddo endif enddo close(FILEUNIT) endif - constitutive_maxSizeDotState = 0_pInt - constitutive_maxSizePostResults = 0_pInt - constitutive_damage_maxSizePostResults = 0_pInt - constitutive_damage_maxSizeDotState = 0_pInt - constitutive_thermal_maxSizePostResults = 0_pInt - constitutive_thermal_maxSizeDotState = 0_pInt - constitutive_vacancy_maxSizePostResults = 0_pInt - constitutive_vacancy_maxSizeDotState = 0_pInt + constitutive_plasticity_maxSizeDotState = 0_pInt + constitutive_plasticity_maxSizePostResults = 0_pInt + constitutive_source_maxSizeDotState = 0_pInt + constitutive_source_maxSizePostResults = 0_pInt PhaseLoop2:do phase = 1_pInt,material_Nphase - plasticState(phase)%partionedState0 = plasticState(phase)%State0 - plasticState(phase)%State = plasticState(phase)%State0 - constitutive_maxSizeDotState = max(constitutive_maxSizeDotState, plasticState(phase)%sizeDotState) - constitutive_maxSizePostResults = max(constitutive_maxSizePostResults, plasticState(phase)%sizePostResults) - damageState(phase)%partionedState0 = damageState(phase)%State0 - damageState(phase)%State = damageState(phase)%State0 - constitutive_damage_maxSizeDotState = max(constitutive_damage_maxSizeDotState, damageState(phase)%sizeDotState) - constitutive_damage_maxSizePostResults = max(constitutive_damage_maxSizePostResults, damageState(phase)%sizePostResults) - thermalState(phase)%partionedState0 = thermalState(phase)%State0 - thermalState(phase)%State = thermalState(phase)%State0 - constitutive_thermal_maxSizeDotState = max(constitutive_thermal_maxSizeDotState, thermalState(phase)%sizeDotState) - constitutive_thermal_maxSizePostResults = max(constitutive_thermal_maxSizePostResults, thermalState(phase)%sizePostResults) - vacancyState(phase)%partionedState0 = vacancyState(phase)%State0 - vacancyState(phase)%State = vacancyState(phase)%State0 - constitutive_vacancy_maxSizeDotState = max(constitutive_vacancy_maxSizeDotState, vacancyState(phase)%sizeDotState) - constitutive_vacancy_maxSizePostResults = max(constitutive_vacancy_maxSizePostResults, vacancyState(phase)%sizePostResults) + plasticState (phase)%partionedState0 = plasticState (phase)%State0 + plasticState (phase)%State = plasticState (phase)%State0 + forall(mySource = 1_pInt:phase_Nsources(phase)) & + sourceState(phase)%p(mySource)%partionedState0 = sourceState(phase)%p(mySource)%State0 + forall(mySource = 1_pInt:phase_Nsources(phase)) & + sourceState(phase)%p(mySource)%State = sourceState(phase)%p(mySource)%State0 + + constitutive_plasticity_maxSizeDotState = max(constitutive_plasticity_maxSizeDotState, & + plasticState(phase)%sizeDotState) + constitutive_plasticity_maxSizePostResults = max(constitutive_plasticity_maxSizePostResults, & + plasticState(phase)%sizePostResults) + constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & + maxval(sourceState(phase)%p(:)%sizeDotState)) + constitutive_source_maxSizePostResults = max(constitutive_source_maxSizePostResults, & + maxval(sourceState(phase)%p(:)%sizePostResults)) enddo PhaseLoop2 #ifdef HDF @@ -434,7 +366,7 @@ subroutine constitutive_init(temperature_init) !-------------------------------------------------------------------------------------------------- ! report constitutive_maxSizeState = maxval(constitutive_sizeState) - constitutive_maxSizeDotState = maxval(constitutive_sizeDotState) + constitutive_plasticity_maxSizeDotState = maxval(constitutive_sizeDotState) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) then write(6,'(a32,1x,7(i8,1x))') 'constitutive_state0: ', shape(constitutive_state0) @@ -448,8 +380,8 @@ subroutine constitutive_init(temperature_init) write(6,'(a32,1x,7(i8,1x))') 'constitutive_sizeDotState: ', shape(constitutive_sizeDotState) write(6,'(a32,1x,7(i8,1x),/)') 'constitutive_sizePostResults: ', shape(constitutive_sizePostResults) write(6,'(a32,1x,7(i8,1x))') 'maxSizeState: ', constitutive_maxSizeState - write(6,'(a32,1x,7(i8,1x))') 'maxSizeDotState: ', constitutive_maxSizeDotState - write(6,'(a32,1x,7(i8,1x))') 'maxSizePostResults: ', constitutive_maxSizePostResults + write(6,'(a32,1x,7(i8,1x))') 'maxSizeDotState: ', constitutive_plasticity_maxSizeDotState + write(6,'(a32,1x,7(i8,1x))') 'maxSizePostResults: ', constitutive_plasticity_maxSizePostResults endif flush(6) #endif @@ -506,76 +438,23 @@ function constitutive_homogenizedC(ipc,ip,el) end function constitutive_homogenizedC -!-------------------------------------------------------------------------------------------------- -!> @brief returns the damaged elasticity matrix if relevant -!-------------------------------------------------------------------------------------------------- -function constitutive_damagedC(ipc,ip,el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_phaseField_ID, & - phase_damage - use damage_isoBrittle, only: & - damage_isoBrittle_getDamagedC66 - use damage_isoDuctile, only: & - damage_isoDuctile_getDamagedC66 - use damage_phaseField, only: & - damage_phaseField_getDamagedC66 - - implicit none - real(pReal), dimension(6,6) :: constitutive_damagedC - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el - - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_isoBrittle_ID) - constitutive_damagedC = damage_isoBrittle_getDamagedC66(constitutive_homogenizedC(ipc,ip,el), & - ipc,ip,el) - - case (LOCAL_DAMAGE_isoDuctile_ID) - constitutive_damagedC = damage_isoDuctile_getDamagedC66(constitutive_homogenizedC(ipc,ip,el), & - ipc,ip,el) - - case (LOCAL_DAMAGE_phaseField_ID) - constitutive_damagedC = damage_phaseField_getDamagedC66(constitutive_homogenizedC(ipc,ip,el), & - ipc,ip,el) - case default - constitutive_damagedC = constitutive_homogenizedC(ipc,ip,el) - - end select - -end function constitutive_damagedC - !-------------------------------------------------------------------------------------------------- !> @brief calls microstructure function of the different constitutive models !-------------------------------------------------------------------------------------------------- -subroutine constitutive_microstructure(Tstar_v, Fe, Fp, Lp, subdt, ipc, ip, el) +subroutine constitutive_microstructure(Fe, Fp, ipc, ip, el) use prec, only: & pReal use material, only: & phase_plasticity, & - phase_damage, & - phase_thermal, & - phase_vacancy, & material_phase, & + material_homog, & + temperature, & + thermalMapping, & PLASTICITY_dislotwin_ID, & PLASTICITY_dislokmc_ID, & PLASTICITY_disloucla_ID, & PLASTICITY_titanmod_ID, & - PLASTICITY_nonlocal_ID, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID, & - LOCAL_VACANCY_generation_ID, & - LOCAL_THERMAL_adiabatic_ID + PLASTICITY_nonlocal_ID use plastic_titanmod, only: & plastic_titanmod_microstructure use plastic_nonlocal, only: & @@ -586,86 +465,36 @@ subroutine constitutive_microstructure(Tstar_v, Fe, Fp, Lp, subdt, ipc, ip, el) plastic_dislokmc_microstructure use plastic_disloucla, only: & plastic_disloucla_microstructure - use damage_isoBrittle, only: & - damage_isoBrittle_microstructure - use damage_isoDuctile, only: & - damage_isoDuctile_microstructure - use damage_anisoBrittle, only: & - damage_anisoBrittle_microstructure - use damage_anisoDuctile, only: & - damage_anisoDuctile_microstructure - use damage_gurson, only: & - damage_gurson_microstructure - use damage_phaseField, only: & - damage_phaseField_microstructure - use vacancy_generation, only: & - vacancy_generation_microstructure - use thermal_adiabatic, only: & - thermal_adiabatic_microstructure implicit none integer(pInt), intent(in) :: & ipc, & !< grain number ip, & !< integration point number el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) real(pReal), intent(in), dimension(3,3) :: & Fe, & !< elastic deformation gradient - Fp, & !< plastic deformation gradient - Lp - real(pReal), intent(in) :: & - subdt !< timestep + Fp !< plastic deformation gradient + integer(pInt) :: & + phase, homog, offset - select case (phase_plasticity(material_phase(ipc,ip,el))) + phase = material_phase(ipc,ip,el) + homog = material_homog( ip,el) + offset = thermalMapping(homog)%p(ip,el) + select case (phase_plasticity(phase)) case (PLASTICITY_DISLOTWIN_ID) - call plastic_dislotwin_microstructure(constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + call plastic_dislotwin_microstructure(temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_DISLOKMC_ID) - call plastic_dislokmc_microstructure(constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + call plastic_dislokmc_microstructure (temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_DISLOUCLA_ID) - call plastic_disloucla_microstructure(constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + call plastic_disloucla_microstructure(temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_TITANMOD_ID) - call plastic_titanmod_microstructure (constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + call plastic_titanmod_microstructure (temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_NONLOCAL_ID) - call plastic_nonlocal_microstructure (Fe,Fp, ip,el) + call plastic_nonlocal_microstructure (Fe,Fp,ip,el) end select - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_isoBrittle_ID) - call damage_isoBrittle_microstructure(constitutive_homogenizedC(ipc,ip,el), Fe, subdt, & - ipc, ip, el) - case (LOCAL_DAMAGE_isoDuctile_ID) - call damage_isoDuctile_microstructure(subdt, ipc, ip, el) - case (LOCAL_DAMAGE_anisoBrittle_ID) - call damage_anisoBrittle_microstructure(Tstar_v, subdt, ipc, ip, el) - case (LOCAL_DAMAGE_anisoDuctile_ID) - call damage_anisoDuctile_microstructure(subdt, ipc, ip, el) - case (LOCAL_DAMAGE_gurson_ID) - call damage_gurson_microstructure(ipc, ip, el) - case (LOCAL_DAMAGE_phaseField_ID) - call damage_phaseField_microstructure(constitutive_homogenizedC(ipc,ip,el), Fe, & - constitutive_getVacancyConcentration(ipc, ip, el), & - subdt, ipc, ip, el) - - end select - - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - call thermal_adiabatic_microstructure(Tstar_v, Lp, subdt, ipc, ip, el) - - end select - - select case (phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - call vacancy_generation_microstructure(Tstar_v, & - constitutive_getTemperature(ipc,ip,el), & - constitutive_getDamage(ipc, ip, el), & - subdt,ipc,ip,el) - - end select - end subroutine constitutive_microstructure @@ -684,6 +513,9 @@ subroutine constitutive_LpAndItsTangent(Lp, dLp_dTstar3333, dLp_dFi3333, Tstar_v use material, only: & phase_plasticity, & material_phase, & + material_homog, & + temperature, & + thermalMapping, & PLASTICITY_NONE_ID, & PLASTICITY_J2_ID, & PLASTICITY_PHENOPOWERLAW_ID, & @@ -728,11 +560,14 @@ subroutine constitutive_LpAndItsTangent(Lp, dLp_dTstar3333, dLp_dFi3333, Tstar_v real(pReal), dimension(3,3) :: & temp_33 integer(pInt) :: & - i, j + i, j, phase, homog, offset + phase = material_phase(ipc,ip,el) + homog = material_homog( ip,el) + offset = thermalMapping(homog)%p(ip,el) Mstar_v = math_Mandel33to6(math_mul33x33(math_mul33x33(math_transpose33(Fi),Fi), & math_Mandel6to33(Tstar_v))) - select case (phase_plasticity(material_phase(ipc,ip,el))) + select case (phase_plasticity(phase)) case (PLASTICITY_NONE_ID) Lp = 0.0_pReal @@ -743,23 +578,23 @@ subroutine constitutive_LpAndItsTangent(Lp, dLp_dTstar3333, dLp_dFi3333, Tstar_v call plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v,ipc,ip,el) case (PLASTICITY_NONLOCAL_ID) call plastic_nonlocal_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v, & - constitutive_getTemperature(ipc,ip,el), & + temperature(homog)%p(offset), & ip,el) case (PLASTICITY_DISLOTWIN_ID) call plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v, & - constitutive_getTemperature(ipc,ip,el), & + temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_DISLOKMC_ID) call plastic_dislokmc_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v, & - constitutive_getTemperature(ipc,ip,el), & + temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_DISLOUCLA_ID) call plastic_disloucla_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v, & - constitutive_getTemperature(ipc,ip,el), & - ipc,ip,el) + temperature(homog)%p(offset), & + ipc,ip,el) case (PLASTICITY_TITANMOD_ID) call plastic_titanmod_LpAndItsTangent(Lp,dLp_dMstar,Mstar_v, & - constitutive_getTemperature(ipc,ip,el), & + temperature(homog)%p(offset), & ipc,ip,el) end select @@ -781,7 +616,7 @@ end subroutine constitutive_LpAndItsTangent !-------------------------------------------------------------------------------------------------- !> @brief contains the constitutive equation for calculating the velocity gradient !-------------------------------------------------------------------------------------------------- -subroutine constitutive_LiAndItsTangent(Li, dLi_dTstar3333, dLi_dFi3333, Tstar_v, Fi, Lp, ipc, ip, el) +subroutine constitutive_LiAndItsTangent(Li, dLi_dTstar3333, dLi_dFi3333, Tstar_v, Fi, ipc, ip, el) use prec, only: & pReal use math, only: & @@ -791,18 +626,24 @@ subroutine constitutive_LiAndItsTangent(Li, dLi_dTstar3333, dLi_dFi3333, Tstar_v math_transpose33, & math_mul33x33 use material, only: & - phase_damage, & - phase_thermal, & + phase_kinematics, & + phase_Nkinematics, & material_phase, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_THERMAL_adiabatic_ID - use damage_anisoBrittle, only: & - damage_anisoBrittle_LdAndItsTangent - use damage_anisoDuctile, only: & - damage_anisoDuctile_LdAndItsTangent - use thermal_adiabatic, only: & - thermal_adiabatic_LTAndItsTangent + KINEMATICS_cleavage_opening_ID, & + KINEMATICS_slipplane_opening_ID, & + KINEMATICS_thermal_expansion_ID, & + KINEMATICS_vacancy_strain_ID, & + KINEMATICS_hydrogen_strain_ID + use kinematics_cleavage_opening, only: & + kinematics_cleavage_opening_LiAndItsTangent + use kinematics_slipplane_opening, only: & + kinematics_slipplane_opening_LiAndItsTangent + use kinematics_thermal_expansion, only: & + kinematics_thermal_expansion_LiAndItsTangent + use kinematics_vacancy_strain, only: & + kinematics_vacancy_strain_LiAndItsTangent + use kinematics_hydrogen_strain, only: & + kinematics_hydrogen_strain_LiAndItsTangent implicit none integer(pInt), intent(in) :: & @@ -812,49 +653,53 @@ subroutine constitutive_LiAndItsTangent(Li, dLi_dTstar3333, dLi_dFi3333, Tstar_v real(pReal), intent(in), dimension(6) :: & Tstar_v !< 2nd Piola-Kirchhoff stress real(pReal), intent(in), dimension(3,3) :: & - Fi, & !< intermediate deformation gradient - Lp !< plastic velocity gradient + Fi !< intermediate deformation gradient real(pReal), intent(out), dimension(3,3) :: & Li !< intermediate velocity gradient real(pReal), intent(out), dimension(3,3,3,3) :: & dLi_dTstar3333, & !< derivative of Li with respect to Tstar (4th-order tensor) dLi_dFi3333 real(pReal), dimension(3,3) :: & - Li_temp !< intermediate velocity gradient + my_Li !< intermediate velocity gradient real(pReal), dimension(3,3,3,3) :: & - dLi_dTstar_temp + my_dLi_dTstar real(pReal), dimension(3,3) :: & FiInv, & temp_33 real(pReal) :: & detFi integer(pInt) :: & - i, j + i, j, kinematics Li = 0.0_pReal dLi_dTstar3333 = 0.0_pReal dLi_dFi3333 = 0.0_pReal - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_anisoBrittle_ID) - call damage_anisoBrittle_LdAndItsTangent(Li_temp, dLi_dTstar_temp, Tstar_v, ipc, ip, el) - Li = Li + Li_temp - dLi_dTstar3333 = dLi_dTstar3333 + dLi_dTstar_temp + do kinematics = 1_pInt, phase_Nkinematics(material_phase(ipc,ip,el)) + select case (phase_kinematics(kinematics,material_phase(ipc,ip,el))) + case (KINEMATICS_cleavage_opening_ID) + call kinematics_cleavage_opening_LiAndItsTangent(my_Li, my_dLi_dTstar, Tstar_v, ipc, ip, el) - case (LOCAL_DAMAGE_anisoDuctile_ID) - call damage_anisoDuctile_LdAndItsTangent(Li_temp, dLi_dTstar_temp, Tstar_v, ipc, ip, el) - Li = Li + Li_temp - dLi_dTstar3333 = dLi_dTstar3333 + dLi_dTstar_temp - end select + case (KINEMATICS_slipplane_opening_ID) + call kinematics_slipplane_opening_LiAndItsTangent(my_Li, my_dLi_dTstar, Tstar_v, ipc, ip, el) + + case (KINEMATICS_thermal_expansion_ID) + call kinematics_thermal_expansion_LiAndItsTangent(my_Li, my_dLi_dTstar, ipc, ip, el) + + case (KINEMATICS_vacancy_strain_ID) + call kinematics_vacancy_strain_LiAndItsTangent(my_Li, my_dLi_dTstar, ipc, ip, el) + + case (KINEMATICS_hydrogen_strain_ID) + call kinematics_hydrogen_strain_LiAndItsTangent(my_Li, my_dLi_dTstar, ipc, ip, el) + + case default + my_Li = 0.0_pReal + my_dLi_dTstar = 0.0_pReal + end select + Li = Li + my_Li + dLi_dTstar3333 = dLi_dTstar3333 + my_dLi_dTstar +enddo - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - call thermal_adiabatic_LTAndItsTangent(Li_temp, dLi_dTstar_temp, Tstar_v, Lp, ipc, ip, el) - Li = Li + Li_temp - dLi_dTstar3333 = dLi_dTstar3333 + dLi_dTstar_temp - - end select - FiInv = math_inv33(Fi) detFi = math_det33(Fi) Li = math_mul33x33(math_mul33x33(Fi,Li),FiInv)*detFi !< push forward to intermediate configuration @@ -912,6 +757,17 @@ subroutine constitutive_hooke_TandItsTangent(T, dT_dFe, dT_dFi, Fe, Fi, ipc, ip, math_transpose33, & math_trace33, & math_I3 + use material, only: & + material_phase, & + material_homog, & + phase_NstiffnessDegradations, & + phase_stiffnessDegradation, & + damage, & + damageMapping, & + porosity, & + porosityMapping, & + STIFFNESS_DEGRADATION_damage_ID, & + STIFFNESS_DEGRADATION_porosity_ID implicit none integer(pInt), intent(in) :: & @@ -927,11 +783,27 @@ subroutine constitutive_hooke_TandItsTangent(T, dT_dFe, dT_dFi, Fe, Fi, ipc, ip, dT_dFe, & !< derivative of 2nd P-K stress with respect to elastic deformation gradient dT_dFi !< derivative of 2nd P-K stress with respect to intermediate deformation gradient - integer(pInt) :: i, j + integer(pInt) :: i, j, phase, homog real(pReal), dimension(3,3) :: E real(pReal), dimension(3,3,3,3) :: C - C = math_Mandel66to3333(constitutive_damagedC(ipc,ip,el)) !< elastic stiffness in lattice configuration + phase = material_phase(ipc,ip,el) + homog = material_homog(ip,el) + C = math_Mandel66to3333(constitutive_homogenizedC(ipc,ip,el)) + do i = 1_pInt, phase_NstiffnessDegradations(phase) + select case(phase_stiffnessDegradation(i,phase)) + case (STIFFNESS_DEGRADATION_damage_ID) + C = damage(homog)%p(damageMapping(homog)%p(ip,el))* & + damage(homog)%p(damageMapping(homog)%p(ip,el))* & + C + + case (STIFFNESS_DEGRADATION_porosity_ID) + C = porosity(homog)%p(porosityMapping(homog)%p(ip,el))* & + porosity(homog)%p(porosityMapping(homog)%p(ip,el))* & + C + end select + enddo + E = 0.5_pReal*(math_mul33x33(math_transpose33(Fe),Fe)-math_I3) !< Green-Lagrange strain in unloaded configuration T = math_mul3333xx33(C,math_mul33x33(math_mul33x33(math_transpose33(Fi),E),Fi)) !< 2PK stress in lattice configuration in work conjugate with GL strain pulled back to lattice configuration @@ -948,8 +820,7 @@ end subroutine constitutive_hooke_TandItsTangent !-------------------------------------------------------------------------------------------------- !> @brief contains the constitutive equation for calculating the rate of change of microstructure !-------------------------------------------------------------------------------------------------- -subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, subfracArray,& - ipc, ip, el) +subroutine constitutive_collectDotState(Tstar_v, FeArray, FpArray, subdt, subfracArray,ipc, ip, el) use prec, only: & pReal, & pLongInt @@ -964,8 +835,12 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su mesh_maxNips use material, only: & phase_plasticity, & - phase_damage, & + phase_source, & + phase_Nsources, & material_phase, & + material_homog, & + temperature, & + thermalMapping, & homogenization_maxNgrains, & PLASTICITY_none_ID, & PLASTICITY_j2_ID, & @@ -975,7 +850,9 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su PLASTICITY_disloucla_ID, & PLASTICITY_titanmod_ID, & PLASTICITY_nonlocal_ID, & - LOCAL_DAMAGE_gurson_ID + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID use plastic_j2, only: & plastic_j2_dotState use plastic_phenopowerlaw, only: & @@ -990,8 +867,12 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su plastic_titanmod_dotState use plastic_nonlocal, only: & plastic_nonlocal_dotState - use damage_gurson, only: & - damage_gurson_dotState + use source_damage_isoDuctile, only: & + source_damage_isoDuctile_dotState + use source_damage_anisoBrittle, only: & + source_damage_anisoBrittle_dotState + use source_damage_anisoDuctile, only: & + source_damage_anisoDuctile_dotState implicit none integer(pInt), intent(in) :: & @@ -1007,42 +888,52 @@ subroutine constitutive_collectDotState(Tstar_v, Lp, FeArray, FpArray, subdt, su FpArray !< plastic deformation gradient real(pReal), intent(in), dimension(6) :: & Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) - real(pReal), intent(in), dimension(3,3) :: & - Lp !< plastic velocity gradient integer(pLongInt) :: & tick, tock, & tickrate, & maxticks + integer(pInt) :: & + phase, homog, offset, mySource if (iand(debug_level(debug_constitutive), debug_levelBasic) /= 0_pInt) & call system_clock(count=tick,count_rate=tickrate,count_max=maxticks) - select case (phase_plasticity(material_phase(ipc,ip,el))) + phase = material_phase(ipc,ip,el) + homog = material_homog( ip,el) + offset = thermalMapping(homog)%p(ip,el) + select case (phase_plasticity(phase)) case (PLASTICITY_J2_ID) call plastic_j2_dotState (Tstar_v,ipc,ip,el) case (PLASTICITY_PHENOPOWERLAW_ID) call plastic_phenopowerlaw_dotState(Tstar_v,ipc,ip,el) case (PLASTICITY_DISLOTWIN_ID) - call plastic_dislotwin_dotState (Tstar_v,constitutive_getTemperature(ipc,ip,el), & + call plastic_dislotwin_dotState (Tstar_v,temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_DISLOKMC_ID) - call plastic_dislokmc_dotState (Tstar_v,constitutive_getTemperature(ipc,ip,el), & + call plastic_dislokmc_dotState (Tstar_v,temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_DISLOUCLA_ID) - call plastic_disloucla_dotState (Tstar_v,constitutive_getTemperature(ipc,ip,el), & + call plastic_disloucla_dotState (Tstar_v,temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_TITANMOD_ID) - call plastic_titanmod_dotState (Tstar_v,constitutive_getTemperature(ipc,ip,el), & + call plastic_titanmod_dotState (Tstar_v,temperature(homog)%p(offset), & ipc,ip,el) case (PLASTICITY_NONLOCAL_ID) - call plastic_nonlocal_dotState (Tstar_v,FeArray,FpArray,constitutive_getTemperature(ipc,ip,el), & + call plastic_nonlocal_dotState (Tstar_v,FeArray,FpArray,temperature(homog)%p(offset), & subdt,subfracArray,ip,el) end select - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_gurson_ID) - call damage_gurson_dotState(Tstar_v, Lp, ipc, ip, el) - end select + do mySource = 1_pInt, phase_Nsources(phase) + select case (phase_source(mySource,phase)) + case (SOURCE_damage_anisoBrittle_ID) + call source_damage_anisoBrittle_dotState(Tstar_v, ipc, ip, el) + case (SOURCE_damage_isoDuctile_ID) + call source_damage_isoDuctile_dotState ( ipc, ip, el) + case (SOURCE_damage_anisoDuctile_ID) + call source_damage_anisoDuctile_dotState( ipc, ip, el) + + end select + enddo if (iand(debug_level(debug_constitutive), debug_levelBasic) /= 0_pInt) then call system_clock(count=tock,count_rate=tickrate,count_max=maxticks) @@ -1059,7 +950,7 @@ end subroutine constitutive_collectDotState !> @brief for constitutive models having an instantaneous change of state (so far, only nonlocal) !> will return false if delta state is not needed/supported by the constitutive model !-------------------------------------------------------------------------------------------------- -logical function constitutive_collectDeltaState(Tstar_v, ipc, ip, el) +logical function constitutive_collectDeltaState(Tstar_v, Fe, ipc, ip, el) use prec, only: & pReal, & pLongInt @@ -1071,10 +962,21 @@ logical function constitutive_collectDeltaState(Tstar_v, ipc, ip, el) debug_levelBasic use material, only: & phase_plasticity, & + phase_source, & + phase_Nsources, & material_phase, & - PLASTICITY_NONLOCAL_ID + PLASTICITY_NONLOCAL_ID, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID use plastic_nonlocal, only: & plastic_nonlocal_deltaState + use source_damage_isoBrittle, only: & + source_damage_isoBrittle_deltaState + use source_vacancy_irradiation, only: & + source_vacancy_irradiation_deltaState + use source_vacancy_thermalfluc, only: & + source_vacancy_thermalfluc_deltaState implicit none integer(pInt), intent(in) :: & @@ -1083,6 +985,10 @@ logical function constitutive_collectDeltaState(Tstar_v, ipc, ip, el) el !< element number real(pReal), intent(in), dimension(6) :: & Tstar_v !< 2nd Piola-Kirchhoff stress + real(pReal), intent(in), dimension(3,3) :: & + Fe !< elastic deformation gradient + integer(pInt) :: & + mySource integer(pLongInt) :: & tick, tock, & tickrate, & @@ -1101,6 +1007,22 @@ logical function constitutive_collectDeltaState(Tstar_v, ipc, ip, el) end select + do mySource = 1_pInt, phase_Nsources(material_phase(ipc,ip,el)) + select case (phase_source(mySource,material_phase(ipc,ip,el))) + case (SOURCE_damage_isoBrittle_ID) + constitutive_collectDeltaState = constitutive_collectDeltaState .and. .true. + call source_damage_isoBrittle_deltaState (constitutive_homogenizedC(ipc,ip,el), Fe, & + ipc, ip, el) + case (SOURCE_vacancy_irradiation_ID) + constitutive_collectDeltaState = constitutive_collectDeltaState .and. .true. + call source_vacancy_irradiation_deltaState(ipc, ip, el) + case (SOURCE_vacancy_thermalfluc_ID) + constitutive_collectDeltaState = constitutive_collectDeltaState .and. .true. + call source_vacancy_thermalfluc_deltaState(ipc, ip, el) + + end select + enddo + if (iand(debug_level(debug_constitutive), debug_levelBasic) /= 0_pInt) then call system_clock(count=tock,count_rate=tickrate,count_max=maxticks) !$OMP CRITICAL (debugTimingDeltaState) @@ -1114,540 +1036,6 @@ logical function constitutive_collectDeltaState(Tstar_v, ipc, ip, el) end function constitutive_collectDeltaState -!-------------------------------------------------------------------------------------------------- -!> @brief Returns the local(regularised) damage -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getLocalDamage(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_phaseField_ID, & - phase_damage - use damage_isoBrittle, only: & - damage_isoBrittle_getLocalDamage - use damage_isoDuctile, only: & - damage_isoDuctile_getLocalDamage - use damage_anisoBrittle, only: & - damage_anisoBrittle_getLocalDamage - use damage_anisoDuctile, only: & - damage_anisoDuctile_getLocalDamage - use damage_phaseField, only: & - damage_phaseField_getLocalDamage - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getLocalDamage - - select case (phase_damage(material_phase(ipc,ip,el))) - case default - constitutive_getLocalDamage = 1.0_pReal - - case (LOCAL_DAMAGE_isoBrittle_ID) - constitutive_getLocalDamage = damage_isoBrittle_getLocalDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_isoDuctile_ID) - constitutive_getLocalDamage = damage_isoDuctile_getLocalDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_anisoBrittle_ID) - constitutive_getLocalDamage = damage_anisoBrittle_getLocalDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_anisoDuctile_ID) - constitutive_getLocalDamage = damage_anisoDuctile_getLocalDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_phaseField_ID) - constitutive_getLocalDamage = damage_phaseField_getLocalDamage(ipc, ip, el) - - end select - -end function constitutive_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns the local(unregularised) damage -!-------------------------------------------------------------------------------------------------- -subroutine constitutive_putLocalDamage(ipc, ip, el, localDamage) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID, & - phase_damage - use damage_isoBrittle, only: & - damage_isoBrittle_putLocalDamage - use damage_isoDuctile, only: & - damage_isoDuctile_putLocalDamage - use damage_anisoBrittle, only: & - damage_anisoBrittle_putLocalDamage - use damage_anisoDuctile, only: & - damage_anisoDuctile_putLocalDamage - use damage_gurson, only: & - damage_gurson_putLocalDamage - use damage_phaseField, only: & - damage_phaseField_putLocalDamage - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localDamage - - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_isoBrittle_ID) - call damage_isoBrittle_putLocalDamage(ipc, ip, el, localDamage) - - case (LOCAL_DAMAGE_isoDuctile_ID) - call damage_isoDuctile_putLocalDamage(ipc, ip, el, localDamage) - - case (LOCAL_DAMAGE_anisoBrittle_ID) - call damage_anisoBrittle_putLocalDamage(ipc, ip, el, localDamage) - - case (LOCAL_DAMAGE_anisoDuctile_ID) - call damage_anisoDuctile_putLocalDamage(ipc, ip, el, localDamage) - - case (LOCAL_DAMAGE_gurson_ID) - call damage_gurson_putLocalDamage(ipc, ip, el, localDamage) - - case (LOCAL_DAMAGE_phaseField_ID) - call damage_phaseField_putLocalDamage(ipc, ip, el, localDamage) - - end select - -end subroutine constitutive_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns nonlocal (regularised) damage -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getDamage(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_phaseField_ID, & - phase_damage - use damage_isoBrittle, only: & - damage_isoBrittle_getDamage - use damage_isoDuctile, only: & - damage_isoDuctile_getDamage - use damage_anisoBrittle, only: & - damage_anisoBrittle_getDamage - use damage_anisoDuctile, only: & - damage_anisoDuctile_getDamage - use damage_phaseField, only: & - damage_phaseField_getDamage - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getDamage - - select case (phase_damage(material_phase(ipc,ip,el))) - case default - constitutive_getDamage = 1.0_pReal - - case (LOCAL_DAMAGE_isoBrittle_ID) - constitutive_getDamage = damage_isoBrittle_getDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_isoDuctile_ID) - constitutive_getDamage = damage_isoDuctile_getDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_anisoBrittle_ID) - constitutive_getDamage = damage_anisoBrittle_getDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_anisoDuctile_ID) - constitutive_getDamage = damage_anisoDuctile_getDamage(ipc, ip, el) - - case (LOCAL_DAMAGE_phaseField_ID) - constitutive_getDamage = damage_phaseField_getDamage(ipc, ip, el) - - end select - -end function constitutive_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getDamageDiffusion33(ipc, ip, el) - use prec, only: & - pReal - use lattice, only: & - lattice_DamageDiffusion33 - use material, only: & - material_phase, & - phase_damage, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_phaseField_ID - use damage_isoBrittle, only: & - damage_isoBrittle_getDamageDiffusion33 - use damage_anisoBrittle, only: & - damage_anisoBrittle_getDamageDiffusion33 - use damage_phaseField, only: & - damage_phaseField_getDamageDiffusion33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - constitutive_getDamageDiffusion33 - - select case(phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_isoBrittle_ID) - constitutive_getDamageDiffusion33 = damage_isoBrittle_getDamageDiffusion33(ipc, ip, el) - case (LOCAL_DAMAGE_anisoBrittle_ID) - constitutive_getDamageDiffusion33 = damage_anisoBrittle_getDamageDiffusion33(ipc, ip, el) - case (LOCAL_DAMAGE_phaseField_ID) - constitutive_getDamageDiffusion33 = damage_phaseField_getDamageDiffusion33(ipc, ip, el) - case default - constitutive_getDamageDiffusion33 = lattice_DamageDiffusion33(1:3,1:3,material_phase(ipc,ip,el)) - - end select - -end function constitutive_getDamageDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local (unregularised) temperature -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getAdiabaticTemperature(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_THERMAL_adiabatic_ID, & - phase_thermal, & - phase_thermalInstance - use thermal_isothermal, only: & - thermal_isothermal_temperature - use thermal_adiabatic, only: & - thermal_adiabatic_getLocalTemperature - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getAdiabaticTemperature - - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - constitutive_getAdiabaticTemperature = thermal_adiabatic_getLocalTemperature(ipc, ip, el) - - case default - constitutive_getAdiabaticTemperature = & - thermal_isothermal_temperature(phase_thermalInstance(material_phase(ipc,ip,el))) - - end select - -end function constitutive_getAdiabaticTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief assigns the local/nonlocal value of temperature to local thermal state -!-------------------------------------------------------------------------------------------------- -subroutine constitutive_putAdiabaticTemperature(ipc, ip, el, localTemperature) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_THERMAL_adiabatic_ID, & - phase_thermal - use thermal_adiabatic, only: & - thermal_adiabatic_putLocalTemperature - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localTemperature - - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - call thermal_adiabatic_putLocalTemperature(ipc, ip, el, localTemperature) - - end select - -end subroutine constitutive_putAdiabaticTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief returns nonlocal (regularised) temperature -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getTemperature(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_THERMAL_adiabatic_ID, & - phase_thermal - use thermal_adiabatic, only: & - thermal_adiabatic_getTemperature - use thermal_isothermal, only: & - thermal_isothermal_temperature - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getTemperature - - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - constitutive_getTemperature = thermal_adiabatic_getTemperature(ipc, ip, el) - - case default - constitutive_getTemperature = thermal_isothermal_temperature(material_phase(ipc,ip,el)) - - end select - -end function constitutive_getTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief returns heat generation rate -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getHeatGeneration(Tstar_v, Lp, ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_THERMAL_adiabatic_ID, & - phase_thermal - use thermal_adiabatic, only: & - thermal_adiabatic_getHeatGeneration - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(in), dimension(3,3) :: & - Lp !< plastic velocity gradient - real(pReal) :: constitutive_getHeatGeneration - - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_adiabatic_ID) - constitutive_getHeatGeneration = thermal_adiabatic_getHeatGeneration(Tstar_v, Lp) - - case default - constitutive_getHeatGeneration = 0.0_pReal - - end select - -end function constitutive_getHeatGeneration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local vacancy concentration -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getLocalVacancyConcentration(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_getLocalConcentration - use lattice, only: & - lattice_equilibriumVacancyConcentration - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getLocalVacancyConcentration - - select case (phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_getLocalVacancyConcentration = vacancy_generation_getLocalConcentration(ipc, ip, el) - - case default - constitutive_getLocalVacancyConcentration = & - lattice_equilibriumVacancyConcentration(material_phase(ipc,ip,el)) - - end select - -end function constitutive_getLocalVacancyConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief Puts local vacancy concentration -!-------------------------------------------------------------------------------------------------- -subroutine constitutive_putLocalVacancyConcentration(ipc, ip, el, localVacancyConcentration) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_putLocalConcentration - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localVacancyConcentration - - select case (phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - call vacancy_generation_putLocalConcentration(ipc, ip, el, localVacancyConcentration) - - end select - -end subroutine constitutive_putLocalVacancyConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns nonlocal vacancy concentration -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getVacancyConcentration(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_getConcentration - use lattice, only: & - lattice_equilibriumVacancyConcentration - implicit none - - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: constitutive_getVacancyConcentration - - select case (phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_getVacancyConcentration = vacancy_generation_getConcentration(ipc, ip, el) - - case default - constitutive_getVacancyConcentration = & - lattice_equilibriumVacancyConcentration(material_phase(ipc,ip,el)) - - end select - -end function constitutive_getVacancyConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns vacancy diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getVacancyDiffusion33(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_getVacancyDiffusion33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - constitutive_getVacancyDiffusion33 - - select case(phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_getVacancyDiffusion33 = & - vacancy_generation_getVacancyDiffusion33(ipc,ip,el) - - end select - -end function constitutive_getVacancyDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns vacancy diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function constitutive_getVacancyMobility33(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_getVacancyMobility33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - constitutive_getVacancyMobility33 - - select case(phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_getVacancyMobility33 = & - vacancy_generation_getVacancyMobility33(constitutive_getTemperature(ipc,ip,el), & - ipc,ip,el) - - end select - -end function constitutive_getVacancyMobility33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns vacancy chemical potential driving force -!-------------------------------------------------------------------------------------------------- -pure real(pReal) function constitutive_getVacancyEnergy(ipc, ip, el) - use prec, only: & - pReal - use material, only: & - material_phase, & - LOCAL_VACANCY_generation_ID, & - phase_vacancy - use vacancy_generation, only: & - vacancy_generation_getVacancyEnergy - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - - select case(phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_getVacancyEnergy = & - vacancy_generation_getVacancyEnergy(ipc,ip,el) - - case default - constitutive_getVacancyEnergy = 0.0_pReal - - end select - -end function constitutive_getVacancyEnergy - - !-------------------------------------------------------------------------------------------------- !> @brief returns array of constitutive results !-------------------------------------------------------------------------------------------------- @@ -1659,14 +1047,14 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) mesh_maxNips use material, only: & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & phase_plasticity, & - phase_damage, & - phase_thermal, & - phase_vacancy, & + phase_source, & + phase_Nsources, & material_phase, & + material_homog, & + temperature, & + thermalMapping, & homogenization_maxNgrains, & PLASTICITY_NONE_ID, & PLASTICITY_J2_ID, & @@ -1676,14 +1064,10 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) PLASTICITY_DISLOUCLA_ID, & PLASTICITY_TITANMOD_ID, & PLASTICITY_NONLOCAL_ID, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID, & - LOCAL_THERMAL_ADIABATIC_ID, & - LOCAL_VACANCY_generation_ID + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID use plastic_j2, only: & #ifdef HDF plastic_j2_postResults2,& @@ -1701,22 +1085,14 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) plastic_titanmod_postResults use plastic_nonlocal, only: & plastic_nonlocal_postResults - use damage_isoBrittle, only: & - damage_isoBrittle_postResults - use damage_isoDuctile, only: & - damage_isoDuctile_postResults - use damage_anisoBrittle, only: & - damage_anisoBrittle_postResults - use damage_anisoDuctile, only: & - damage_anisoDuctile_postResults - use damage_gurson, only: & - damage_gurson_postResults - use damage_phaseField, only: & - damage_phaseField_postResults - use thermal_adiabatic, only: & - thermal_adiabatic_postResults - use vacancy_generation, only: & - vacancy_generation_postResults + use source_damage_isoBrittle, only: & + source_damage_isoBrittle_postResults + use source_damage_isoDuctile, only: & + source_damage_isoDuctile_postResults + use source_damage_anisoBrittle, only: & + source_damage_anisoBrittle_postResults + use source_damage_anisoDuctile, only: & + source_damage_anisoDuctile_postResults implicit none integer(pInt), intent(in) :: & @@ -1724,19 +1100,21 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) ip, & !< integration point number el !< element number real(pReal), dimension(plasticState(material_phase(ipc,ip,el))%sizePostResults + & - damageState( material_phase(ipc,ip,el))%sizePostResults + & - thermalState(material_phase(ipc,ip,el))%sizePostResults + & - vacancyState(material_phase(ipc,ip,el))%sizePostResults) :: & + sum(sourceState(material_phase(ipc,ip,el))%p(:)%sizePostResults)) :: & constitutive_postResults real(pReal), intent(in), dimension(3,3,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & FeArray !< elastic deformation gradient real(pReal), intent(in), dimension(6) :: & Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) integer(pInt) :: & - startPos, endPos + startPos, endPos, phase, homog, offset, mySource constitutive_postResults = 0.0_pReal + phase = material_phase(ipc,ip,el) + homog = material_homog( ip,el) + offset = thermalMapping(homog)%p(ip,el) + startPos = 1_pInt endPos = plasticState(material_phase(ipc,ip,el))%sizePostResults select case (phase_plasticity(material_phase(ipc,ip,el))) @@ -1749,50 +1127,33 @@ function constitutive_postResults(Tstar_v, FeArray, ipc, ip, el) plastic_phenopowerlaw_postResults(Tstar_v,ipc,ip,el) case (PLASTICITY_DISLOTWIN_ID) constitutive_postResults(startPos:endPos) = & - plastic_dislotwin_postResults(Tstar_v,constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + plastic_dislotwin_postResults(Tstar_v,temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_DISLOKMC_ID) constitutive_postResults(startPos:endPos) = & - plastic_dislokmc_postResults(Tstar_v,constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + plastic_dislokmc_postResults(Tstar_v,temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_DISLOUCLA_ID) constitutive_postResults(startPos:endPos) = & - plastic_disloucla_postResults(Tstar_v,constitutive_getTemperature(ipc,ip,el),ipc,ip,el) + plastic_disloucla_postResults(Tstar_v,temperature(homog)%p(offset),ipc,ip,el) case (PLASTICITY_NONLOCAL_ID) constitutive_postResults(startPos:endPos) = & plastic_nonlocal_postResults (Tstar_v,FeArray,ip,el) end select - startPos = endPos + 1_pInt - endPos = endPos + damageState(material_phase(ipc,ip,el))%sizePostResults - select case (phase_damage(material_phase(ipc,ip,el))) - case (LOCAL_DAMAGE_isoBrittle_ID) - constitutive_postResults(startPos:endPos) = damage_isoBrittle_postResults(ipc, ip, el) - case (LOCAL_DAMAGE_isoDuctile_ID) - constitutive_postResults(startPos:endPos) = damage_isoDuctile_postResults(ipc, ip, el) - case (LOCAL_DAMAGE_anisoBrittle_ID) - constitutive_postResults(startPos:endPos) = damage_anisoBrittle_postResults(ipc, ip, el) - case (LOCAL_DAMAGE_anisoDuctile_ID) - constitutive_postResults(startPos:endPos) = damage_anisoDuctile_postResults(ipc, ip, el) - case (LOCAL_DAMAGE_gurson_ID) - constitutive_postResults(startPos:endPos) = damage_gurson_postResults(ipc, ip, el) - case (LOCAL_DAMAGE_phaseField_ID) - constitutive_postResults(startPos:endPos) = damage_phaseField_postResults(ipc, ip, el) - end select + do mySource = 1_pInt, phase_Nsources(phase) + startPos = endPos + 1_pInt + endPos = endPos + sourceState(material_phase(ipc,ip,el))%p(mySource)%sizePostResults + select case (phase_source(mySource,material_phase(ipc,ip,el))) + case (SOURCE_damage_isoBrittle_ID) + constitutive_postResults(startPos:endPos) = source_damage_isoBrittle_postResults(ipc, ip, el) + case (SOURCE_damage_isoDuctile_ID) + constitutive_postResults(startPos:endPos) = source_damage_isoDuctile_postResults(ipc, ip, el) + case (SOURCE_damage_anisoBrittle_ID) + constitutive_postResults(startPos:endPos) = source_damage_anisoBrittle_postResults(ipc, ip, el) + case (SOURCE_damage_anisoDuctile_ID) + constitutive_postResults(startPos:endPos) = source_damage_anisoDuctile_postResults(ipc, ip, el) + end select + enddo - startPos = endPos + 1_pInt - endPos = endPos + thermalState(material_phase(ipc,ip,el))%sizePostResults - select case (phase_thermal(material_phase(ipc,ip,el))) - case (LOCAL_THERMAL_ADIABATIC_ID) - constitutive_postResults(startPos:endPos) = thermal_adiabatic_postResults(ipc, ip, el) - end select - - startPos = endPos + 1_pInt - endPos = endPos + vacancyState(material_phase(ipc,ip,el))%sizePostResults - select case (phase_vacancy(material_phase(ipc,ip,el))) - case (LOCAL_VACANCY_generation_ID) - constitutive_postResults(startPos:endPos) = vacancy_generation_postResults(ipc, ip, el) - end select - end function constitutive_postResults - end module constitutive diff --git a/code/crystallite.f90 b/code/crystallite.f90 index 98edb62eb..8bcc539fc 100644 --- a/code/crystallite.f90 +++ b/code/crystallite.f90 @@ -55,9 +55,9 @@ module crystallite crystallite_Li, & !< current intermediate velocitiy grad (end of converged time step) crystallite_Li0, & !< intermediate velocitiy grad at start of FE inc crystallite_partionedLi0,& !< intermediate velocity grad at start of homog inc + crystallite_Fe, & !< current "elastic" def grad (end of converged time step) crystallite_P !< 1st Piola-Kirchhoff stress per grain real(pReal), dimension(:,:,:,:,:), allocatable, private :: & - crystallite_Fe, & !< current "elastic" def grad (end of converged time step) crystallite_subFe0,& !< "elastic" def grad at start of crystallite inc crystallite_invFp, & !< inverse of current plastic def grad (end of converged time step) crystallite_subFp0,& !< plastic def grad at start of crystallite inc @@ -443,11 +443,9 @@ subroutine crystallite_init do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) do g = 1_pInt,myNgrains call constitutive_microstructure( & - crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g,i,e) ! update dependent state variables to be consistent with basic states + g,i,e) ! update dependent state variables to be consistent with basic states enddo enddo enddo @@ -574,9 +572,8 @@ subroutine crystallite_stressAndItsTangent(updateJaco) use material, only: & homogenization_Ngrains, & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & + phase_Nsources, & mappingConstitutive, & homogenization_maxNgrains use constitutive, only: & @@ -623,7 +620,8 @@ subroutine crystallite_stressAndItsTangent(updateJaco) o, & p, & perturbation , & ! loop counter for forward,backward perturbation mode - myNgrains + myNgrains, & + mySource logical, dimension(homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & convergenceFlag_backup ! local variables used for calculating analytic Jacobian @@ -670,31 +668,30 @@ subroutine crystallite_stressAndItsTangent(updateJaco) !$OMP PARALLEL DO PRIVATE(myNgrains) elementLooping1: do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall (i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & - g = 1_pInt:myNgrains, crystallite_requested(g,i,e)) - plasticState(mappingConstitutive(2,g,i,e))%subState0( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%subState0( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%subState0( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%subState0( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - crystallite_subFp0(1:3,1:3,g,i,e) = crystallite_partionedFp0(1:3,1:3,g,i,e) ! ...plastic def grad - crystallite_subLp0(1:3,1:3,g,i,e) = crystallite_partionedLp0(1:3,1:3,g,i,e) ! ...plastic velocity grad - crystallite_subFi0(1:3,1:3,g,i,e) = crystallite_partionedFi0(1:3,1:3,g,i,e) ! ...intermediate def grad - crystallite_subLi0(1:3,1:3,g,i,e) = crystallite_partionedLi0(1:3,1:3,g,i,e) ! ...intermediate velocity grad - crystallite_dPdF0(1:3,1:3,1:3,1:3,g,i,e) = crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,g,i,e) ! ...stiffness - crystallite_subF0(1:3,1:3,g,i,e) = crystallite_partionedF0(1:3,1:3,g,i,e) ! ...def grad - crystallite_subTstar0_v(1:6,g,i,e) = crystallite_partionedTstar0_v(1:6,g,i,e) !...2nd PK stress - crystallite_subFe0(1:3,1:3,g,i,e) = math_mul33x33(math_mul33x33(crystallite_subF0(1:3,1:3,g,i,e), & - math_inv33(crystallite_subFp0(1:3,1:3,g,i,e))), & - math_inv33(crystallite_subFi0(1:3,1:3,g,i,e)))! only needed later on for stiffness calculation - crystallite_subFrac(g,i,e) = 0.0_pReal - crystallite_subStep(g,i,e) = 1.0_pReal/subStepSizeCryst - crystallite_todo(g,i,e) = .true. - crystallite_converged(g,i,e) = .false. ! pretend failed step of twice the required size - endforall + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1_pInt,myNgrains + if (crystallite_requested(g,i,e)) then + plasticState (mappingConstitutive(2,g,i,e))%subState0( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%subState0( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%partionedState0(:,mappingConstitutive(1,g,i,e)) + enddo + crystallite_subFp0(1:3,1:3,g,i,e) = crystallite_partionedFp0(1:3,1:3,g,i,e) ! ...plastic def grad + crystallite_subLp0(1:3,1:3,g,i,e) = crystallite_partionedLp0(1:3,1:3,g,i,e) ! ...plastic velocity grad + crystallite_subFi0(1:3,1:3,g,i,e) = crystallite_partionedFi0(1:3,1:3,g,i,e) ! ...intermediate def grad + crystallite_subLi0(1:3,1:3,g,i,e) = crystallite_partionedLi0(1:3,1:3,g,i,e) ! ...intermediate velocity grad + crystallite_dPdF0(1:3,1:3,1:3,1:3,g,i,e) = crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,g,i,e) ! ...stiffness + crystallite_subF0(1:3,1:3,g,i,e) = crystallite_partionedF0(1:3,1:3,g,i,e) ! ...def grad + crystallite_subTstar0_v(1:6,g,i,e) = crystallite_partionedTstar0_v(1:6,g,i,e) !...2nd PK stress + crystallite_subFe0(1:3,1:3,g,i,e) = math_mul33x33(math_mul33x33(crystallite_subF0(1:3,1:3,g,i,e), & + math_inv33(crystallite_subFp0(1:3,1:3,g,i,e))), & + math_inv33(crystallite_subFi0(1:3,1:3,g,i,e)))! only needed later on for stiffness calculation + crystallite_subFrac(g,i,e) = 0.0_pReal + crystallite_subStep(g,i,e) = 1.0_pReal/subStepSizeCryst + crystallite_todo(g,i,e) = .true. + crystallite_converged(g,i,e) = .false. ! pretend failed step of twice the required size + endif + enddo; enddo enddo elementLooping1 !$OMP END PARALLEL DO @@ -963,14 +960,12 @@ subroutine crystallite_stressAndItsTangent(updateJaco) crystallite_invFp(1:3,1:3,g,i,e)), & crystallite_invFi(1:3,1:3,g,i,e)) ! only needed later on for stiffness calculation !if abbrevation, make c and p private in omp - plasticState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%subState0(:,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) + enddo crystallite_subTstar0_v(1:6,g,i,e) = crystallite_Tstar_v(1:6,g,i,e) ! ...2nd PK stress if (crystallite_syncSubFrac(i,e)) then ! if we just did a synchronization of states, then we wind forward without any further time integration crystallite_syncSubFracCompleted(i,e) = .true. @@ -1019,14 +1014,12 @@ subroutine crystallite_stressAndItsTangent(updateJaco) !$OMP FLUSH(crystallite_invFi) crystallite_Lp(1:3,1:3,g,i,e) = crystallite_subLp0(1:3,1:3,g,i,e) ! ...plastic velocity grad crystallite_Li(1:3,1:3,g,i,e) = crystallite_subLi0(1:3,1:3,g,i,e) ! ...intermediate velocity grad - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%subState0(:,mappingConstitutive(1,g,i,e)) + enddo crystallite_Tstar_v(1:6,g,i,e) = crystallite_subTstar0_v(1:6,g,i,e) ! ...2nd PK stress ! cant restore dotState here, since not yet calculated in first cutback after initialization @@ -1176,7 +1169,7 @@ subroutine crystallite_stressAndItsTangent(updateJaco) crystallite_Fi(1:3,1:3,g,i,e),g,i,e) ! call constitutive law to calculate elastic stress tangent call constitutive_LiAndItsTangent(temp_33,dLidS,dLidFi,crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fi(1:3,1:3,g,i,e),crystallite_Lp(1:3,1:3,g,i,e), & + crystallite_Fi(1:3,1:3,g,i,e), & g,i,e) ! call constitutive law to calculate Li tangent in lattice configuration if (sum(abs(dLidS)) < tol_math_check) then dFidS = 0.0_pReal @@ -1286,25 +1279,21 @@ subroutine crystallite_stressAndItsTangent(updateJaco) !$OMP PARALLEL DO PRIVATE(myNgrains) elementLooping7: do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall (i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), g = 1:myNgrains) + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1,myNgrains - plasticState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state_backup(:,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) + enddo - plasticState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState_backup(:,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState( :,mappingConstitutive(1,g,i,e)) + enddo F_backup(1:3,1:3,g,i,e) = crystallite_subF(1:3,1:3,g,i,e) ! ... and kinematics Fp_backup(1:3,1:3,g,i,e) = crystallite_Fp(1:3,1:3,g,i,e) @@ -1317,7 +1306,7 @@ subroutine crystallite_stressAndItsTangent(updateJaco) Tstar_v_backup(1:6,g,i,e) = crystallite_Tstar_v(1:6,g,i,e) P_backup(1:3,1:3,g,i,e) = crystallite_P(1:3,1:3,g,i,e) convergenceFlag_backup(g,i,e) = crystallite_converged(g,i,e) - endforall + enddo; enddo enddo elementLooping7 !$END PARALLEL DO ! --- CALCULATE STATE AND STRESS FOR PERTURBATION --- @@ -1339,25 +1328,21 @@ subroutine crystallite_stressAndItsTangent(updateJaco) !why not OMP? ! Fix-point method: restore to last converged state at end of subinc, since this is probably closest to perturbed state do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall (i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), g = 1:myNgrains) + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1,myNgrains - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state_backup(:,mappingConstitutive(1,g,i,e)) + enddo - plasticState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState_backup(:,mappingConstitutive(1,g,i,e)) + enddo crystallite_Fp(1:3,1:3,g,i,e) = Fp_backup(1:3,1:3,g,i,e) crystallite_invFp(1:3,1:3,g,i,e) = InvFp_backup(1:3,1:3,g,i,e) @@ -1367,32 +1352,28 @@ subroutine crystallite_stressAndItsTangent(updateJaco) crystallite_Lp(1:3,1:3,g,i,e) = Lp_backup(1:3,1:3,g,i,e) crystallite_Li(1:3,1:3,g,i,e) = Li_backup(1:3,1:3,g,i,e) crystallite_Tstar_v(1:6,g,i,e) = Tstar_v_backup(1:6,g,i,e) - endforall + enddo; enddo enddo case(2_pInt,3_pInt) ! explicit Euler methods: nothing to restore (except for F), since we are only doing a stress integration step case(4_pInt,5_pInt) !why not OMP? ! explicit Runge-Kutta methods: restore to start of subinc, since we are doing a full integration of state and stress do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall (i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), g = 1:myNgrains) + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1,myNgrains - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%subState0(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%subState0(:,mappingConstitutive(1,g,i,e)) + enddo - plasticState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState_backup(:,mappingConstitutive(1,g,i,e)) + enddo crystallite_Fp(1:3,1:3,g,i,e) = crystallite_subFp0(1:3,1:3,g,i,e) crystallite_Fi(1:3,1:3,g,i,e) = crystallite_subFi0(1:3,1:3,g,i,e) @@ -1400,7 +1381,7 @@ subroutine crystallite_stressAndItsTangent(updateJaco) crystallite_Lp(1:3,1:3,g,i,e) = crystallite_subLp0(1:3,1:3,g,i,e) crystallite_Li(1:3,1:3,g,i,e) = crystallite_subLi0(1:3,1:3,g,i,e) crystallite_Tstar_v(1:6,g,i,e) = crystallite_subTstar0_v(1:6,g,i,e) - endforall + enddo; enddo enddo end select @@ -1480,25 +1461,21 @@ subroutine crystallite_stressAndItsTangent(updateJaco) !why not OMP? elementLooping10: do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall (i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), g = 1:myNgrains) + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1,myNgrains - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state_backup(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state_backup(:,mappingConstitutive(1,g,i,e)) + enddo - plasticState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%dotState( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%dotState_backup(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%dotState_backup(:,mappingConstitutive(1,g,i,e)) + enddo crystallite_subF(1:3,1:3,g,i,e) = F_backup(1:3,1:3,g,i,e) crystallite_Fp(1:3,1:3,g,i,e) = Fp_backup(1:3,1:3,g,i,e) @@ -1511,7 +1488,7 @@ subroutine crystallite_stressAndItsTangent(updateJaco) crystallite_Tstar_v(1:6,g,i,e) = Tstar_v_backup(1:6,g,i,e) crystallite_P(1:3,1:3,g,i,e) = P_backup(1:3,1:3,g,i,e) crystallite_converged(g,i,e) = convergenceFlag_backup(g,i,e) - endforall + enddo; enddo enddo elementLooping10 endif jacobianMethod @@ -1548,9 +1525,9 @@ subroutine crystallite_integrateStateRK4() use material, only: & homogenization_Ngrains, & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & + phase_Nsources, & + material_Nphase, & mappingConstitutive use constitutive, only: & constitutive_collectDotState, & @@ -1568,14 +1545,14 @@ subroutine crystallite_integrateStateRK4() p, & ! phase loop c, & n, & + mySource, & mySizePlasticDotState, & - mySizeDamageDotState, & - mySizeThermalDotState, & - mySizeVacancyDotState + mySizeSourceDotState integer(pInt), dimension(2) :: eIter ! bounds for element iteration integer(pInt), dimension(2,mesh_NcpElems) :: iIter, & ! bounds for ip iteration gIter ! bounds for grain iteration - logical :: singleRun ! flag indicating computation for single (g,i,e) triple + logical :: isNaN, & + singleRun ! flag indicating computation for single (g,i,e) triple eIter = FEsolving_execElem(1:2) do e = eIter(1),eIter(2) @@ -1588,18 +1565,20 @@ subroutine crystallite_integrateStateRK4() !-------------------------------------------------------------------------------------------------- ! initialize dotState if (.not. singleRun) then - forall(p = 1_pInt:size(plasticState)) plasticState(p)%RK4dotState = 0.0_pReal - forall(p = 1_pInt:size(damageState)) damageState(p)%RK4dotState = 0.0_pReal - forall(p = 1_pInt:size(thermalState)) thermalState(p)%RK4dotState = 0.0_pReal - forall(p = 1_pInt:size(vacancyState)) vacancyState(p)%RK4dotState = 0.0_pReal + do p = 1_pInt, material_Nphase + plasticState(p)%RK4dotState = 0.0_pReal + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%RK4dotState = 0.0_pReal + enddo + enddo else e = eIter(1) i = iIter(1,e) do g = iIter(1,e), iIter(2,e) - plasticState(mappingConstitutive(2,g,i,e))%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal - damageState( mappingConstitutive(2,g,i,e))%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal - thermalState(mappingConstitutive(2,g,i,e))%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal - vacancyState(mappingConstitutive(2,g,i,e))%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal + plasticState (mappingConstitutive(2,g,i,e))%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%RK4dotState(:,mappingConstitutive(1,g,i,e)) = 0.0_pReal + enddo enddo endif @@ -1609,27 +1588,30 @@ subroutine crystallite_integrateStateRK4() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then c = mappingConstitutive(1,g,i,e) p = mappingConstitutive(2,g,i,e) - if ( any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState - if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState + if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) - crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped + crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped !$OMP END CRITICAL (checkTodo) - else ! if broken local... - crystallite_todo(g,i,e) = .false. ! ... skip this one next time + else ! if broken local... + crystallite_todo(g,i,e) = .false. ! ... skip this one next time endif endif endif @@ -1648,41 +1630,34 @@ subroutine crystallite_integrateStateRK4() if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - plasticState(p)%RK4dotState(:,c) = plasticState(p)%RK4dotState(:,c) & + weight(n)*plasticState(p)%dotState(:,c) - damageState(p)%RK4dotState(:,c) = damageState(p)%RK4dotState(:,c) & - + weight(n)*damageState(p)%dotState(:,c) - thermalState(p)%RK4dotState(:,c) = thermalState(p)%RK4dotState(:,c) & - + weight(n)*thermalState(p)%dotState(:,c) - vacancyState(p)%RK4dotState(:,c) = vacancyState(p)%RK4dotState(:,c) & - + weight(n)*vacancyState(p)%dotState(:,c) + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%RK4dotState(:,c) = sourceState(p)%p(mySource)%RK4dotState(:,c) & + + weight(n)*sourceState(p)%p(mySource)%dotState(:,c) + enddo endif enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,c) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState(p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - plasticState(p)%state(1:mySizePlasticDotState,c) = plasticState(p)%subState0(1:mySizePlasticDotState,c) & - + plasticState(p)%dotState (1:mySizePlasticDotState,c) & - * crystallite_subdt(g,i,e) * timeStepFraction(n) - damageState( p)%state(1:mySizeDamageDotState,c) = damageState(p)%subState0(1:mySizeDamageDotState,c) & - + damageState(p)%dotState (1:mySizeDamageDotState,c) & - * crystallite_subdt(g,i,e) * timeStepFraction(n) - thermalState(p)%state(1:mySizeThermalDotState,c) = thermalState(p)%subState0(1:mySizeThermalDotState,c) & - + thermalState(p)%dotState (1:mySizeThermalDotState,c) & - * crystallite_subdt(g,i,e) * timeStepFraction(n) - vacancyState(p)%state(1:mySizeVacancyDotState,c) = vacancyState(p)%subState0(1:mySizeVacancyDotState,c) & - + vacancyState(p)%dotState (1:mySizeVacancyDotState,c) & - * crystallite_subdt(g,i,e) * timeStepFraction(n) + plasticState(p)%state (1:mySizePlasticDotState,c) = & + plasticState(p)%subState0(1:mySizePlasticDotState,c) & + + plasticState(p)%dotState (1:mySizePlasticDotState,c) & + * crystallite_subdt(g,i,e) * timeStepFraction(n) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state (1:mySizeSourceDotState,c) = & + sourceState(p)%p(mySource)%subState0(1:mySizeSourceDotState,c) & + + sourceState(p)%p(mySource)%dotState (1:mySizeSourceDotState,c) & + * crystallite_subdt(g,i,e) * timeStepFraction(n) + enddo #ifndef _OPENMP if (n == 4 & @@ -1723,11 +1698,9 @@ subroutine crystallite_integrateStateRK4() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states enddo; enddo; enddo !$OMP ENDDO @@ -1756,7 +1729,7 @@ subroutine crystallite_integrateStateRK4() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & timeStepFraction(n)*crystallite_subdt(g,i,e), & ! fraction of original timestep @@ -1764,15 +1737,18 @@ subroutine crystallite_integrateStateRK4() enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -1846,17 +1822,14 @@ subroutine crystallite_integrateStateRKCK45() use material, only: & homogenization_Ngrains, & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & + phase_Nsources, & mappingConstitutive, & homogenization_maxNgrains use constitutive, only: & constitutive_collectDotState, & - constitutive_maxSizeDotState, & - constitutive_damage_maxSizeDotState, & - constitutive_thermal_maxSizeDotState, & - constitutive_vacancy_maxSizeDotState, & + constitutive_plasticity_maxSizeDotState, & + constitutive_source_maxSizeDotState, & constitutive_microstructure implicit none @@ -1890,29 +1863,26 @@ subroutine crystallite_integrateStateRKCK45() n, & p, & cc, & + mySource, & mySizePlasticDotState, & ! size of dot States - mySizeDamageDotState, & - mySizeThermalDotState, & - mySizeVacancyDotState + mySizeSourceDotState integer(pInt), dimension(2) :: & eIter ! bounds for element iteration integer(pInt), dimension(2,mesh_NcpElems) :: & iIter, & ! bounds for ip iteration gIter ! bounds for grain iteration - real(pReal), dimension(constitutive_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - stateResiduum, & ! residuum from evolution in microstructure - relStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_damage_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - damageStateResiduum, & ! residuum from evolution in microstructure - relDamageStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_thermal_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - thermalStateResiduum, & ! residuum from evolution in microstructure - relThermalStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_vacancy_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - vacancyStateResiduum, & ! residuum from evolution in microstructure - relVacancyStateResiduum ! relative residuum from evolution in microstructure + real(pReal), dimension(constitutive_plasticity_maxSizeDotState, & + homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & + plasticStateResiduum, & ! residuum from evolution in microstructure + relPlasticStateResiduum ! relative residuum from evolution in microstructure + real(pReal), dimension(constitutive_source_maxSizeDotState, & + maxval(phase_Nsources), & + homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & + sourceStateResiduum, & ! residuum from evolution in microstructure + relSourceStateResiduum ! relative residuum from evolution in microstructure logical :: & + isNaN, & singleRun ! flag indicating computation for single (g,i,e) triple eIter = FEsolving_execElem(1:2) @@ -1935,20 +1905,23 @@ subroutine crystallite_integrateStateRKCK45() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,cc) + !$OMP DO PRIVATE(p,cc,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then cc = mappingConstitutive(1,g,i,e) p = mappingConstitutive(2,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,cc), damageState(p)%dotState(:,cc), & - thermalState(p)%dotState(:,cc), vacancyState(p)%dotState(:,cc)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,cc))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,cc))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -1976,9 +1949,9 @@ subroutine crystallite_integrateStateRKCK45() p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) plasticState(p)%RKCK45dotState(stage,:,cc) = plasticState(p)%dotState(:,cc) ! store Runge-Kutta dotState - damageState(p)%RKCK45dotState(stage,:,cc) = damageState(p)%dotState(:,cc) ! store Runge-Kutta dotState - thermalState(p)%RKCK45dotState(stage,:,cc) = thermalState(p)%dotState(:,cc) ! store Runge-Kutta dotState - vacancyState(p)%RKCK45dotState(stage,:,cc) = vacancyState(p)%dotState(:,cc) ! store Runge-Kutta dotState + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%RKCK45dotState(stage,:,cc) = sourceState(p)%p(mySource)%dotState(:,cc) + enddo endif enddo; enddo; enddo !$OMP ENDDO @@ -1990,44 +1963,38 @@ subroutine crystallite_integrateStateRKCK45() cc = mappingConstitutive(1,g,i,e) plasticState(p)%dotState(:,cc) = A(1,stage) * plasticState(p)%RKCK45dotState(1,:,cc) - damageState( p)%dotState(:,cc) = A(1,stage) * damageState( p)%RKCK45dotState(1,:,cc) - thermalState(p)%dotState(:,cc) = A(1,stage) * thermalState(p)%RKCK45dotState(1,:,cc) - vacancyState(p)%dotState(:,cc) = A(1,stage) * vacancyState(p)%RKCK45dotState(1,:,cc) + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%dotState(:,cc) = A(1,stage) * sourceState(p)%p(mySource)%RKCK45dotState(1,:,cc) + enddo do n = 2_pInt, stage plasticState(p)%dotState(:,cc) = & plasticState(p)%dotState(:,cc) + A(n,stage) * plasticState(p)%RKCK45dotState(n,:,cc) - damageState( p)%dotState(:,cc) = & - damageState( p)%dotState(:,cc) + A(n,stage) * damageState( p)%RKCK45dotState(n,:,cc) - thermalState(p)%dotState(:,cc) = & - thermalState(p)%dotState(:,cc) + A(n,stage) * thermalState(p)%RKCK45dotState(n,:,cc) - vacancyState(p)%dotState(:,cc) = & - vacancyState(p)%dotState(:,cc) + A(n,stage) * vacancyState(p)%RKCK45dotState(n,:,cc) + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%dotState(:,cc) = & + sourceState(p)%p(mySource)%dotState(:,cc) + A(n,stage) * sourceState(p)%p(mySource)%RKCK45dotState(n,:,cc) + enddo enddo endif enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,cc) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,cc) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - plasticState(p)%state(1:mySizePlasticDotState,cc) = plasticState(p)%subState0(1:mySizePlasticDotState,cc) & - + plasticState(p)%dotState (1:mySizePlasticDotState,cc) & - * crystallite_subdt(g,i,e) - damageState(p)%state(1:mySizeDamageDotState,cc) = damageState(p)%subState0( 1:mySizeDamageDotState,cc) & - + damageState(p)%dotState ( 1:mySizeDamageDotState,cc) & - * crystallite_subdt(g,i,e) - thermalState(p)%state(1:mySizeThermalDotState,cc) = thermalState(p)%subState0(1:mySizeThermalDotState,cc) & - + thermalState(p)%dotState (1:mySizeThermalDotState,cc) & - * crystallite_subdt(g,i,e) - vacancyState(p)%state(1:mySizeVacancyDotState,cc) = vacancyState(p)%subState0(1:mySizeVacancyDotState,cc) & - + vacancyState(p)%dotState (1:mySizeVacancyDotState,cc) & - * crystallite_subdt(g,i,e) + plasticState (p)%state (1:mySizePlasticDotState, cc) = & + plasticState (p)%subState0(1:mySizePlasticDotState, cc) & + + plasticState (p)%dotState (1:mySizePlasticDotState, cc) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state (1:mySizeSourceDotState,cc) = & + sourceState(p)%p(mySource)%subState0(1:mySizeSourceDotState,cc) & + + sourceState(p)%p(mySource)%dotState (1:mySizeSourceDotState,cc) & + * crystallite_subdt(g,i,e) + enddo endif enddo; enddo; enddo !$OMP ENDDO @@ -2056,11 +2023,9 @@ subroutine crystallite_integrateStateRKCK45() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states enddo; enddo; enddo !$OMP ENDDO @@ -2091,22 +2056,25 @@ subroutine crystallite_integrateStateRKCK45() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & C(stage)*crystallite_subdt(g,i,e), & ! fraction of original timestep crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,cc) + !$OMP DO PRIVATE(p,cc,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,cc), damageState(p)%dotState(:,cc), & - thermalState(p)%dotState(:,cc), vacancyState(p)%dotState(:,cc)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,cc))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,cc))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -2126,130 +2094,109 @@ subroutine crystallite_integrateStateRKCK45() !-------------------------------------------------------------------------------------------------- ! --- STATE UPDATE WITH ERROR ESTIMATE FOR STATE --- - relStateResiduum = 0.0_pReal - relDamageStateResiduum = 0.0_pReal - relThermalStateResiduum = 0.0_pReal - relVacancyStateResiduum = 0.0_pReal + relPlasticStateResiduum = 0.0_pReal + relSourceStateResiduum = 0.0_pReal !$OMP PARALLEL !$OMP DO PRIVATE(p,cc) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) - plasticState(p)%RKCK45dotState(6,:,cc) = plasticState(p)%dotState(:,cc) ! store Runge-Kutta dotState - damageState( p)%RKCK45dotState(6,:,cc) = damageState( p)%dotState(:,cc) ! store Runge-Kutta dotState - thermalState(p)%RKCK45dotState(6,:,cc) = thermalState(p)%dotState(:,cc) ! store Runge-Kutta dotState - vacancyState(p)%RKCK45dotState(6,:,cc) = vacancyState(p)%dotState(:,cc) ! store Runge-Kutta dotState + plasticState(p)%RKCK45dotState(6,:,cc) = plasticState (p)%dotState(:,cc) ! store Runge-Kutta dotState + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%RKCK45dotState(6,:,cc) = sourceState(p)%p(mySource)%dotState(:,cc) ! store Runge-Kutta dotState + enddo endif enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,cc) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,cc) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) - mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState ! --- absolute residuum in state --- - stateResiduum(1:mySizePlasticDotState,g,i,e) = & - matmul(transpose(plasticState(p)%RKCK45dotState(1:6,1:mySizePlasticDotState,cc)),DB) & - * crystallite_subdt(g,i,e) - damageStateResiduum(1:mySizeDamageDotState,g,i,e) = & - matmul(transpose(damageState(p)%RKCK45dotState(1:6,1:mySizeDamageDotState,cc)),DB) & - * crystallite_subdt(g,i,e) - thermalStateResiduum(1:mySizeThermalDotState,g,i,e) = & - matmul(transpose(thermalState(p)%RKCK45dotState(1:6,1:mySizeThermalDotState,cc)),DB) & - * crystallite_subdt(g,i,e) - vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e) = & - matmul(transpose(vacancyState(p)%RKCK45dotState(1:6,1:mySizevacancyDotState,cc)),DB) & - * crystallite_subdt(g,i,e) + mySizePlasticDotState = plasticState(p)%sizeDotState + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) = & + matmul(transpose(plasticState(p)%RKCK45dotState(1:6,1:mySizePlasticDotState,cc)),DB) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e) = & + matmul(transpose(sourceState(p)%p(mySource)%RKCK45dotState(1:6,1:mySizeSourceDotState,cc)),DB) & + * crystallite_subdt(g,i,e) + enddo ! --- dot state --- - plasticState(p)%dotState (:,cc) = & - matmul(transpose(plasticState(p)%RKCK45dotState(1:6,1:mySizePlasticDotState,cc)),B) - damageState(p)%dotState (:,cc) = & - matmul(transpose(damageState(p)%RKCK45dotState(1:6,1:mySizeDamageDotState,cc)),B) - thermalState(p)%dotState (:,cc) = & - matmul(transpose(thermalState(p)%RKCK45dotState(1:6,1:mySizeThermalDotState,cc)),B) - vacancyState(p)%dotState (:,cc) = & - matmul(transpose(vacancyState(p)%RKCK45dotState(1:6,1:mySizevacancyDotState,cc)),B) + plasticState(p)%dotState(:,cc) = & + matmul(transpose(plasticState(p)%RKCK45dotState(1:6,1:mySizePlasticDotState,cc)), B) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%dotState(:,cc) = & + matmul(transpose(sourceState(p)%p(mySource)%RKCK45dotState(1:6,1:mySizeSourceDotState,cc)),B) + enddo endif enddo; enddo; enddo !$OMP ENDDO ! --- state and update --- - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,cc) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,cc) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - plasticState(p)%state(1:mySizePlasticDotState,cc) = plasticState(p)%subState0(1:mySizePlasticDotState,cc)& - + plasticState(p)%dotState (1:mySizePlasticDotState,cc)& - * crystallite_subdt(g,i,e) - damageState(p)%state (1:mySizeDamageDotState,cc) = damageState(p)%subState0(1:mySizeDamageDotState,cc)& - + damageState(p)%dotState (1:mySizeDamageDotState,cc)& - * crystallite_subdt(g,i,e) - thermalState(p)%state(1:mySizeThermalDotState,cc) = thermalState(p)%subState0(1:mySizeThermalDotState,cc)& - + thermalState(p)%dotState (1:mySizeThermalDotState,cc)& - * crystallite_subdt(g,i,e) - vacancyState(p)%state(1:mySizeVacancyDotState,cc) = vacancyState(p)%subState0(1:mySizeVacancyDotState,cc)& - + vacancyState(p)%dotState (1:mySizeVacancyDotState,cc)& - * crystallite_subdt(g,i,e) + plasticState(p)%state (1:mySizePlasticDotState,cc) = & + plasticState(p)%subState0(1:mySizePlasticDotState,cc) & + + plasticState(p)%dotState (1:mySizePlasticDotState,cc) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state (1:mySizeSourceDotState,cc) = & + sourceState(p)%p(mySource)%subState0(1:mySizeSourceDotState,cc) & + + sourceState(p)%p(mySource)%dotState (1:mySizeSourceDotState,cc)& + * crystallite_subdt(g,i,e) + enddo endif enddo; enddo; enddo !$OMP ENDDO ! --- relative residui and state convergence --- - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,cc,s) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,cc,s) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then - p = mappingConstitutive(2,g,i,e) + p = mappingConstitutive(2,g,i,e) cc = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - forall (s = 1_pInt:mySizePlasticDotState, abs(plasticState(p)%state(s,cc)) > 0.0_pReal) & - relStateResiduum(s,g,i,e) = stateResiduum(s,g,i,e) / plasticState(p)%state(s,cc) - forall (s = 1_pInt:mySizeDamageDotState, abs(damageState( p)%state(s,cc)) > 0.0_pReal) & - relDamageStateResiduum(s,g,i,e) = damageStateResiduum(s,g,i,e) / damageState(p)%state(s,cc) - forall (s = 1_pInt:mySizeThermalDotState, abs(thermalState(p)%state(s,cc)) > 0.0_pReal) & - relThermalStateResiduum(s,g,i,e) = thermalStateResiduum(s,g,i,e) / thermalState(p)%state(s,cc) - forall (s = 1_pInt:mySizeVacancyDotState, abs(vacancyState(p)%state(s,cc)) > 0.0_pReal) & - relVacancyStateResiduum(s,g,i,e) = vacancyStateResiduum(s,g,i,e) / vacancyState(p)%state(s,cc) - !$OMP FLUSH(relStateResiduum) - !$OMP FLUSH(relDamageStateResiduum) - !$OMP FLUSH(relThermalStateResiduum) - !$OMP FLUSH(relVacancyStateResiduum) + forall (s = 1_pInt:mySizePlasticDotState, abs(plasticState(p)%state(s,cc)) > 0.0_pReal) & + relPlasticStateResiduum(s,g,i,e) = & + plasticStateResiduum(s,g,i,e) / plasticState(p)%state(s,cc) + + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + forall (s = 1_pInt:mySizeSourceDotState,abs(sourceState(p)%p(mySource)%state(s,cc)) > 0.0_pReal) & + relSourceStateResiduum(s,mySource,g,i,e) = & + sourceStateResiduum(s,mySource,g,i,e) / sourceState(p)%p(mySource)%state(s,cc) + enddo + !$OMP FLUSH(relPlasticStateResiduum) + !$OMP FLUSH(relSourceStateResiduum) ! @Martin: do we need flushing? why..? - crystallite_todo(g,i,e) = & - ( all(abs(relStateResiduum(1:mySizePlasticDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(stateResiduum(1:mySizePlasticDotState,g,i,e)) < & - plasticState(p)%aTolState(1:mySizePlasticDotState)) & - .and. all(abs(relDamageStateResiduum(1:mySizeDamageDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(damageStateResiduum(1:mySizeDamageDotState,g,i,e)) < & - damageState(p)%aTolState(1:mySizeDamageDotState)) & - .and. all(abs(relThermalStateResiduum(1:mySizeThermalDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(thermalStateResiduum(1:mySizeThermalDotState,g,i,e)) < & - thermalState(p)%aTolState(1:mySizeThermalDotState)) & - .and. all(abs(relVacancyStateResiduum(1:mySizeVacancyDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e)) < & - vacancyState(p)%aTolState(1:mySizeVacancyDotState))) + crystallite_todo(g,i,e) = all(abs(relPlasticStateResiduum(1:mySizePlasticDotState,g,i,e)) < & + rTol_crystalliteState .or. & + abs(plasticStateResiduum(1:mySizePlasticDotState,g,i,e)) < & + plasticState(p)%aTolState(1:mySizePlasticDotState)) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + crystallite_todo(g,i,e) = crystallite_todo(g,i,e) .and. & + all(abs(relSourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e)) < & + rTol_crystalliteState .or. & + abs(sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e)) < & + sourceState(p)%p(mySource)%aTolState(1:mySizeSourceDotState)) + enddo #ifndef _OPENMP if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt& @@ -2257,9 +2204,9 @@ subroutine crystallite_integrateStateRKCK45() .or. .not. iand(debug_level(debug_crystallite), debug_levelSelective) /= 0_pInt)) then write(6,'(a,i8,1x,i3,1x,i3,/)') '<< CRYST >> updateState at el ip g ',e,i,g write(6,'(a,/,(12x,12(f12.1,1x)),/)') '<< CRYST >> absolute residuum tolerance', & - stateResiduum(1:mySizePlasticDotState,g,i,e) / plasticState(p)%aTolState(1:mySizePlasticDotState) + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) / plasticState(p)%aTolState(1:mySizePlasticDotState) write(6,'(a,/,(12x,12(f12.1,1x)),/)') '<< CRYST >> relative residuum tolerance', & - relStateResiduum(1:mySizePlasticDotState,g,i,e) / rTol_crystalliteState + relPlasticStateResiduum(1:mySizePlasticDotState,g,i,e) / rTol_crystalliteState write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> dotState', & plasticState(p)%dotState(1:mySizePlasticDotState,cc) write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state', & @@ -2294,11 +2241,9 @@ subroutine crystallite_integrateStateRKCK45() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states enddo; enddo; enddo !$OMP ENDDO @@ -2379,18 +2324,15 @@ subroutine crystallite_integrateStateAdaptiveEuler() use material, only: & homogenization_Ngrains, & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & mappingConstitutive, & + phase_Nsources, & homogenization_maxNgrains use constitutive, only: & constitutive_collectDotState, & constitutive_microstructure, & - constitutive_maxSizeDotState, & - constitutive_damage_maxSizeDotState, & - constitutive_thermal_maxSizeDotState, & - constitutive_vacancy_maxSizeDotState + constitutive_plasticity_maxSizeDotState, & + constitutive_source_maxSizeDotState implicit none integer(pInt) :: & @@ -2400,29 +2342,27 @@ subroutine crystallite_integrateStateAdaptiveEuler() s, & ! state index p, & c, & + mySource, & mySizePlasticDotState, & ! size of dot states - mySizeDamageDotState, & - mySizeThermalDotState, & - mySizeVacancyDotState + mySizeSourceDotState integer(pInt), dimension(2) :: & eIter ! bounds for element iteration integer(pInt), dimension(2,mesh_NcpElems) :: & iIter, & ! bounds for ip iteration gIter ! bounds for grain iteration - real(pReal), dimension(constitutive_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - stateResiduum, & ! residuum from evolution in micrstructure - relStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_damage_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - damageStateResiduum, & ! residuum from evolution in micrstructure - relDamageStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_thermal_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - thermalStateResiduum, & ! residuum from evolution in micrstructure - relThermalStateResiduum ! relative residuum from evolution in microstructure - real(pReal), dimension(constitutive_vacancy_maxSizeDotState,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & - vacancyStateResiduum, & ! residuum from evolution in micrstructure - relVacancyStateResiduum ! relative residuum from evolution in microstructure + real(pReal), dimension(constitutive_plasticity_maxSizeDotState, & + homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & + plasticStateResiduum, & ! residuum from evolution in micrstructure + relPlasticStateResiduum ! relative residuum from evolution in microstructure + real(pReal), dimension(constitutive_source_maxSizeDotState,& + maxval(phase_Nsources), & + homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems) :: & + sourceStateResiduum, & ! residuum from evolution in micrstructure + relSourceStateResiduum ! relative residuum from evolution in microstructure logical :: & + converged, & + isNaN, & singleRun ! flag indicating computation for single (g,i,e) triple @@ -2436,15 +2376,10 @@ subroutine crystallite_integrateStateAdaptiveEuler() singleRun = (eIter(1) == eIter(2) .and. iIter(1,eIter(1)) == iIter(2,eIter(2))) - stateResiduum = 0.0_pReal - relStateResiduum = 0.0_pReal - damageStateResiduum = 0.0_pReal - relDamageStateResiduum = 0.0_pReal - thermalStateResiduum = 0.0_pReal - relThermalStateResiduum = 0.0_pReal - vacancyStateResiduum = 0.0_pReal - relVacancyStateResiduum = 0.0_pReal - + plasticStateResiduum = 0.0_pReal + relPlasticStateResiduum = 0.0_pReal + sourceStateResiduum = 0.0_pReal + relSourceStateResiduum = 0.0_pReal integrationMode: if (numerics_integrationMode == 1_pInt) then @@ -2454,20 +2389,23 @@ subroutine crystallite_integrateStateAdaptiveEuler() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -2483,39 +2421,31 @@ subroutine crystallite_integrateStateAdaptiveEuler() ! --- STATE UPDATE (EULER INTEGRATION) --- - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,c) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - stateResiduum(1:mySizePlasticDotState,g,i,e) = - 0.5_pReal & - * plasticState(p)%dotstate(1:mySizePlasticDotState,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - damageStateResiduum(1:mySizeDamageDotState,g,i,e) = - 0.5_pReal & - * damageState(p)%dotstate(1:mySizeDamageDotState,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - thermalStateResiduum(1:mySizeThermalDotState,g,i,e) = - 0.5_pReal & - * thermalState(p)%dotstate(1:mySizeThermalDotState,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e) = - 0.5_pReal & - * vacancyState(p)%dotstate(1:mySizeVacancyDotState,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - plasticState(p)%state(1:mySizePlasticDotState,c) = plasticState(p)%state(1:mySizePlasticDotState,c) & - + plasticState(p)%dotstate(1:mySizePlasticDotState,c) & - * crystallite_subdt(g,i,e) - damageState(p)%state(1:mySizeDamageDotState,c) = damageState(p)%state(1:mySizeDamageDotState,c) & - + damageState(p)%dotstate(1:mySizeDamageDotState,c) & - * crystallite_subdt(g,i,e) - thermalState(p)%state(1:mySizeThermalDotState,c) = thermalState(p)%state(1:mySizeThermalDotState,c) & - + thermalState(p)%dotstate(1:mySizeThermalDotState,c) & - * crystallite_subdt(g,i,e) - vacancyState(p)%state(1:mySizeVacancyDotState,c) = vacancyState(p)%state(1:mySizeVacancyDotState,c) & - + vacancyState(p)%dotstate(1:mySizeVacancyDotState,c) & - * crystallite_subdt(g,i,e) + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) = & + - 0.5_pReal & + * plasticState(p)%dotstate(1:mySizePlasticDotState,c) & + * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state + plasticState(p)%state (1:mySizePlasticDotState,c) = & + plasticState(p)%state (1:mySizePlasticDotState,c) & + + plasticState(p)%dotstate(1:mySizePlasticDotState,c) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e) = & + - 0.5_pReal & + * sourceState(p)%p(mySource)%dotstate(1:mySizeSourceDotState,c) & + * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state + sourceState(p)%p(mySource)%state (1:mySizeSourceDotState,c) = & + sourceState(p)%p(mySource)%state (1:mySizeSourceDotState,c) & + + sourceState(p)%p(mySource)%dotstate(1:mySizeSourceDotState,c) & + * crystallite_subdt(g,i,e) + enddo endif enddo; enddo; enddo !$OMP ENDDO @@ -2544,11 +2474,9 @@ subroutine crystallite_integrateStateAdaptiveEuler() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states enddo; enddo; enddo !$OMP ENDDO !$OMP END PARALLEL @@ -2581,20 +2509,23 @@ subroutine crystallite_integrateStateAdaptiveEuler() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -2611,54 +2542,43 @@ subroutine crystallite_integrateStateAdaptiveEuler() ! --- ERROR ESTIMATE FOR STATE (HEUN METHOD) --- !$OMP SINGLE - relStateResiduum = 0.0_pReal - relDamageStateResiduum = 0.0_pReal - relThermalStateResiduum = 0.0_pReal - relVacancyStateResiduum = 0.0_pReal + relPlasticStateResiduum = 0.0_pReal + relSourceStateResiduum = 0.0_pReal !$OMP END SINGLE - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,c,s) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,converged,p,c,s) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState(p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState ! --- contribution of heun step to absolute residui --- - - stateResiduum(1:mySizePlasticDotState,g,i,e) = stateResiduum(1:mySizePlasticDotState,g,i,e) & - + 0.5_pReal * plasticState(p)%dotState(:,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - damageStateResiduum(1:mySizeDamageDotState,g,i,e) = damageStateResiduum(1:mySizeDamageDotState,g,i,e) & - + 0.5_pReal * damageState(p)%dotState(:,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - thermalStateResiduum(1:mySizeThermalDotState,g,i,e) = thermalStateResiduum(1:mySizeThermalDotState,g,i,e) & - + 0.5_pReal * thermalState(p)%dotState(:,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e) = vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e) & - + 0.5_pReal * vacancyState(p)%dotState(:,c) & - * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state - - !$OMP FLUSH(stateResiduum) - !$OMP FLUSH(damageStateResiduum) - !$OMP FLUSH(thermalStateResiduum) - !$OMP FLUSH(vacancyStateResiduum) + mySizePlasticDotState = plasticState(p)%sizeDotState + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) = & + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) & + + 0.5_pReal * plasticState(p)%dotState(:,c) & + * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e) = & + sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e) & + + 0.5_pReal * sourceState(p)%p(mySource)%dotState(:,c) & + * crystallite_subdt(g,i,e) ! contribution to absolute residuum in state + enddo + !$OMP FLUSH(plasticStateResiduum) + !$OMP FLUSH(sourceStateResiduum) ! --- relative residui --- forall (s = 1_pInt:mySizePlasticDotState, abs(plasticState(p)%dotState(s,c)) > 0.0_pReal) & - relStateResiduum(s,g,i,e) = stateResiduum(s,g,i,e) / plasticState(p)%dotState(s,c) - forall (s = 1_pInt:mySizeDamageDotState, abs(damageState(p)%dotState(s,c)) > 0.0_pReal) & - relDamageStateResiduum(s,g,i,e) = damageStateResiduum(s,g,i,e) / damageState(p)%dotState(s,c) - forall (s = 1_pInt:mySizeThermalDotState, abs(thermalState(p)%dotState(s,c)) > 0.0_pReal) & - relThermalStateResiduum(s,g,i,e) = thermalStateResiduum(s,g,i,e) / thermalState(p)%dotState(s,c) - forall (s = 1_pInt:mySizeVacancyDotState, abs(vacancyState(p)%dotState(s,c)) > 0.0_pReal) & - relVacancyStateResiduum(s,g,i,e) = vacancyStateResiduum(s,g,i,e) / vacancyState(p)%dotState(s,c) - !$OMP FLUSH(relStateResiduum) - !$OMP FLUSH(relDamageStateResiduum) - !$OMP FLUSH(relthermalStateResiduum) - !$OMP FLUSH(relVacancyStateResiduum) + relPlasticStateResiduum(s,g,i,e) = & + plasticStateResiduum(s,g,i,e) / plasticState(p)%dotState(s,c) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + forall (s = 1_pInt:mySizeSourceDotState,abs(sourceState(p)%p(mySource)%dotState(s,c)) > 0.0_pReal) & + relSourceStateResiduum(s,mySource,g,i,e) = & + sourceStateResiduum(s,mySource,g,i,e) / sourceState(p)%p(mySource)%dotState(s,c) + enddo + !$OMP FLUSH(relPlasticStateResiduum) + !$OMP FLUSH(relSourceStateResiduum) #ifndef _OPENMP @@ -2667,32 +2587,29 @@ subroutine crystallite_integrateStateAdaptiveEuler() .or. .not. iand(debug_level(debug_crystallite), debug_levelSelective) /= 0_pInt)) then write(6,'(a,i8,1x,i2,1x,i3,/)') '<< CRYST >> updateState at el ip g ',e,i,g write(6,'(a,/,(12x,12(f12.1,1x)),/)') '<< CRYST >> absolute residuum tolerance', & - stateResiduum(1:mySizePlasticDotState,g,i,e) / plasticState(p)%aTolState(1:mySizePlasticDotState) + plasticStateResiduum(1:mySizePlasticDotState,g,i,e) / plasticState(p)%aTolState(1:mySizePlasticDotState) write(6,'(a,/,(12x,12(f12.1,1x)),/)') '<< CRYST >> relative residuum tolerance', & - relStateResiduum(1:mySizePlasticDotState,g,i,e) / rTol_crystalliteState + relPlasticStateResiduum(1:mySizePlasticDotState,g,i,e) / rTol_crystalliteState write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> dotState', plasticState(p)%dotState(1:mySizePlasticDotState,c) & - - 2.0_pReal * stateResiduum(1:mySizePlasticDotState,g,i,e) / crystallite_subdt(g,i,e) ! calculate former dotstate from higher order solution and state residuum + - 2.0_pReal * plasticStateResiduum(1:mySizePlasticDotState,g,i,e) / crystallite_subdt(g,i,e) ! calculate former dotstate from higher order solution and state residuum write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state', plasticState(p)%state(1:mySizePlasticDotState,c) endif #endif ! --- converged ? --- - if ( all(abs(relStateResiduum(1:mySizePlasticDotState,g,i,e)) < & + converged = all(abs(relPlasticStateResiduum(1:mySizePlasticDotState,g,i,e)) < & + rTol_crystalliteState .or. & + abs(plasticStateResiduum(1:mySizePlasticDotState,g,i,e)) < & + plasticState(p)%aTolState(1:mySizePlasticDotState)) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + converged = converged .and. & + all(abs(relSourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e)) < & rTol_crystalliteState .or. & - abs(stateResiduum(1:mySizePlasticDotState,g,i,e)) < & - plasticState(p)%aTolState(1:mySizePlasticDotState)) & - .and. all(abs(relDamageStateResiduum(1:mySizeDamageDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(damageStateResiduum(1:mySizeDamageDotState,g,i,e)) < & - damageState(p)%aTolState(1:mySizeDamageDotState)) & - .and. all(abs(relThermalStateResiduum(1:mySizeThermalDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(thermalStateResiduum(1:mySizeThermalDotState,g,i,e)) < & - thermalState(p)%aTolState(1:mySizeThermalDotState)) & - .and. all(abs(relVacancyStateResiduum(1:mySizeVacancyDotState,g,i,e)) < & - rTol_crystalliteState .or. & - abs(vacancyStateResiduum(1:mySizeVacancyDotState,g,i,e)) < & - vacancyState(p)%aTolState(1:mySizeVacancyDotState))) then + abs(sourceStateResiduum(1:mySizeSourceDotState,mySource,g,i,e)) < & + sourceState(p)%p(mySource)%aTolState(1:mySizeSourceDotState)) + enddo + if (converged) then crystallite_converged(g,i,e) = .true. ! ... converged per definitionem if (iand(debug_level(debug_crystallite), debug_levelBasic) /= 0_pInt) then !$OMP CRITICAL (distributionState) @@ -2764,10 +2681,9 @@ subroutine crystallite_integrateStateEuler() mesh_NcpElems use material, only: & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & mappingConstitutive, & + phase_Nsources, & homogenization_Ngrains use constitutive, only: & constitutive_collectDotState, & @@ -2779,18 +2695,18 @@ subroutine crystallite_integrateStateEuler() e, & ! element index in element loop i, & ! integration point index in ip loop g, & ! grain index in grain loop - p, & ! phase loop + p, & ! phase loop c, & + mySource, & mySizePlasticDotState, & - mySizeDamageDotState, & - mySizeThermalDotState, & - mySizeVacancyDotState + mySizeSourceDotState integer(pInt), dimension(2) :: & eIter ! bounds for element iteration integer(pInt), dimension(2,mesh_NcpElems) :: & iIter, & ! bounds for ip iteration gIter ! bounds for grain iteration logical :: & + isNaN, & singleRun ! flag indicating computation for single (g,i,e) triple @@ -2810,20 +2726,23 @@ eIter = FEsolving_execElem(1:2) !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) then c = mappingConstitutive(1,g,i,e) p = mappingConstitutive(2,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e) .and. .not. numerics_timeSyncing) then ! if broken non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals skipped @@ -2839,27 +2758,23 @@ eIter = FEsolving_execElem(1:2) ! --- UPDATE STATE --- - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,c) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - plasticState(p)%state(1:mySizePlasticDotState,c) = plasticState(p)%state( 1:mySizePlasticDotState,c) & - + plasticState(p)%dotState(1:mySizePlasticDotState,c) & - * crystallite_subdt(g,i,e) - damageState( p)%state(1:mySizeDamageDotState,c) = damageState( p)%state( 1:mySizeDamageDotState,c) & - + damageState( p)%dotState(1:mySizeDamageDotState,c) & - * crystallite_subdt(g,i,e) - thermalState(p)%state(1:mySizeThermalDotState,c) = thermalState(p)%state( 1:mySizeThermalDotState,c) & - + thermalState(p)%dotState(1:mySizeThermalDotState,c) & - * crystallite_subdt(g,i,e) - vacancyState(p)%state(1:mySizeVacancyDotState,c) = vacancyState(p)%state( 1:mySizeVacancyDotState,c) & - + vacancyState(p)%dotState(1:mySizeVacancyDotState,c) & - * crystallite_subdt(g,i,e) + plasticState(p)%state( 1:mySizePlasticDotState,c) = & + plasticState(p)%state( 1:mySizePlasticDotState,c) & + + plasticState(p)%dotState(1:mySizePlasticDotState,c) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state( 1:mySizeSourceDotState,c) = & + sourceState(p)%p(mySource)%state( 1:mySizeSourceDotState,c) & + + sourceState(p)%p(mySource)%dotState(1:mySizeSourceDotState,c) & + * crystallite_subdt(g,i,e) + enddo #ifndef _OPENMP if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & @@ -2868,8 +2783,8 @@ eIter = FEsolving_execElem(1:2) p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) write(6,'(a,i8,1x,i2,1x,i3,/)') '<< CRYST >> update state at el ip g ',e,i,g - write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> dotState', plasticState(p)%dotState (1:mySizePlasticDotState,c) - write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state', plasticState(p)%state (1:mySizePlasticDotState,c) + write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> dotState', plasticState(p)%dotState(1:mySizePlasticDotState,c) + write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state', plasticState(p)%state (1:mySizePlasticDotState,c) endif #endif endif @@ -2901,11 +2816,9 @@ eIter = FEsolving_execElem(1:2) !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states enddo; enddo; enddo !$OMP ENDDO !$OMP END PARALLEL @@ -2991,18 +2904,15 @@ subroutine crystallite_integrateStateFPI() mesh_NcpElems use material, only: & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & mappingConstitutive, & + phase_Nsources, & homogenization_Ngrains use constitutive, only: & constitutive_collectDotState, & constitutive_microstructure, & - constitutive_maxSizeDotState, & - constitutive_damage_maxSizeDotState, & - constitutive_thermal_maxSizeDotState, & - constitutive_vacancy_maxSizeDotState + constitutive_plasticity_maxSizeDotState, & + constitutive_source_maxSizeDotState implicit none @@ -3013,10 +2923,9 @@ subroutine crystallite_integrateStateFPI() g, & !< grain index in grain loop p, & c, & + mySource, & mySizePlasticDotState, & ! size of dot states - mySizeDamageDotState, & - mySizeThermalDotState, & - mySizeVacancyDotState + mySizeSourceDotState integer(pInt), dimension(2) :: & eIter ! bounds for element iteration integer(pInt), dimension(2,mesh_NcpElems) :: & @@ -3025,23 +2934,17 @@ subroutine crystallite_integrateStateFPI() real(pReal) :: & dot_prod12, & dot_prod22, & - stateDamper, & ! damper for integration of state - damageStateDamper, & - thermalStateDamper, & - vacancyStateDamper - real(pReal), dimension(constitutive_maxSizeDotState) :: & - stateResiduum, & - tempState - real(pReal), dimension(constitutive_damage_maxSizeDotState) :: & - damageStateResiduum, & ! residuum from evolution in micrstructure - tempDamageState - real(pReal), dimension(constitutive_thermal_maxSizeDotState) :: & - thermalStateResiduum, & ! residuum from evolution in micrstructure - tempThermalState - real(pReal), dimension(constitutive_vacancy_maxSizeDotState) :: & - vacancyStateResiduum, & ! residuum from evolution in micrstructure - tempVacancyState + plasticStateDamper, & ! damper for integration of state + sourceStateDamper + real(pReal), dimension(constitutive_plasticity_maxSizeDotState) :: & + plasticStateResiduum, & + tempPlasticState + real(pReal), dimension(constitutive_source_maxSizeDotState, maxval(phase_Nsources)) :: & + sourceStateResiduum, & ! residuum from evolution in micrstructure + tempSourceState logical :: & + converged, & + isNaN, & singleRun, & ! flag indicating computation for single (g,i,e) triple doneWithIntegration @@ -3060,18 +2963,10 @@ subroutine crystallite_integrateStateFPI() plasticState(p)%previousDotState = 0.0_pReal plasticState(p)%previousDotState2 = 0.0_pReal end forall - forall(p = 1_pInt:size(damageState)) - damageState(p)%previousDotState = 0.0_pReal - damageState(p)%previousDotState2 = 0.0_pReal - end forall - forall(p = 1_pInt:size(thermalState)) - thermalState(p)%previousDotState = 0.0_pReal - thermalState(p)%previousDotState2 = 0.0_pReal - end forall - forall(p = 1_pInt:size(vacancyState)) - vacancyState(p)%previousDotState = 0.0_pReal - vacancyState(p)%previousDotState2 = 0.0_pReal - end forall + do p = 1_pInt, size(sourceState); do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%previousDotState = 0.0_pReal + sourceState(p)%p(mySource)%previousDotState2 = 0.0_pReal + enddo; enddo else e = eIter(1) i = iIter(1,e) @@ -3080,12 +2975,10 @@ subroutine crystallite_integrateStateFPI() c = mappingConstitutive(1,g,i,e) plasticState(p)%previousDotState (:,c) = 0.0_pReal plasticState(p)%previousDotState2(:,c) = 0.0_pReal - damageState( p)%previousDotState (:,c) = 0.0_pReal - damageState( p)%previousDotState2(:,c) = 0.0_pReal - thermalState(p)%previousDotState (:,c) = 0.0_pReal - thermalState(p)%previousDotState2(:,c) = 0.0_pReal - vacancyState(p)%previousDotState (:,c) = 0.0_pReal - vacancyState(p)%previousDotState2(:,c) = 0.0_pReal + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%previousDotState (:,c) = 0.0_pReal + sourceState(p)%p(mySource)%previousDotState2(:,c) = 0.0_pReal + enddo enddo endif @@ -3097,21 +2990,24 @@ subroutine crystallite_integrateStateFPI() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) enddo; enddo; enddo !$OMP ENDDO - !$OMP DO PRIVATE(p,c) + !$OMP DO PRIVATE(p,c,isNaN) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains !$OMP FLUSH(crystallite_todo) if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState if (.not. crystallite_localPlasticity(g,i,e)) then ! if broken is a non-local... !$OMP CRITICAL (checkTodo) crystallite_todo = crystallite_todo .and. crystallite_localPlasticity ! ...all non-locals done (and broken) @@ -3126,27 +3022,23 @@ subroutine crystallite_integrateStateFPI() ! --- UPDATE STATE --- - !$OMP DO PRIVATE(mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState,p,c) + !$OMP DO PRIVATE(mySizePlasticDotState,mySizeSourceDotState,p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - plasticState(p)%state(1:mySizePlasticDotState,c) = plasticState(p)%subState0(1:mySizePlasticDotState,c) & - + plasticState(p)%dotState (1:mySizePlasticDotState,c) & - * crystallite_subdt(g,i,e) - damageState( p)%state(1:mySizeDamageDotState,c) = damageState( p)%subState0(1:mySizeDamageDotState,c) & - + damageState( p)%dotState (1:mySizeDamageDotState,c) & - * crystallite_subdt(g,i,e) - thermalState(p)%state(1:mySizeThermalDotState,c) = thermalState(p)%subState0(1:mySizeThermalDotState,c) & - + thermalState(p)%dotState (1:mySizeThermalDotState,c) & - * crystallite_subdt(g,i,e) - vacancyState(p)%state(1:mySizeVacancyDotState,c) = vacancyState(p)%subState0(1:mySizeVacancyDotState,c) & - + vacancyState(p)%dotState (1:mySizeVacancyDotState,c) & - * crystallite_subdt(g,i,e) + plasticState(p)%state(1:mySizePlasticDotState,c) = & + plasticState(p)%subState0(1:mySizePlasticDotState,c) & + + plasticState(p)%dotState (1:mySizePlasticDotState,c) & + * crystallite_subdt(g,i,e) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state(1:mySizeSourceDotState,c) = & + sourceState(p)%p(mySource)%subState0(1:mySizeSourceDotState,c) & + + sourceState(p)%p(mySource)%dotState (1:mySizeSourceDotState,c) & + * crystallite_subdt(g,i,e) + enddo endif enddo; enddo; enddo !$OMP ENDDO @@ -3167,21 +3059,17 @@ subroutine crystallite_integrateStateFPI() !$OMP DO PRIVATE(p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) & - call constitutive_microstructure(crystallite_Tstar_v(1:6,g,i,e), & - crystallite_Fe(1:3,1:3,g,i,e), & + call constitutive_microstructure(crystallite_Fe(1:3,1:3,g,i,e), & crystallite_Fp(1:3,1:3,g,i,e), & - crystallite_Lp(1:3,1:3,g,i,e), & - crystallite_subdt(g,i,e), g, i, e) ! update dependent state variables to be consistent with basic states + g, i, e) ! update dependent state variables to be consistent with basic states p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) plasticState(p)%previousDotState2(:,c) = plasticState(p)%previousDotState(:,c) - damageState( p)%previousDotState2(:,c) = damageState( p)%previousDotState(:,c) - thermalState(p)%previousDotState2(:,c) = thermalState(p)%previousDotState(:,c) - vacancyState(p)%previousDotState2(:,c) = vacancyState(p)%previousDotState(:,c) plasticState(p)%previousDotState (:,c) = plasticState(p)%dotState(:,c) - damageState( p)%previousDotState (:,c) = damageState( p)%dotState(:,c) - thermalState(p)%previousDotState (:,c) = thermalState(p)%dotState(:,c) - vacancyState(p)%previousDotState (:,c) = vacancyState(p)%dotState(:,c) + do mySource = 1_pInt, phase_Nsources(p) + sourceState(p)%p(mySource)%previousDotState2(:,c) = sourceState(p)%p(mySource)%previousDotState(:,c) + sourceState(p)%p(mySource)%previousDotState (:,c) = sourceState(p)%p(mySource)%dotState(:,c) + enddo enddo; enddo; enddo !$OMP ENDDO @@ -3215,7 +3103,7 @@ subroutine crystallite_integrateStateFPI() !$OMP DO do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) & - call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Lp(1:3,1:3,g,i,e), & + call constitutive_collectDotState(crystallite_Tstar_v(1:6,g,i,e), & crystallite_Fe, & crystallite_Fp, & crystallite_subdt(g,i,e), crystallite_subFrac, g,i,e) @@ -3228,8 +3116,11 @@ subroutine crystallite_integrateStateFPI() if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - if (any(prec_isNaN([plasticState(p)%dotState(:,c), damageState(p)%dotState(:,c), & - thermalState(p)%dotState(:,c), vacancyState(p)%dotState(:,c)]))) then ! NaN occured in any dotState + isNaN = any(prec_isNaN(plasticState(p)%dotState(:,c))) + do mySource = 1_pInt, phase_Nsources(p) + isNaN = isNaN .or. any(prec_isNaN(sourceState(p)%p(mySource)%dotState(:,c))) + enddo + if (isNaN) then ! NaN occured in any dotState crystallite_todo(g,i,e) = .false. ! ... skip me next time if (.not. crystallite_localPlasticity(g,i,e)) then ! if me is non-local... !$OMP CRITICAL (checkTodo) @@ -3246,141 +3137,117 @@ subroutine crystallite_integrateStateFPI() ! --- UPDATE STATE --- !$OMP DO PRIVATE(dot_prod12,dot_prod22, & - !$OMP& mySizePlasticDotState,mySizeDamageDotState,mySizeThermalDotState,mySizeVacancyDotState, & - !$OMP& stateResiduum, damageStateResiduum,thermalStateResiduum,vacancyStateResiduum, & - !$OMP& statedamper, damageStateDamper,thermalStateDamper,vacancyStateDamper, & - !$OMP& tempState, tempDamageState,tempThermalState,tempVacancyState,p,c) + !$OMP& mySizePlasticDotState,mySizeSourceDotState, & + !$OMP& plasticStateResiduum,sourceStateResiduum, & + !$OMP& plasticStatedamper,sourceStateDamper, & + !$OMP& tempPlasticState,tempSourceState,converged,p,c) do e = eIter(1),eIter(2); do i = iIter(1,e),iIter(2,e); do g = gIter(1,e),gIter(2,e) ! iterate over elements, ips and grains if (crystallite_todo(g,i,e) .and. .not. crystallite_converged(g,i,e)) then p = mappingConstitutive(2,g,i,e) c = mappingConstitutive(1,g,i,e) - mySizePlasticDotState = plasticState(p)%sizeDotState - mySizeDamageDotState = damageState( p)%sizeDotState - mySizeThermalDotState = thermalState(p)%sizeDotState - mySizeVacancyDotState = vacancyState(p)%sizeDotState - - dot_prod12 = dot_product(plasticState(p)%dotState(:,c) - plasticState(p)%previousDotState(:,c), & - plasticState(p)%previousDotState(:,c) - plasticState(p)%previousDotState2(:,c)) - dot_prod22 = dot_product(plasticState(p)%previousDotState(:,c) - plasticState(p)%previousDotState2(:,c), & - plasticState(p)%previousDotState(:,c) - plasticState(p)%previousDotState2(:,c)) + dot_prod12 = dot_product( plasticState(p)%dotState (:,c) & + - plasticState(p)%previousDotState (:,c), & + plasticState(p)%previousDotState (:,c) & + - plasticState(p)%previousDotState2(:,c)) + dot_prod22 = dot_product( plasticState(p)%previousDotState (:,c) & + - plasticState(p)%previousDotState2(:,c), & + plasticState(p)%previousDotState (:,c) & + - plasticState(p)%previousDotState2(:,c)) if ( dot_prod22 > 0.0_pReal & .and. ( dot_prod12 < 0.0_pReal & .or. dot_product(plasticState(p)%dotState(:,c), & plasticState(p)%previousDotState(:,c)) < 0.0_pReal) ) then - stateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) + plasticStateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) else - stateDamper = 1.0_pReal - endif - - dot_prod12 = dot_product(damageState(p)%dotState(:,c) - damageState(p)%previousDotState(:,c), & - damageState(p)%previousDotState(:,c) - damageState(p)%previousDotState2(:,c)) - dot_prod22 = dot_product(damageState(p)%previousDotState(:,c) - damageState(p)%previousDotState2(:,c), & - damageState(p)%previousDotState(:,c) - damageState(p)%previousDotState2(:,c)) - if ( dot_prod22 > 0.0_pReal & - .and. ( dot_prod12 < 0.0_pReal & - .or. dot_product(damageState(p)%dotState(:,c), & - damageState(p)%previousDotState(:,c)) < 0.0_pReal) ) then - damageStateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) - else - damageStateDamper = 1.0_pReal - endif - - dot_prod12 = dot_product(thermalState(p)%dotState(:,c) - thermalState(p)%previousDotState(:,c), & - thermalState(p)%previousDotState(:,c) - thermalState(p)%previousDotState2(:,c)) - dot_prod22 = dot_product(thermalState(p)%previousDotState(:,c) - thermalState(p)%previousDotState2(:,c), & - thermalState(p)%previousDotState(:,c) - thermalState(p)%previousDotState2(:,c)) - if ( dot_prod22 > 0.0_pReal & - .and. ( dot_prod12 < 0.0_pReal & - .or. dot_product(thermalState(p)%dotState(:,c), & - thermalState(p)%previousDotState(:,c)) < 0.0_pReal) ) then - thermalStateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) - else - thermalStateDamper = 1.0_pReal - endif - - dot_prod12 = dot_product(vacancyState(p)%dotState(:,c) - vacancyState(p)%previousDotState(:,c), & - vacancyState(p)%previousDotState(:,c) - vacancyState(p)%previousDotState2(:,c)) - dot_prod22 = dot_product(vacancyState(p)%previousDotState(:,c) - vacancyState(p)%previousDotState2(:,c), & - vacancyState(p)%previousDotState(:,c) - vacancyState(p)%previousDotState2(:,c)) - if ( dot_prod22 > 0.0_pReal & - .and. ( dot_prod12 < 0.0_pReal & - .or. dot_product(vacancyState(p)%dotState(:,c), & - vacancyState(p)%previousDotState(:,c)) < 0.0_pReal) ) then - vacancyStateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) - else - vacancyStateDamper = 1.0_pReal + plasticStateDamper = 1.0_pReal endif ! --- get residui --- - stateResiduum(1:mySizePlasticDotState) = plasticState(p)%state(1:mySizePlasticDotState,c) & - - plasticState(p)%subState0(1:mySizePlasticDotState,c) & - - (plasticState(p)%dotState(1:mySizePlasticDotState,c) * stateDamper & - + plasticState(p)%previousDotState(1:mySizePlasticDotState,c) & - * (1.0_pReal - stateDamper)) * crystallite_subdt(g,i,e) + mySizePlasticDotState = plasticState(p)%sizeDotState + plasticStateResiduum(1:mySizePlasticDotState) = & + plasticState(p)%state(1:mySizePlasticDotState,c) & + - plasticState(p)%subState0(1:mySizePlasticDotState,c) & + - ( plasticState(p)%dotState(1:mySizePlasticDotState,c) * plasticStateDamper & + + plasticState(p)%previousDotState(1:mySizePlasticDotState,c) & + * (1.0_pReal - plasticStateDamper)) * crystallite_subdt(g,i,e) - damageStateResiduum(1:mySizeDamageDotState) = damageState(p)%state(1:mySizeDamageDotState,c) & - - damageState(p)%subState0(1:mySizeDamageDotState,c) & - - (damageState(p)%dotState(1:mySizeDamageDotState,c) * damageStateDamper & - + damageState(p)%previousDotState(1:mySizeDamageDotState,c) & - * (1.0_pReal - damageStateDamper)) * crystallite_subdt(g,i,e) - - thermalStateResiduum(1:mySizeThermalDotState) = thermalState(p)%state(1:mySizeThermalDotState,c) & - - thermalState(p)%subState0(1:mySizeThermalDotState,c) & - - (thermalState(p)%dotState(1:mySizeThermalDotState,c) * thermalStateDamper & - + thermalState(p)%previousDotState(1:mySizeThermalDotState,c) & - * (1.0_pReal - thermalStateDamper)) * crystallite_subdt(g,i,e) - vacancyStateResiduum(1:mySizeVacancyDotState) = vacancyState(p)%state(1:mySizeVacancyDotState,c) & - - vacancyState(p)%subState0(1:mySizeVacancyDotState,c) & - - (vacancyState(p)%dotState(1:mySizeVacancyDotState,c) * vacancyStateDamper & - + vacancyState(p)%previousDotState(1:mySizeVacancyDotState,c) & - * (1.0_pReal - vacancyStateDamper)) * crystallite_subdt(g,i,e) ! --- correct state with residuum --- - tempState(1:mySizePlasticDotState) = plasticState(p)%state(1:mySizePlasticDotState,c) & - - stateResiduum(1:mySizePlasticDotState) ! need to copy to local variable, since we cant flush a pointer in openmp - tempDamageState(1:mySizeDamageDotState) = damageState(p)%state(1:mySizeDamageDotState,c) & - - damageStateResiduum(1:mySizeDamageDotState) ! need to copy to local variable, since we cant flush a pointer in openmp - tempThermalState(1:mySizeThermalDotState) = thermalState(p)%state(1:mySizeThermalDotState,c) & - - thermalStateResiduum(1:mySizeThermalDotState) ! need to copy to local variable, since we cant flush a pointer in openmp - tempVacancyState(1:mySizeVacancyDotState) = vacancyState(p)%state(1:mySizeVacancyDotState,c) & - - vacancyStateResiduum(1:mySizeVacancyDotState) ! need to copy to local variable, since we cant flush a pointer in openmp + tempPlasticState(1:mySizePlasticDotState) = & + plasticState(p)%state(1:mySizePlasticDotState,c) & + - plasticStateResiduum(1:mySizePlasticDotState) ! need to copy to local variable, since we cant flush a pointer in openmp + + ! --- store corrected dotState --- (cannot do this before state update, because not sure how to flush pointers in openmp) + + plasticState(p)%dotState(:,c) = plasticState(p)%dotState(:,c) * plasticStateDamper & + + plasticState(p)%previousDotState(:,c) & + * (1.0_pReal - plasticStateDamper) + + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + dot_prod12 = dot_product( sourceState(p)%p(mySource)%dotState (:,c) & + - sourceState(p)%p(mySource)%previousDotState (:,c), & + sourceState(p)%p(mySource)%previousDotState (:,c) & + - sourceState(p)%p(mySource)%previousDotState2(:,c)) + dot_prod22 = dot_product( sourceState(p)%p(mySource)%previousDotState (:,c) & + - sourceState(p)%p(mySource)%previousDotState2(:,c), & + sourceState(p)%p(mySource)%previousDotState (:,c) & + - sourceState(p)%p(mySource)%previousDotState2(:,c)) + + if ( dot_prod22 > 0.0_pReal & + .and. ( dot_prod12 < 0.0_pReal & + .or. dot_product(sourceState(p)%p(mySource)%dotState(:,c), & + sourceState(p)%p(mySource)%previousDotState(:,c)) < 0.0_pReal) ) then + sourceStateDamper = 0.75_pReal + 0.25_pReal * tanh(2.0_pReal + 4.0_pReal * dot_prod12 / dot_prod22) + else + sourceStateDamper = 1.0_pReal + endif + ! --- get residui --- + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceStateResiduum(1:mySizeSourceDotState,mySource) = & + sourceState(p)%p(mySource)%state(1:mySizeSourceDotState,c) & + - sourceState(p)%p(mySource)%subState0(1:mySizeSourceDotState,c) & + - ( sourceState(p)%p(mySource)%dotState(1:mySizeSourceDotState,c) * sourceStateDamper & + + sourceState(p)%p(mySource)%previousDotState(1:mySizeSourceDotState,c) & + * (1.0_pReal - sourceStateDamper)) * crystallite_subdt(g,i,e) + + ! --- correct state with residuum --- + tempSourceState(1:mySizeSourceDotState,mySource) = & + sourceState(p)%p(mySource)%state(1:mySizeSourceDotState,c) & + - sourceStateResiduum(1:mySizeSourceDotState,mySource) ! need to copy to local variable, since we cant flush a pointer in openmp + + ! --- store corrected dotState --- (cannot do this before state update, because not sure how to flush pointers in openmp) + sourceState(p)%p(mySource)%dotState(:,c) = & + sourceState(p)%p(mySource)%dotState(:,c) * sourceStateDamper & + + sourceState(p)%p(mySource)%previousDotState(:,c) & + * (1.0_pReal - sourceStateDamper) + enddo + #ifndef _OPENMP if (iand(debug_level(debug_crystallite), debug_levelExtensive) /= 0_pInt & .and. ((e == debug_e .and. i == debug_i .and. g == debug_g) & .or. .not. iand(debug_level(debug_crystallite), debug_levelSelective) /= 0_pInt)) then write(6,'(a,i8,1x,i2,1x,i3,/)') '<< CRYST >> update state at el ip g ',e,i,g - write(6,'(a,f6.1,/)') '<< CRYST >> statedamper ',statedamper - write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> state residuum',stateResiduum(1:mySizePlasticDotState) - write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state',tempState(1:mySizePlasticDotState) + write(6,'(a,f6.1,/)') '<< CRYST >> plasticstatedamper ',plasticStatedamper + write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> plastic state residuum',plasticStateResiduum(1:mySizePlasticDotState) + write(6,'(a,/,(12x,12(e12.5,1x)),/)') '<< CRYST >> new state',tempPlasticState(1:mySizePlasticDotState) endif #endif - ! --- store corrected dotState --- (cannot do this before state update, because not sure how to flush pointers in openmp) - plasticState(p)%dotState(:,c) = plasticState(p)%dotState(:,c) * stateDamper & - + plasticState(p)%previousDotState(:,c) & - * (1.0_pReal - stateDamper) - damageState( p)%dotState(:,c) = damageState(p)%dotState(:,c) * damageStateDamper & - + damageState(p)%previousDotState(:,c) & - * (1.0_pReal - damageStateDamper) - thermalState(p)%dotState(:,c) = thermalState(p)%dotState(:,c) * thermalStateDamper & - + thermalState(p)%previousDotState(:,c) & - * (1.0_pReal - thermalStateDamper) - vacancyState(p)%dotState(:,c) = vacancyState(p)%dotState(:,c) * vacancyStateDamper & - + vacancyState(p)%previousDotState(:,c) & - * (1.0_pReal - vacancyStateDamper) ! --- converged ? --- - if ( all( abs(stateResiduum(1:mySizePlasticDotState)) < plasticState(p)%aTolState(1:mySizePlasticDotState) & - .or. abs(stateResiduum(1:mySizePlasticDotState)) < rTol_crystalliteState & - * abs(tempState(1:mySizePlasticDotState)) ) & - .and. all( abs(damageStateResiduum(1:mySizeDamageDotState)) < damageState(p)%aTolState(1:mySizeDamageDotState) & - .or. abs(damageStateResiduum(1:mySizeDamageDotState)) < rTol_crystalliteState & - * abs(tempDamageState(1:mySizeDamageDotState)) ) & - .and. all( abs(thermalStateResiduum(1:mySizeThermalDotState)) < thermalState(p)%aTolState(1:mySizeThermalDotState) & - .or. abs(thermalStateResiduum(1:mySizeThermalDotState)) < rTol_crystalliteState & - * abs(tempThermalState(1:mySizeThermalDotState)) ) & - .and. all( abs(vacancyStateResiduum(1:mySizeVacancyDotState)) < vacancyState(p)%aTolState(1:mySizeVacancyDotState) & - .or. abs(vacancyStateResiduum(1:mySizeVacancyDotState)) < rTol_crystalliteState & - * abs(tempVacancyState(1:mySizeVacancyDotState)) )) then + converged = all( abs(plasticStateResiduum(1:mySizePlasticDotState)) < & + plasticState(p)%aTolState(1:mySizePlasticDotState) & + .or. abs(plasticStateResiduum(1:mySizePlasticDotState)) < & + rTol_crystalliteState * abs(tempPlasticState(1:mySizePlasticDotState))) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + converged = converged .and. & + all( abs(sourceStateResiduum(1:mySizeSourceDotState,mySource)) < & + sourceState(p)%p(mySource)%aTolState(1:mySizeSourceDotState) & + .or. abs(sourceStateResiduum(1:mySizeSourceDotState,mySource)) < & + rTol_crystalliteState * abs(tempSourceState(1:mySizeSourceDotState,mySource))) + enddo + if (converged) then crystallite_converged(g,i,e) = .true. ! ... converged per definition if (iand(debug_level(debug_crystallite), debug_levelBasic) /= 0_pInt) then @@ -3390,10 +3257,13 @@ subroutine crystallite_integrateStateFPI() !$OMP END CRITICAL (distributionState) endif endif - plasticState(p)%state(1:mySizePlasticDotState,c) = tempState(1:mySizePlasticDotState) - damageState( p)%state(1:mySizeDamageDotState, c) = tempDamageState(1:mySizeDamageDotState) - thermalState(p)%state(1:mySizeThermalDotState,c) = tempThermalState(1:mySizeThermalDotState) - vacancyState(p)%state(1:mySizeVacancyDotState,c) = tempVacancyState(1:mySizeVacancyDotState) + plasticState(p)%state(1:mySizePlasticDotState,c) = & + tempPlasticState(1:mySizePlasticDotState) + do mySource = 1_pInt, phase_Nsources(p) + mySizeSourceDotState = sourceState(p)%p(mySource)%sizeDotState + sourceState(p)%p(mySource)%state(1:mySizeSourceDotState,c) = & + tempSourceState(1:mySizeSourceDotState,mySource) + enddo endif enddo; enddo; enddo !$OMP ENDDO @@ -3484,7 +3354,7 @@ logical function crystallite_stateJump(g,i,e) c = mappingConstitutive(1,g,i,e) p = mappingConstitutive(2,g,i,e) - if (constitutive_collectDeltaState(crystallite_Tstar_v(1:6,g,i,e), g,i,e)) then + if (constitutive_collectDeltaState(crystallite_Tstar_v(1:6,g,i,e), crystallite_Fe(1:3,1:3,g,i,e), g,i,e)) then mySizePlasticDotState = plasticState(p)%sizeDotState if( any(plasticState(p)%deltaState(:,c) /= plasticState(p)%deltaState(:,c))) then ! NaN occured in deltaState crystallite_stateJump = .false. @@ -3889,7 +3759,7 @@ logical function crystallite_integrateStress(& !* calculate intermediate velocity gradient and its tangent from constitutive law call constitutive_LiAndItsTangent(Li_constitutive, dLi_dT3333, dLi_dFi3333, & - Tstar_v, Fi_new, Lpguess, g, i, e) + Tstar_v, Fi_new, g, i, e) !* update current residuum and check for convergence of loop @@ -4150,9 +4020,7 @@ function crystallite_postResults(ipc, ip, el) FE_celltype use material, only: & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & microstructure_crystallite, & crystallite_Noutput, & material_phase, & @@ -4170,9 +4038,7 @@ function crystallite_postResults(ipc, ip, el) real(pReal), dimension(1+crystallite_sizePostResults(microstructure_crystallite(mesh_element(4,el))) + & 1+plasticState(material_phase(ipc,ip,el))%sizePostResults + & - damageState( material_phase(ipc,ip,el))%sizePostResults + & - thermalState(material_phase(ipc,ip,el))%sizePostResults + & - vacancyState(material_phase(ipc,ip,el))%sizePostResults) :: & + sum(sourceState(material_phase(ipc,ip,el))%p(:)%sizePostResults)) :: & crystallite_postResults real(pReal), dimension(3,3) :: & Ee diff --git a/code/damage_anisoBrittle.f90 b/code/damage_anisoBrittle.f90 deleted file mode 100644 index 394e48276..000000000 --- a/code/damage_anisoBrittle.f90 +++ /dev/null @@ -1,635 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @brief material subroutine incorporating anisotropic ductile damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_anisoBrittle - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_anisoBrittle_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_anisoBrittle_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_anisoBrittle_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_anisoBrittle_Noutput !< number of outputs per instance of this damage - - integer(pInt), dimension(:), allocatable, private :: & - damage_anisoBrittle_totalNcleavage !< total number of cleavage systems - - integer(pInt), dimension(:,:), allocatable, private :: & - damage_anisoBrittle_Ncleavage !< number of cleavage systems per family - - real(pReal), dimension(:), allocatable, private :: & - damage_anisoBrittle_aTol_damage, & - damage_anisoBrittle_aTol_disp, & - damage_anisoBrittle_sdot_0, & - damage_anisoBrittle_N - - real(pReal), dimension(:,:), allocatable, private :: & - damage_anisoBrittle_critDisp, & - damage_anisoBrittle_critLoad - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_anisoBrittle_outputID !< ID of each post result output - - - public :: & - damage_anisoBrittle_init, & - damage_anisoBrittle_stateInit, & - damage_anisoBrittle_aTolState, & - damage_anisoBrittle_microstructure, & - damage_anisoBrittle_LdAndItsTangent, & - damage_anisoBrittle_getDamage, & - damage_anisoBrittle_putLocalDamage, & - damage_anisoBrittle_getLocalDamage, & - damage_anisoBrittle_getDamageDiffusion33, & - damage_anisoBrittle_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_damage_anisoBrittle_label, & - LOCAL_damage_anisoBrittle_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - use lattice, only: & - lattice_maxNcleavageFamily, & - lattice_NcleavageSystem - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_anisoBrittle_LABEL//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_damage_anisoBrittle_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_anisoBrittle_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_anisoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt) - allocate(damage_anisoBrittle_output(maxval(phase_Noutput),maxNinstance)) - damage_anisoBrittle_output = '' - allocate(damage_anisoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_anisoBrittle_Noutput(maxNinstance), source=0_pInt) - allocate(damage_anisoBrittle_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) - allocate(damage_anisoBrittle_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) - allocate(damage_anisoBrittle_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt) - allocate(damage_anisoBrittle_totalNcleavage(maxNinstance), source=0_pInt) - allocate(damage_anisoBrittle_aTol_damage(maxNinstance), source=0.0_pReal) - allocate(damage_anisoBrittle_aTol_disp(maxNinstance), source=0.0_pReal) - allocate(damage_anisoBrittle_sdot_0(maxNinstance), source=0.0_pReal) - allocate(damage_anisoBrittle_N(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_anisoBrittle_Noutput(instance) = damage_anisoBrittle_Noutput(instance) + 1_pInt - damage_anisoBrittle_outputID(damage_anisoBrittle_Noutput(instance),instance) = local_damage_ID - damage_anisoBrittle_output(damage_anisoBrittle_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('atol_damage') - damage_anisoBrittle_aTol_damage(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atol_disp') - damage_anisoBrittle_aTol_disp(instance) = IO_floatValue(line,positions,2_pInt) - - case ('sdot0') - damage_anisoBrittle_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) - - case ('damageratesensitivity') - damage_anisoBrittle_N(instance) = IO_floatValue(line,positions,2_pInt) - - case ('ncleavage') ! - Nchunks_CleavageFamilies = positions(1) - 1_pInt - do j = 1_pInt, Nchunks_CleavageFamilies - damage_anisoBrittle_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j) - enddo - - case ('criticaldisplacement') - do j = 1_pInt, Nchunks_CleavageFamilies - damage_anisoBrittle_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j) - enddo - - case ('criticalload') - do j = 1_pInt, Nchunks_CleavageFamilies - damage_anisoBrittle_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) - enddo - - end select - endif; endif - enddo parsingFile - - sanityChecks: do phase = 1_pInt, size(phase_damage) - myPhase: if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -! sanity checks - damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance) = & - min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested - damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance)) - damage_anisoBrittle_totalNcleavage(instance) = sum(damage_anisoBrittle_Ncleavage(:,instance)) ! how many cleavage systems altogether - if (damage_anisoBrittle_aTol_damage(instance) < 0.0_pReal) & - damage_anisoBrittle_aTol_damage(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_anisoBrittle_aTol_disp(instance) >= 1.0e-3_pReal) & - damage_anisoBrittle_aTol_disp(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_anisoBrittle_sdot_0(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')') - if (any(damage_anisoBrittle_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & - call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')') - if (any(damage_anisoBrittle_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & - call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')') - if (damage_anisoBrittle_N(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity_damage ('//LOCAL_DAMAGE_anisoBrittle_LABEL//')') - endif myPhase - enddo sanityChecks - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_damage_anisoBrittle_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_anisoBrittle_Noutput(instance) - select case(damage_anisoBrittle_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_anisoBrittle_sizePostResult(o,instance) = mySize - damage_anisoBrittle_sizePostResults(instance) = damage_anisoBrittle_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = sizeDotState + & - 1_pInt + & ! non-local damage - 1_pInt ! opening on each damage system - - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_anisoBrittle_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call damage_anisoBrittle_stateInit(phase,instance) - call damage_anisoBrittle_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_anisoBrittle_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_stateInit(phase,instance) - use material, only: & - damageState - use math, only: & - math_I3 - - implicit none - integer(pInt), intent(in) :: phase, instance !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState(1) = 1.0_pReal - tempState(2) = 1.0_pReal - - damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:))) - -end subroutine damage_anisoBrittle_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol(1) = damage_anisoBrittle_aTol_damage(instance) - tempTol(2) = damage_anisoBrittle_aTol_disp (instance) - - damageState(phase)%aTolState = tempTol - -end subroutine damage_anisoBrittle_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_microstructure(Tstar_v, subdt, ipc, ip, el) - use numerics, only: & - residualStiffness - use material, only: & - mappingConstitutive, & - phase_damageInstance, & - damageState - use lattice, only: & - lattice_DamageMobility, & - lattice_Scleavage_v, & - lattice_maxNcleavageFamily, & - lattice_NcleavageSystem - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, & - constituent, & - instance, & - f, i, index_myFamily - real(pReal) :: & - localDamage - real(pReal) :: & - traction_d, traction_t, traction_n, traction_crit - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - damageState(phase)%state(2,constituent) = damageState(phase)%subState0(2,constituent) - do f = 1_pInt,lattice_maxNcleavageFamily - index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family - do i = 1_pInt,damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family - traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase)) - traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase)) - traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase)) - - traction_crit = damage_anisoBrittle_critLoad(f,instance)* & - damage_anisoBrittle_getDamage(ipc, ip, el) - damageState(phase)%state(2,constituent) = & - damageState(phase)%state(2,constituent) + & - subdt*damage_anisoBrittle_sdot_0(instance)* & - ((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) + & - (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) + & - (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance))/ & - damage_anisoBrittle_critDisp(f,instance) - - enddo - enddo - - localDamage = max(residualStiffness,1.0_pReal/damageState(phase)%state(2,constituent)) - - damageState(phase)%state(1,constituent) = & - localDamage + & - (damageState(phase)%subState0(1,constituent) - localDamage)* & - exp(-subdt/lattice_DamageMobility(phase)) - -end subroutine damage_anisoBrittle_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief contains the constitutive equation for calculating the velocity gradient -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_LdAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el) - use prec, only: & - tol_math_check - use material, only: & - mappingConstitutive, & - phase_damageInstance - use math, only: & - math_Plain3333to99 - use lattice, only: & - lattice_Scleavage, & - lattice_Scleavage_v, & - lattice_maxNcleavageFamily, & - lattice_NcleavageSystem - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(out), dimension(3,3) :: & - Ld !< damage velocity gradient - real(pReal), intent(out), dimension(3,3,3,3) :: & - dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor) - integer(pInt) :: & - phase, & - constituent, & - instance, & - f, i, index_myFamily, k, l, m, n - real(pReal) :: & - traction_d, traction_t, traction_n, traction_crit, & - udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - Ld = 0.0_pReal - dLd_dTstar3333 = 0.0_pReal - do f = 1_pInt,lattice_maxNcleavageFamily - index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family - do i = 1_pInt,damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family - traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase)) - traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase)) - traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase)) - traction_crit = damage_anisoBrittle_critLoad(f,instance)* & - damage_anisoBrittle_getDamage(ipc, ip, el) - udotd = & - sign(1.0_pReal,traction_d)* & - damage_anisoBrittle_sdot_0(instance)* & - (max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) - if (abs(udotd) > tol_math_check) then - Ld = Ld + udotd*lattice_Scleavage(1:3,1:3,1,index_myFamily+i,phase) - dudotd_dt = sign(1.0_pReal,traction_d)*udotd*damage_anisoBrittle_N(instance)/ & - max(0.0_pReal, abs(traction_d) - traction_crit) - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudotd_dt*lattice_Scleavage(k,l,1,index_myFamily+i,phase)* & - lattice_Scleavage(m,n,1,index_myFamily+i,phase) - endif - - udott = & - sign(1.0_pReal,traction_t)* & - damage_anisoBrittle_sdot_0(instance)* & - (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) - if (abs(udott) > tol_math_check) then - Ld = Ld + udott*lattice_Scleavage(1:3,1:3,2,index_myFamily+i,phase) - dudott_dt = sign(1.0_pReal,traction_t)*udott*damage_anisoBrittle_N(instance)/ & - max(0.0_pReal, abs(traction_t) - traction_crit) - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudott_dt*lattice_Scleavage(k,l,2,index_myFamily+i,phase)* & - lattice_Scleavage(m,n,2,index_myFamily+i,phase) - endif - - udotn = & - sign(1.0_pReal,traction_n)* & - damage_anisoBrittle_sdot_0(instance)* & - (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**damage_anisoBrittle_N(instance) - if (abs(udotn) > tol_math_check) then - Ld = Ld + udotn*lattice_Scleavage(1:3,1:3,3,index_myFamily+i,phase) - dudotn_dt = sign(1.0_pReal,traction_n)*udotn*damage_anisoBrittle_N(instance)/ & - max(0.0_pReal, abs(traction_n) - traction_crit) - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudotn_dt*lattice_Scleavage(k,l,3,index_myFamily+i,phase)* & - lattice_Scleavage(m,n,3,index_myFamily+i,phase) - endif - - enddo - enddo - -end subroutine damage_anisoBrittle_LdAndItsTangent - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -pure function damage_anisoBrittle_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - mappingConstitutive, & - damageState, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_LOCAL_ID, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_anisoBrittle_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case default - damage_anisoBrittle_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% & - state(1,mappingConstitutive(1,ipc,ip,el)) - - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_anisoBrittle_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - end select - -end function damage_anisoBrittle_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage value based on local damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoBrittle_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_anisoBrittle_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -pure function damage_anisoBrittle_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: & - damage_anisoBrittle_getLocalDamage - - damage_anisoBrittle_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_anisoBrittle_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns brittle damage diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_anisoBrittle_getDamageDiffusion33(ipc, ip, el) - use lattice, only: & - lattice_DamageDiffusion33 - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - damage_anisoBrittle_getDamageDiffusion33 - integer(pInt) :: & - phase, constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage_anisoBrittle_getDamageDiffusion33 = & - lattice_DamageDiffusion33(1:3,1:3,phase) - -end function damage_anisoBrittle_getDamageDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_anisoBrittle_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_damageInstance - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_anisoBrittle_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_anisoBrittle_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_anisoBrittle_postResults = 0.0_pReal - - do o = 1_pInt,damage_anisoBrittle_Noutput(instance) - select case(damage_anisoBrittle_outputID(o,instance)) - case (local_damage_ID) - damage_anisoBrittle_postResults(c+1_pInt) = & - damage_anisoBrittle_getLocalDamage(ipc, ip, el) - c = c + 1_pInt - - end select - enddo -end function damage_anisoBrittle_postResults - -end module damage_anisoBrittle diff --git a/code/damage_anisoDuctile.f90 b/code/damage_anisoDuctile.f90 deleted file mode 100644 index fac1ee1d5..000000000 --- a/code/damage_anisoDuctile.f90 +++ /dev/null @@ -1,608 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine incorporating anisotropic ductile damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_anisoDuctile - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_anisoDuctile_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_anisoDuctile_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_anisoDuctile_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_anisoDuctile_Noutput !< number of outputs per instance of this damage - - integer(pInt), dimension(:), allocatable, private :: & - damage_anisoDuctile_totalNslip !< total number of slip systems - - integer(pInt), dimension(:,:), allocatable, private :: & - damage_anisoDuctile_Nslip !< number of slip systems per family - - real(pReal), dimension(:), allocatable, private :: & - damage_anisoDuctile_aTol_damage - - real(pReal), dimension(:,:), allocatable, private :: & - damage_anisoDuctile_critPlasticStrain - - real(pReal), dimension(:), allocatable, private :: & - damage_anisoDuctile_sdot_0, & - damage_anisoDuctile_N - - real(pReal), dimension(:,:), allocatable, private :: & - damage_anisoDuctile_critLoad - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_anisoDuctile_outputID !< ID of each post result output - - - public :: & - damage_anisoDuctile_init, & - damage_anisoDuctile_stateInit, & - damage_anisoDuctile_aTolState, & - damage_anisoDuctile_microstructure, & - damage_anisoDuctile_LdAndItsTangent, & - damage_anisoDuctile_getDamage, & - damage_anisoDuctile_putLocalDamage, & - damage_anisoDuctile_getLocalDamage, & - damage_anisoDuctile_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_damage_anisoDuctile_label, & - LOCAL_damage_anisoDuctile_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - use lattice, only: & - lattice_maxNslipFamily, & - lattice_NslipSystem - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_anisoDuctile_LABEL//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_damage_anisoDuctile_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_anisoDuctile_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_anisoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(damage_anisoDuctile_output(maxval(phase_Noutput),maxNinstance)) - damage_anisoDuctile_output = '' - allocate(damage_anisoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_anisoDuctile_Noutput(maxNinstance), source=0_pInt) - allocate(damage_anisoDuctile_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal) - allocate(damage_anisoDuctile_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal) - allocate(damage_anisoDuctile_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt) - allocate(damage_anisoDuctile_totalNslip(maxNinstance), source=0_pInt) - allocate(damage_anisoDuctile_N(maxNinstance), source=0.0_pReal) - allocate(damage_anisoDuctile_sdot_0(maxNinstance), source=0.0_pReal) - allocate(damage_anisoDuctile_aTol_damage(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_anisoDuctile_Noutput(instance) = damage_anisoDuctile_Noutput(instance) + 1_pInt - damage_anisoDuctile_outputID(damage_anisoDuctile_Noutput(instance),instance) = local_damage_ID - damage_anisoDuctile_output(damage_anisoDuctile_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('atol_damage') - damage_anisoDuctile_aTol_damage(instance) = IO_floatValue(line,positions,2_pInt) - - case ('nslip') ! - Nchunks_SlipFamilies = positions(1) - 1_pInt - do j = 1_pInt, Nchunks_SlipFamilies - damage_anisoDuctile_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j) - enddo - - case ('sdot0') - damage_anisoDuctile_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) - - case ('criticalplasticstrain') - do j = 1_pInt, Nchunks_SlipFamilies - damage_anisoDuctile_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j) - enddo - - case ('damageratesensitivity') - damage_anisoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt) - - case ('criticalload') - do j = 1_pInt, Nchunks_SlipFamilies - damage_anisoDuctile_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) - enddo - - end select - endif; endif - enddo parsingFile - - sanityChecks: do phase = 1_pInt, size(phase_damage) - myPhase: if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -! sanity checks - damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance) = & - min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested - damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance)) - damage_anisoDuctile_totalNslip(instance) = sum(damage_anisoDuctile_Nslip(:,instance)) - if (damage_anisoDuctile_aTol_damage(instance) < 0.0_pReal) & - damage_anisoDuctile_aTol_damage(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_anisoDuctile_sdot_0(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')') - if (any(damage_anisoDuctile_critPlasticStrain(:,instance) < 0.0_pReal)) & - call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')') - if (damage_anisoDuctile_N(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity_damage ('//LOCAL_DAMAGE_anisoDuctile_LABEL//')') - endif myPhase - enddo sanityChecks - - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_damage_anisoDuctile_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_anisoDuctile_Noutput(instance) - select case(damage_anisoDuctile_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_anisoDuctile_sizePostResult(o,instance) = mySize - damage_anisoDuctile_sizePostResults(instance) = damage_anisoDuctile_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = sizeDotState + & - 1_pInt + & ! time regularised damage - 1_pInt ! damaged plasticity - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_anisoDuctile_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - call damage_anisoDuctile_stateInit(phase,instance) - call damage_anisoDuctile_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_anisoDuctile_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_stateInit(phase, instance) - use material, only: & - damageState - use math, only: & - math_I3 - implicit none - integer(pInt), intent(in) :: phase , instance !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState(1) = 1.0_pReal - tempState(2) = 0.0_pReal - - damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:))) - -end subroutine damage_anisoDuctile_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol = damage_anisoDuctile_aTol_damage(instance) - damageState(phase)%aTolState = tempTol - -end subroutine damage_anisoDuctile_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_microstructure(subdt, ipc, ip, el) - use numerics, only: & - residualStiffness - use material, only: & - mappingConstitutive, & - phase_damageInstance, & - plasticState, & - damageState - use lattice, only: & - lattice_maxNslipFamily, & - lattice_DamageMobility - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, & - constituent, & - instance, & - index, f, i - real(pReal) :: & - localDamage - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - index = 1_pInt - damageState(phase)%state(2,constituent) = damageState(phase)%subState0(2,constituent) - do f = 1_pInt,lattice_maxNslipFamily - do i = 1_pInt,damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family - damageState(phase)%state(2,constituent) = & - damageState(phase)%state(2,constituent) + & - subdt* & - plasticState(phase)%slipRate(index,constituent)/ & - (damage_anisoDuctile_getDamage(ipc, ip, el)**damage_anisoDuctile_N(instance))/ & - damage_anisoDuctile_critPlasticStrain(f,instance) - - index = index + 1_pInt - enddo - enddo - - localDamage = & - max(residualStiffness,min(1.0_pReal,1.0_pReal/damageState(phase)%state(2,constituent))) - - damageState(phase)%state(1,constituent) = & - localDamage + & - (damageState(phase)%subState0(1,constituent) - localDamage)* & - exp(-subdt/lattice_DamageMobility(phase)) - -end subroutine damage_anisoDuctile_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief contains the constitutive equation for calculating the velocity gradient -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_LdAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el) - use prec, only: & - tol_math_check - use lattice, only: & - lattice_maxNslipFamily, & - lattice_NslipSystem, & - lattice_sd, & - lattice_st, & - lattice_sn - use material, only: & - mappingConstitutive, & - phase_damageInstance - use math, only: & - math_Plain3333to99, & - math_I3, & - math_identity4th, & - math_symmetric33, & - math_Mandel33to6, & - math_tensorproduct, & - math_det33, & - math_mul33x33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(out), dimension(3,3) :: & - Ld !< damage velocity gradient - real(pReal), intent(out), dimension(3,3,3,3) :: & - dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor) - real(pReal), dimension(3,3) :: & - projection_d, projection_t, projection_n !< projection modes 3x3 tensor - real(pReal), dimension(6) :: & - projection_d_v, projection_t_v, projection_n_v !< projection modes 3x3 vector - integer(pInt) :: & - phase, & - constituent, & - instance, & - f, i, index_myFamily, k, l, m, n - real(pReal) :: & - traction_d, traction_t, traction_n, traction_crit, & - udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - Ld = 0.0_pReal - dLd_dTstar3333 = 0.0_pReal - do f = 1_pInt,lattice_maxNslipFamily - index_myFamily = sum(lattice_NslipSystem(1:f-1_pInt,phase)) ! at which index starts my family - do i = 1_pInt,damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family - projection_d = math_tensorproduct(lattice_sd(1:3,index_myFamily+i,phase),& - lattice_sn(1:3,index_myFamily+i,phase)) - projection_t = math_tensorproduct(lattice_st(1:3,index_myFamily+i,phase),& - lattice_sn(1:3,index_myFamily+i,phase)) - projection_n = math_tensorproduct(lattice_sn(1:3,index_myFamily+i,phase),& - lattice_sn(1:3,index_myFamily+i,phase)) - - projection_d_v(1:6) = math_Mandel33to6(math_symmetric33(projection_d(1:3,1:3))) - projection_t_v(1:6) = math_Mandel33to6(math_symmetric33(projection_t(1:3,1:3))) - projection_n_v(1:6) = math_Mandel33to6(math_symmetric33(projection_n(1:3,1:3))) - - traction_d = dot_product(Tstar_v,projection_d_v(1:6)) - traction_t = dot_product(Tstar_v,projection_t_v(1:6)) - traction_n = dot_product(Tstar_v,projection_n_v(1:6)) - - traction_crit = damage_anisoDuctile_critLoad(f,instance)* & - damage_anisoDuctile_getDamage(ipc, ip, el) ! degrading critical load carrying capacity by damage - - udotd = & - sign(1.0_pReal,traction_d)* & - damage_anisoDuctile_sdot_0(instance)* & - (abs(traction_d)/traction_crit - & - abs(traction_d)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance) - if (abs(udotd) > tol_math_check) then - Ld = Ld + udotd*projection_d - dudotd_dt = udotd*damage_anisoDuctile_N(instance)/traction_d - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudotd_dt*projection_d(k,l)*projection_d(m,n) - endif - - udott = & - sign(1.0_pReal,traction_t)* & - damage_anisoDuctile_sdot_0(instance)* & - (abs(traction_t)/traction_crit - & - abs(traction_t)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance) - if (abs(udott) > tol_math_check) then - Ld = Ld + udott*projection_t - dudott_dt = udott*damage_anisoDuctile_N(instance)/traction_t - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudott_dt*projection_t(k,l)*projection_t(m,n) - endif - udotn = & - damage_anisoDuctile_sdot_0(instance)* & - (max(0.0_pReal,traction_n)/traction_crit - & - max(0.0_pReal,traction_n)/damage_anisoDuctile_critLoad(f,instance))**damage_anisoDuctile_N(instance) - if (abs(udotn) > tol_math_check) then - Ld = Ld + udotn*projection_n - dudotn_dt = udotn*damage_anisoDuctile_N(instance)/traction_n - forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & - dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & - dudotn_dt*projection_n(k,l)*projection_n(m,n) - endif - enddo - enddo - -end subroutine damage_anisoDuctile_LdAndItsTangent - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -pure function damage_anisoDuctile_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - mappingConstitutive, & - damageState, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_LOCAL_ID, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_anisoDuctile_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case default - damage_anisoDuctile_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% & - state(1,mappingConstitutive(1,ipc,ip,el)) - - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_anisoDuctile_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - end select - -end function damage_anisoDuctile_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage value based on local damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_anisoDuctile_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_anisoDuctile_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -pure function damage_anisoDuctile_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: & - damage_anisoDuctile_getLocalDamage - - damage_anisoDuctile_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_anisoDuctile_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_anisoDuctile_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_damageInstance - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_anisoDuctile_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_anisoDuctile_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_anisoDuctile_postResults = 0.0_pReal - - do o = 1_pInt,damage_anisoDuctile_Noutput(instance) - select case(damage_anisoDuctile_outputID(o,instance)) - case (local_damage_ID) - damage_anisoDuctile_postResults(c+1_pInt) = & - damage_anisoDuctile_getLocalDamage(ipc, ip, el) - c = c + 1_pInt - - end select - enddo -end function damage_anisoDuctile_postResults - -end module damage_anisoDuctile diff --git a/code/damage_gurson.f90 b/code/damage_gurson.f90 deleted file mode 100644 index e9ff5256a..000000000 --- a/code/damage_gurson.f90 +++ /dev/null @@ -1,503 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine incoprorating gurson damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_gurson - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_gurson_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_gurson_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_gurson_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_gurson_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, private :: & - damage_gurson_aTol, & - damage_gurson_coeff_torsion, & - damage_gurson_coeff_ten_comp, & - damage_gurson_coeff_triaxiality, & - damage_gurson_fracture_tough, & - damage_gurson_lengthscale, & - damage_gurson_crit_void_fraction - - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum !!!!! ToDo - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_gurson_outputID !< ID of each post result output - - - public :: & - damage_gurson_init, & - damage_gurson_stateInit, & - damage_gurson_aTolState, & - damage_gurson_dotState, & - damage_gurson_microstructure, & - damage_gurson_getDamage, & - damage_gurson_getSlipDamage, & - damage_gurson_putLocalDamage, & - damage_gurson_getLocalDamage, & - damage_gurson_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_DAMAGE_gurson_label, & - LOCAL_DAMAGE_gurson_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_DAMAGE_gurson_LABEL//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_DAMAGE_gurson_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_gurson_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_gurson_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(damage_gurson_output(maxval(phase_Noutput),maxNinstance)) - damage_gurson_output = '' - allocate(damage_gurson_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_gurson_Noutput(maxNinstance), source=0_pInt) - allocate(damage_gurson_coeff_torsion(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_coeff_ten_comp(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_coeff_triaxiality(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_fracture_tough(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_lengthscale(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_crit_void_fraction(maxNinstance), source=0.0_pReal) - allocate(damage_gurson_aTol(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_gurson_Noutput(instance) = damage_gurson_Noutput(instance) + 1_pInt - damage_gurson_outputID(damage_gurson_Noutput(instance),instance) = local_damage_ID - damage_gurson_output(damage_gurson_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select -! input parameters - case ('coeff_torsion') - damage_gurson_coeff_torsion(instance) = IO_floatValue(line,positions,2_pInt) !> coefficent of torsional stress component - - case ('coeff_tension_comp') - damage_gurson_coeff_ten_comp(instance) = IO_floatValue(line,positions,2_pInt) !> coefficent of tensile or compressive stress component - - case ('coeff_triaxiality') - damage_gurson_coeff_triaxiality(instance) = IO_floatValue(line,positions,2_pInt) - - case ('fracture_toughness') - damage_gurson_fracture_tough(instance) = IO_floatValue(line,positions,2_pInt) - - case ('lengthscale') - damage_gurson_lengthscale(instance) = IO_floatValue(line,positions,2_pInt) - - case ('critical_voidFraction') - damage_gurson_crit_void_fraction(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atol_damage') - damage_gurson_aTol(instance) = IO_floatValue(line,positions,2_pInt) - end select - endif; endif - enddo parsingFile - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_DAMAGE_gurson_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_gurson_Noutput(instance) - select case(damage_gurson_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_gurson_sizePostResult(o,instance) = mySize - damage_gurson_sizePostResults(instance) = damage_gurson_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 3_pInt - sizeState = 4_pInt - - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_gurson_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call damage_gurson_stateInit(phase) - call damage_gurson_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_gurson_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant NEW state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_stateInit(phase) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState(1) = 1.0_pReal - tempState(2) = 1.0_pReal - tempState(3) = 1.0_pReal - tempState(4) = 1.0_pReal - - damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:))) - damageState(phase)%state0 = damageState(phase)%state - damageState(phase)%partionedState0 = damageState(phase)%state -end subroutine damage_gurson_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol = damage_gurson_aTol(instance) - damageState(phase)%aTolState = tempTol - -end subroutine damage_gurson_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_dotState(Tstar_v, Lp, ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - use math, only: & - math_equivStrain33, & - math_norm33, & - math_j3_33, & - math_trace33, & - math_I3, & - math_Mandel6to33 - use lattice, only: & - lattice_DamageMobility - - implicit none - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) - real(pReal), intent(in), dimension(3,3) :: & - Lp - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - integer(pInt) :: & - phase, constituent - real(pReal) :: & - i1, j2, j3 - real(pReal) , dimension(3,3) :: & - Tstar_dev - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - Tstar_dev = math_Mandel6to33(Tstar_v) - math_trace33(math_Mandel6to33(Tstar_v))/3.0_pReal*math_I3 - i1 = sum(Tstar_v(1:3)) - j2 = 0.5_pReal*(math_norm33(Tstar_dev))**2.0_pReal - j3 = math_j3_33(math_Mandel6to33(Tstar_v)) - - damageState(phase)%dotState(1,constituent) = & - (1.0_pReal/lattice_DamageMobility(phase))* & - (damageState(phase)%state(4,constituent) - & - damageState(phase)%state(1,constituent)) - - - damageState(phase)%dotState(2,constituent) = & !> void nucleation rate - math_norm33(Lp)*sqrt(damage_gurson_lengthscale(phase))/damage_gurson_fracture_tough(phase)* & - damageState(phase)%state(2,constituent) * ( & - damage_gurson_coeff_torsion(phase) * ((4_pReal/27_pReal) - (j3**(2)/j2**(3))) + & - damage_gurson_coeff_ten_comp(phase) * (j3/j2**(1.5_pReal)) + & - damage_gurson_coeff_triaxiality(phase) * abs(i1/sqrt(j2))) !> to be coupled with vacancy generation - - damageState(phase)%dotState(3,constituent) = & - ( damageState(phase)%state(4,constituent)) * math_trace33(Lp) !> void growth rate - - -end subroutine damage_gurson_dotState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_microstructure(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - use math, only: & - math_Mandel6to33, & - math_mul33x33, & - math_norm33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal) :: & - voidFraction - integer(pInt) :: & - phase, constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - voidFraction = damageState(phase)%state(2,constituent) + damageState(phase)%state(3,constituent) - - if(voidFraction < damage_gurson_crit_void_fraction(phase)) then - damageState(phase)%state(4,constituent) = 1.0_pReal - voidFraction ! damage parameter is 1 when no void present - else - damageState(phase)%state(4,constituent) = 1.0_pReal - damage_gurson_crit_void_fraction(phase) + & - 5.0_pReal * (voidFraction - damage_gurson_crit_void_fraction(phase)) ! this accelerated void increase models the effect of void coalescence - endif - -end subroutine damage_gurson_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -function damage_gurson_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_LOCAL_ID, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_gurson_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case (FIELD_DAMAGE_LOCAL_ID) - damage_gurson_getDamage = damage_gurson_getLocalDamage(ipc, ip, el) - - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_gurson_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - end select - -end function damage_gurson_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns slip damage -!-------------------------------------------------------------------------------------------------- -function damage_gurson_getSlipDamage(Tstar_v, ipc, ip, el) - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(6), intent(in) :: & - Tstar_v !< 2nd Piola Kirchhoff stress tensor in Mandel notation - real(pReal) :: damage_gurson_getSlipDamage, porosity - - porosity = damage_gurson_getDamage(ipc, ip, el) - damage_gurson_getSlipDamage = porosity*porosity ! Gurson yield function should go here - -end function damage_gurson_getSlipDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief puts local damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_gurson_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_gurson_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -function damage_gurson_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_gurson_getLocalDamage - - damage_gurson_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_gurson_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_gurson_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_damageInstance,& - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_gurson_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_gurson_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_gurson_postResults = 0.0_pReal - - do o = 1_pInt,damage_gurson_Noutput(instance) - select case(damage_gurson_outputID(o,instance)) - case (local_damage_ID) - damage_gurson_postResults(c+1_pInt) = damageState(phase)%state(1,constituent) - c = c + 1 - - end select - enddo -end function damage_gurson_postResults - -end module damage_gurson diff --git a/code/damage_isoBrittle.f90 b/code/damage_isoBrittle.f90 deleted file mode 100644 index 5e431ba18..000000000 --- a/code/damage_isoBrittle.f90 +++ /dev/null @@ -1,484 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine incoprorating isotropic brittle damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_isoBrittle - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_isoBrittle_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_isoBrittle_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_isoBrittle_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_isoBrittle_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, private :: & - damage_isoBrittle_aTol, & - damage_isoBrittle_critStrainEnergy - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_isoBrittle_outputID !< ID of each post result output - - - public :: & - damage_isoBrittle_init, & - damage_isoBrittle_stateInit, & - damage_isoBrittle_aTolState, & - damage_isoBrittle_microstructure, & - damage_isoBrittle_getDamage, & - damage_isoBrittle_putLocalDamage, & - damage_isoBrittle_getLocalDamage, & - damage_isoBrittle_getDamageDiffusion33, & - damage_isoBrittle_getDamagedC66, & - damage_isoBrittle_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoBrittle_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_damage_isoBrittle_label, & - LOCAL_damage_isoBrittle_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_isoBrittle_label//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_damage_isoBrittle_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_isoBrittle_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_isoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(damage_isoBrittle_output(maxval(phase_Noutput),maxNinstance)) - damage_isoBrittle_output = '' - allocate(damage_isoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_isoBrittle_Noutput(maxNinstance), source=0_pInt) - allocate(damage_isoBrittle_critStrainEnergy(maxNinstance), source=0.0_pReal) - allocate(damage_isoBrittle_aTol(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_isoBrittle_Noutput(instance) = damage_isoBrittle_Noutput(instance) + 1_pInt - damage_isoBrittle_outputID(damage_isoBrittle_Noutput(instance),instance) = local_damage_ID - damage_isoBrittle_output(damage_isoBrittle_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('criticalstrainenergy') - damage_isoBrittle_critStrainEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atol_damage') - damage_isoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt) - - end select - endif; endif - enddo parsingFile - - - sanityChecks: do phase = 1_pInt, size(phase_damage) - myPhase: if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -! sanity checks - if (damage_isoBrittle_aTol(instance) < 0.0_pReal) & - damage_isoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_isoBrittle_critStrainEnergy(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='criticalStrainEnergy ('//LOCAL_DAMAGE_isoBrittle_LABEL//')') - endif myPhase - enddo sanityChecks - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_damage_isoBrittle_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_isoBrittle_Noutput(instance) - select case(damage_isoBrittle_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_isoBrittle_sizePostResult(o,instance) = mySize - damage_isoBrittle_sizePostResults(instance) = damage_isoBrittle_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = 2_pInt - - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_isoBrittle_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call damage_isoBrittle_stateInit(phase) - call damage_isoBrittle_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_isoBrittle_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant NEW state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoBrittle_stateInit(phase) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState = 1.0_pReal - damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:))) - damageState(phase)%state0 = damageState(phase)%state - damageState(phase)%partionedState0 = damageState(phase)%state -end subroutine damage_isoBrittle_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoBrittle_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol = damage_isoBrittle_aTol(instance) - damageState(phase)%aTolState = tempTol -end subroutine damage_isoBrittle_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoBrittle_microstructure(C, Fe, subdt, ipc, ip, el) - use numerics, only: & - residualStiffness - use material, only: & - mappingConstitutive, & - phase_damageInstance, & - damageState - use math, only : & - math_mul33x33, & - math_mul66x6, & - math_Mandel33to6, & - math_transpose33, & - math_I3 - use lattice, only: & - lattice_DamageMobility - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in), dimension(3,3) :: & - Fe - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, constituent, instance - real(pReal) :: & - strain(6), & - stress(6), & - C(6,6) - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3) - stress = math_mul66x6(C,strain) - - damageState(phase)%state(2,constituent) = & - max(residualStiffness, & - min(damageState(phase)%state0(2,constituent), & - damage_isoBrittle_critStrainEnergy(instance)/(2.0_pReal*sum(abs(stress*strain))))) !< residualStiffness < damage < damage0 - - damageState(phase)%state(1,constituent) = & - damageState(phase)%state(2,constituent) + & - (damageState(phase)%subState0(1,constituent) - damageState(phase)%state(2,constituent))* & - exp(-subdt/lattice_DamageMobility(phase)) - -end subroutine damage_isoBrittle_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -pure function damage_isoBrittle_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - mappingConstitutive, & - damageState, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_isoBrittle_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_isoBrittle_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - case default - damage_isoBrittle_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% & - state0(1,mappingConstitutive(1,ipc,ip,el)) - - end select - -end function damage_isoBrittle_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoBrittle_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_isoBrittle_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -pure function damage_isoBrittle_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_isoBrittle_getLocalDamage - - damage_isoBrittle_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_isoBrittle_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns brittle damage diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_isoBrittle_getDamageDiffusion33(ipc, ip, el) - use lattice, only: & - lattice_DamageDiffusion33 - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - damage_isoBrittle_getDamageDiffusion33 - integer(pInt) :: & - phase, constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage_isoBrittle_getDamageDiffusion33 = & - lattice_DamageDiffusion33(1:3,1:3,phase) - -end function damage_isoBrittle_getDamageDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns brittle damaged stiffness tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_isoBrittle_getDamagedC66(C, ipc, ip, el) - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6,6) :: & - C - real(pReal), dimension(6,6) :: & - damage_isoBrittle_getDamagedC66 - integer(pInt) :: & - phase, constituent - real(pReal) :: & - damage - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage = damage_isoBrittle_getDamage(ipc, ip, el) - damage_isoBrittle_getDamagedC66 = & - damage*damage*C - -end function damage_isoBrittle_getDamagedC66 - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_isoBrittle_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - damageState, & - phase_damageInstance - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_isoBrittle_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_isoBrittle_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_isoBrittle_postResults = 0.0_pReal - - do o = 1_pInt,damage_isoBrittle_Noutput(instance) - select case(damage_isoBrittle_outputID(o,instance)) - case (local_damage_ID) - damage_isoBrittle_postResults(c+1_pInt) = damageState(phase)%state(1,constituent) - c = c + 1 - - end select - enddo -end function damage_isoBrittle_postResults - -end module damage_isoBrittle diff --git a/code/damage_isoDuctile.f90 b/code/damage_isoDuctile.f90 deleted file mode 100644 index 07d3c9708..000000000 --- a/code/damage_isoDuctile.f90 +++ /dev/null @@ -1,457 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH -!> @brief material subroutine incoprorating isotropic ductile damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_isoDuctile - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_isoDuctile_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_isoDuctile_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_isoDuctile_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_isoDuctile_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, private :: & - damage_isoDuctile_aTol, & - damage_isoDuctile_critPlasticStrain, & - damage_isoDuctile_N - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_isoDuctile_outputID !< ID of each post result output - - - public :: & - damage_isoDuctile_init, & - damage_isoDuctile_stateInit, & - damage_isoDuctile_aTolState, & - damage_isoDuctile_microstructure, & - damage_isoDuctile_getDamage, & - damage_isoDuctile_putLocalDamage, & - damage_isoDuctile_getLocalDamage, & - damage_isoDuctile_getDamagedC66, & - damage_isoDuctile_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoDuctile_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_damage_isoDuctile_label, & - LOCAL_damage_isoDuctile_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_isoDuctile_LABEL//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_damage_isoDuctile_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_isoDuctile_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_isoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(damage_isoDuctile_output(maxval(phase_Noutput),maxNinstance)) - damage_isoDuctile_output = '' - allocate(damage_isoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_isoDuctile_Noutput(maxNinstance), source=0_pInt) - allocate(damage_isoDuctile_critPlasticStrain(maxNinstance), source=0.0_pReal) - allocate(damage_isoDuctile_N(maxNinstance), source=0.0_pReal) - allocate(damage_isoDuctile_aTol(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_isoDuctile_Noutput(instance) = damage_isoDuctile_Noutput(instance) + 1_pInt - damage_isoDuctile_outputID(damage_isoDuctile_Noutput(instance),instance) = local_damage_ID - damage_isoDuctile_output(damage_isoDuctile_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('criticalplasticstrain') - damage_isoDuctile_critPlasticStrain(instance) = IO_floatValue(line,positions,2_pInt) - - case ('damageratesensitivity') - damage_isoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atol_damage') - damage_isoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt) - - end select - endif; endif - enddo parsingFile - - sanityChecks: do phase = 1_pInt, size(phase_damage) - myPhase: if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -! sanity checks - if (damage_isoDuctile_aTol(instance) < 0.0_pReal) & - damage_isoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_isoDuctile_critPlasticStrain(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='critical_plastic_strain ('//LOCAL_DAMAGE_isoDuctile_LABEL//')') - endif myPhase - enddo sanityChecks - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_damage_isoDuctile_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_isoDuctile_Noutput(instance) - select case(damage_isoDuctile_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_isoDuctile_sizePostResult(o,instance) = mySize - damage_isoDuctile_sizePostResults(instance) = damage_isoDuctile_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = 2_pInt - - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_isoDuctile_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call damage_isoDuctile_stateInit(phase) - call damage_isoDuctile_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_isoDuctile_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoDuctile_stateInit(phase) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState(1) = 1.0_pReal - tempState(2) = 0.0_pReal - - damageState(phase)%state0 = spread(tempState,2,size(damageState(phase)%state(1,:))) - -end subroutine damage_isoDuctile_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoDuctile_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol = damage_isoDuctile_aTol(instance) - damageState(phase)%aTolState = tempTol - -end subroutine damage_isoDuctile_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoDuctile_microstructure(subdt,ipc, ip, el) - use numerics, only: & - residualStiffness - use material, only: & - phase_damageInstance, & - mappingConstitutive, & - plasticState, & - damageState - use lattice, only: & - lattice_DamageMobility - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, constituent, instance - real(pReal) :: & - localDamage - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - damageState(phase)%state(2,constituent) = & - damageState(phase)%subState0(2,constituent) + & - subdt* & - sum(plasticState(phase)%slipRate(:,constituent))/ & - (damage_isoDuctile_getDamage(ipc, ip, el)**damage_isoDuctile_N(instance))/ & - damage_isoDuctile_critPlasticStrain(instance) - - localDamage = & - max(residualStiffness,min(1.0_pReal, 1.0_pReal/damageState(phase)%state(2,constituent))) - - damageState(phase)%state(1,constituent) = & - localDamage + & - (damageState(phase)%subState0(1,constituent) - localDamage)* & - exp(-subdt/lattice_DamageMobility(phase)) - -end subroutine damage_isoDuctile_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -pure function damage_isoDuctile_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - mappingConstitutive, & - damageState, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_LOCAL_ID, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_isoDuctile_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case default - damage_isoDuctile_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% & - state0(1,mappingConstitutive(1,ipc,ip,el)) - - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_isoDuctile_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - end select - -end function damage_isoDuctile_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief puts local damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_isoDuctile_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_isoDuctile_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -pure function damage_isoDuctile_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_isoDuctile_getLocalDamage - - damage_isoDuctile_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_isoDuctile_getLocalDamage -!-------------------------------------------------------------------------------------------------- -!> @brief returns ductile damaged stiffness tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_isoDuctile_getDamagedC66(C, ipc, ip, el) - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6,6) :: & - C - real(pReal), dimension(6,6) :: & - damage_isoDuctile_getDamagedC66 - integer(pInt) :: & - phase, constituent - real(pReal) :: & - damage - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage = damage_isoDuctile_getDamage(ipc, ip, el) - damage_isoDuctile_getDamagedC66 = & - damage*damage*C - -end function damage_isoDuctile_getDamagedC66 - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_isoDuctile_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_damageInstance,& - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_isoDuctile_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_isoDuctile_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_isoDuctile_postResults = 0.0_pReal - - do o = 1_pInt,damage_isoDuctile_Noutput(instance) - select case(damage_isoDuctile_outputID(o,instance)) - case (local_damage_ID) - damage_isoDuctile_postResults(c+1_pInt) = damageState(phase)%state(1,constituent) - c = c + 1 - - end select - enddo -end function damage_isoDuctile_postResults - -end module damage_isoDuctile diff --git a/code/damage_local.f90 b/code/damage_local.f90 new file mode 100644 index 000000000..afc3999a9 --- /dev/null +++ b/code/damage_local.f90 @@ -0,0 +1,327 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for locally evolving damage field +!-------------------------------------------------------------------------------------------------- +module damage_local + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + damage_local_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + damage_local_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + damage_local_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + damage_local_Noutput !< number of outputs per instance of this damage + + enum, bind(c) + enumerator :: undefined_ID, & + damage_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + damage_local_outputID !< ID of each post result output + + public :: & + damage_local_init, & + damage_local_updateState, & + damage_local_postResults + private :: & + damage_local_getSourceAndItsTangent + +contains + +!-------------------------------------------------------------------------------------------------- +!> @brief allocates all neccessary fields, reads information from material configuration file +!-------------------------------------------------------------------------------------------------- +subroutine damage_local_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + damage_type, & + damage_typeInstance, & + homogenization_Noutput, & + DAMAGE_local_label, & + DAMAGE_local_ID, & + material_homog, & + mappingHomogenization, & + damageState, & + damageMapping, & + damage, & + material_partHomogenization + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,homog,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_local_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(damage_type == DAMAGE_local_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(damage_local_sizePostResults(maxNinstance), source=0_pInt) + allocate(damage_local_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(damage_local_output (maxval(homogenization_Noutput),maxNinstance)) + damage_local_output = '' + allocate(damage_local_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(damage_local_Noutput (maxNinstance), source=0_pInt) + + rewind(fileUnit) + homog = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + homog = homog + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (homog > 0_pInt ) then; if (damage_type(homog) == DAMAGE_local_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = damage_typeInstance(homog) ! which instance of my damage is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('damage') + damage_local_Noutput(instance) = damage_local_Noutput(instance) + 1_pInt + damage_local_outputID(damage_local_Noutput(instance),instance) = damage_ID + damage_local_output(damage_local_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingFile + + initializeInstances: do homog = 1_pInt, size(damage_type) + + myhomog: if (damage_type(homog) == DAMAGE_local_ID) then + NofMyHomog = count(material_homog == homog) + instance = damage_typeInstance(homog) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,damage_local_Noutput(instance) + select case(damage_local_outputID(o,instance)) + case(damage_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + damage_local_sizePostResult(o,instance) = mySize + damage_local_sizePostResults(instance) = damage_local_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 1_pInt + damageState(homog)%sizeState = sizeState + damageState(homog)%sizePostResults = damage_local_sizePostResults(instance) + allocate(damageState(homog)%state0 (sizeState,NofMyHomog)) + allocate(damageState(homog)%subState0(sizeState,NofMyHomog)) + allocate(damageState(homog)%state (sizeState,NofMyHomog)) + + nullify(damageMapping(homog)%p) + damageMapping(homog)%p => mappingHomogenization(1,:,:) + deallocate(damage(homog)%p) + damage(homog)%p => damageState(homog)%state(1,:) + + endif myhomog + enddo initializeInstances + + +end subroutine damage_local_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates local change in damage field +!-------------------------------------------------------------------------------------------------- +function damage_local_updateState(subdt, ip, el) + use numerics, only: & + err_damage_tolAbs, & + err_damage_tolRel + use material, only: & + mappingHomogenization, & + damageState + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + subdt + logical, dimension(2) :: & + damage_local_updateState + integer(pInt) :: & + homog, & + offset + real(pReal) :: & + phi, phiDot, dPhiDot_dPhi + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + phi = damageState(homog)%subState0(1,offset) + call damage_local_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el) + phi = phi + subdt*phiDot + + damage_local_updateState = [ abs(phi - damageState(homog)%state(1,offset)) & + <= err_damage_tolAbs & + .or. abs(phi - damageState(homog)%state(1,offset)) & + <= err_damage_tolRel*abs(damageState(homog)%state(1,offset)), & + .true.] + + damageState(homog)%state(1,offset) = phi + +end function damage_local_updateState + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates homogenized local damage driving forces +!-------------------------------------------------------------------------------------------------- +subroutine damage_local_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el) + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + phase_source, & + phase_Nsources, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID + use source_damage_isoBrittle, only: & + source_damage_isobrittle_getRateAndItsTangent + use source_damage_isoDuctile, only: & + source_damage_isoductile_getRateAndItsTangent + use source_damage_anisoBrittle, only: & + source_damage_anisobrittle_getRateAndItsTangent + use source_damage_anisoDuctile, only: & + source_damage_anisoductile_getRateAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + phi + integer(pInt) :: & + phase, & + grain, & + source + real(pReal) :: & + phiDot, dPhiDot_dPhi, localphiDot, dLocalphiDot_dPhi + + phiDot = 0.0_pReal + dPhiDot_dPhi = 0.0_pReal + do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el)) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_damage_isoBrittle_ID) + call source_damage_isobrittle_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_isoDuctile_ID) + call source_damage_isoductile_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_anisoBrittle_ID) + call source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_anisoDuctile_ID) + call source_damage_anisoductile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case default + localphiDot = 0.0_pReal + dLocalphiDot_dPhi = 0.0_pReal + + end select + phiDot = phiDot + localphiDot + dPhiDot_dPhi = dPhiDot_dPhi + dLocalphiDot_dPhi + enddo + enddo + + phiDot = phiDot/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + dPhiDot_dPhi = dPhiDot_dPhi/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + +end subroutine damage_local_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of damage results +!-------------------------------------------------------------------------------------------------- +function damage_local_postResults(ip,el) + use material, only: & + mappingHomogenization, & + damage_typeInstance, & + damageMapping, & + damage + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(damage_local_sizePostResults(damage_typeInstance(mappingHomogenization(2,ip,el)))) :: & + damage_local_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = damageMapping(homog)%p(ip,el) + instance = damage_typeInstance(homog) + + c = 0_pInt + damage_local_postResults = 0.0_pReal + + do o = 1_pInt,damage_local_Noutput(instance) + select case(damage_local_outputID(o,instance)) + + case (damage_ID) + damage_local_postResults(c+1_pInt) = damage(homog)%p(offset) + c = c + 1 + end select + enddo +end function damage_local_postResults + +end module damage_local diff --git a/code/damage_none.f90 b/code/damage_none.f90 index 889fee8d0..9bf0f95af 100644 --- a/code/damage_none.f90 +++ b/code/damage_none.f90 @@ -1,100 +1,61 @@ !-------------------------------------------------------------------------------------------------- ! $Id$ !-------------------------------------------------------------------------------------------------- -!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH -!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine for purely elastic material +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for constant damage field !-------------------------------------------------------------------------------------------------- module damage_none - use prec, only: & - pInt implicit none private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_none_sizePostResults - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_none_sizePostResult !< size of each post result output - + public :: & damage_none_init contains - !-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks +!> @brief allocates all neccessary fields, reads information from material configuration file !-------------------------------------------------------------------------------------------------- -subroutine damage_none_init +subroutine damage_none_init() use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level, & - debug_constitutive, & - debug_levelBasic + use prec, only: & + pReal, & + pInt use IO, only: & IO_timeStamp + use material use numerics, only: & - worldrank, & - numerics_integrator - use material, only: & - phase_damage, & - LOCAL_DAMAGE_NONE_label, & - LOCAL_DAMAGE_NONE_ID, & - material_phase, & - damageState - + worldrank + implicit none - integer(pInt) :: & - maxNinstance, & - phase, & - NofMyPhase, & - sizeState, & - sizeDotState + homog, & + NofMyHomog mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_DAMAGE_NONE_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_none_label//' init -+>>>' write(6,'(a)') ' $Id$' write(6,'(a15,a)') ' Current time: ',IO_timeStamp() #include "compilation_info.f90" endif mainProcess - maxNinstance = int(count(phase_damage == LOCAL_DAMAGE_NONE_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - initializeInstances: do phase = 1_pInt, size(phase_damage) - NofMyPhase=count(material_phase==phase) - if (phase_damage(phase) == LOCAL_DAMAGE_none_ID) then - sizeState = 0_pInt - damageState(phase)%sizeState = sizeState - sizeDotState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = 0_pInt - allocate(damageState(phase)%state0 (sizeState,NofMyPhase)) - allocate(damageState(phase)%partionedState0(sizeState,NofMyPhase)) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase)) - allocate(damageState(phase)%state (sizeState,NofMyPhase)) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase)) - allocate(damageState(phase)%aTolState (NofMyPhase)) - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase)) - allocate(damageState(phase)%dotState_backup(sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase)) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase)) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase)) - endif + initializeInstances: do homog = 1_pInt, material_Nhomogenization + + myhomog: if (damage_type(homog) == DAMAGE_none_ID) then + NofMyHomog = count(material_homog == homog) + damageState(homog)%sizeState = 0_pInt + damageState(homog)%sizePostResults = 0_pInt + allocate(damageState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal) + allocate(damageState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal) + allocate(damageState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal) + + deallocate(damage(homog)%p) + allocate (damage(homog)%p(1), source=1.0_pReal) + + endif myhomog enddo initializeInstances - allocate(damage_none_sizePostResults(maxNinstance), source=0_pInt) end subroutine damage_none_init diff --git a/code/damage_nonlocal.f90 b/code/damage_nonlocal.f90 new file mode 100644 index 000000000..d0b327234 --- /dev/null +++ b/code/damage_nonlocal.f90 @@ -0,0 +1,378 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for non-locally evolving damage field +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module damage_nonlocal + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + damage_nonlocal_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + damage_nonlocal_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + damage_nonlocal_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + damage_nonlocal_Noutput !< number of outputs per instance of this damage + + enum, bind(c) + enumerator :: undefined_ID, & + damage_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + damage_nonlocal_outputID !< ID of each post result output + + + public :: & + damage_nonlocal_init, & + damage_nonlocal_getSourceAndItsTangent, & + damage_nonlocal_getDiffusion33, & + damage_nonlocal_getMobility, & + damage_nonlocal_putNonLocalDamage, & + damage_nonlocal_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine damage_nonlocal_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + damage_type, & + damage_typeInstance, & + homogenization_Noutput, & + DAMAGE_nonlocal_label, & + DAMAGE_nonlocal_ID, & + material_homog, & + mappingHomogenization, & + damageState, & + damageMapping, & + damage, & + material_partHomogenization + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_nonlocal_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(damage_type == DAMAGE_nonlocal_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(damage_nonlocal_sizePostResults(maxNinstance), source=0_pInt) + allocate(damage_nonlocal_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(damage_nonlocal_output (maxval(homogenization_Noutput),maxNinstance)) + damage_nonlocal_output = '' + allocate(damage_nonlocal_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(damage_nonlocal_Noutput (maxNinstance), source=0_pInt) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (damage_type(section) == DAMAGE_nonlocal_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = damage_typeInstance(section) ! which instance of my damage is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('damage') + damage_nonlocal_Noutput(instance) = damage_nonlocal_Noutput(instance) + 1_pInt + damage_nonlocal_outputID(damage_nonlocal_Noutput(instance),instance) = damage_ID + damage_nonlocal_output(damage_nonlocal_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingFile + + initializeInstances: do section = 1_pInt, size(damage_type) + if (damage_type(section) == DAMAGE_nonlocal_ID) then + NofMyHomog=count(material_homog==section) + instance = damage_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,damage_nonlocal_Noutput(instance) + select case(damage_nonlocal_outputID(o,instance)) + case(damage_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + damage_nonlocal_sizePostResult(o,instance) = mySize + damage_nonlocal_sizePostResults(instance) = damage_nonlocal_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 0_pInt + damageState(section)%sizeState = sizeState + damageState(section)%sizePostResults = damage_nonlocal_sizePostResults(instance) + allocate(damageState(section)%state0 (sizeState,NofMyHomog)) + allocate(damageState(section)%subState0(sizeState,NofMyHomog)) + allocate(damageState(section)%state (sizeState,NofMyHomog)) + + nullify(damageMapping(section)%p) + damageMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(damage(section)%p) + allocate(damage(section)%p(NofMyHomog), source=1.0_pReal) + + endif + + enddo initializeInstances +end subroutine damage_nonlocal_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates homogenized damage driving forces +!-------------------------------------------------------------------------------------------------- +subroutine damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el) + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + phase_source, & + phase_Nsources, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID + use source_damage_isoBrittle, only: & + source_damage_isobrittle_getRateAndItsTangent + use source_damage_isoDuctile, only: & + source_damage_isoductile_getRateAndItsTangent + use source_damage_anisoBrittle, only: & + source_damage_anisobrittle_getRateAndItsTangent + use source_damage_anisoDuctile, only: & + source_damage_anisoductile_getRateAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + phi + integer(pInt) :: & + phase, & + grain, & + source + real(pReal) :: & + phiDot, dPhiDot_dPhi, localphiDot, dLocalphiDot_dPhi + + phiDot = 0.0_pReal + dPhiDot_dPhi = 0.0_pReal + do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el)) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1_pInt, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_damage_isoBrittle_ID) + call source_damage_isobrittle_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_isoDuctile_ID) + call source_damage_isoductile_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_anisoBrittle_ID) + call source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case (SOURCE_damage_anisoDuctile_ID) + call source_damage_anisoductile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, grain, ip, el) + + case default + localphiDot = 0.0_pReal + dLocalphiDot_dPhi = 0.0_pReal + + end select + phiDot = phiDot + localphiDot + dPhiDot_dPhi = dPhiDot_dPhi + dLocalphiDot_dPhi + enddo + enddo + + phiDot = phiDot/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + dPhiDot_dPhi = dPhiDot_dPhi/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + +end subroutine damage_nonlocal_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized non local damage diffusion tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function damage_nonlocal_getDiffusion33(ip,el) + use lattice, only: & + lattice_DamageDiffusion33 + use material, only: & + homogenization_Ngrains, & + material_phase, & + mappingHomogenization + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + damage_nonlocal_getDiffusion33 + integer(pInt) :: & + homog, & + grain + + homog = mappingHomogenization(2,ip,el) + damage_nonlocal_getDiffusion33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(homog) + damage_nonlocal_getDiffusion33 = damage_nonlocal_getDiffusion33 + & + crystallite_push33ToRef(grain,ip,el,lattice_DamageDiffusion33(1:3,1:3,material_phase(grain,ip,el))) + enddo + + damage_nonlocal_getDiffusion33 = & + damage_nonlocal_getDiffusion33/ & + homogenization_Ngrains(homog) + +end function damage_nonlocal_getDiffusion33 + +!-------------------------------------------------------------------------------------------------- +!> @brief Returns homogenized nonlocal damage mobility +!-------------------------------------------------------------------------------------------------- +real(pReal) function damage_nonlocal_getMobility(ip,el) + use mesh, only: & + mesh_element + use lattice, only: & + lattice_damageMobility + use material, only: & + material_phase, & + homogenization_Ngrains + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + integer(pInt) :: & + ipc + + damage_nonlocal_getMobility = 0.0_pReal + + do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) + damage_nonlocal_getMobility = damage_nonlocal_getMobility + lattice_DamageMobility(material_phase(ipc,ip,el)) + enddo + + damage_nonlocal_getMobility = damage_nonlocal_getMobility /homogenization_Ngrains(mesh_element(3,el)) + +end function damage_nonlocal_getMobility + +!-------------------------------------------------------------------------------------------------- +!> @brief updated nonlocal damage field with solution from damage phase field PDE +!-------------------------------------------------------------------------------------------------- +subroutine damage_nonlocal_putNonLocalDamage(phi,ip,el) + use material, only: & + material_homog, & + damageMapping, & + damage + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + phi + integer(pInt) :: & + homog, & + offset + + homog = material_homog(ip,el) + offset = damageMapping(homog)%p(ip,el) + damage(homog)%p(offset) = phi + +end subroutine damage_nonlocal_putNonLocalDamage + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of damage results +!-------------------------------------------------------------------------------------------------- +function damage_nonlocal_postResults(ip,el) + use material, only: & + mappingHomogenization, & + damage_typeInstance, & + damage + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(damage_nonlocal_sizePostResults(damage_typeInstance(mappingHomogenization(2,ip,el)))) :: & + damage_nonlocal_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + instance = damage_typeInstance(homog) + + c = 0_pInt + damage_nonlocal_postResults = 0.0_pReal + + do o = 1_pInt,damage_nonlocal_Noutput(instance) + select case(damage_nonlocal_outputID(o,instance)) + + case (damage_ID) + damage_nonlocal_postResults(c+1_pInt) = damage(homog)%p(offset) + c = c + 1 + end select + enddo +end function damage_nonlocal_postResults + +end module damage_nonlocal diff --git a/code/damage_phaseField.f90 b/code/damage_phaseField.f90 deleted file mode 100644 index c8a7b190e..000000000 --- a/code/damage_phaseField.f90 +++ /dev/null @@ -1,510 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine incoprorating isotropic brittle damage -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module damage_phaseField - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - damage_phaseField_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - damage_phaseField_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_phaseField_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - damage_phaseField_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, private :: & - damage_phaseField_aTol, & - damage_phaseField_surfaceEnergy, & - damage_phaseField_vacancyFormationEnergy, & - damage_phaseField_atomicVol, & - damage_phaseField_specificVacancyFormationEnergy - - enum, bind(c) - enumerator :: undefined_ID, & - local_damage_ID - end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo - - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - damage_phaseField_outputID !< ID of each post result output - - - public :: & - damage_phaseField_init, & - damage_phaseField_stateInit, & - damage_phaseField_aTolState, & - damage_phaseField_microstructure, & - damage_phaseField_getDamage, & - damage_phaseField_putLocalDamage, & - damage_phaseField_getLocalDamage, & - damage_phaseField_getDamageDiffusion33, & - damage_phaseField_getDamagedC66, & - damage_phaseField_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine damage_phaseField_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - phase_damage, & - phase_damageInstance, & - phase_Noutput, & - LOCAL_damage_phaseField_label, & - LOCAL_damage_phaseField_ID, & - material_phase, & - damageState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- damage_'//LOCAL_damage_phaseField_label//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_damage == LOCAL_damage_phaseField_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(damage_phaseField_sizePostResults(maxNinstance), source=0_pInt) - allocate(damage_phaseField_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(damage_phaseField_output(maxval(phase_Noutput),maxNinstance)) - damage_phaseField_output = '' - allocate(damage_phaseField_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(damage_phaseField_Noutput(maxNinstance), source=0_pInt) - allocate(damage_phaseField_surfaceEnergy(maxNinstance), source=0.0_pReal) - allocate(damage_phaseField_vacancyFormationEnergy(maxNinstance), source=0.0_pReal) - allocate(damage_phaseField_atomicVol(maxNinstance), source=0.0_pReal) - allocate(damage_phaseField_specificVacancyFormationEnergy(maxNinstance), source=0.0_pReal) - allocate(damage_phaseField_aTol(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - if (phase > 0_pInt ) then; if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_damageInstance(phase) ! which instance of my damage is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('local_damage') - damage_phaseField_Noutput(instance) = damage_phaseField_Noutput(instance) + 1_pInt - damage_phaseField_outputID(damage_phaseField_Noutput(instance),instance) = local_damage_ID - damage_phaseField_output(damage_phaseField_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('surfaceenergy') - damage_phaseField_surfaceEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancyformationenergy') - damage_phaseField_vacancyFormationEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atomicvolume') - damage_phaseField_atomicVol(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atol_damage') - damage_phaseField_aTol(instance) = IO_floatValue(line,positions,2_pInt) - - end select - endif; endif - enddo parsingFile - - - sanityChecks: do phase = 1_pInt, size(phase_damage) - myPhase: if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) -! sanity checks - if (damage_phaseField_aTol(instance) < 0.0_pReal) & - damage_phaseField_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 - if (damage_phaseField_surfaceEnergy(instance) <= 0.0_pReal) & - call IO_error(211_pInt,el=instance,ext_msg='surfaceEnergy ('//LOCAL_damage_phaseField_LABEL//')') - endif myPhase - enddo sanityChecks - - initializeInstances: do phase = 1_pInt, size(phase_damage) - if (phase_damage(phase) == LOCAL_damage_phaseField_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_damageInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! pre-calculating derived material parameters - damage_phaseField_specificVacancyFormationEnergy(instance) = & - damage_phaseField_vacancyFormationEnergy(instance)/damage_phaseField_atomicVol(instance) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,damage_phaseField_Noutput(instance) - select case(damage_phaseField_outputID(o,instance)) - case(local_damage_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - damage_phaseField_sizePostResult(o,instance) = mySize - damage_phaseField_sizePostResults(instance) = damage_phaseField_sizePostResults(instance) + mySize - endif - enddo outputsLoop - -! Determine size of state array - sizeDotState = 0_pInt - sizeState = 2_pInt - - damageState(phase)%sizeState = sizeState - damageState(phase)%sizeDotState = sizeDotState - damageState(phase)%sizePostResults = damage_phaseField_sizePostResults(instance) - allocate(damageState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(damageState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(damageState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(damageState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(damageState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(damageState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(damageState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call damage_phaseField_stateInit(phase) - call damage_phaseField_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine damage_phaseField_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant NEW state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_phaseField_stateInit(phase) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the damage - - real(pReal), dimension(damageState(phase)%sizeState) :: tempState - - tempState = 1.0_pReal - damageState(phase)%state = spread(tempState,2,size(damageState(phase)%state(1,:))) - damageState(phase)%state0 = damageState(phase)%state - damageState(phase)%partionedState0 = damageState(phase)%state -end subroutine damage_phaseField_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this damage -!-------------------------------------------------------------------------------------------------- -subroutine damage_phaseField_aTolState(phase,instance) - use material, only: & - damageState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the damage - real(pReal), dimension(damageState(phase)%sizeState) :: tempTol - - tempTol = damage_phaseField_aTol(instance) - damageState(phase)%aTolState = tempTol -end subroutine damage_phaseField_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine damage_phaseField_microstructure(C, Fe, Cv, subdt, ipc, ip, el) - use numerics, only: & - residualStiffness - use material, only: & - mappingConstitutive, & - phase_damageInstance, & - damageState - use math, only : & - math_mul33x33, & - math_mul66x6, & - math_Mandel33to6, & - math_transpose33, & - math_I3 - use lattice, only: & - lattice_DamageMobility - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in), dimension(3,3) :: & - Fe - real(pReal), intent(in), dimension(6,6) :: & - C - real(pReal), intent(in) :: & - Cv - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, constituent, instance - real(pReal) :: & - strain(6), & - stress(6), & - drivingForce - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3) - stress = math_mul66x6(C,strain) - - drivingForce = (1.0_pReal - Cv)*(1.0_pReal - Cv) + & - (Cv*damage_phaseField_specificVacancyFormationEnergy(instance) + & - sum(abs(stress*strain)))/damage_phaseField_surfaceEnergy(instance) - damageState(phase)%state(2,constituent) = & - max(residualStiffness,(1.0_pReal - Cv)*(1.0_pReal - Cv)/drivingForce) - - damageState(phase)%state(1,constituent) = & - damageState(phase)%state(2,constituent) + & - (damageState(phase)%subState0(1,constituent) - damageState(phase)%state(2,constituent))* & - exp(-2.0_pReal*subdt*drivingForce/lattice_DamageMobility(phase)) - -end subroutine damage_phaseField_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief returns damage -!-------------------------------------------------------------------------------------------------- -pure function damage_phaseField_getDamage(ipc, ip, el) - use material, only: & - material_homog, & - mappingHomogenization, & - mappingConstitutive, & - damageState, & - fieldDamage, & - field_damage_type, & - FIELD_DAMAGE_LOCAL_ID, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_phaseField_getDamage - - select case(field_damage_type(material_homog(ip,el))) - case default - damage_phaseField_getDamage = damageState(mappingConstitutive(2,ipc,ip,el))% & - state0(1,mappingConstitutive(1,ipc,ip,el)) - - case (FIELD_DAMAGE_NONLOCAL_ID) - damage_phaseField_getDamage = fieldDamage(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - end select - -end function damage_phaseField_getDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -subroutine damage_phaseField_putLocalDamage(ipc, ip, el, localDamage) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: localDamage - - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) = & - localDamage - -end subroutine damage_phaseField_putLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns local damage -!-------------------------------------------------------------------------------------------------- -pure function damage_phaseField_getLocalDamage(ipc, ip, el) - use material, only: & - mappingConstitutive, & - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: damage_phaseField_getLocalDamage - - damage_phaseField_getLocalDamage = & - damageState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function damage_phaseField_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief returns brittle damage diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_phaseField_getDamageDiffusion33(ipc, ip, el) - use lattice, only: & - lattice_DamageDiffusion33 - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - damage_phaseField_getDamageDiffusion33 - integer(pInt) :: & - phase, constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage_phaseField_getDamageDiffusion33 = & - lattice_DamageDiffusion33(1:3,1:3,phase) - -end function damage_phaseField_getDamageDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns brittle damaged stiffness tensor -!-------------------------------------------------------------------------------------------------- -pure function damage_phaseField_getDamagedC66(C, ipc, ip, el) - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6,6) :: & - C - real(pReal), dimension(6,6) :: & - damage_phaseField_getDamagedC66 - integer(pInt) :: & - phase, constituent - real(pReal) :: & - damage - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - damage = damage_phaseField_getDamage(ipc, ip, el) - - damage_phaseField_getDamagedC66 = & - damage*damage*C - -end function damage_phaseField_getDamagedC66 - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function damage_phaseField_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_damageInstance,& - damageState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(damage_phaseField_sizePostResults(phase_damageInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - damage_phaseField_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_damageInstance(phase) - - c = 0_pInt - damage_phaseField_postResults = 0.0_pReal - - do o = 1_pInt,damage_phaseField_Noutput(instance) - select case(damage_phaseField_outputID(o,instance)) - case (local_damage_ID) - damage_phaseField_postResults(c+1_pInt) = damageState(phase)%state(2,constituent) - c = c + 1 - - end select - enddo -end function damage_phaseField_postResults - -end module damage_phaseField diff --git a/code/homogenization.f90 b/code/homogenization.f90 index 2344db4ad..29c5745c3 100644 --- a/code/homogenization.f90 +++ b/code/homogenization.f90 @@ -37,7 +37,11 @@ module homogenization integer(pInt), public, protected :: & materialpoint_sizeResults, & homogenization_maxSizePostResults, & - field_maxSizePostResults + thermal_maxSizePostResults, & + damage_maxSizePostResults, & + vacancyflux_maxSizePostResults, & + porosity_maxSizePostResults, & + hydrogenflux_maxSizePostResults real(pReal), dimension(:,:,:,:), allocatable, private :: & materialpoint_subF0, & !< def grad of IP at beginning of homogenization increment @@ -51,45 +55,11 @@ module homogenization materialpoint_converged logical, dimension(:,:,:), allocatable, private :: & materialpoint_doneAndHappy - enum, bind(c) - enumerator :: undefined_ID, & - temperature_ID, & - damage_ID, & - vacancy_concentration_ID - end enum - integer(pInt), dimension(:), allocatable, public, protected :: & - field_sizePostResults - integer(pInt), dimension(:,:), allocatable, private :: & - field_sizePostResult - - character(len=64), dimension(:,:), allocatable, private :: & - field_output !< name of each post result output - integer(pInt), dimension(:), allocatable, private :: & - field_Noutput !< number of outputs per homog instance - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - field_outputID !< ID of each post result output public :: & homogenization_init, & materialpoint_stressAndItsTangent, & - field_getLocalDamage, & - field_getFieldDamage, & - field_putFieldDamage, & - field_getLocalTemperature, & - field_putFieldTemperature, & - field_getHeatGeneration, & - field_getLocalVacancyConcentration, & - field_putFieldVacancyConcentration, & - field_getDamageMobility, & - field_getDamageDiffusion33, & - field_getThermalConductivity33, & - field_getMassDensity, & - field_getSpecificHeat, & - field_getVacancyMobility33, & - field_getVacancyDiffusion33, & - field_getVacancyEnergy, & - materialpoint_postResults, & - field_postResults + materialpoint_postResults private :: & homogenization_partitionDeformation, & homogenization_updateState, & @@ -102,7 +72,7 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief module initialization !-------------------------------------------------------------------------------------------------- -subroutine homogenization_init() +subroutine homogenization_init(temperature_init) #ifdef HDF use hdf5, only: & HID_T @@ -129,10 +99,8 @@ subroutine homogenization_init() crystallite_sizePostResults #else use constitutive, only: & - constitutive_maxSizePostResults, & - constitutive_damage_maxSizePostResults, & - constitutive_thermal_maxSizePostResults, & - constitutive_vacancy_maxSizePostResults + constitutive_plasticity_maxSizePostResults, & + constitutive_source_maxSizePostResults use crystallite, only: & crystallite_maxSizePostResults #endif @@ -140,30 +108,38 @@ subroutine homogenization_init() use homogenization_none use homogenization_isostrain use homogenization_RGC + use thermal_isothermal + use thermal_adiabatic + use thermal_conduction + use damage_none + use damage_local + use damage_nonlocal + use vacancyflux_isoconc + use vacancyflux_isochempot + use vacancyflux_cahnhilliard + use porosity_none + use porosity_phasefield + use hydrogenflux_isoconc + use hydrogenflux_cahnhilliard use IO use numerics, only: & worldrank implicit none + real(pReal), intent(in) :: temperature_init !< initial temperature integer(pInt), parameter :: FILEUNIT = 200_pInt - integer(pInt) :: e,i,p,myInstance + integer(pInt) :: e,i,p integer(pInt), dimension(:,:), pointer :: thisSize integer(pInt), dimension(:) , pointer :: thisNoutput character(len=64), dimension(:,:), pointer :: thisOutput character(len=32) :: outputName !< name of output, intermediate fix until HDF5 output is ready - logical :: knownHomogenization + logical :: knownHomogenization, knownThermal, knownDamage, knownVacancyflux, knownPorosity, knownHydrogenflux #ifdef HDF integer(pInt), dimension(:,:), allocatable :: mapping integer(pInt), dimension(:), allocatable :: InstancePosition allocate(mapping(mesh_ncpelems,4),source=0_pInt) allocate(InstancePosition(material_Nhomogenization),source=0_pInt) #endif - integer(pInt), parameter :: MAXNCHUNKS = 2_pInt - integer(pInt), dimension(1_pInt+2_pInt*MAXNCHUNKS) :: positions - integer(pInt) :: section = 0_pInt - character(len=65536) :: & - tag = '', & - line = '' !-------------------------------------------------------------------------------------------------- ! parse homogenization from config file @@ -178,64 +154,59 @@ subroutine homogenization_init() close(FILEUNIT) !-------------------------------------------------------------------------------------------------- -! parse field from config file - allocate(field_sizePostResults(material_Nhomogenization), source=0_pInt) - allocate(field_sizePostResult(maxval(homogenization_Noutput),material_Nhomogenization), & - source=0_pInt) - allocate(field_Noutput(material_Nhomogenization), source=0_pInt) - allocate(field_outputID(maxval(homogenization_Noutput),material_Nhomogenization), & - source=undefined_ID) - allocate(field_output(maxval(homogenization_Noutput),material_Nhomogenization)) - field_output = '' - +! parse thermal 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 - rewind(FILEUNIT) - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to - line = IO_read(FILEUNIT) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homogenization part - line = IO_read(FILEUNIT) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(FILEUNIT, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next section - section = section + 1_pInt - cycle - endif - if (section > 0_pInt ) then ! do not short-circuit here (.and. with next if-statement). It's not safe in Fortran - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case('temperature') - field_Noutput(section) = field_Noutput(section) + 1_pInt - field_outputID(field_Noutput(section),section) = temperature_ID - field_sizePostResult(field_Noutput(section),section) = 1_pInt - field_sizePostResults(section) = field_sizePostResults(section) + 1_pInt - field_output(field_Noutput(section),section) = IO_lc(IO_stringValue(line,positions,2_pInt)) - case('damage') - field_Noutput(section) = field_Noutput(section) + 1_pInt - field_outputID(field_Noutput(section),section) = damage_ID - field_sizePostResult(field_Noutput(section),section) = 1_pInt - field_sizePostResults(section) = field_sizePostResults(section) + 1_pInt - field_output(field_Noutput(section),section) = IO_lc(IO_stringValue(line,positions,2_pInt)) - case('vacancy_concentration') - field_Noutput(section) = field_Noutput(section) + 1_pInt - field_outputID(field_Noutput(section),section) = vacancy_concentration_ID - field_sizePostResult(field_Noutput(section),section) = 1_pInt - field_sizePostResults(section) = field_sizePostResults(section) + 1_pInt - field_output(field_Noutput(section),section) = IO_lc(IO_stringValue(line,positions,2_pInt)) - - end select - - end select - endif - enddo parsingFile + if (any(thermal_type == THERMAL_isothermal_ID)) & + call thermal_isothermal_init(temperature_init) + if (any(thermal_type == THERMAL_adiabatic_ID)) & + call thermal_adiabatic_init(FILEUNIT,temperature_init) + if (any(thermal_type == THERMAL_conduction_ID)) & + call thermal_conduction_init(FILEUNIT,temperature_init) + close(FILEUNIT) + +!-------------------------------------------------------------------------------------------------- +! 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(damage_type == DAMAGE_none_ID)) & + call damage_none_init() + if (any(damage_type == DAMAGE_local_ID)) & + call damage_local_init(FILEUNIT) + if (any(damage_type == DAMAGE_nonlocal_ID)) & + call damage_nonlocal_init(FILEUNIT) + close(FILEUNIT) + +!-------------------------------------------------------------------------------------------------- +! parse vacancy transport 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(vacancyflux_type == VACANCYFLUX_isoconc_ID)) & + call vacancyflux_isoconc_init() + if (any(vacancyflux_type == VACANCYFLUX_isochempot_ID)) & + call vacancyflux_isochempot_init(FILEUNIT) + if (any(vacancyflux_type == VACANCYFLUX_cahnhilliard_ID)) & + call vacancyflux_cahnhilliard_init(FILEUNIT) + close(FILEUNIT) + +!-------------------------------------------------------------------------------------------------- +! parse porosity 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(porosity_type == POROSITY_none_ID)) & + call porosity_none_init() + if (any(porosity_type == POROSITY_phasefield_ID)) & + call porosity_phasefield_init(FILEUNIT) + close(FILEUNIT) + +!-------------------------------------------------------------------------------------------------- +! parse hydrogen transport 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(hydrogenflux_type == HYDROGENFLUX_isoconc_ID)) & + call hydrogenflux_isoconc_init() + if (any(hydrogenflux_type == HYDROGENFLUX_cahnhilliard_ID)) & + call hydrogenflux_cahnhilliard_init(FILEUNIT) close(FILEUNIT) !-------------------------------------------------------------------------------------------------- @@ -275,9 +246,141 @@ subroutine homogenization_init() enddo endif endif - do e = 1_pInt,field_Noutput(p) - write(FILEUNIT,'(a,i4)') trim(field_output(e,p))//char(9),field_sizePostResult(e,p) - enddo + i = thermal_typeInstance(p) ! which instance of this thermal type + knownThermal = .true. ! assume valid + select case(thermal_type(p)) ! split per thermal type + case (THERMAL_isothermal_ID) + outputName = THERMAL_isothermal_label + thisNoutput => null() + thisOutput => null() + thisSize => null() + case (THERMAL_adiabatic_ID) + outputName = THERMAL_adiabatic_label + thisNoutput => thermal_adiabatic_Noutput + thisOutput => thermal_adiabatic_output + thisSize => thermal_adiabatic_sizePostResult + case (THERMAL_conduction_ID) + outputName = THERMAL_conduction_label + thisNoutput => thermal_conduction_Noutput + thisOutput => thermal_conduction_output + thisSize => thermal_conduction_sizePostResult + case default + knownThermal = .false. + end select + if (knownThermal) then + write(FILEUNIT,'(a)') '(thermal)'//char(9)//trim(outputName) + if (thermal_type(p) /= THERMAL_isothermal_ID) then + do e = 1,thisNoutput(i) + write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) + enddo + endif + endif + i = damage_typeInstance(p) ! which instance of this damage type + knownDamage = .true. ! assume valid + select case(damage_type(p)) ! split per damage type + case (DAMAGE_none_ID) + outputName = DAMAGE_none_label + thisNoutput => null() + thisOutput => null() + thisSize => null() + case (DAMAGE_local_ID) + outputName = DAMAGE_local_label + thisNoutput => damage_local_Noutput + thisOutput => damage_local_output + thisSize => damage_local_sizePostResult + case (DAMAGE_nonlocal_ID) + outputName = DAMAGE_nonlocal_label + thisNoutput => damage_nonlocal_Noutput + thisOutput => damage_nonlocal_output + thisSize => damage_nonlocal_sizePostResult + case default + knownDamage = .false. + end select + if (knownDamage) then + write(FILEUNIT,'(a)') '(damage)'//char(9)//trim(outputName) + if (damage_type(p) /= DAMAGE_none_ID) then + do e = 1,thisNoutput(i) + write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) + enddo + endif + endif + i = vacancyflux_typeInstance(p) ! which instance of this vacancy flux type + knownVacancyflux = .true. ! assume valid + select case(vacancyflux_type(p)) ! split per vacancy flux type + case (VACANCYFLUX_isoconc_ID) + outputName = VACANCYFLUX_isoconc_label + thisNoutput => null() + thisOutput => null() + thisSize => null() + case (VACANCYFLUX_isochempot_ID) + outputName = VACANCYFLUX_isochempot_label + thisNoutput => vacancyflux_isochempot_Noutput + thisOutput => vacancyflux_isochempot_output + thisSize => vacancyflux_isochempot_sizePostResult + case (VACANCYFLUX_cahnhilliard_ID) + outputName = VACANCYFLUX_cahnhilliard_label + thisNoutput => vacancyflux_cahnhilliard_Noutput + thisOutput => vacancyflux_cahnhilliard_output + thisSize => vacancyflux_cahnhilliard_sizePostResult + case default + knownVacancyflux = .false. + end select + if (knownVacancyflux) then + write(FILEUNIT,'(a)') '(vacancyflux)'//char(9)//trim(outputName) + if (vacancyflux_type(p) /= VACANCYFLUX_isoconc_ID) then + do e = 1,thisNoutput(i) + write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) + enddo + endif + endif + i = porosity_typeInstance(p) ! which instance of this porosity type + knownPorosity = .true. ! assume valid + select case(porosity_type(p)) ! split per porosity type + case (POROSITY_none_ID) + outputName = POROSITY_none_label + thisNoutput => null() + thisOutput => null() + thisSize => null() + case (POROSITY_phasefield_ID) + outputName = POROSITY_phasefield_label + thisNoutput => porosity_phasefield_Noutput + thisOutput => porosity_phasefield_output + thisSize => porosity_phasefield_sizePostResult + case default + knownPorosity = .false. + end select + if (knownPorosity) then + write(FILEUNIT,'(a)') '(porosity)'//char(9)//trim(outputName) + if (porosity_type(p) /= POROSITY_none_ID) then + do e = 1,thisNoutput(i) + write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) + enddo + endif + endif + i = hydrogenflux_typeInstance(p) ! which instance of this hydrogen flux type + knownHydrogenflux = .true. ! assume valid + select case(hydrogenflux_type(p)) ! split per hydrogen flux type + case (HYDROGENFLUX_isoconc_ID) + outputName = HYDROGENFLUX_isoconc_label + thisNoutput => null() + thisOutput => null() + thisSize => null() + case (HYDROGENFLUX_cahnhilliard_ID) + outputName = HYDROGENFLUX_cahnhilliard_label + thisNoutput => hydrogenflux_cahnhilliard_Noutput + thisOutput => hydrogenflux_cahnhilliard_output + thisSize => hydrogenflux_cahnhilliard_sizePostResult + case default + knownHydrogenflux = .false. + end select + if (knownHydrogenflux) then + write(FILEUNIT,'(a)') '(hydrogenflux)'//char(9)//trim(outputName) + if (hydrogenflux_type(p) /= HYDROGENFLUX_isoconc_ID) then + do e = 1,thisNoutput(i) + write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) + enddo + endif + endif endif enddo close(FILEUNIT) @@ -302,24 +405,30 @@ subroutine homogenization_init() !-------------------------------------------------------------------------------------------------- ! allocate and initialize global state and postresutls variables +#ifdef HDF elementLooping: do e = 1,mesh_NcpElems myInstance = homogenization_typeInstance(mesh_element(3,e)) IpLooping: do i = 1,FE_Nips(FE_geomtype(mesh_element(2,e))) -#ifdef HDF InstancePosition(myInstance) = InstancePosition(myInstance)+1_pInt mapping(e,1:4) = [instancePosition(myinstance),myinstance,e,i] -#endif enddo IpLooping enddo elementLooping -#ifdef HDF call HDF5_mappingHomogenization(mapping) #endif homogenization_maxSizePostResults = 0_pInt - field_maxSizePostResults = 0_pInt + thermal_maxSizePostResults = 0_pInt + damage_maxSizePostResults = 0_pInt + vacancyflux_maxSizePostResults = 0_pInt + porosity_maxSizePostResults = 0_pInt + hydrogenflux_maxSizePostResults = 0_pInt do p = 1,material_Nhomogenization - homogenization_maxSizePostResults = max(homogenization_maxSizePostResults,homogState(p)%sizePostResults) - field_maxSizePostResults = max(field_maxSizePostResults,field_sizePostResults(p)) + homogenization_maxSizePostResults = max(homogenization_maxSizePostResults,homogState (p)%sizePostResults) + thermal_maxSizePostResults = max(thermal_maxSizePostResults, thermalState (p)%sizePostResults) + damage_maxSizePostResults = max(damage_maxSizePostResults ,damageState (p)%sizePostResults) + vacancyflux_maxSizePostResults = max(vacancyflux_maxSizePostResults ,vacancyfluxState (p)%sizePostResults) + porosity_maxSizePostResults = max(porosity_maxSizePostResults ,porosityState (p)%sizePostResults) + hydrogenflux_maxSizePostResults = max(hydrogenflux_maxSizePostResults ,hydrogenfluxState(p)%sizePostResults) enddo #ifdef FEM @@ -327,7 +436,12 @@ subroutine homogenization_init() allocate(crystalliteOutput(material_Ncrystallite, homogenization_maxNgrains)) allocate(phaseOutput (material_Nphase, homogenization_maxNgrains)) do p = 1, material_Nhomogenization - homogOutput(p)%sizeResults = homogState(p)%sizePostResults + field_sizePostResults(p) + homogOutput(p)%sizeResults = homogState (p)%sizePostResults + & + thermalState (p)%sizePostResults + & + damageState (p)%sizePostResults + & + vacancyfluxState (p)%sizePostResults + & + porosityState (p)%sizePostResults + & + hydrogenfluxState(p)%sizePostResults homogOutput(p)%sizeIpCells = count(material_homog==p) allocate(homogOutput(p)%output(homogOutput(p)%sizeResults,homogOutput(p)%sizeIpCells)) enddo @@ -338,22 +452,22 @@ subroutine homogenization_init() allocate(crystalliteOutput(p,e)%output(crystalliteOutput(p,e)%sizeResults,crystalliteOutput(p,e)%sizeIpCells)) enddo; enddo do p = 1, material_Nphase; do e = 1, homogenization_maxNgrains - phaseOutput(p,e)%sizeResults = plasticState(p)%sizePostResults + & - damageState (p)%sizePostResults + & - thermalState(p)%sizePostResults + & - vacancyState(p)%sizePostResults + phaseOutput(p,e)%sizeResults = plasticState (p)%sizePostResults + & + sum(sourceState (p)%p(:)%sizePostResults) phaseOutput(p,e)%sizeIpCells = count(material_phase(e,:,:) == p) allocate(phaseOutput(p,e)%output(phaseOutput(p,e)%sizeResults,phaseOutput(p,e)%sizeIpCells)) enddo; enddo #else materialpoint_sizeResults = 1 & ! grain count + 1 + homogenization_maxSizePostResults & ! homogSize & homogResult - + field_maxSizePostResults & ! field size & field result + + thermal_maxSizePostResults & + + damage_maxSizePostResults & + + vacancyflux_maxSizePostResults & + + porosity_maxSizePostResults & + + hydrogenflux_maxSizePostResults & + homogenization_maxNgrains * (1 + crystallite_maxSizePostResults & ! crystallite size & crystallite results - + 1 + constitutive_maxSizePostResults & ! constitutive size & constitutive results - + constitutive_damage_maxSizePostResults & - + constitutive_thermal_maxSizePostResults & - + constitutive_vacancy_maxSizePostResults) + + 1 + constitutive_plasticity_maxSizePostResults & ! constitutive size & constitutive results + + constitutive_source_maxSizePostResults) allocate(materialpoint_results(materialpoint_sizeResults,mesh_maxNips,mesh_NcpElems)) #endif @@ -415,10 +529,14 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) mesh_element use material, only: & plasticState, & - damageState, & - thermalState, & - vacancyState, & + sourceState, & homogState, & + thermalState, & + damageState, & + vacancyfluxState, & + porosityState, & + hydrogenfluxState, & + phase_Nsources, & mappingHomogenization, & mappingConstitutive, & homogenization_Ngrains @@ -472,6 +590,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) g, & !< grain number i, & !< integration point number e, & !< element number + mySource, & myNgrains !-------------------------------------------------------------------------------------------------- @@ -491,16 +610,14 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) ! initialize restoration points of ... do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(mesh_element(3,e)) - forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), g = 1:myNgrains) + do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e); do g = 1,myNgrains - plasticState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state0( :,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state0( :,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state0( :,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state0( :,mappingConstitutive(1,g,i,e)) + plasticState (mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state0( :,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%partionedState0(:,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state0( :,mappingConstitutive(1,g,i,e)) + enddo crystallite_partionedFp0(1:3,1:3,g,i,e) = crystallite_Fp0(1:3,1:3,g,i,e) ! ...plastic def grads crystallite_partionedLp0(1:3,1:3,g,i,e) = crystallite_Lp0(1:3,1:3,g,i,e) ! ...plastic velocity grads @@ -510,7 +627,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) crystallite_partionedF0(1:3,1:3,g,i,e) = crystallite_F0(1:3,1:3,g,i,e) ! ...def grads crystallite_partionedTstar0_v(1:6,g,i,e) = crystallite_Tstar0_v(1:6,g,i,e) ! ...2nd PK stress - endforall + enddo; enddo forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e)) materialpoint_subF0(1:3,1:3,i,e) = materialpoint_F0(1:3,1:3,i,e) ! ...def grad materialpoint_subFrac(i,e) = 0.0_pReal @@ -521,7 +638,27 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & homogState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & homogState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & - homogState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal homogenization state + homogState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal homogenization state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + thermalState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + thermalState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + thermalState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal thermal state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + damageState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + damageState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + damageState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal damage state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + vacancyfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + vacancyfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + vacancyfluxState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal vacancy transport state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + porosityState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + porosityState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + porosityState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal porosity state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + hydrogenfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + hydrogenfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + hydrogenfluxState(mappingHomogenization(2,i,e))%State0( :,mappingHomogenization(1,i,e)) ! ...internal hydrogen transport state enddo NiterationHomog = 0_pInt @@ -549,35 +686,61 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) materialpoint_subFrac(i,e) = materialpoint_subFrac(i,e) + materialpoint_subStep(i,e) !$OMP FLUSH(materialpoint_subFrac) materialpoint_subStep(i,e) = min(1.0_pReal-materialpoint_subFrac(i,e), & - stepIncreaseHomog*materialpoint_subStep(i,e)) ! introduce flexibility for step increase/acceleration + stepIncreaseHomog*materialpoint_subStep(i,e)) ! introduce flexibility for step increase/acceleration !$OMP FLUSH(materialpoint_subStep) steppingNeeded: if (materialpoint_subStep(i,e) > subStepMinHomog) then ! wind forward grain starting point of... - crystallite_partionedF0(1:3,1:3,1:myNgrains,i,e) = crystallite_partionedF(1:3,1:3,1:myNgrains,i,e) ! ...def grads - crystallite_partionedFp0(1:3,1:3,1:myNgrains,i,e) = crystallite_Fp(1:3,1:3,1:myNgrains,i,e) ! ...plastic def grads - crystallite_partionedLp0(1:3,1:3,1:myNgrains,i,e) = crystallite_Lp(1:3,1:3,1:myNgrains,i,e) ! ...plastic velocity grads - crystallite_partionedFi0(1:3,1:3,1:myNgrains,i,e) = crystallite_Fi(1:3,1:3,1:myNgrains,i,e) ! ...intermediate def grads - crystallite_partionedLi0(1:3,1:3,1:myNgrains,i,e) = crystallite_Li(1:3,1:3,1:myNgrains,i,e) ! ...intermediate velocity grads - crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,1:myNgrains,i,e) = crystallite_dPdF(1:3,1:3,1:3,1:3,1:myNgrains,i,e)! ...stiffness - crystallite_partionedTstar0_v(1:6,1:myNgrains,i,e) = crystallite_Tstar_v(1:6,1:myNgrains,i,e) ! ...2nd PK stress - forall (g = 1:myNgrains) - plasticState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) - end forall - if (homogState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & - homogState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & - homogState(mappingHomogenization(2,i,e))%state( :,mappingHomogenization(1,i,e)) - materialpoint_subF0(1:3,1:3,i,e) = materialpoint_subF(1:3,1:3,i,e) ! ...def grad + crystallite_partionedF0(1:3,1:3,1:myNgrains,i,e) = & + crystallite_partionedF(1:3,1:3,1:myNgrains,i,e) ! ...def grads + crystallite_partionedFp0(1:3,1:3,1:myNgrains,i,e) = & + crystallite_Fp(1:3,1:3,1:myNgrains,i,e) ! ...plastic def grads + crystallite_partionedLp0(1:3,1:3,1:myNgrains,i,e) = & + crystallite_Lp(1:3,1:3,1:myNgrains,i,e) ! ...plastic velocity grads + crystallite_partionedFi0(1:3,1:3,1:myNgrains,i,e) = & + crystallite_Fi(1:3,1:3,1:myNgrains,i,e) ! ...intermediate def grads + crystallite_partionedLi0(1:3,1:3,1:myNgrains,i,e) = & + crystallite_Li(1:3,1:3,1:myNgrains,i,e) ! ...intermediate velocity grads + crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,1:myNgrains,i,e) = & + crystallite_dPdF(1:3,1:3,1:3,1:3,1:myNgrains,i,e) ! ...stiffness + crystallite_partionedTstar0_v(1:6,1:myNgrains,i,e) = & + crystallite_Tstar_v(1:6,1:myNgrains,i,e) ! ...2nd PK stress + do g = 1,myNgrains + plasticState (mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%partionedState0(:,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) + enddo + enddo + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + homogState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + homogState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + homogState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) ! ...internal homogenization state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + thermalState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + thermalState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + thermalState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) ! ...internal thermal state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + damageState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + damageState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + damageState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) ! ...internal damage state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + vacancyfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + vacancyfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + vacancyfluxState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e))! ...internal vacancy transport state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + porosityState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + porosityState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + porosityState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e))! ...internal porosity state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + hydrogenfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + hydrogenfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) = & + hydrogenfluxState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e))! ...internal hydrogen transport state + materialpoint_subF0(1:3,1:3,i,e) = materialpoint_subF(1:3,1:3,i,e) ! ...def grad !$OMP FLUSH(materialpoint_subF0) - elseif (materialpoint_requested(i,e)) then steppingNeeded ! already at final time (??) + elseif (materialpoint_requested(i,e)) then steppingNeeded ! already at final time (??) if (iand(debug_level(debug_homogenization), debug_levelBasic) /= 0_pInt) then !$OMP CRITICAL (distributionHomog) debug_MaterialpointLoopDistribution(min(nHomog+1,NiterationHomog)) = & @@ -587,20 +750,20 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) endif steppingNeeded else converged - if ( (myNgrains == 1_pInt .and. materialpoint_subStep(i,e) <= 1.0 ) .or. & ! single grain already tried internal subStepping in crystallite - subStepSizeHomog * materialpoint_subStep(i,e) <= subStepMinHomog ) then ! would require too small subStep - ! cutback makes no sense + if ( (myNgrains == 1_pInt .and. materialpoint_subStep(i,e) <= 1.0 ) .or. & ! single grain already tried internal subStepping in crystallite + subStepSizeHomog * materialpoint_subStep(i,e) <= subStepMinHomog ) then ! would require too small subStep + ! cutback makes no sense !$OMP FLUSH(terminallyIll) - if (.not. terminallyIll) then ! so first signals terminally ill... + if (.not. terminallyIll) then ! so first signals terminally ill... !$OMP CRITICAL (write2out) write(6,*) 'Integration point ', i,' at element ', e, ' terminally ill' !$OMP END CRITICAL (write2out) endif !$OMP CRITICAL (setTerminallyIll) - terminallyIll = .true. ! ...and kills all others + terminallyIll = .true. ! ...and kills all others !$OMP END CRITICAL (setTerminallyIll) - else ! cutback makes sense - materialpoint_subStep(i,e) = subStepSizeHomog * materialpoint_subStep(i,e) ! crystallite had severe trouble, so do a significant cutback + else ! cutback makes sense + materialpoint_subStep(i,e) = subStepSizeHomog * materialpoint_subStep(i,e) ! crystallite had severe trouble, so do a significant cutback !$OMP FLUSH(materialpoint_subStep) #ifndef _OPENMP @@ -615,25 +778,50 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) !-------------------------------------------------------------------------------------------------- ! restore... - crystallite_Fp(1:3,1:3,1:myNgrains,i,e) = crystallite_partionedFp0(1:3,1:3,1:myNgrains,i,e) ! ...plastic def grads - crystallite_Lp(1:3,1:3,1:myNgrains,i,e) = crystallite_partionedLp0(1:3,1:3,1:myNgrains,i,e) ! ...plastic velocity grads - crystallite_Fi(1:3,1:3,1:myNgrains,i,e) = crystallite_partionedFi0(1:3,1:3,1:myNgrains,i,e) ! ...intermediate def grads - crystallite_Li(1:3,1:3,1:myNgrains,i,e) = crystallite_partionedLi0(1:3,1:3,1:myNgrains,i,e) ! ...intermediate velocity grads - crystallite_dPdF(1:3,1:3,1:3,1:3,1:myNgrains,i,e) = crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,1:myNgrains,i,e) ! ...stiffness - crystallite_Tstar_v(1:6,1:myNgrains,i,e) = crystallite_partionedTstar0_v(1:6,1:myNgrains,i,e) ! ...2nd PK stress - forall (g = 1:myNgrains) - plasticState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - plasticState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - damageState( mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - damageState( mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - thermalState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - thermalState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - vacancyState(mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & - vacancyState(mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) - end forall - if (homogState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & - homogState(mappingHomogenization(2,i,e))%state( :,mappingHomogenization(1,i,e)) = & - homogState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) + crystallite_Fp(1:3,1:3,1:myNgrains,i,e) = & + crystallite_partionedFp0(1:3,1:3,1:myNgrains,i,e) ! ...plastic def grads + crystallite_Lp(1:3,1:3,1:myNgrains,i,e) = & + crystallite_partionedLp0(1:3,1:3,1:myNgrains,i,e) ! ...plastic velocity grads + crystallite_Fi(1:3,1:3,1:myNgrains,i,e) = & + crystallite_partionedFi0(1:3,1:3,1:myNgrains,i,e) ! ...intermediate def grads + crystallite_Li(1:3,1:3,1:myNgrains,i,e) = & + crystallite_partionedLi0(1:3,1:3,1:myNgrains,i,e) ! ...intermediate velocity grads + crystallite_dPdF(1:3,1:3,1:3,1:3,1:myNgrains,i,e) = & + crystallite_partioneddPdF0(1:3,1:3,1:3,1:3,1:myNgrains,i,e) ! ...stiffness + crystallite_Tstar_v(1:6,1:myNgrains,i,e) = & + crystallite_partionedTstar0_v(1:6,1:myNgrains,i,e) ! ...2nd PK stress + do g = 1, myNgrains + plasticState (mappingConstitutive(2,g,i,e))%state( :,mappingConstitutive(1,g,i,e)) = & + plasticState (mappingConstitutive(2,g,i,e))%partionedState0(:,mappingConstitutive(1,g,i,e)) + do mySource = 1_pInt, phase_Nsources(mappingConstitutive(2,g,i,e)) + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%state( :,mappingConstitutive(1,g,i,e)) = & + sourceState(mappingConstitutive(2,g,i,e))%p(mySource)%partionedState0(:,mappingConstitutive(1,g,i,e)) + enddo + enddo + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + homogState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + homogState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + homogState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) ! ...internal homogenization state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + thermalState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + thermalState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + thermalState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) ! ...internal thermal state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + damageState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + damageState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + damageState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e)) ! ...internal damage state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + vacancyfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + vacancyfluxState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + vacancyfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e))! ...internal vacancy transport state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + porosityState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + porosityState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + porosityState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e))! ...internal porosity state + forall(i = FEsolving_execIP(1,e):FEsolving_execIP(2,e), & + hydrogenfluxState(mappingHomogenization(2,i,e))%sizeState > 0_pInt) & + hydrogenfluxState(mappingHomogenization(2,i,e))%State( :,mappingHomogenization(1,i,e)) = & + hydrogenfluxState(mappingHomogenization(2,i,e))%subState0(:,mappingHomogenization(1,i,e))! ...internal hydrogen transport state endif endif converged @@ -695,7 +883,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) materialpoint_converged(i,e) = .false. else materialpoint_doneAndHappy(1:2,i,e) = homogenization_updateState(i,e) - materialpoint_converged(i,e) = all(homogenization_updateState(i,e)) ! converged if done and happy + materialpoint_converged(i,e) = all(materialpoint_doneAndHappy(1:2,i,e)) ! converged if done and happy endif !$OMP FLUSH(materialpoint_converged) if (materialpoint_converged(i,e)) then @@ -751,21 +939,23 @@ subroutine materialpoint_postResults homogenization_maxNgrains, & material_Ncrystallite, & material_Nphase, & -#endif +#else homogState, & - plasticState, & - damageState, & thermalState, & - vacancyState, & + damageState, & + vacancyfluxState, & + porosityState, & + hydrogenfluxState, & +#endif + plasticState, & + sourceState, & material_phase, & homogenization_Ngrains, & microstructure_crystallite use constitutive, only: & #ifdef FEM - constitutive_maxSizePostResults, & - constitutive_damage_maxSizePostResults, & - constitutive_thermal_maxSizePostResults, & - constitutive_vacancy_maxSizePostResults, & + constitutive_plasticity_maxSizePostResults, & + constitutive_source_maxSizePostResults, & #endif constitutive_postResults use crystallite, only: & @@ -791,10 +981,8 @@ subroutine materialpoint_postResults crystalliteCtr(material_Ncrystallite, homogenization_maxNgrains), & phaseCtr (material_Nphase, homogenization_maxNgrains) real(pReal), dimension(1+crystallite_maxSizePostResults + & - 1+constitutive_maxSizePostResults + & - constitutive_damage_maxSizePostResults + & - constitutive_thermal_maxSizePostResults + & - constitutive_vacancy_maxSizePostResults) :: & + 1+constitutive_plasticity_maxSizePostResults + & + constitutive_source_maxSizePostResults) :: & crystalliteResults @@ -807,35 +995,29 @@ subroutine materialpoint_postResults myHomog = mappingHomogenization(2,i,e) thePos = mappingHomogenization(1,i,e) homogOutput(myHomog)%output(1: & - homogState(myHomog)%sizePostResults, & + homogOutput(myHomog)%sizeResults, & thePos) = homogenization_postResults(i,e) - homogOutput(myHomog)%output(homogState(myHomog)%sizePostResults+1: & - homogState(myHomog)%sizePostResults+field_sizePostResults(myHomog), & - thePos) = field_postResults(i,e) grainLooping :do g = 1,myNgrains myPhase = mappingConstitutive(2,g,i,e) crystalliteResults(1:1+crystallite_sizePostResults(myCrystallite) + & 1+plasticState(myPhase)%sizePostResults + & - damageState (myPhase)%sizePostResults + & - thermalState(myPhase)%sizePostResults + & - vacancyState(myPhase)%sizePostResults) = crystallite_postResults(g,i,e) + sum(sourceState(myPhase)%p(:)%sizePostResults)) = crystallite_postResults(g,i,e) if (microstructure_crystallite(mesh_element(4,e)) == myCrystallite .and. & homogenization_Ngrains (mesh_element(3,e)) >= g) then crystalliteCtr(myCrystallite,g) = crystalliteCtr(myCrystallite,g) + 1_pInt crystalliteOutput(myCrystallite,g)% & output(1:crystalliteOutput(myCrystallite,g)%sizeResults,crystalliteCtr(myCrystallite,g)) = & - crystalliteResults(2:1+crystallite_sizePostResults(myCrystallite)) + crystalliteResults(2:1+crystalliteOutput(myCrystallite,g)%sizeResults) endif if (material_phase(g,i,e) == myPhase) then phaseCtr(myPhase,g) = phaseCtr(myPhase,g) + 1_pInt phaseOutput(myPhase,g)% & output(1:phaseOutput(myPhase,g)%sizeResults,phaseCtr(myPhase,g)) = & - crystalliteResults(3 + crystallite_sizePostResults(myCrystallite): & - plasticState(myphase)%sizePostResults + & - damageState (myphase)%sizePostResults + & - thermalState(myphase)%sizePostResults + & - vacancyState(myphase)%sizePostResults) + crystalliteResults(3 + crystalliteOutput(myCrystallite,g)%sizeResults: & + 1 + crystalliteOutput(myCrystallite,g)%sizeResults + & + 1 + plasticState (myphase)%sizePostResults + & + sum(sourceState(myphase)%p(:)%sizePostResults)) endif enddo grainLooping enddo IpLooping @@ -849,7 +1031,12 @@ subroutine materialpoint_postResults IpLooping: do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) thePos = 0_pInt - theSize = homogState(mappingHomogenization(2,i,e))%sizePostResults + theSize = homogState (mappingHomogenization(2,i,e))%sizePostResults & + + thermalState (mappingHomogenization(2,i,e))%sizePostResults & + + damageState (mappingHomogenization(2,i,e))%sizePostResults & + + vacancyfluxState (mappingHomogenization(2,i,e))%sizePostResults & + + porosityState (mappingHomogenization(2,i,e))%sizePostResults & + + hydrogenfluxState(mappingHomogenization(2,i,e))%sizePostResults materialpoint_results(thePos+1,i,e) = real(theSize,pReal) ! tell size of homogenization results thePos = thePos + 1_pInt @@ -858,21 +1045,13 @@ subroutine materialpoint_postResults thePos = thePos + theSize endif - theSize = field_sizePostResults(mappingHomogenization(2,i,e)) - if (theSize > 0_pInt) then ! any homogenization results to mention? - materialpoint_results(thePos+1:thePos+theSize,i,e) = field_postResults(i,e) ! tell field results - thePos = thePos + theSize - endif - materialpoint_results(thePos+1,i,e) = real(myNgrains,pReal) ! tell number of grains at materialpoint thePos = thePos + 1_pInt grainLooping :do g = 1,myNgrains theSize = 1 + crystallite_sizePostResults(myCrystallite) + & - 1 + plasticState(material_phase(g,i,e))%sizePostResults + & !ToDo - damageState(material_phase(g,i,e))%sizePostResults + & - thermalState(material_phase(g,i,e))%sizePostResults + & - vacancyState(material_phase(g,i,e))%sizePostResults + 1 + plasticState (material_phase(g,i,e))%sizePostResults + & !ToDo + sum(sourceState(material_phase(g,i,e))%p(:)%sizePostResults) materialpoint_results(thePos+1:thePos+theSize,i,e) = crystallite_postResults(g,i,e) ! tell crystallite results thePos = thePos + theSize enddo grainLooping @@ -940,8 +1119,14 @@ function homogenization_updateState(ip,el) mesh_element use material, only: & homogenization_type, & + thermal_type, & + damage_type, & + vacancyflux_type, & homogenization_maxNgrains, & - HOMOGENIZATION_RGC_ID + HOMOGENIZATION_RGC_ID, & + THERMAL_adiabatic_ID, & + DAMAGE_local_ID, & + VACANCYFLUX_isochempot_ID use crystallite, only: & crystallite_P, & crystallite_dPdF, & @@ -949,6 +1134,12 @@ function homogenization_updateState(ip,el) crystallite_partionedF0 use homogenization_RGC, only: & homogenization_RGC_updateState + use thermal_adiabatic, only: & + thermal_adiabatic_updateState + use damage_local, only: & + damage_local_updateState + use vacancyflux_isochempot, only: & + vacancyflux_isochempot_updateState implicit none integer(pInt), intent(in) :: & @@ -956,23 +1147,60 @@ function homogenization_updateState(ip,el) el !< element number logical, dimension(2) :: homogenization_updateState + homogenization_updateState = .true. chosenHomogenization: select case(homogenization_type(mesh_element(3,el))) - case (HOMOGENIZATION_RGC_ID) chosenHomogenization homogenization_updateState = & - + homogenization_updateState .and. & homogenization_RGC_updateState(crystallite_P(1:3,1:3,1:homogenization_maxNgrains,ip,el), & - crystallite_partionedF(1:3,1:3,1:homogenization_maxNgrains,ip,el), & - crystallite_partionedF0(1:3,1:3,1:homogenization_maxNgrains,ip,el),& - materialpoint_subF(1:3,1:3,ip,el),& - materialpoint_subdt(ip,el), & - crystallite_dPdF(1:3,1:3,1:3,1:3,1:homogenization_maxNgrains,ip,el), & - ip, & - el) + crystallite_partionedF(1:3,1:3,1:homogenization_maxNgrains,ip,el), & + crystallite_partionedF0(1:3,1:3,1:homogenization_maxNgrains,ip,el),& + materialpoint_subF(1:3,1:3,ip,el),& + materialpoint_subdt(ip,el), & + crystallite_dPdF(1:3,1:3,1:3,1:3,1:homogenization_maxNgrains,ip,el), & + ip, & + el) case default chosenHomogenization - homogenization_updateState = .true. + homogenization_updateState = & + homogenization_updateState .and. [.true., .true.] end select chosenHomogenization + chosenThermal: select case (thermal_type(mesh_element(3,el))) + case (THERMAL_adiabatic_ID) chosenThermal + homogenization_updateState = & + homogenization_updateState .and. & + thermal_adiabatic_updateState(materialpoint_subdt(ip,el), & + ip, & + el) + case default chosenThermal + homogenization_updateState = & + homogenization_updateState .and. [.true., .true.] + end select chosenThermal + + chosenDamage: select case (damage_type(mesh_element(3,el))) + case (DAMAGE_local_ID) chosenDamage + homogenization_updateState = & + homogenization_updateState .and. & + damage_local_updateState(materialpoint_subdt(ip,el), & + ip, & + el) + case default chosenDamage + homogenization_updateState = & + homogenization_updateState .and. [.true., .true.] + end select chosenDamage + + chosenVacancyflux: select case (vacancyflux_type(mesh_element(3,el))) + case (VACANCYFLUX_isochempot_ID) chosenVacancyflux + homogenization_updateState = & + homogenization_updateState .and. & + vacancyflux_isochempot_updateState(materialpoint_subdt(ip,el), & + ip, & + el) + case default chosenVacancyflux + homogenization_updateState = & + homogenization_updateState .and. [.true., .true.] + end select chosenVacancyflux + end function homogenization_updateState @@ -1023,557 +1251,6 @@ subroutine homogenization_averageStressAndItsTangent(ip,el) end subroutine homogenization_averageStressAndItsTangent -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average specific heat at each integration point -!-------------------------------------------------------------------------------------------------- -function field_getSpecificHeat(ip,el) - use mesh, only: & - mesh_element - use lattice, only: & - lattice_specificHeat - use material, only: & - material_phase, & - material_homog, & - field_thermal_type, & - FIELD_THERMAL_local_ID, & - FIELD_THERMAL_nonlocal_ID, & - homogenization_Ngrains - - implicit none - real(pReal) :: field_getSpecificHeat - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getSpecificHeat =0.0_pReal - - select case(field_thermal_type(material_homog(ip,el))) - - case (FIELD_THERMAL_local_ID) - field_getSpecificHeat = 0.0_pReal - - case (FIELD_THERMAL_nonlocal_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getSpecificHeat = field_getSpecificHeat + lattice_specificHeat(material_phase(ipc,ip,el)) - enddo - - end select - - field_getSpecificHeat = field_getSpecificHeat /homogenization_Ngrains(mesh_element(3,el)) - -end function field_getSpecificHeat - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average mass density at each integration point -!-------------------------------------------------------------------------------------------------- -function field_getMassDensity(ip,el) - use mesh, only: & - mesh_element - use lattice, only: & - lattice_massDensity - use material, only: & - material_phase, & - material_homog, & - field_thermal_type, & - FIELD_THERMAL_local_ID, & - FIELD_THERMAL_nonlocal_ID, & - homogenization_Ngrains - - - implicit none - real(pReal) :: field_getMassDensity - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getMassDensity =0.0_pReal - - select case(field_thermal_type(material_homog(ip,el))) - - case (FIELD_THERMAL_local_ID) - field_getMassDensity = 0.0_pReal - - case (FIELD_THERMAL_nonlocal_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getMassDensity = field_getMassDensity + lattice_massDensity(material_phase(ipc,ip,el)) - enddo - - end select - - field_getMassDensity = field_getMassDensity /homogenization_Ngrains(mesh_element(3,el)) - -end function field_getMassDensity -!------------------------------------------------------------------------------------------- -!> @brief Returns average conductivity tensor for thermal field at each integration point -!------------------------------------------------------------------------------------------- -function field_getThermalConductivity33(ip,el) - use mesh, only: & - mesh_element - use lattice, only: & - lattice_thermalConductivity33 - use material, only: & - material_phase, & - material_homog, & - field_thermal_type, & - FIELD_THERMAL_nonlocal_ID, & - homogenization_Ngrains - use crystallite, only: & - crystallite_push33ToRef - - - implicit none - real(pReal), dimension(3,3) :: field_getThermalConductivity33 - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getThermalConductivity33 =0.0_pReal - - select case(field_thermal_type(material_homog(ip,el))) - case (FIELD_THERMAL_nonlocal_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getThermalConductivity33 = field_getThermalConductivity33 + & - crystallite_push33ToRef(ipc,ip,el,lattice_thermalConductivity33(:,:,material_phase(ipc,ip,el))) - enddo - - end select - - field_getThermalConductivity33 = field_getThermalConductivity33 /homogenization_Ngrains(mesh_element(3,el)) - -end function field_getThermalConductivity33 -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average diffusion tensor for damage field at each integration point -!-------------------------------------------------------------------------------------------------- -function field_getDamageDiffusion33(ip,el) - use mesh, only: & - mesh_element - use material, only: & - material_homog, & - field_damage_type, & - FIELD_DAMAGE_NONLOCAL_ID, & - homogenization_Ngrains - use crystallite, only: & - crystallite_push33ToRef - use constitutive, only: & - constitutive_getDamageDiffusion33 - - implicit none - real(pReal), dimension(3,3) :: field_getDamageDiffusion33 - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getDamageDiffusion33 =0.0_pReal - - select case(field_damage_type(material_homog(ip,el))) - case (FIELD_DAMAGE_NONLOCAL_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getDamageDiffusion33 = field_getDamageDiffusion33 + & - crystallite_push33ToRef(ipc,ip,el,constitutive_getDamageDiffusion33(ipc,ip,el)) - enddo - - end select - - field_getDamageDiffusion33 = field_getDamageDiffusion33 /homogenization_Ngrains(mesh_element(3,el)) - -end function field_getDamageDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average mobility for damage field at each integration point -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getDamageMobility(ip,el) - use mesh, only: & - mesh_element - use lattice, only: & - lattice_damageMobility - use material, only: & - material_phase, & - material_homog, & - field_damage_type, & - FIELD_DAMAGE_NONLOCAL_ID, & - homogenization_Ngrains - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getDamageMobility =0.0_pReal - - select case(field_damage_type(material_homog(ip,el))) - case (FIELD_DAMAGE_NONLOCAL_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getDamageMobility = field_getDamageMobility + lattice_DamageMobility(material_phase(ipc,ip,el)) - enddo - - end select - - field_getDamageMobility = field_getDamageMobility /homogenization_Ngrains(mesh_element(3,el)) - -end function field_getDamageMobility - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average diffusion tensor for vacancy field at each integration point -!-------------------------------------------------------------------------------------------------- -function field_getVacancyDiffusion33(ip,el) - use mesh, only: & - mesh_element - use material, only: & - material_homog, & - field_vacancy_type, & - FIELD_VACANCY_NONLOCAL_ID, & - homogenization_Ngrains - use crystallite, only: & - crystallite_push33ToRef - use constitutive, only: & - constitutive_getVacancyDiffusion33 - - implicit none - real(pReal), dimension(3,3) :: field_getVacancyDiffusion33 - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getVacancyDiffusion33 = 0.0_pReal - - select case(field_vacancy_type(material_homog(ip,el))) - case (FIELD_VACANCY_NONLOCAL_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getVacancyDiffusion33 = field_getVacancyDiffusion33 + & - crystallite_push33ToRef(ipc,ip,el, & - constitutive_getVacancyDiffusion33(ipc,ip,el)) - enddo - - end select - - field_getVacancyDiffusion33 = field_getVacancyDiffusion33/ & - homogenization_Ngrains(mesh_element(3,el)) - -end function field_getVacancyDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average mobility for vacancy field at each integration point -!-------------------------------------------------------------------------------------------------- -function field_getVacancyMobility33(ip,el) - use mesh, only: & - mesh_element - use material, only: & - material_homog, & - field_vacancy_type, & - FIELD_VACANCY_NONLOCAL_ID, & - homogenization_Ngrains - use crystallite, only: & - crystallite_push33ToRef - use constitutive, only: & - constitutive_getVacancyMobility33 - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - field_getVacancyMobility33 - integer(pInt) :: & - ipc - - - field_getVacancyMobility33 = 0.0_pReal - - select case(field_vacancy_type(material_homog(ip,el))) - case (FIELD_VACANCY_NONLOCAL_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getVacancyMobility33 = field_getVacancyMobility33 + & - crystallite_push33ToRef(ipc,ip,el, & - constitutive_getVacancyMobility33(ipc,ip,el)) - enddo - - end select - - field_getVacancyMobility33 = field_getVacancyMobility33/ & - homogenization_Ngrains(mesh_element(3,el)) - -end function field_getVacancyMobility33 - -!-------------------------------------------------------------------------------------------------- -!> @brief Returns average driving for vacancy chemical potential at each integration point -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getVacancyEnergy(ip,el) - use mesh, only: & - mesh_element - use material, only: & - material_homog, & - field_vacancy_type, & - FIELD_VACANCY_NONLOCAL_ID, & - homogenization_Ngrains - use constitutive, only: & - constitutive_getVacancyEnergy - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - - field_getVacancyEnergy = 0.0_pReal - - select case(field_vacancy_type(material_homog(ip,el))) - case (FIELD_VACANCY_NONLOCAL_ID) - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getVacancyEnergy = field_getVacancyEnergy + & - constitutive_getVacancyEnergy(ipc,ip,el) - enddo - - end select - - field_getVacancyEnergy = field_getVacancyEnergy/ & - homogenization_Ngrains(mesh_element(3,el)) - -end function field_getVacancyEnergy - -!-------------------------------------------------------------------------------------------------- -!> @brief ToDo -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getLocalDamage(ip,el) - use mesh, only: & - mesh_element - use material, only: & - homogenization_Ngrains - use constitutive, only: & - constitutive_getLocalDamage - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - -!-------------------------------------------------------------------------------------------------- -! computing the damage value needed to be passed to field solver - field_getLocalDamage =0.0_pReal - - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getLocalDamage = field_getLocalDamage + constitutive_getLocalDamage(ipc,ip,el) - enddo - - field_getLocalDamage = field_getLocalDamage/homogenization_Ngrains(mesh_element(3,el)) - -end function field_getLocalDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief ToDo -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getFieldDamage(ip,el) - use mesh, only: & - mesh_element - use material, only: & - homogenization_Ngrains - use constitutive, only: & - constitutive_getDamage - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - -!-------------------------------------------------------------------------------------------------- -! computing the damage value needed to be passed to field solver - field_getFieldDamage = 0.0_pReal - - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getFieldDamage = field_getFieldDamage + constitutive_getDamage(ipc,ip,el) - enddo - - field_getFieldDamage = field_getFieldDamage/homogenization_Ngrains(mesh_element(3,el)) - -end function field_getFieldDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief Sets the regularised damage value in field state -!-------------------------------------------------------------------------------------------------- -subroutine field_putFieldDamage(ip,el,fieldDamageValue) ! naming scheme - use material, only: & - fieldDamage, & - material_homog, & - mappingHomogenization, & - field_damage_type, & - FIELD_DAMAGE_NONLOCAL_ID - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el - real(pReal), intent(in) :: & - fieldDamageValue - - select case(field_damage_type(material_homog(ip,el))) - case (FIELD_DAMAGE_NONLOCAL_ID) - fieldDamage(material_homog(ip,el))% & - field(1, mappingHomogenization(1,ip,el)) = fieldDamageValue - - end select - -end subroutine field_putFieldDamage - -!-------------------------------------------------------------------------------------------------- -!> @brief ToDo -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getLocalTemperature(ip,el) - use mesh, only: & - mesh_element - use material, only: & - homogenization_Ngrains - use constitutive, only: & - constitutive_getAdiabaticTemperature - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - - field_getLocalTemperature = 0.0_pReal - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getLocalTemperature = field_getLocalTemperature + & - constitutive_getAdiabaticTemperature(ipc,ip,el) ! array/function/subroutine which is faster - enddo - field_getLocalTemperature = field_getLocalTemperature/homogenization_Ngrains(mesh_element(3,el)) - -end function field_getLocalTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief Sets the regularised temperature value in field state -!-------------------------------------------------------------------------------------------------- -subroutine field_putFieldTemperature(ip,el,fieldThermalValue) - use material, only: & - material_homog, & - fieldThermal, & - mappingHomogenization, & - field_thermal_type, & - FIELD_THERMAL_nonlocal_ID - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el - real(pReal), intent(in) :: & - fieldThermalValue - - select case(field_thermal_type(material_homog(ip,el))) - case (FIELD_THERMAL_nonlocal_ID) - fieldThermal(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) = fieldThermalValue - - end select - -end subroutine field_putFieldTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief return heat generation rate -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getHeatGeneration(ip,el) - use mesh, only: & - mesh_element - use material, only: & - homogenization_Ngrains - use crystallite, only: & - crystallite_Tstar_v, & - crystallite_Lp - use constitutive, only: & - constitutive_getHeatGeneration - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - field_getHeatGeneration = 0.0_pReal - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getHeatGeneration = field_getHeatGeneration + & - constitutive_getHeatGeneration(crystallite_Tstar_v(1:6,ipc,ip,el), & - crystallite_Lp (1:3,1:3,ipc,ip,el), & - ipc,ip,el) - enddo - field_getHeatGeneration = field_getHeatGeneration/homogenization_Ngrains(mesh_element(3,el)) - -end function field_getHeatGeneration - -!-------------------------------------------------------------------------------------------------- -!> @brief ToDo -!-------------------------------------------------------------------------------------------------- -real(pReal) function field_getLocalVacancyConcentration(ip,el) - use mesh, only: & - mesh_element - use material, only: & - homogenization_Ngrains - use constitutive, only: & - constitutive_getLocalVacancyConcentration - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el !< element number - integer(pInt) :: & - ipc - - - field_getLocalVacancyConcentration = 0.0_pReal - do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) - field_getLocalVacancyConcentration = field_getLocalVacancyConcentration + & - constitutive_getLocalVacancyConcentration(ipc,ip,el) ! array/function/subroutine which is faster - enddo - field_getLocalVacancyConcentration = field_getLocalVacancyConcentration/ & - homogenization_Ngrains(mesh_element(3,el)) - -end function field_getLocalVacancyConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief Sets the diffused vacancy concentration in field state -!-------------------------------------------------------------------------------------------------- -subroutine field_putFieldVacancyConcentration(ip,el,fieldVacancyConcentration) - use material, only: & - material_homog, & - fieldVacancy, & - mappingHomogenization, & - field_vacancy_type, & - FIELD_VACANCY_nonlocal_ID - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point number - el - real(pReal), intent(in) :: & - fieldVacancyConcentration - - select case(field_vacancy_type(material_homog(ip,el))) - case (FIELD_VACANCY_nonlocal_ID) - fieldVacancy(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) = fieldVacancyConcentration - - end select - -end subroutine field_putFieldVacancyConcentration - !-------------------------------------------------------------------------------------------------- !> @brief return array of homogenization results for post file inclusion. call only, !> if homogenization_sizePostResults(i,e) > 0 !! @@ -1584,80 +1261,151 @@ function homogenization_postResults(ip,el) use material, only: & mappingHomogenization, & homogState, & + thermalState, & + damageState, & + vacancyfluxState, & + porosityState, & + hydrogenfluxState, & homogenization_type, & + thermal_type, & + damage_type, & + vacancyflux_type, & + porosity_type, & + hydrogenflux_type, & HOMOGENIZATION_NONE_ID, & HOMOGENIZATION_ISOSTRAIN_ID, & - HOMOGENIZATION_RGC_ID + HOMOGENIZATION_RGC_ID, & + THERMAL_isothermal_ID, & + THERMAL_adiabatic_ID, & + THERMAL_conduction_ID, & + DAMAGE_none_ID, & + DAMAGE_local_ID, & + DAMAGE_nonlocal_ID, & + VACANCYFLUX_isoconc_ID, & + VACANCYFLUX_isochempot_ID, & + VACANCYFLUX_cahnhilliard_ID, & + POROSITY_none_ID, & + POROSITY_phasefield_ID, & + HYDROGENFLUX_isoconc_ID, & + HYDROGENFLUX_cahnhilliard_ID use homogenization_isostrain, only: & homogenization_isostrain_postResults use homogenization_RGC, only: & homogenization_RGC_postResults + use thermal_adiabatic, only: & + thermal_adiabatic_postResults + use thermal_conduction, only: & + thermal_conduction_postResults + use damage_local, only: & + damage_local_postResults + use damage_nonlocal, only: & + damage_nonlocal_postResults + use vacancyflux_isochempot, only: & + vacancyflux_isochempot_postResults + use vacancyflux_cahnhilliard, only: & + vacancyflux_cahnhilliard_postResults + use porosity_phasefield, only: & + porosity_phasefield_postResults + use hydrogenflux_cahnhilliard, only: & + hydrogenflux_cahnhilliard_postResults implicit none integer(pInt), intent(in) :: & ip, & !< integration point el !< element number - real(pReal), dimension(homogState(mappingHomogenization(2,ip,el))%sizePostResults) :: & + real(pReal), dimension( homogState (mappingHomogenization(2,ip,el))%sizePostResults & + + thermalState (mappingHomogenization(2,ip,el))%sizePostResults & + + damageState (mappingHomogenization(2,ip,el))%sizePostResults & + + vacancyfluxState (mappingHomogenization(2,ip,el))%sizePostResults & + + porosityState (mappingHomogenization(2,ip,el))%sizePostResults & + + hydrogenfluxState(mappingHomogenization(2,ip,el))%sizePostResults) :: & homogenization_postResults - + integer(pInt) :: & + startPos, endPos + homogenization_postResults = 0.0_pReal + + startPos = 1_pInt + endPos = homogState(mappingHomogenization(2,ip,el))%sizePostResults chosenHomogenization: select case (homogenization_type(mesh_element(3,el))) case (HOMOGENIZATION_NONE_ID) chosenHomogenization case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization - homogenization_postResults = homogenization_isostrain_postResults(& + homogenization_postResults(startPos:endPos) = & + homogenization_isostrain_postResults(& ip, & el, & materialpoint_P(1:3,1:3,ip,el), & materialpoint_F(1:3,1:3,ip,el)) case (HOMOGENIZATION_RGC_ID) chosenHomogenization - homogenization_postResults = homogenization_RGC_postResults(& + homogenization_postResults(startPos:endPos) = & + homogenization_RGC_postResults(& ip, & el, & materialpoint_P(1:3,1:3,ip,el), & materialpoint_F(1:3,1:3,ip,el)) end select chosenHomogenization + startPos = endPos + 1_pInt + endPos = endPos + thermalState(mappingHomogenization(2,ip,el))%sizePostResults + chosenThermal: select case (thermal_type(mesh_element(3,el))) + case (THERMAL_isothermal_ID) chosenThermal + + case (THERMAL_adiabatic_ID) chosenThermal + homogenization_postResults(startPos:endPos) = & + thermal_adiabatic_postResults(ip, el) + case (THERMAL_conduction_ID) chosenThermal + homogenization_postResults(startPos:endPos) = & + thermal_conduction_postResults(ip, el) + end select chosenThermal + + startPos = endPos + 1_pInt + endPos = endPos + damageState(mappingHomogenization(2,ip,el))%sizePostResults + chosenDamage: select case (damage_type(mesh_element(3,el))) + case (DAMAGE_none_ID) chosenDamage + + case (DAMAGE_local_ID) chosenDamage + homogenization_postResults(startPos:endPos) = & + damage_local_postResults(ip, el) + + case (DAMAGE_nonlocal_ID) chosenDamage + homogenization_postResults(startPos:endPos) = & + damage_nonlocal_postResults(ip, el) + end select chosenDamage + + startPos = endPos + 1_pInt + endPos = endPos + vacancyfluxState(mappingHomogenization(2,ip,el))%sizePostResults + chosenVacancyflux: select case (vacancyflux_type(mesh_element(3,el))) + case (VACANCYFLUX_isoconc_ID) chosenVacancyflux + + case (VACANCYFLUX_isochempot_ID) chosenVacancyflux + homogenization_postResults(startPos:endPos) = & + vacancyflux_isochempot_postResults(ip, el) + case (VACANCYFLUX_cahnhilliard_ID) chosenVacancyflux + homogenization_postResults(startPos:endPos) = & + vacancyflux_cahnhilliard_postResults(ip, el) + end select chosenVacancyflux + + startPos = endPos + 1_pInt + endPos = endPos + porosityState(mappingHomogenization(2,ip,el))%sizePostResults + chosenPorosity: select case (porosity_type(mesh_element(3,el))) + case (POROSITY_none_ID) chosenPorosity + + case (POROSITY_phasefield_ID) chosenPorosity + homogenization_postResults(startPos:endPos) = & + porosity_phasefield_postResults(ip, el) + end select chosenPorosity + + startPos = endPos + 1_pInt + endPos = endPos + hydrogenfluxState(mappingHomogenization(2,ip,el))%sizePostResults + chosenHydrogenflux: select case (hydrogenflux_type(mesh_element(3,el))) + case (HYDROGENFLUX_isoconc_ID) chosenHydrogenflux + + case (HYDROGENFLUX_cahnhilliard_ID) chosenHydrogenflux + homogenization_postResults(startPos:endPos) = & + hydrogenflux_cahnhilliard_postResults(ip, el) + end select chosenHydrogenflux + end function homogenization_postResults -!-------------------------------------------------------------------------------------------------- -!> @brief return array of homogenization results for post file inclusion. call only, -!> if homogenization_sizePostResults(i,e) > 0 !! -!-------------------------------------------------------------------------------------------------- -function field_postResults(ip,el) - use material, only: & - mappingHomogenization, & - fieldThermal, & - fieldDamage, & - fieldVacancy - - implicit none - integer(pInt), intent(in) :: & - ip, & !< integration point - el !< element number - real(pReal), dimension(field_sizePostResults(mappingHomogenization(2,ip,el))) :: & - field_postResults - integer(pInt) :: & - c, homog, pos, o - - field_postResults = 0.0_pReal - homog = mappingHomogenization(2,ip,el) - pos = mappingHomogenization(1,ip,el) - c = 0_pInt - do o = 1_pInt,field_Noutput(homog) - select case(field_outputID(o,homog)) - case (temperature_ID) - field_postResults(c+1_pInt) = fieldThermal(homog)%field(1,pos) - c = c + 1_pInt - case (damage_ID) - field_postResults(c+1_pInt) = fieldDamage(homog)%field(1,pos) - c = c + 1_pInt - case (vacancy_concentration_ID) - field_postResults(c+1_pInt) = fieldVacancy(homog)%field(1,pos) - c = c + 1_pInt - end select - enddo - -end function field_postResults - end module homogenization diff --git a/code/homogenization_RGC.f90 b/code/homogenization_RGC.f90 index 7a311bd70..8344f97ec 100644 --- a/code/homogenization_RGC.f90 +++ b/code/homogenization_RGC.f90 @@ -336,7 +336,6 @@ subroutine homogenization_RGC_partitionDeformation(F,avgF,ip,el) use material, only: & homogenization_maxNgrains, & homogenization_Ngrains,& - mappingHomogenization, & homogenization_typeInstance use FEsolving, only: & theInc,& @@ -903,7 +902,6 @@ subroutine homogenization_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF, use mesh, only: mesh_element use material, only: & homogenization_maxNgrains, & - mappingHomogenization, & homogenization_Ngrains, & homogenization_typeInstance use math, only: math_Plain3333to99 diff --git a/code/hydrogenflux_cahnhilliard.f90 b/code/hydrogenflux_cahnhilliard.f90 new file mode 100644 index 000000000..b2b4d8734 --- /dev/null +++ b/code/hydrogenflux_cahnhilliard.f90 @@ -0,0 +1,544 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for conservative transport of solute hydrogen +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module hydrogenflux_cahnhilliard + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + hydrogenflux_cahnhilliard_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + hydrogenflux_cahnhilliard_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + hydrogenflux_cahnhilliard_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + hydrogenflux_cahnhilliard_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + hydrogenflux_cahnhilliard_formationEnergyCoeff, & + hydrogenflux_cahnhilliard_kBCoeff + + real(pReal), parameter, private :: & + kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin + + enum, bind(c) + enumerator :: undefined_ID, & + hydrogenConc_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + hydrogenflux_cahnhilliard_outputID !< ID of each post result output + + + public :: & + hydrogenflux_cahnhilliard_init, & + hydrogenflux_cahnhilliard_getMobility33, & + hydrogenflux_cahnhilliard_getDiffusion33, & + hydrogenflux_cahnhilliard_getFormationEnergy, & + hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent, & + hydrogenflux_cahnhilliard_getChemPotAndItsTangent, & + hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate, & + hydrogenflux_cahnhilliard_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine hydrogenflux_cahnhilliard_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use lattice, only: & + lattice_hydrogenVol + use material, only: & + hydrogenflux_type, & + hydrogenflux_typeInstance, & + homogenization_Noutput, & + HYDROGENFLUX_cahnhilliard_label, & + HYDROGENFLUX_cahnhilliard_ID, & + material_homog, & + material_Nphase, & + mappingHomogenization, & + hydrogenfluxState, & + hydrogenfluxMapping, & + hydrogenConc, & + hydrogenConcRate, & + material_partHomogenization, & + material_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- hydrogenflux_'//HYDROGENFLUX_cahnhilliard_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(hydrogenflux_type == HYDROGENFLUX_cahnhilliard_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(hydrogenflux_cahnhilliard_sizePostResults(maxNinstance), source=0_pInt) + allocate(hydrogenflux_cahnhilliard_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(hydrogenflux_cahnhilliard_output (maxval(homogenization_Noutput),maxNinstance)) + hydrogenflux_cahnhilliard_output = '' + allocate(hydrogenflux_cahnhilliard_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(hydrogenflux_cahnhilliard_Noutput (maxNinstance), source=0_pInt) + + allocate(hydrogenflux_cahnhilliard_kBCoeff (material_Nphase), source=0.0_pReal) + allocate(hydrogenflux_cahnhilliard_formationEnergyCoeff(material_Nphase), source=0.0_pReal) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = hydrogenflux_typeInstance(section) ! which instance of my hydrogenflux is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('hydrogenconc') + hydrogenflux_cahnhilliard_Noutput(instance) = hydrogenflux_cahnhilliard_Noutput(instance) + 1_pInt + hydrogenflux_cahnhilliard_outputID(hydrogenflux_cahnhilliard_Noutput(instance),instance) = hydrogenConc_ID + hydrogenflux_cahnhilliard_output(hydrogenflux_cahnhilliard_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingHomog + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('hydrogenformationenergy') + hydrogenflux_cahnhilliard_formationEnergyCoeff(section) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingPhase + + initializeInstances: do section = 1_pInt, size(hydrogenflux_type) + if (hydrogenflux_type(section) == HYDROGENFLUX_cahnhilliard_ID) then + NofMyHomog=count(material_homog==section) + instance = hydrogenflux_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,hydrogenflux_cahnhilliard_Noutput(instance) + select case(hydrogenflux_cahnhilliard_outputID(o,instance)) + case(hydrogenConc_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + hydrogenflux_cahnhilliard_sizePostResult(o,instance) = mySize + hydrogenflux_cahnhilliard_sizePostResults(instance) = hydrogenflux_cahnhilliard_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 0_pInt + hydrogenfluxState(section)%sizeState = sizeState + hydrogenfluxState(section)%sizePostResults = hydrogenflux_cahnhilliard_sizePostResults(instance) + allocate(hydrogenfluxState(section)%state0 (sizeState,NofMyHomog)) + allocate(hydrogenfluxState(section)%subState0(sizeState,NofMyHomog)) + allocate(hydrogenfluxState(section)%state (sizeState,NofMyHomog)) + + nullify(hydrogenfluxMapping(section)%p) + hydrogenfluxMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(hydrogenConc (section)%p) + deallocate(hydrogenConcRate(section)%p) + allocate (hydrogenConc (section)%p(NofMyHomog), source=0.0_pReal) + allocate (hydrogenConcRate(section)%p(NofMyHomog), source=0.0_pReal) + + endif + + enddo initializeInstances + + initializeParams: do section = 1_pInt, material_Nphase + hydrogenflux_cahnhilliard_kBCoeff(section) = & + kB/ & + hydrogenflux_cahnhilliard_formationEnergyCoeff(section) + hydrogenflux_cahnhilliard_formationEnergyCoeff(section) = & + hydrogenflux_cahnhilliard_formationEnergyCoeff(section)/ & + lattice_hydrogenVol(section) + enddo initializeParams + +end subroutine hydrogenflux_cahnhilliard_init + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized solute mobility tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function hydrogenflux_cahnhilliard_getMobility33(ip,el) + use lattice, only: & + lattice_hydrogenfluxMobility33 + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + hydrogenflux_cahnhilliard_getMobility33 + integer(pInt) :: & + grain + + hydrogenflux_cahnhilliard_getMobility33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + hydrogenflux_cahnhilliard_getMobility33 = hydrogenflux_cahnhilliard_getMobility33 + & + crystallite_push33ToRef(grain,ip,el,lattice_hydrogenfluxMobility33(:,:,material_phase(grain,ip,el))) + enddo + + hydrogenflux_cahnhilliard_getMobility33 = & + hydrogenflux_cahnhilliard_getMobility33/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function hydrogenflux_cahnhilliard_getMobility33 + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized solute nonlocal diffusion tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function hydrogenflux_cahnhilliard_getDiffusion33(ip,el) + use lattice, only: & + lattice_hydrogenfluxDiffusion33 + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + hydrogenflux_cahnhilliard_getDiffusion33 + integer(pInt) :: & + grain + + hydrogenflux_cahnhilliard_getDiffusion33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + hydrogenflux_cahnhilliard_getDiffusion33 = hydrogenflux_cahnhilliard_getDiffusion33 + & + crystallite_push33ToRef(grain,ip,el,lattice_hydrogenfluxDiffusion33(:,:,material_phase(grain,ip,el))) + enddo + + hydrogenflux_cahnhilliard_getDiffusion33 = & + hydrogenflux_cahnhilliard_getDiffusion33/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function hydrogenflux_cahnhilliard_getDiffusion33 + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized solution energy +!-------------------------------------------------------------------------------------------------- +function hydrogenflux_cahnhilliard_getFormationEnergy(ip,el) + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + hydrogenflux_cahnhilliard_getFormationEnergy + integer(pInt) :: & + grain + + hydrogenflux_cahnhilliard_getFormationEnergy = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + hydrogenflux_cahnhilliard_getFormationEnergy = hydrogenflux_cahnhilliard_getFormationEnergy + & + hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el)) + enddo + + hydrogenflux_cahnhilliard_getFormationEnergy = & + hydrogenflux_cahnhilliard_getFormationEnergy/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function hydrogenflux_cahnhilliard_getFormationEnergy + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized hydrogen entropy coefficient +!-------------------------------------------------------------------------------------------------- +function hydrogenflux_cahnhilliard_getEntropicCoeff(ip,el) + use material, only: & + homogenization_Ngrains, & + material_homog, & + material_phase, & + temperature, & + thermalMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + hydrogenflux_cahnhilliard_getEntropicCoeff + integer(pInt) :: & + grain + + hydrogenflux_cahnhilliard_getEntropicCoeff = 0.0_pReal + do grain = 1, homogenization_Ngrains(material_homog(ip,el)) + hydrogenflux_cahnhilliard_getEntropicCoeff = hydrogenflux_cahnhilliard_getEntropicCoeff + & + hydrogenflux_cahnhilliard_kBCoeff(material_phase(grain,ip,el)) + enddo + + hydrogenflux_cahnhilliard_getEntropicCoeff = & + hydrogenflux_cahnhilliard_getEntropicCoeff* & + temperature(material_homog(ip,el))%p(thermalMapping(material_homog(ip,el))%p(ip,el))/ & + homogenization_Ngrains(material_homog(ip,el)) + +end function hydrogenflux_cahnhilliard_getEntropicCoeff + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized kinematic contribution to chemical potential +!-------------------------------------------------------------------------------------------------- +subroutine hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCh, Ch, ip, el) + use material, only: & + homogenization_Ngrains, & + material_homog, & + phase_kinematics, & + phase_Nkinematics, & + material_phase, & + KINEMATICS_hydrogen_strain_ID + use crystallite, only: & + crystallite_Tstar_v, & + crystallite_Fi0, & + crystallite_Fi + use kinematics_hydrogen_strain, only: & + kinematics_hydrogen_strain_ChemPotAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Ch + real(pReal), intent(out) :: & + KPot, dKPot_dCh + real(pReal) :: & + my_KPot, my_dKPot_dCh + integer(pInt) :: & + grain, kinematics + + KPot = 0.0_pReal + dKPot_dCh = 0.0_pReal + do grain = 1_pInt,homogenization_Ngrains(material_homog(ip,el)) + do kinematics = 1_pInt, phase_Nkinematics(material_phase(grain,ip,el)) + select case (phase_kinematics(kinematics,material_phase(grain,ip,el))) + case (KINEMATICS_hydrogen_strain_ID) + call kinematics_hydrogen_strain_ChemPotAndItsTangent(my_KPot, my_dKPot_dCh, & + crystallite_Tstar_v(1:6,grain,ip,el), & + crystallite_Fi0(1:3,1:3,grain,ip,el), & + crystallite_Fi (1:3,1:3,grain,ip,el), & + grain,ip, el) + + case default + my_KPot = 0.0_pReal + my_dKPot_dCh = 0.0_pReal + + end select + KPot = KPot + my_KPot/hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el)) + dKPot_dCh = dKPot_dCh + my_dKPot_dCh/hydrogenflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el)) + enddo + enddo + + KPot = KPot/homogenization_Ngrains(material_homog(ip,el)) + dKPot_dCh = dKPot_dCh/homogenization_Ngrains(material_homog(ip,el)) + +end subroutine hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized chemical potential +!-------------------------------------------------------------------------------------------------- +subroutine hydrogenflux_cahnhilliard_getChemPotAndItsTangent(ChemPot,dChemPot_dCh,Ch,ip,el) + use numerics, only: & + hydrogenBoundPenalty, & + hydrogenPolyOrder + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Ch + real(pReal), intent(out) :: & + ChemPot, & + dChemPot_dCh + real(pReal) :: & + kBT, KPot, dKPot_dCh + integer(pInt) :: & + o + + ChemPot = 1.0_pReal + dChemPot_dCh = 0.0_pReal + kBT = hydrogenflux_cahnhilliard_getEntropicCoeff(ip,el) + do o = 1_pInt, hydrogenPolyOrder + ChemPot = ChemPot + kBT*((2.0_pReal*Ch - 1.0_pReal)**real(2_pInt*o-1_pInt,pReal))/ & + real(2_pInt*o-1_pInt,pReal) + dChemPot_dCh = dChemPot_dCh + 2.0_pReal*kBT*(2.0_pReal*Ch - 1.0_pReal)**real(2_pInt*o-2_pInt,pReal) + enddo + + call hydrogenflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCh, Ch, ip, el) + ChemPot = ChemPot + KPot + dChemPot_dCh = dChemPot_dCh + dKPot_dCh + + if (Ch < 0.0_pReal) then + ChemPot = ChemPot - 3.0_pReal*hydrogenBoundPenalty*Ch*Ch + dChemPot_dCh = dChemPot_dCh - 6.0_pReal*hydrogenBoundPenalty*Ch + elseif (Ch > 1.0_pReal) then + ChemPot = ChemPot + 3.0_pReal*hydrogenBoundPenalty*(1.0_pReal - Ch)*(1.0_pReal - Ch) + dChemPot_dCh = dChemPot_dCh - 6.0_pReal*hydrogenBoundPenalty*(1.0_pReal - Ch) + endif + +end subroutine hydrogenflux_cahnhilliard_getChemPotAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief updates hydrogen concentration with solution from Cahn-Hilliard PDE for solute transport +!-------------------------------------------------------------------------------------------------- +subroutine hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate(Ch,Chdot,ip,el) + use material, only: & + mappingHomogenization, & + hydrogenConc, & + hydrogenConcRate, & + hydrogenfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Ch, & + Chdot + integer(pInt) :: & + homog, & + offset + + homog = mappingHomogenization(2,ip,el) + offset = hydrogenfluxMapping(homog)%p(ip,el) + hydrogenConc (homog)%p(offset) = Ch + hydrogenConcRate(homog)%p(offset) = Chdot + +end subroutine hydrogenflux_cahnhilliard_putHydrogenConcAndItsRate + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of hydrogen transport results +!-------------------------------------------------------------------------------------------------- +function hydrogenflux_cahnhilliard_postResults(ip,el) + use material, only: & + mappingHomogenization, & + hydrogenflux_typeInstance, & + hydrogenConc, & + hydrogenfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(hydrogenflux_cahnhilliard_sizePostResults(hydrogenflux_typeInstance(mappingHomogenization(2,ip,el)))) :: & + hydrogenflux_cahnhilliard_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = hydrogenfluxMapping(homog)%p(ip,el) + instance = hydrogenflux_typeInstance(homog) + + c = 0_pInt + hydrogenflux_cahnhilliard_postResults = 0.0_pReal + + do o = 1_pInt,hydrogenflux_cahnhilliard_Noutput(instance) + select case(hydrogenflux_cahnhilliard_outputID(o,instance)) + + case (hydrogenConc_ID) + hydrogenflux_cahnhilliard_postResults(c+1_pInt) = hydrogenConc(homog)%p(offset) + c = c + 1 + end select + enddo +end function hydrogenflux_cahnhilliard_postResults + +end module hydrogenflux_cahnhilliard diff --git a/code/hydrogenflux_isoconc.f90 b/code/hydrogenflux_isoconc.f90 new file mode 100644 index 000000000..e5defd029 --- /dev/null +++ b/code/hydrogenflux_isoconc.f90 @@ -0,0 +1,64 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for constant hydrogen concentration +!-------------------------------------------------------------------------------------------------- +module hydrogenflux_isoconc + + implicit none + private + + public :: & + hydrogenflux_isoconc_init + +contains + +!-------------------------------------------------------------------------------------------------- +!> @brief allocates all neccessary fields, reads information from material configuration file +!-------------------------------------------------------------------------------------------------- +subroutine hydrogenflux_isoconc_init() + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use prec, only: & + pReal, & + pInt + use IO, only: & + IO_timeStamp + use material + use numerics, only: & + worldrank + + implicit none + integer(pInt) :: & + homog, & + NofMyHomog + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- hydrogenflux_'//HYDROGENFLUX_isoconc_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + initializeInstances: do homog = 1_pInt, material_Nhomogenization + + myhomog: if (hydrogenflux_type(homog) == HYDROGENFLUX_isoconc_ID) then + NofMyHomog = count(material_homog == homog) + hydrogenfluxState(homog)%sizeState = 0_pInt + hydrogenfluxState(homog)%sizePostResults = 0_pInt + allocate(hydrogenfluxState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal) + allocate(hydrogenfluxState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal) + allocate(hydrogenfluxState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal) + + deallocate(hydrogenConc (homog)%p) + deallocate(hydrogenConcRate(homog)%p) + allocate (hydrogenConc (homog)%p(1), source=0.0_pReal) + allocate (hydrogenConcRate(homog)%p(1), source=0.0_pReal) + + endif myhomog + enddo initializeInstances + + +end subroutine hydrogenflux_isoconc_init + +end module hydrogenflux_isoconc diff --git a/code/kinematics_cleavage_opening.f90 b/code/kinematics_cleavage_opening.f90 new file mode 100644 index 000000000..8ff4ca2ba --- /dev/null +++ b/code/kinematics_cleavage_opening.f90 @@ -0,0 +1,305 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @brief material subroutine incorporating kinematics resulting from opening of cleavage planes +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module kinematics_cleavage_opening + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + kinematics_cleavage_opening_sizePostResults, & !< cumulative size of post results + kinematics_cleavage_opening_offset, & !< which kinematics is my current damage mechanism? + kinematics_cleavage_opening_instance !< instance of damage kinematics mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + kinematics_cleavage_opening_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + kinematics_cleavage_opening_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + kinematics_cleavage_opening_Noutput !< number of outputs per instance of this damage + + integer(pInt), dimension(:), allocatable, private :: & + kinematics_cleavage_opening_totalNcleavage !< total number of cleavage systems + + integer(pInt), dimension(:,:), allocatable, private :: & + kinematics_cleavage_opening_Ncleavage !< number of cleavage systems per family + + real(pReal), dimension(:), allocatable, private :: & + kinematics_cleavage_opening_sdot_0, & + kinematics_cleavage_opening_N + + real(pReal), dimension(:,:), allocatable, private :: & + kinematics_cleavage_opening_critDisp, & + kinematics_cleavage_opening_critLoad + + public :: & + kinematics_cleavage_opening_init, & + kinematics_cleavage_opening_LiAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_cleavage_opening_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_kinematics, & + phase_Nkinematics, & + phase_Noutput, & + KINEMATICS_cleavage_opening_label, & + KINEMATICS_cleavage_opening_ID, & + material_Nphase, & + MATERIAL_partPhase + use numerics,only: & + worldrank + use lattice, only: & + lattice_maxNcleavageFamily, & + lattice_NcleavageSystem + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,kinematics + integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_cleavage_opening_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_kinematics == KINEMATICS_cleavage_opening_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(kinematics_cleavage_opening_offset(material_Nphase), source=0_pInt) + allocate(kinematics_cleavage_opening_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + kinematics_cleavage_opening_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_cleavage_opening_ID) + do kinematics = 1, phase_Nkinematics(phase) + if (phase_kinematics(kinematics,phase) == kinematics_cleavage_opening_ID) & + kinematics_cleavage_opening_offset(phase) = kinematics + enddo + enddo + + allocate(kinematics_cleavage_opening_sizePostResults(maxNinstance), source=0_pInt) + allocate(kinematics_cleavage_opening_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt) + allocate(kinematics_cleavage_opening_output(maxval(phase_Noutput),maxNinstance)) + kinematics_cleavage_opening_output = '' + allocate(kinematics_cleavage_opening_Noutput(maxNinstance), source=0_pInt) + allocate(kinematics_cleavage_opening_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) + allocate(kinematics_cleavage_opening_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) + allocate(kinematics_cleavage_opening_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt) + allocate(kinematics_cleavage_opening_totalNcleavage(maxNinstance), source=0_pInt) + allocate(kinematics_cleavage_opening_sdot_0(maxNinstance), source=0.0_pReal) + allocate(kinematics_cleavage_opening_N(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_cleavage_opening_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = kinematics_cleavage_opening_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('anisobrittle_sdot0') + kinematics_cleavage_opening_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisobrittle_ratesensitivity') + kinematics_cleavage_opening_N(instance) = IO_floatValue(line,positions,2_pInt) + + case ('ncleavage') ! + Nchunks_CleavageFamilies = positions(1) - 1_pInt + do j = 1_pInt, Nchunks_CleavageFamilies + kinematics_cleavage_opening_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j) + enddo + + case ('anisobrittle_criticaldisplacement') + do j = 1_pInt, Nchunks_CleavageFamilies + kinematics_cleavage_opening_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + case ('anisobrittle_criticalload') + do j = 1_pInt, Nchunks_CleavageFamilies + kinematics_cleavage_opening_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + end select + endif; endif + enddo parsingFile + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, material_Nphase + myPhase: if (any(phase_kinematics(:,phase) == KINEMATICS_cleavage_opening_ID)) then + instance = kinematics_cleavage_opening_instance(phase) + kinematics_cleavage_opening_Ncleavage(1:lattice_maxNcleavageFamily,instance) = & + min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested + kinematics_cleavage_opening_Ncleavage(1:lattice_maxNcleavageFamily,instance)) + kinematics_cleavage_opening_totalNcleavage(instance) = sum(kinematics_cleavage_opening_Ncleavage(:,instance)) ! how many cleavage systems altogether + if (kinematics_cleavage_opening_sdot_0(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//KINEMATICS_cleavage_opening_LABEL//')') + if (any(kinematics_cleavage_opening_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//KINEMATICS_cleavage_opening_LABEL//')') + if (any(kinematics_cleavage_opening_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//KINEMATICS_cleavage_opening_LABEL//')') + if (kinematics_cleavage_opening_N(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//KINEMATICS_cleavage_opening_LABEL//')') + endif myPhase + enddo sanityChecks + +end subroutine kinematics_cleavage_opening_init + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the constitutive equation for calculating the velocity gradient +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_cleavage_opening_LiAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el) + use prec, only: & + tol_math_check + use material, only: & + mappingConstitutive, & + material_homog, & + damage, & + damageMapping + use lattice, only: & + lattice_Scleavage, & + lattice_Scleavage_v, & + lattice_maxNcleavageFamily, & + lattice_NcleavageSystem + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in), dimension(6) :: & + Tstar_v !< 2nd Piola-Kirchhoff stress + real(pReal), intent(out), dimension(3,3) :: & + Ld !< damage velocity gradient + real(pReal), intent(out), dimension(3,3,3,3) :: & + dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor) + integer(pInt) :: & + phase, & + constituent, & + instance, & + homog, damageOffset, & + f, i, index_myFamily, k, l, m, n + real(pReal) :: & + traction_d, traction_t, traction_n, traction_crit, & + udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = kinematics_cleavage_opening_instance(phase) + homog = material_homog(ip,el) + damageOffset = damageMapping(homog)%p(ip,el) + + Ld = 0.0_pReal + dLd_dTstar3333 = 0.0_pReal + do f = 1_pInt,lattice_maxNcleavageFamily + index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family + do i = 1_pInt,kinematics_cleavage_opening_Ncleavage(f,instance) ! process each (active) cleavage system in family + traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase)) + traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase)) + traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase)) + traction_crit = kinematics_cleavage_opening_critLoad(f,instance)* & + damage(homog)%p(damageOffset) + udotd = & + sign(1.0_pReal,traction_d)* & + kinematics_cleavage_opening_sdot_0(instance)* & + (max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance) + if (abs(udotd) > tol_math_check) then + Ld = Ld + udotd*lattice_Scleavage(1:3,1:3,1,index_myFamily+i,phase) + dudotd_dt = sign(1.0_pReal,traction_d)*udotd*kinematics_cleavage_opening_N(instance)/ & + max(0.0_pReal, abs(traction_d) - traction_crit) + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudotd_dt*lattice_Scleavage(k,l,1,index_myFamily+i,phase)* & + lattice_Scleavage(m,n,1,index_myFamily+i,phase) + endif + + udott = & + sign(1.0_pReal,traction_t)* & + kinematics_cleavage_opening_sdot_0(instance)* & + (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance) + if (abs(udott) > tol_math_check) then + Ld = Ld + udott*lattice_Scleavage(1:3,1:3,2,index_myFamily+i,phase) + dudott_dt = sign(1.0_pReal,traction_t)*udott*kinematics_cleavage_opening_N(instance)/ & + max(0.0_pReal, abs(traction_t) - traction_crit) + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudott_dt*lattice_Scleavage(k,l,2,index_myFamily+i,phase)* & + lattice_Scleavage(m,n,2,index_myFamily+i,phase) + endif + + udotn = & + sign(1.0_pReal,traction_n)* & + kinematics_cleavage_opening_sdot_0(instance)* & + (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**kinematics_cleavage_opening_N(instance) + if (abs(udotn) > tol_math_check) then + Ld = Ld + udotn*lattice_Scleavage(1:3,1:3,3,index_myFamily+i,phase) + dudotn_dt = sign(1.0_pReal,traction_n)*udotn*kinematics_cleavage_opening_N(instance)/ & + max(0.0_pReal, abs(traction_n) - traction_crit) + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudotn_dt*lattice_Scleavage(k,l,3,index_myFamily+i,phase)* & + lattice_Scleavage(m,n,3,index_myFamily+i,phase) + endif + + enddo + enddo + +end subroutine kinematics_cleavage_opening_LiAndItsTangent + +end module kinematics_cleavage_opening diff --git a/code/kinematics_hydrogen_strain.f90 b/code/kinematics_hydrogen_strain.f90 new file mode 100644 index 000000000..79f6677e5 --- /dev/null +++ b/code/kinematics_hydrogen_strain.f90 @@ -0,0 +1,220 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incorporating kinematics resulting from interstitial hydrogen +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module kinematics_hydrogen_strain + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + kinematics_hydrogen_strain_sizePostResults, & !< cumulative size of post results + kinematics_hydrogen_strain_offset, & !< which kinematics is my current damage mechanism? + kinematics_hydrogen_strain_instance !< instance of damage kinematics mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + kinematics_hydrogen_strain_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + kinematics_hydrogen_strain_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + kinematics_hydrogen_strain_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + kinematics_hydrogen_strain_coeff + + public :: & + kinematics_hydrogen_strain_init, & + kinematics_hydrogen_strain_LiAndItsTangent, & + kinematics_hydrogen_strain_ChemPotAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_hydrogen_strain_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_kinematics, & + phase_Nkinematics, & + phase_Noutput, & + KINEMATICS_hydrogen_strain_label, & + KINEMATICS_hydrogen_strain_ID, & + material_Nphase, & + MATERIAL_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,kinematics + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_hydrogen_strain_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_kinematics == KINEMATICS_hydrogen_strain_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(kinematics_hydrogen_strain_offset(material_Nphase), source=0_pInt) + allocate(kinematics_hydrogen_strain_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + kinematics_hydrogen_strain_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_hydrogen_strain_ID) + do kinematics = 1, phase_Nkinematics(phase) + if (phase_kinematics(kinematics,phase) == kinematics_hydrogen_strain_ID) & + kinematics_hydrogen_strain_offset(phase) = kinematics + enddo + enddo + + allocate(kinematics_hydrogen_strain_sizePostResults(maxNinstance), source=0_pInt) + allocate(kinematics_hydrogen_strain_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(kinematics_hydrogen_strain_output(maxval(phase_Noutput),maxNinstance)) + kinematics_hydrogen_strain_output = '' + allocate(kinematics_hydrogen_strain_Noutput(maxNinstance), source=0_pInt) + allocate(kinematics_hydrogen_strain_coeff(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_hydrogen_strain_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = kinematics_hydrogen_strain_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('hydrogen_strain_coeff') + kinematics_hydrogen_strain_coeff(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + +end subroutine kinematics_hydrogen_strain_init + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the constitutive equation for calculating the velocity gradient +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_hydrogen_strain_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el) + use material, only: & + material_phase, & + material_homog, & + hydrogenConcRate, & + hydrogenfluxMapping + use math, only: & + math_I3 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out), dimension(3,3) :: & + Li !< thermal velocity gradient + real(pReal), intent(out), dimension(3,3,3,3) :: & + dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor) + integer(pInt) :: & + phase, & + instance, & + homog, offset + + phase = material_phase(ipc,ip,el) + instance = kinematics_hydrogen_strain_instance(phase) + homog = material_homog(ip,el) + offset = hydrogenfluxMapping(homog)%p(ip,el) + + Li = hydrogenConcRate(homog)%p(offset)* & + kinematics_hydrogen_strain_coeff(instance)* & + math_I3 + dLi_dTstar3333 = 0.0_pReal + +end subroutine kinematics_hydrogen_strain_LiAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the kinematic contribution to hydrogen chemical potential +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_hydrogen_strain_ChemPotAndItsTangent(ChemPot, dChemPot_dCh, Tstar_v, Fi0, Fi, ipc, ip, el) + use material, only: & + material_phase + use math, only: & + math_inv33, & + math_mul33x33, & + math_Mandel6to33, & + math_transpose33 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in), dimension(6) :: & + Tstar_v + real(pReal), intent(in), dimension(3,3) :: & + Fi0, Fi + real(pReal), intent(out) :: & + ChemPot, dChemPot_dCh + integer(pInt) :: & + phase, & + instance + + phase = material_phase(ipc,ip,el) + instance = kinematics_hydrogen_strain_instance(phase) + + ChemPot = -kinematics_hydrogen_strain_coeff(instance)* & + sum(math_mul33x33(Fi,math_Mandel6to33(Tstar_v))* & + math_mul33x33(math_mul33x33(Fi,math_inv33(Fi0)),Fi)) + dChemPot_dCh = 0.0_pReal + +end subroutine kinematics_hydrogen_strain_ChemPotAndItsTangent + +end module kinematics_hydrogen_strain diff --git a/code/kinematics_slipplane_opening.f90 b/code/kinematics_slipplane_opening.f90 new file mode 100644 index 000000000..59de2708b --- /dev/null +++ b/code/kinematics_slipplane_opening.f90 @@ -0,0 +1,325 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incorporating kinematics resulting from opening of slip planes +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module kinematics_slipplane_opening + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + kinematics_slipplane_opening_sizePostResults, & !< cumulative size of post results + kinematics_slipplane_opening_offset, & !< which kinematics is my current damage mechanism? + kinematics_slipplane_opening_instance !< instance of damage kinematics mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + kinematics_slipplane_opening_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + kinematics_slipplane_opening_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + kinematics_slipplane_opening_Noutput !< number of outputs per instance of this damage + + integer(pInt), dimension(:), allocatable, private :: & + kinematics_slipplane_opening_totalNslip !< total number of slip systems + + integer(pInt), dimension(:,:), allocatable, private :: & + kinematics_slipplane_opening_Nslip !< number of slip systems per family + + real(pReal), dimension(:), allocatable, private :: & + kinematics_slipplane_opening_sdot_0, & + kinematics_slipplane_opening_N + + real(pReal), dimension(:,:), allocatable, private :: & + kinematics_slipplane_opening_critPlasticStrain, & + kinematics_slipplane_opening_critLoad + + public :: & + kinematics_slipplane_opening_init, & + kinematics_slipplane_opening_LiAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_slipplane_opening_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_kinematics, & + phase_Nkinematics, & + phase_Noutput, & + KINEMATICS_slipplane_opening_label, & + KINEMATICS_slipplane_opening_ID, & + material_Nphase, & + MATERIAL_partPhase + use numerics,only: & + worldrank + use lattice, only: & + lattice_maxNslipFamily, & + lattice_NslipSystem + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,kinematics + integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_slipplane_opening_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_kinematics == KINEMATICS_slipplane_opening_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(kinematics_slipplane_opening_offset(material_Nphase), source=0_pInt) + allocate(kinematics_slipplane_opening_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + kinematics_slipplane_opening_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_slipplane_opening_ID) + do kinematics = 1, phase_Nkinematics(phase) + if (phase_kinematics(kinematics,phase) == kinematics_slipplane_opening_ID) & + kinematics_slipplane_opening_offset(phase) = kinematics + enddo + enddo + + allocate(kinematics_slipplane_opening_sizePostResults(maxNinstance), source=0_pInt) + allocate(kinematics_slipplane_opening_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(kinematics_slipplane_opening_output(maxval(phase_Noutput),maxNinstance)) + kinematics_slipplane_opening_output = '' + allocate(kinematics_slipplane_opening_Noutput(maxNinstance), source=0_pInt) + allocate(kinematics_slipplane_opening_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal) + allocate(kinematics_slipplane_opening_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal) + allocate(kinematics_slipplane_opening_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt) + allocate(kinematics_slipplane_opening_totalNslip(maxNinstance), source=0_pInt) + allocate(kinematics_slipplane_opening_N(maxNinstance), source=0.0_pReal) + allocate(kinematics_slipplane_opening_sdot_0(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_slipplane_opening_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = kinematics_slipplane_opening_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('nslip') ! + Nchunks_SlipFamilies = positions(1) - 1_pInt + do j = 1_pInt, Nchunks_SlipFamilies + kinematics_slipplane_opening_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j) + enddo + + case ('anisoductile_sdot0') + kinematics_slipplane_opening_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisoductile_criticalplasticstrain') + do j = 1_pInt, Nchunks_SlipFamilies + kinematics_slipplane_opening_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + case ('anisoductile_ratesensitivity') + kinematics_slipplane_opening_N(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisoductile_criticalload') + do j = 1_pInt, Nchunks_SlipFamilies + kinematics_slipplane_opening_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + end select + endif; endif + enddo parsingFile + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, material_Nphase + myPhase: if (any(phase_kinematics(:,phase) == KINEMATICS_slipplane_opening_ID)) then + instance = kinematics_slipplane_opening_instance(phase) + kinematics_slipplane_opening_Nslip(1:lattice_maxNslipFamily,instance) = & + min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested + kinematics_slipplane_opening_Nslip(1:lattice_maxNslipFamily,instance)) + kinematics_slipplane_opening_totalNslip(instance) = sum(kinematics_slipplane_opening_Nslip(:,instance)) + if (kinematics_slipplane_opening_sdot_0(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//KINEMATICS_slipplane_opening_LABEL//')') + if (any(kinematics_slipplane_opening_critPlasticStrain(:,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//KINEMATICS_slipplane_opening_LABEL//')') + if (kinematics_slipplane_opening_N(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//KINEMATICS_slipplane_opening_LABEL//')') + endif myPhase + enddo sanityChecks + + +end subroutine kinematics_slipplane_opening_init + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the constitutive equation for calculating the velocity gradient +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_slipplane_opening_LiAndItsTangent(Ld, dLd_dTstar3333, Tstar_v, ipc, ip, el) + use prec, only: & + tol_math_check + use lattice, only: & + lattice_maxNslipFamily, & + lattice_NslipSystem, & + lattice_sd, & + lattice_st, & + lattice_sn + use material, only: & + mappingConstitutive, & + material_homog, & + damage, & + damageMapping + use math, only: & + math_Plain3333to99, & + math_I3, & + math_identity4th, & + math_symmetric33, & + math_Mandel33to6, & + math_tensorproduct, & + math_det33, & + math_mul33x33 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in), dimension(6) :: & + Tstar_v !< 2nd Piola-Kirchhoff stress + real(pReal), intent(out), dimension(3,3) :: & + Ld !< damage velocity gradient + real(pReal), intent(out), dimension(3,3,3,3) :: & + dLd_dTstar3333 !< derivative of Ld with respect to Tstar (4th-order tensor) + real(pReal), dimension(3,3) :: & + projection_d, projection_t, projection_n !< projection modes 3x3 tensor + real(pReal), dimension(6) :: & + projection_d_v, projection_t_v, projection_n_v !< projection modes 3x3 vector + integer(pInt) :: & + phase, & + constituent, & + instance, & + homog, damageOffset, & + f, i, index_myFamily, k, l, m, n + real(pReal) :: & + traction_d, traction_t, traction_n, traction_crit, & + udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = kinematics_slipplane_opening_instance(phase) + homog = material_homog(ip,el) + damageOffset = damageMapping(homog)%p(ip,el) + + Ld = 0.0_pReal + dLd_dTstar3333 = 0.0_pReal + do f = 1_pInt,lattice_maxNslipFamily + index_myFamily = sum(lattice_NslipSystem(1:f-1_pInt,phase)) ! at which index starts my family + do i = 1_pInt,kinematics_slipplane_opening_Nslip(f,instance) ! process each (active) slip system in family + projection_d = math_tensorproduct(lattice_sd(1:3,index_myFamily+i,phase),& + lattice_sn(1:3,index_myFamily+i,phase)) + projection_t = math_tensorproduct(lattice_st(1:3,index_myFamily+i,phase),& + lattice_sn(1:3,index_myFamily+i,phase)) + projection_n = math_tensorproduct(lattice_sn(1:3,index_myFamily+i,phase),& + lattice_sn(1:3,index_myFamily+i,phase)) + + projection_d_v(1:6) = math_Mandel33to6(math_symmetric33(projection_d(1:3,1:3))) + projection_t_v(1:6) = math_Mandel33to6(math_symmetric33(projection_t(1:3,1:3))) + projection_n_v(1:6) = math_Mandel33to6(math_symmetric33(projection_n(1:3,1:3))) + + traction_d = dot_product(Tstar_v,projection_d_v(1:6)) + traction_t = dot_product(Tstar_v,projection_t_v(1:6)) + traction_n = dot_product(Tstar_v,projection_n_v(1:6)) + + traction_crit = kinematics_slipplane_opening_critLoad(f,instance)* & + damage(homog)%p(damageOffset) ! degrading critical load carrying capacity by damage + + udotd = & + sign(1.0_pReal,traction_d)* & + kinematics_slipplane_opening_sdot_0(instance)* & + (abs(traction_d)/traction_crit - & + abs(traction_d)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance) + if (abs(udotd) > tol_math_check) then + Ld = Ld + udotd*projection_d + dudotd_dt = udotd*kinematics_slipplane_opening_N(instance)/traction_d + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudotd_dt*projection_d(k,l)*projection_d(m,n) + endif + + udott = & + sign(1.0_pReal,traction_t)* & + kinematics_slipplane_opening_sdot_0(instance)* & + (abs(traction_t)/traction_crit - & + abs(traction_t)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance) + if (abs(udott) > tol_math_check) then + Ld = Ld + udott*projection_t + dudott_dt = udott*kinematics_slipplane_opening_N(instance)/traction_t + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudott_dt*projection_t(k,l)*projection_t(m,n) + endif + udotn = & + kinematics_slipplane_opening_sdot_0(instance)* & + (max(0.0_pReal,traction_n)/traction_crit - & + max(0.0_pReal,traction_n)/kinematics_slipplane_opening_critLoad(f,instance))**kinematics_slipplane_opening_N(instance) + if (abs(udotn) > tol_math_check) then + Ld = Ld + udotn*projection_n + dudotn_dt = udotn*kinematics_slipplane_opening_N(instance)/traction_n + forall (k=1_pInt:3_pInt,l=1_pInt:3_pInt,m=1_pInt:3_pInt,n=1_pInt:3_pInt) & + dLd_dTstar3333(k,l,m,n) = dLd_dTstar3333(k,l,m,n) + & + dudotn_dt*projection_n(k,l)*projection_n(m,n) + endif + enddo + enddo + +end subroutine kinematics_slipplane_opening_LiAndItsTangent + +end module kinematics_slipplane_opening diff --git a/code/kinematics_thermal_expansion.f90 b/code/kinematics_thermal_expansion.f90 new file mode 100644 index 000000000..f34b3abcb --- /dev/null +++ b/code/kinematics_thermal_expansion.f90 @@ -0,0 +1,182 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incorporating kinematics resulting from thermal expansion +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module kinematics_thermal_expansion + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + kinematics_thermal_expansion_sizePostResults, & !< cumulative size of post results + kinematics_thermal_expansion_offset, & !< which kinematics is my current damage mechanism? + kinematics_thermal_expansion_instance !< instance of damage kinematics mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + kinematics_thermal_expansion_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + kinematics_thermal_expansion_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + kinematics_thermal_expansion_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + kinematics_thermal_expansion_coeff + + public :: & + kinematics_thermal_expansion_init, & + kinematics_thermal_expansion_LiAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_thermal_expansion_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_kinematics, & + phase_Nkinematics, & + phase_Noutput, & + KINEMATICS_thermal_expansion_label, & + KINEMATICS_thermal_expansion_ID, & + material_Nphase, & + MATERIAL_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,kinematics + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_thermal_expansion_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_kinematics == KINEMATICS_thermal_expansion_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(kinematics_thermal_expansion_offset(material_Nphase), source=0_pInt) + allocate(kinematics_thermal_expansion_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + kinematics_thermal_expansion_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_thermal_expansion_ID) + do kinematics = 1, phase_Nkinematics(phase) + if (phase_kinematics(kinematics,phase) == kinematics_thermal_expansion_ID) & + kinematics_thermal_expansion_offset(phase) = kinematics + enddo + enddo + + allocate(kinematics_thermal_expansion_sizePostResults(maxNinstance), source=0_pInt) + allocate(kinematics_thermal_expansion_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(kinematics_thermal_expansion_output(maxval(phase_Noutput),maxNinstance)) + kinematics_thermal_expansion_output = '' + allocate(kinematics_thermal_expansion_Noutput(maxNinstance), source=0_pInt) + allocate(kinematics_thermal_expansion_coeff(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_thermal_expansion_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = kinematics_thermal_expansion_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('thermal_expansion_coeff') + kinematics_thermal_expansion_coeff(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + +end subroutine kinematics_thermal_expansion_init + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the constitutive equation for calculating the velocity gradient +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_thermal_expansion_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el) + use material, only: & + material_phase, & + material_homog, & + temperatureRate, & + thermalMapping + use math, only: & + math_I3 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out), dimension(3,3) :: & + Li !< thermal velocity gradient + real(pReal), intent(out), dimension(3,3,3,3) :: & + dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor) + integer(pInt) :: & + phase, & + instance, & + homog, offset + + phase = material_phase(ipc,ip,el) + instance = kinematics_thermal_expansion_instance(phase) + homog = material_homog(ip,el) + offset = thermalMapping(homog)%p(ip,el) + + Li = temperatureRate(homog)%p(offset)* & + kinematics_thermal_expansion_coeff(instance)* & + math_I3 + dLi_dTstar3333 = 0.0_pReal + +end subroutine kinematics_thermal_expansion_LiAndItsTangent + +end module kinematics_thermal_expansion diff --git a/code/kinematics_vacancy_strain.f90 b/code/kinematics_vacancy_strain.f90 new file mode 100644 index 000000000..403b1b730 --- /dev/null +++ b/code/kinematics_vacancy_strain.f90 @@ -0,0 +1,220 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incorporating kinematics resulting from vacancy point defects +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module kinematics_vacancy_strain + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + kinematics_vacancy_strain_sizePostResults, & !< cumulative size of post results + kinematics_vacancy_strain_offset, & !< which kinematics is my current damage mechanism? + kinematics_vacancy_strain_instance !< instance of damage kinematics mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + kinematics_vacancy_strain_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + kinematics_vacancy_strain_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + kinematics_vacancy_strain_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + kinematics_vacancy_strain_coeff + + public :: & + kinematics_vacancy_strain_init, & + kinematics_vacancy_strain_LiAndItsTangent, & + kinematics_vacancy_strain_ChemPotAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_vacancy_strain_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_kinematics, & + phase_Nkinematics, & + phase_Noutput, & + KINEMATICS_vacancy_strain_label, & + KINEMATICS_vacancy_strain_ID, & + material_Nphase, & + MATERIAL_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,kinematics + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_vacancy_strain_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_kinematics == KINEMATICS_vacancy_strain_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(kinematics_vacancy_strain_offset(material_Nphase), source=0_pInt) + allocate(kinematics_vacancy_strain_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + kinematics_vacancy_strain_instance(phase) = count(phase_kinematics(:,1:phase) == kinematics_vacancy_strain_ID) + do kinematics = 1, phase_Nkinematics(phase) + if (phase_kinematics(kinematics,phase) == kinematics_vacancy_strain_ID) & + kinematics_vacancy_strain_offset(phase) = kinematics + enddo + enddo + + allocate(kinematics_vacancy_strain_sizePostResults(maxNinstance), source=0_pInt) + allocate(kinematics_vacancy_strain_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(kinematics_vacancy_strain_output(maxval(phase_Noutput),maxNinstance)) + kinematics_vacancy_strain_output = '' + allocate(kinematics_vacancy_strain_Noutput(maxNinstance), source=0_pInt) + allocate(kinematics_vacancy_strain_coeff(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_kinematics(:,phase) == KINEMATICS_vacancy_strain_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = kinematics_vacancy_strain_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('vacancy_strain_coeff') + kinematics_vacancy_strain_coeff(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + +end subroutine kinematics_vacancy_strain_init + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the constitutive equation for calculating the velocity gradient +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_vacancy_strain_LiAndItsTangent(Li, dLi_dTstar3333, ipc, ip, el) + use material, only: & + material_phase, & + material_homog, & + vacancyConcRate, & + vacancyfluxMapping + use math, only: & + math_I3 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out), dimension(3,3) :: & + Li !< thermal velocity gradient + real(pReal), intent(out), dimension(3,3,3,3) :: & + dLi_dTstar3333 !< derivative of Li with respect to Tstar (4th-order tensor) + integer(pInt) :: & + phase, & + instance, & + homog, offset + + phase = material_phase(ipc,ip,el) + instance = kinematics_vacancy_strain_instance(phase) + homog = material_homog(ip,el) + offset = vacancyfluxMapping(homog)%p(ip,el) + + Li = vacancyConcRate(homog)%p(offset)* & + kinematics_vacancy_strain_coeff(instance)* & + math_I3 + dLi_dTstar3333 = 0.0_pReal + +end subroutine kinematics_vacancy_strain_LiAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief contains the kinematic contribution to vacancy chemical potential +!-------------------------------------------------------------------------------------------------- +subroutine kinematics_vacancy_strain_ChemPotAndItsTangent(ChemPot, dChemPot_dCv, Tstar_v, Fi0, Fi, ipc, ip, el) + use material, only: & + material_phase + use math, only: & + math_inv33, & + math_mul33x33, & + math_Mandel6to33, & + math_transpose33 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in), dimension(6) :: & + Tstar_v + real(pReal), intent(in), dimension(3,3) :: & + Fi0, Fi + real(pReal), intent(out) :: & + ChemPot, dChemPot_dCv + integer(pInt) :: & + phase, & + instance + + phase = material_phase(ipc,ip,el) + instance = kinematics_vacancy_strain_instance(phase) + + ChemPot = -kinematics_vacancy_strain_coeff(instance)* & + sum(math_mul33x33(Fi,math_Mandel6to33(Tstar_v))* & + math_mul33x33(math_mul33x33(Fi,math_inv33(Fi0)),Fi)) + dChemPot_dCv = 0.0_pReal + +end subroutine kinematics_vacancy_strain_ChemPotAndItsTangent + +end module kinematics_vacancy_strain diff --git a/code/lattice.f90 b/code/lattice.f90 index bb3c9a3df..93ca65e8e 100644 --- a/code/lattice.f90 +++ b/code/lattice.f90 @@ -833,12 +833,18 @@ module lattice lattice_thermalConductivity33, & lattice_thermalExpansion33, & lattice_damageDiffusion33, & - lattice_vacancyDiffusion33 + lattice_vacancyfluxDiffusion33, & + lattice_vacancyfluxMobility33, & + lattice_porosityDiffusion33, & + lattice_hydrogenfluxDiffusion33, & + lattice_hydrogenfluxMobility33 real(pReal), dimension(:), allocatable, public, protected :: & lattice_damageMobility, & - lattice_vacancyMobility, & + lattice_porosityMobility, & lattice_massDensity, & lattice_specificHeat, & + lattice_vacancyVol, & + lattice_hydrogenVol, & lattice_referenceTemperature, & lattice_equilibriumVacancyConcentration enum, bind(c) @@ -1101,15 +1107,21 @@ subroutine lattice_init allocate(lattice_structure(Nphases),source = LATTICE_undefined_ID) allocate(lattice_C66(6,6,Nphases), source=0.0_pReal) allocate(lattice_C3333(3,3,3,3,Nphases), source=0.0_pReal) - allocate(lattice_thermalConductivity33(3,3,Nphases), source=0.0_pReal) - allocate(lattice_thermalExpansion33 (3,3,Nphases), source=0.0_pReal) - allocate(lattice_damageDiffusion33 (3,3,Nphases), source=0.0_pReal) - allocate(lattice_vacancyDiffusion33 (3,3,Nphases), source=0.0_pReal) - allocate(lattice_damageMobility ( Nphases), source=0.0_pReal) - allocate(lattice_vacancyMobility ( Nphases), source=0.0_pReal) - allocate(lattice_massDensity ( Nphases), source=0.0_pReal) - allocate(lattice_specificHeat ( Nphases), source=0.0_pReal) - allocate(lattice_referenceTemperature ( Nphases), source=0.0_pReal) + allocate(lattice_thermalConductivity33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_thermalExpansion33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_damageDiffusion33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_vacancyfluxDiffusion33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_vacancyfluxMobility33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_PorosityDiffusion33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_hydrogenfluxDiffusion33(3,3,Nphases), source=0.0_pReal) + allocate(lattice_hydrogenfluxMobility33 (3,3,Nphases), source=0.0_pReal) + allocate(lattice_damageMobility ( Nphases), source=0.0_pReal) + allocate(lattice_PorosityMobility ( Nphases), source=0.0_pReal) + allocate(lattice_massDensity ( Nphases), source=0.0_pReal) + allocate(lattice_specificHeat ( Nphases), source=0.0_pReal) + allocate(lattice_vacancyVol ( Nphases), source=0.0_pReal) + allocate(lattice_hydrogenVol ( Nphases), source=0.0_pReal) + allocate(lattice_referenceTemperature ( Nphases), source=0.0_pReal) allocate(lattice_equilibriumVacancyConcentration(Nphases), source=0.0_pReal) allocate(lattice_mu(Nphases), source=0.0_pReal) @@ -1232,6 +1244,10 @@ subroutine lattice_init lattice_thermalExpansion33(3,3,section) = IO_floatValue(line,positions,2_pInt) case ('specific_heat') lattice_specificHeat(section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyvolume') + lattice_vacancyVol(section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenvolume') + lattice_hydrogenVol(section) = IO_floatValue(line,positions,2_pInt) case ('mass_density') lattice_massDensity(section) = IO_floatValue(line,positions,2_pInt) case ('reference_temperature') @@ -1244,14 +1260,38 @@ subroutine lattice_init lattice_DamageDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) case ('damage_mobility') lattice_DamageMobility(section) = IO_floatValue(line,positions,2_pInt) - case ('vacancy_diffusion11') - lattice_VacancyDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt) - case ('vacancy_diffusion22') - lattice_VacancyDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt) - case ('vacancy_diffusion33') - lattice_VacancyDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) - case ('vacancy_mobility') - lattice_VacancyMobility(section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_diffusion11') + lattice_vacancyfluxDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_diffusion22') + lattice_vacancyfluxDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_diffusion33') + lattice_vacancyfluxDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_mobility11') + lattice_vacancyfluxMobility33(1,1,section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_mobility22') + lattice_vacancyfluxMobility33(2,2,section) = IO_floatValue(line,positions,2_pInt) + case ('vacancyflux_mobility33') + lattice_vacancyfluxMobility33(3,3,section) = IO_floatValue(line,positions,2_pInt) + case ('porosity_diffusion11') + lattice_PorosityDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt) + case ('porosity_diffusion22') + lattice_PorosityDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt) + case ('porosity_diffusion33') + lattice_PorosityDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) + case ('porosity_mobility') + lattice_PorosityMobility(section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_diffusion11') + lattice_hydrogenfluxDiffusion33(1,1,section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_diffusion22') + lattice_hydrogenfluxDiffusion33(2,2,section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_diffusion33') + lattice_hydrogenfluxDiffusion33(3,3,section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_mobility11') + lattice_hydrogenfluxMobility33(1,1,section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_mobility22') + lattice_hydrogenfluxMobility33(2,2,section) = IO_floatValue(line,positions,2_pInt) + case ('hydrogenflux_mobility33') + lattice_hydrogenfluxMobility33(3,3,section) = IO_floatValue(line,positions,2_pInt) case ('vacancy_eqcv') lattice_equilibriumVacancyConcentration(section) = IO_floatValue(line,positions,2_pInt) end select @@ -1322,7 +1362,7 @@ subroutine lattice_initializeStructure(myPhase,CoverA,aA,aM,cM) cd, cn, ct integer(pInt) :: & i,j, & - myNslip, myNtwin, myNtrans, myNcleavage + myNslip = 0_pInt, myNtwin = 0_pInt, myNtrans = 0_pInt, myNcleavage = 0_pInt lattice_C66(1:6,1:6,myPhase) = lattice_symmetrizeC66(lattice_structure(myPhase),& lattice_C66(1:6,1:6,myPhase)) @@ -1347,8 +1387,16 @@ subroutine lattice_initializeStructure(myPhase,CoverA,aA,aM,cM) lattice_thermalExpansion33(1:3,1:3,myPhase)) lattice_DamageDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& lattice_DamageDiffusion33(1:3,1:3,myPhase)) - lattice_VacancyDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& - lattice_VacancyDiffusion33(1:3,1:3,myPhase)) + lattice_vacancyfluxDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& + lattice_vacancyfluxDiffusion33(1:3,1:3,myPhase)) + lattice_vacancyfluxMobility33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& + lattice_vacancyfluxMobility33(1:3,1:3,myPhase)) + lattice_PorosityDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& + lattice_PorosityDiffusion33(1:3,1:3,myPhase)) + lattice_hydrogenfluxDiffusion33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& + lattice_hydrogenfluxDiffusion33(1:3,1:3,myPhase)) + lattice_hydrogenfluxMobility33(1:3,1:3,myPhase) = lattice_symmetrize33(lattice_structure(myPhase),& + lattice_hydrogenfluxMobility33(1:3,1:3,myPhase)) select case(lattice_structure(myPhase)) !-------------------------------------------------------------------------------------------------- diff --git a/code/material.f90 b/code/material.f90 index 1d7a8eb2d..a00873cac 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -14,41 +14,55 @@ module material pInt, & tState, & tPlasticState, & - tFieldData, & + tSourceState, & + tHomogMapping, & + tPhaseMapping, & + p_vec, & p_intvec implicit none private character(len=*), parameter, public :: & - ELASTICITY_hooke_label = 'hooke', & - PLASTICITY_none_label = 'none', & - PLASTICITY_j2_label = 'j2', & - PLASTICITY_phenopowerlaw_label = 'phenopowerlaw', & - PLASTICITY_dislotwin_label = 'dislotwin', & - PLASTICITY_dislokmc_label = 'dislokmc', & - PLASTICITY_disloucla_label = 'disloucla', & - PLASTICITY_titanmod_label = 'titanmod', & - PLASTICITY_nonlocal_label = 'nonlocal', & - LOCAL_DAMAGE_none_LABEL = 'none', & - LOCAL_DAMAGE_isoBrittle_LABEL = 'isobrittle', & - LOCAL_DAMAGE_isoDuctile_LABEL = 'isoductile', & - LOCAL_DAMAGE_anisoBrittle_LABEL= 'anisobrittle', & - LOCAL_DAMAGE_anisoDuctile_LABEL= 'anisoductile', & - LOCAL_DAMAGE_gurson_LABEL = 'gurson', & - LOCAL_DAMAGE_phaseField_LABEL = 'phasefield', & - LOCAL_THERMAL_isothermal_label = 'isothermal', & - LOCAL_THERMAL_adiabatic_label = 'adiabatic', & - LOCAL_VACANCY_constant_label = 'constant', & - LOCAL_VACANCY_generation_label = 'generation', & - FIELD_DAMAGE_local_label = 'local', & - FIELD_DAMAGE_nonlocal_label = 'nonlocal', & - FIELD_THERMAL_local_label = 'local', & - FIELD_THERMAL_nonlocal_label = 'nonlocal', & - FIELD_VACANCY_local_label = 'local', & - FIELD_VACANCY_nonlocal_label = 'nonlocal', & - HOMOGENIZATION_none_label = 'none', & - HOMOGENIZATION_isostrain_label = 'isostrain', & - HOMOGENIZATION_rgc_label = 'rgc' + ELASTICITY_hooke_label = 'hooke', & + PLASTICITY_none_label = 'none', & + PLASTICITY_j2_label = 'j2', & + PLASTICITY_phenopowerlaw_label = 'phenopowerlaw', & + PLASTICITY_dislotwin_label = 'dislo&twin', & + PLASTICITY_dislokmc_label = 'dislokmc', & + PLASTICITY_disloucla_label = 'disloucla', & + PLASTICITY_titanmod_label = 'titanmod', & + PLASTICITY_nonlocal_label = 'nonlocal', & + SOURCE_thermal_dissipation_label = 'thermal_dissipation', & + SOURCE_damage_isoBrittle_label = 'damage_isobrittle', & + SOURCE_damage_isoDuctile_label = 'damage_isoductile', & + SOURCE_damage_anisoBrittle_label = 'damage_anisobrittle', & + SOURCE_damage_anisoDuctile_label = 'damage_anisoductile', & + SOURCE_vacancy_phenoplasticity_label = 'vacancy_phenoplasticity', & + SOURCE_vacancy_irradiation_label = 'vacancy_irradiation', & + SOURCE_vacancy_thermalfluc_label = 'vacancy_thermalfluctuation', & + KINEMATICS_thermal_expansion_label = 'thermal_expansion', & + KINEMATICS_cleavage_opening_label = 'cleavage_opening', & + KINEMATICS_slipplane_opening_label = 'slipplane_opening', & + KINEMATICS_vacancy_strain_label = 'vacancy_strain', & + KINEMATICS_hydrogen_strain_label = 'hydrogen_strain', & + STIFFNESS_DEGRADATION_damage_label = 'damage', & + STIFFNESS_DEGRADATION_porosity_label = 'porosity', & + THERMAL_isothermal_label = 'isothermal', & + THERMAL_adiabatic_label = 'adiabatic', & + THERMAL_conduction_label = 'conduction', & + DAMAGE_none_label = 'none', & + DAMAGE_local_label = 'local', & + DAMAGE_nonlocal_label = 'nonlocal', & + VACANCYFLUX_isoconc_label = 'isoconcentration', & + VACANCYFLUX_isochempot_label = 'isochemicalpotential', & + VACANCYFLUX_cahnhilliard_label = 'cahnhilliard', & + POROSITY_none_label = 'none', & + POROSITY_phasefield_label = 'phasefield', & + HYDROGENFLUX_isoconc_label = 'isoconcentration', & + HYDROGENFLUX_cahnhilliard_label = 'cahnhilliard', & + HOMOGENIZATION_none_label = 'none', & + HOMOGENIZATION_isostrain_label = 'isostrain', & + HOMOGENIZATION_rgc_label = 'rgc' @@ -67,37 +81,61 @@ module material PLASTICITY_titanmod_ID, & PLASTICITY_nonlocal_ID end enum + enum, bind(c) - enumerator :: LOCAL_DAMAGE_none_ID, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID - end enum - enum, bind(c) - enumerator :: LOCAL_THERMAL_isothermal_ID, & - LOCAL_THERMAL_adiabatic_ID - end enum - enum, bind(c) - enumerator :: LOCAL_VACANCY_constant_ID, & - LOCAL_VACANCY_generation_ID + enumerator :: SOURCE_undefined_ID, & + SOURCE_thermal_dissipation_ID, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID, & + SOURCE_vacancy_phenoplasticity_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID end enum enum, bind(c) - enumerator :: FIELD_DAMAGE_local_ID ,& - FIELD_DAMAGE_nonlocal_ID - + enumerator :: KINEMATICS_undefined_ID, & + KINEMATICS_cleavage_opening_ID, & + KINEMATICS_slipplane_opening_ID, & + KINEMATICS_thermal_expansion_ID, & + KINEMATICS_vacancy_strain_ID, & + KINEMATICS_hydrogen_strain_ID + end enum + + enum, bind(c) + enumerator :: STIFFNESS_DEGRADATION_undefined_ID, & + STIFFNESS_DEGRADATION_damage_ID, & + STIFFNESS_DEGRADATION_porosity_ID + end enum + + enum, bind(c) + enumerator :: THERMAL_isothermal_ID, & + THERMAL_adiabatic_ID, & + THERMAL_conduction_ID + end enum + + enum, bind(c) + enumerator :: DAMAGE_none_ID, & + DAMAGE_local_ID, & + DAMAGE_nonlocal_ID + end enum + + enum, bind(c) + enumerator :: VACANCYFLUX_isoconc_ID, & + VACANCYFLUX_isochempot_ID, & + VACANCYFLUX_cahnhilliard_ID + end enum + + enum, bind(c) + enumerator :: POROSITY_none_ID, & + POROSITY_phasefield_ID end enum enum, bind(c) - enumerator :: FIELD_THERMAL_local_ID, & - FIELD_THERMAL_nonlocal_ID - end enum - enum, bind(c) - enumerator :: FIELD_VACANCY_local_ID, & - FIELD_VACANCY_nonlocal_ID + enumerator :: HYDROGENFLUX_isoconc_ID, & + HYDROGENFLUX_cahnhilliard_ID end enum + enum, bind(c) enumerator :: HOMOGENIZATION_undefined_ID, & HOMOGENIZATION_none_ID, & @@ -118,18 +156,21 @@ module material phase_elasticity !< elasticity of each phase integer(kind(PLASTICITY_undefined_ID)), dimension(:), allocatable, public, protected :: & phase_plasticity !< plasticity of each phase - integer(kind(LOCAL_DAMAGE_none_ID)), dimension(:), allocatable, public, protected :: & - phase_damage !< local damage of each phase - integer(kind(LOCAL_THERMAL_isothermal_ID)), dimension(:), allocatable, public, protected :: & - phase_thermal !< local thermal of each phase - integer(kind(LOCAL_VACANCY_constant_ID)), dimension(:), allocatable, public, protected :: & - phase_vacancy !< local vacancy model of each phase - integer(kind(FIELD_DAMAGE_local_ID)), dimension(:), allocatable, public, protected :: & - field_damage_type !< field damage of each phase - integer(kind(FIELD_THERMAL_local_ID)), dimension(:), allocatable, public, protected :: & - field_thermal_type !< field thermal of each phase - integer(kind(FIELD_VACANCY_local_ID)), dimension(:), allocatable, public, protected :: & - field_vacancy_type !< field vacancy of each phase + integer(kind(THERMAL_isothermal_ID)), dimension(:), allocatable, public, protected :: & + thermal_type !< thermal transport model + integer(kind(DAMAGE_none_ID)), dimension(:), allocatable, public, protected :: & + damage_type !< nonlocal damage model + integer(kind(VACANCYFLUX_isoconc_ID)), dimension(:), allocatable, public, protected :: & + vacancyflux_type !< vacancy transport model + integer(kind(POROSITY_none_ID)), dimension(:), allocatable, public, protected :: & + porosity_type !< porosity evolution model + integer(kind(HYDROGENFLUX_isoconc_ID)), dimension(:), allocatable, public, protected :: & + hydrogenflux_type !< hydrogen transport model + + integer(kind(SOURCE_undefined_ID)), dimension(:,:), allocatable, public, protected :: & + phase_source, & !< active sources mechanisms of each phase + phase_kinematics, & !< active kinematic mechanisms of each phase + phase_stiffnessDegradation !< active stiffness degradation mechanisms of each phase integer(kind(HOMOGENIZATION_undefined_ID)), dimension(:), allocatable, public, protected :: & homogenization_type !< type of each homogenization @@ -146,17 +187,24 @@ module material material_Nmicrostructure, & !< number of microstructures material_Ncrystallite !< number of crystallite settings + integer(pInt), dimension(:), allocatable, public, protected :: & + phase_Nsources, & !< number of source mechanisms active in each phase + phase_Nkinematics, & !< number of kinematic mechanisms active in each phase + phase_NstiffnessDegradations !< number of stiffness degradation mechanisms active in each phase + integer(pInt), dimension(:), allocatable, public, protected :: & homogenization_Ngrains, & !< number of grains in each homogenization homogenization_Noutput, & !< number of '(output)' items per homogenization phase_Noutput, & !< number of '(output)' items per phase phase_elasticityInstance, & !< instance of particular elasticity of each phase phase_plasticityInstance, & !< instance of particular plasticity of each phase - phase_damageInstance, & !< instance of particular damage of each phase - phase_thermalInstance, & !< instance of particular thermal of each phase - phase_vacancyInstance, & !< instance of particular vacancy model of each phase crystallite_Noutput, & !< number of '(output)' items per crystallite setting homogenization_typeInstance, & !< instance of particular type of each homogenization + thermal_typeInstance, & !< instance of particular type of each thermal transport + damage_typeInstance, & !< instance of particular type of each nonlocal damage + vacancyflux_typeInstance, & !< instance of particular type of each vacancy flux + porosity_typeInstance, & !< instance of particular type of each porosity model + hydrogenflux_typeInstance, & !< instance of particular type of each hydrogen flux microstructure_crystallite !< crystallite setting ID of each microstructure integer(pInt), dimension(:,:,:), allocatable, public :: & @@ -165,19 +213,15 @@ module material material_homog !< homogenization (index) of each IP,element type(tPlasticState), allocatable, dimension(:), public :: & plasticState - type(tState), allocatable, dimension(:), public :: & + type(tSourceState), allocatable, dimension(:), public :: & + sourceState + type(tState), allocatable, dimension(:), public :: & + homogState, & + thermalState, & damageState, & - thermalState,& - vacancyState,& - homogState - - type(tFieldData), allocatable, dimension(:), public :: & - fieldDamage - type(tFieldData), allocatable, dimension(:), public :: & - fieldThermal - type(tFieldData), allocatable, dimension(:), public :: & - fieldVacancy - + vacancyfluxState, & + porosityState, & + hydrogenfluxState integer(pInt), dimension(:,:,:), allocatable, public, protected :: & material_texture !< texture (index) of each grain,IP,element @@ -230,9 +274,27 @@ module material logical, dimension(:), allocatable, private :: & homogenization_active - integer(pInt), dimension(:,:,:,:), allocatable, public, protected :: mappingConstitutive - integer(pInt), dimension(:,:,:), allocatable, public, protected :: mappingCrystallite - integer(pInt), dimension(:,:,:), allocatable, public, protected :: mappingHomogenization + integer(pInt), dimension(:,:,:,:), allocatable, public, target :: mappingConstitutive + integer(pInt), dimension(:,:,:), allocatable, public, target :: mappingCrystallite + integer(pInt), dimension(:,:,:), allocatable, public, target :: mappingHomogenization !< mapping from material points to offset in heterogenous state/field + integer(pInt), dimension(:,:), allocatable, public, target :: mappingHomogenizationConst !< mapping from material points to offset in constant state/field + + type(tHomogMapping), allocatable, dimension(:), public :: & + thermalMapping, & !< mapping for thermal state/fields + damageMapping, & !< mapping for damage state/fields + vacancyfluxMapping, & !< mapping for vacancy conc state/fields + porosityMapping, & !< mapping for porosity state/fields + hydrogenfluxMapping !< mapping for hydrogen conc state/fields + + type(p_vec), allocatable, dimension(:), public :: & + temperature, & !< temperature field + damage, & !< damage field + vacancyConc, & !< vacancy conc field + porosity, & !< porosity field + hydrogenConc, & !< hydrogen conc field + temperatureRate, & !< temperature change rate field + vacancyConcRate, & !< vacancy conc change field + hydrogenConcRate !< hydrogen conc change field public :: & material_init, & @@ -245,23 +307,34 @@ module material PLASTICITY_disloucla_ID, & PLASTICITY_titanmod_ID, & PLASTICITY_nonlocal_ID, & - LOCAL_DAMAGE_none_ID, & - LOCAL_DAMAGE_isoBrittle_ID, & - LOCAL_DAMAGE_isoDuctile_ID, & - LOCAL_DAMAGE_anisoBrittle_ID, & - LOCAL_DAMAGE_anisoDuctile_ID, & - LOCAL_DAMAGE_gurson_ID, & - LOCAL_DAMAGE_phaseField_ID, & - LOCAL_THERMAL_isothermal_ID, & - LOCAL_THERMAL_adiabatic_ID, & - LOCAL_VACANCY_constant_ID, & - LOCAL_VACANCY_generation_ID, & - FIELD_DAMAGE_local_ID, & - FIELD_DAMAGE_nonlocal_ID, & - FIELD_THERMAL_local_ID, & - FIELD_THERMAL_nonlocal_ID, & - FIELD_VACANCY_local_ID, & - FIELD_VACANCY_nonlocal_ID, & + SOURCE_thermal_dissipation_ID, & + SOURCE_damage_isoBrittle_ID, & + SOURCE_damage_isoDuctile_ID, & + SOURCE_damage_anisoBrittle_ID, & + SOURCE_damage_anisoDuctile_ID, & + SOURCE_vacancy_phenoplasticity_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID, & + KINEMATICS_cleavage_opening_ID, & + KINEMATICS_slipplane_opening_ID, & + KINEMATICS_thermal_expansion_ID, & + KINEMATICS_vacancy_strain_ID, & + KINEMATICS_hydrogen_strain_ID, & + STIFFNESS_DEGRADATION_damage_ID, & + STIFFNESS_DEGRADATION_porosity_ID, & + THERMAL_isothermal_ID, & + THERMAL_adiabatic_ID, & + THERMAL_conduction_ID, & + DAMAGE_none_ID, & + DAMAGE_local_ID, & + DAMAGE_nonlocal_ID, & + VACANCYFLUX_isoconc_ID, & + VACANCYFLUX_isochempot_ID, & + VACANCYFLUX_cahnhilliard_ID, & + POROSITY_none_ID, & + POROSITY_phasefield_ID, & + HYDROGENFLUX_isoconc_ID, & + HYDROGENFLUX_cahnhilliard_ID, & HOMOGENIZATION_none_ID, & HOMOGENIZATION_isostrain_ID, & #ifdef HDF @@ -285,7 +358,7 @@ contains !> @details figures out if solverJobName.materialConfig is present, if not looks for !> material.config !-------------------------------------------------------------------------------------------------- -subroutine material_init(temperature_init) +subroutine material_init() use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) use IO, only: & IO_error, & @@ -307,16 +380,13 @@ subroutine material_init(temperature_init) worldrank implicit none - real(pReal), intent(in) :: temperature_init !< initial field temperature integer(pInt), parameter :: FILEUNIT = 200_pInt - integer(pInt) :: m,c,h, myDebug, myHomog + integer(pInt) :: m,c,h, myDebug, myPhase, myHomog integer(pInt) :: & g, & !< grain number i, & !< integration point number e, & !< element number - phase, & - homog, & - NofMyField + phase integer(pInt), dimension(:), allocatable :: ConstitutivePosition integer(pInt), dimension(:), allocatable :: CrystallitePosition integer(pInt), dimension(:), allocatable :: HomogenizationPosition @@ -344,14 +414,35 @@ subroutine material_init(temperature_init) if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6) close(FILEUNIT) - allocate(plasticState(material_Nphase)) - allocate(damageState (material_Nphase)) - allocate(thermalState(material_Nphase)) - allocate(vacancyState(material_Nphase)) - allocate(homogState (material_Nhomogenization)) - allocate(fieldDamage (material_Nhomogenization)) - allocate(fieldThermal(material_Nhomogenization)) - allocate(fieldVacancy(material_Nhomogenization)) + allocate(plasticState (material_Nphase)) + allocate(sourceState (material_Nphase)) + do myPhase = 1,material_Nphase + allocate(sourceState(myPhase)%p(phase_Nsources(myPhase))) + enddo + + allocate(homogState (material_Nhomogenization)) + allocate(thermalState (material_Nhomogenization)) + allocate(damageState (material_Nhomogenization)) + allocate(vacancyfluxState (material_Nhomogenization)) + allocate(porosityState (material_Nhomogenization)) + allocate(hydrogenfluxState (material_Nhomogenization)) + + allocate(thermalMapping (material_Nhomogenization)) + allocate(damageMapping (material_Nhomogenization)) + allocate(vacancyfluxMapping (material_Nhomogenization)) + allocate(porosityMapping (material_Nhomogenization)) + allocate(hydrogenfluxMapping(material_Nhomogenization)) + + allocate(temperature (material_Nhomogenization)) + allocate(damage (material_Nhomogenization)) + allocate(vacancyConc (material_Nhomogenization)) + allocate(porosity (material_Nhomogenization)) + allocate(hydrogenConc (material_Nhomogenization)) + + allocate(temperatureRate (material_Nhomogenization)) + allocate(vacancyConcRate (material_Nhomogenization)) + allocate(hydrogenConcRate (material_Nhomogenization)) + do m = 1_pInt,material_Nmicrostructure if(microstructure_crystallite(m) < 1_pInt .or. & microstructure_crystallite(m) > material_Ncrystallite) & @@ -365,6 +456,7 @@ subroutine material_init(temperature_init) if(microstructure_Nconstituents(m) < 1_pInt) & call IO_error(151_pInt,m) enddo + debugOut: if (iand(myDebug,debug_levelExtensive) /= 0_pInt) then write(6,'(/,a,/)') ' MATERIAL configuration' write(6,'(a32,1x,a16,1x,a6)') 'homogenization ','type ','grains' @@ -390,14 +482,14 @@ subroutine material_init(temperature_init) call material_populateGrains - allocate(mappingConstitutive(2,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems),source=0_pInt) - allocate(mappingHomogenization(2,mesh_maxNips,mesh_NcpElems),source=0_pInt) - - allocate(mappingCrystallite (2,homogenization_maxNgrains,mesh_NcpElems),source=0_pInt) - allocate(ConstitutivePosition(material_Nphase),source=0_pInt) - + allocate(mappingConstitutive (2,homogenization_maxNgrains,mesh_maxNips,mesh_NcpElems),source=0_pInt) + allocate(mappingHomogenization (2, mesh_maxNips,mesh_NcpElems),source=0_pInt) + allocate(mappingCrystallite (2,homogenization_maxNgrains, mesh_NcpElems),source=0_pInt) + allocate(mappingHomogenizationConst( mesh_maxNips,mesh_NcpElems),source=1_pInt) + + allocate(ConstitutivePosition (material_Nphase), source=0_pInt) allocate(HomogenizationPosition(material_Nhomogenization),source=0_pInt) - allocate(CrystallitePosition(material_Nphase),source=0_pInt) + allocate(CrystallitePosition (material_Nphase), source=0_pInt) ElemLoop:do e = 1_pInt,mesh_NcpElems ! loop over elements myHomog = mesh_element(3,e) @@ -412,57 +504,23 @@ subroutine material_init(temperature_init) enddo IPloop enddo ElemLoop - do homog = 1,material_Nhomogenization - NofMyField=count(material_homog==homog) - select case(field_damage_type(homog)) - case (FIELD_DAMAGE_LOCAL_ID) - fieldDamage(homog)%sizeField = 0_pInt - fieldDamage(homog)%sizePostResults = 0_pInt - allocate(fieldDamage(homog)%field(fieldDamage(homog)%sizeField,NofMyField), source = 1.0_pReal) - - case (FIELD_DAMAGE_NONLOCAL_ID) - fieldDamage(homog)%sizeField = 1_pInt - fieldDamage(homog)%sizePostResults = 1_pInt - allocate(fieldDamage(homog)%field(fieldDamage(homog)%sizeField,NofMyField), source = 1.0_pReal) - - end select +! hack needed to initialize field values used during constitutive and crystallite initializations + do myHomog = 1,material_Nhomogenization + thermalMapping (myHomog)%p => mappingHomogenizationConst + damageMapping (myHomog)%p => mappingHomogenizationConst + vacancyfluxMapping (myHomog)%p => mappingHomogenizationConst + porosityMapping (myHomog)%p => mappingHomogenizationConst + hydrogenfluxMapping(myHomog)%p => mappingHomogenizationConst + allocate(temperature (myHomog)%p(1), source=300.0_pReal) + allocate(damage (myHomog)%p(1), source=1.0_pReal) + allocate(vacancyConc (myHomog)%p(1), source=0.0_pReal) + allocate(porosity (myHomog)%p(1), source=1.0_pReal) + allocate(hydrogenConc (myHomog)%p(1), source=0.0_pReal) + allocate(temperatureRate (myHomog)%p(1), source=0.0_pReal) + allocate(vacancyConcRate (myHomog)%p(1), source=0.0_pReal) + allocate(hydrogenConcRate(myHomog)%p(1), source=0.0_pReal) enddo - do homog = 1,material_Nhomogenization - NofMyField=count(material_homog==homog) - select case(field_thermal_type(homog)) - case (FIELD_THERMAL_local_ID) - fieldThermal(homog)%sizeField = 0_pInt - fieldThermal(homog)%sizePostResults = 0_pInt - allocate(fieldThermal(homog)%field(fieldThermal(homog)%sizeField,NofMyField)) - - case (FIELD_THERMAL_nonlocal_ID) - fieldThermal(homog)%sizeField = 1_pInt - fieldThermal(homog)%sizePostResults = 1_pInt - allocate(fieldThermal(homog)%field(fieldThermal(homog)%sizeField,NofMyField), & - source = temperature_init) - - end select - enddo - - do homog = 1,material_Nhomogenization - NofMyField=count(material_homog==homog) - select case(field_vacancy_type(homog)) - case (FIELD_VACANCY_local_ID) - fieldVacancy(homog)%sizeField = 0_pInt - fieldVacancy(homog)%sizePostResults = 0_pInt - allocate(fieldVacancy(homog)%field(fieldVacancy(homog)%sizeField,NofMyField), & - source = 0.0_pReal) - - case (FIELD_VACANCY_nonlocal_ID) - fieldVacancy(homog)%sizeField = 1_pInt - fieldVacancy(homog)%sizePostResults = 1_pInt - allocate(fieldVacancy(homog)%field(fieldVacancy(homog)%sizeField,NofMyField), & - source = 0.0_pReal) - - end select - enddo - end subroutine material_init @@ -493,7 +551,7 @@ subroutine material_parseHomogenization(fileUnit,myPart) integer(pInt), parameter :: MAXNCHUNKS = 2_pInt integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: Nsections, section, s + integer(pInt) :: Nsections, section, s, p character(len=65536) :: & tag, line logical :: echo @@ -504,11 +562,18 @@ subroutine material_parseHomogenization(fileUnit,myPart) if (Nsections < 1_pInt) call IO_error(160_pInt,ext_msg=myPart) allocate(homogenization_name(Nsections)); homogenization_name = '' - allocate(homogenization_type(Nsections), source=HOMOGENIZATION_undefined_ID) - allocate(FIELD_DAMAGE_type(Nsections), source=FIELD_DAMAGE_local_ID) - allocate(FIELD_THERMAL_type(Nsections), source=FIELD_THERMAL_local_ID) - allocate(FIELD_VACANCY_type(Nsections), source=FIELD_VACANCY_local_ID) + allocate(homogenization_type(Nsections), source=HOMOGENIZATION_undefined_ID) + allocate(thermal_type(Nsections), source=THERMAL_isothermal_ID) + allocate(damage_type (Nsections), source=DAMAGE_none_ID) + allocate(vacancyflux_type(Nsections), source=VACANCYFLUX_isoconc_ID) + allocate(porosity_type (Nsections), source=POROSITY_none_ID) + allocate(hydrogenflux_type(Nsections), source=HYDROGENFLUX_isoconc_ID) allocate(homogenization_typeInstance(Nsections), source=0_pInt) + allocate(thermal_typeInstance(Nsections), source=0_pInt) + allocate(damage_typeInstance(Nsections), source=0_pInt) + allocate(vacancyflux_typeInstance(Nsections), source=0_pInt) + allocate(porosity_typeInstance(Nsections), source=0_pInt) + allocate(hydrogenflux_typeInstance(Nsections), source=0_pInt) allocate(homogenization_Ngrains(Nsections), source=0_pInt) allocate(homogenization_Noutput(Nsections), source=0_pInt) allocate(homogenization_active(Nsections), source=.false.) !!!!!!!!!!!!!!! @@ -554,32 +619,58 @@ subroutine material_parseHomogenization(fileUnit,myPart) end select homogenization_typeInstance(section) = & count(homogenization_type==homogenization_type(section)) ! count instances - case ('field_damage') + case ('thermal') select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case(FIELD_DAMAGE_LOCAL_label) - FIELD_DAMAGE_type(section) = FIELD_DAMAGE_LOCAL_ID - case(FIELD_DAMAGE_NONLOCAL_label) - FIELD_DAMAGE_type(section) = FIELD_DAMAGE_NONLOCAL_ID - case default - call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) - end select - - case ('field_thermal') - select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case(FIELD_THERMAL_local_label) - FIELD_THERMAL_type(section) = FIELD_THERMAL_local_ID - case(FIELD_THERMAL_nonlocal_label) - FIELD_THERMAL_type(section) = FIELD_THERMAL_nonlocal_ID + case(THERMAL_isothermal_label) + thermal_type(section) = THERMAL_isothermal_ID + case(THERMAL_adiabatic_label) + thermal_type(section) = THERMAL_adiabatic_ID + case(THERMAL_conduction_label) + thermal_type(section) = THERMAL_conduction_ID case default call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) end select - case ('field_vacancy') + case ('damage') select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case(FIELD_VACANCY_local_label) - FIELD_VACANCY_type(section) = FIELD_VACANCY_local_ID - case(FIELD_VACANCY_nonlocal_label) - FIELD_VACANCY_type(section) = FIELD_VACANCY_nonlocal_ID + case(DAMAGE_NONE_label) + damage_type(section) = DAMAGE_none_ID + case(DAMAGE_LOCAL_label) + damage_type(section) = DAMAGE_local_ID + case(DAMAGE_NONLOCAL_label) + damage_type(section) = DAMAGE_nonlocal_ID + case default + call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + end select + + case ('vacancyflux') + select case (IO_lc(IO_stringValue(line,positions,2_pInt))) + case(VACANCYFLUX_isoconc_label) + vacancyflux_type(section) = VACANCYFLUX_isoconc_ID + case(VACANCYFLUX_isochempot_label) + vacancyflux_type(section) = VACANCYFLUX_isochempot_ID + case(VACANCYFLUX_cahnhilliard_label) + vacancyflux_type(section) = VACANCYFLUX_cahnhilliard_ID + case default + call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + end select + + case ('porosity') + select case (IO_lc(IO_stringValue(line,positions,2_pInt))) + case(POROSITY_NONE_label) + porosity_type(section) = POROSITY_none_ID + case(POROSITY_phasefield_label) + porosity_type(section) = POROSITY_phasefield_ID + case default + call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + end select + + case ('hydrogenflux') + select case (IO_lc(IO_stringValue(line,positions,2_pInt))) + case(HYDROGENFLUX_isoconc_label) + hydrogenflux_type(section) = HYDROGENFLUX_isoconc_ID + case(HYDROGENFLUX_cahnhilliard_label) + hydrogenflux_type(section) = HYDROGENFLUX_cahnhilliard_ID case default call IO_error(500_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) end select @@ -590,6 +681,15 @@ subroutine material_parseHomogenization(fileUnit,myPart) endif enddo + do p=1_pInt, Nsections + homogenization_typeInstance(p) = count(homogenization_type(1:p) == homogenization_type(p)) + thermal_typeInstance(p) = count(thermal_type (1:p) == thermal_type (p)) + damage_typeInstance(p) = count(damage_type (1:p) == damage_type (p)) + vacancyflux_typeInstance(p) = count(vacancyflux_type (1:p) == vacancyflux_type (p)) + porosity_typeInstance(p) = count(porosity_type (1:p) == porosity_type (p)) + hydrogenflux_typeInstance(p) = count(hydrogenflux_type (1:p) == hydrogenflux_type (p)) + enddo + homogenization_maxNgrains = maxval(homogenization_Ngrains,homogenization_active) end subroutine material_parseHomogenization @@ -775,7 +875,7 @@ subroutine material_parsePhase(fileUnit,myPart) integer(pInt), parameter :: MAXNCHUNKS = 2_pInt integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: Nsections, section, p + integer(pInt) :: Nsections, section, sourceCtr, kinematicsCtr, stiffDegradationCtr, p character(len=65536) :: & tag,line logical :: echo @@ -791,18 +891,23 @@ subroutine material_parsePhase(fileUnit,myPart) allocate(phase_elasticityInstance(Nsections), source=0_pInt) allocate(phase_plasticity(Nsections) , source=PLASTICITY_undefined_ID) allocate(phase_plasticityInstance(Nsections), source=0_pInt) - allocate(phase_damage(Nsections) , source=LOCAL_DAMAGE_none_ID) - allocate(phase_damageInstance(Nsections), source=0_pInt) - allocate(phase_thermal(Nsections) , source=LOCAL_THERMAL_isothermal_ID) - allocate(phase_thermalInstance(Nsections), source=0_pInt) - allocate(phase_vacancy(Nsections) , source=LOCAL_VACANCY_constant_ID) - allocate(phase_vacancyInstance(Nsections), source=0_pInt) + allocate(phase_Nsources(Nsections), source=0_pInt) + allocate(phase_Nkinematics(Nsections), source=0_pInt) + allocate(phase_NstiffnessDegradations(Nsections),source=0_pInt) allocate(phase_Noutput(Nsections), source=0_pInt) allocate(phase_localPlasticity(Nsections), source=.false.) phase_Noutput = IO_countTagInPart(fileUnit,myPart,'(output)',Nsections) + phase_Nsources = IO_countTagInPart(fileUnit,myPart,'(source)',Nsections) + phase_Nkinematics = IO_countTagInPart(fileUnit,myPart,'(kinematics)',Nsections) + phase_NstiffnessDegradations = IO_countTagInPart(fileUnit,myPart,'(stiffness_degradation)',Nsections) phase_localPlasticity = .not. IO_spotTagInPart(fileUnit,myPart,'/nonlocal/',Nsections) + allocate(phase_source(maxval(phase_Nsources),Nsections), source=SOURCE_undefined_ID) + allocate(phase_kinematics(maxval(phase_Nkinematics),Nsections), source=KINEMATICS_undefined_ID) + allocate(phase_stiffnessDegradation(maxval(phase_NstiffnessDegradations),Nsections), & + source=STIFFNESS_DEGRADATION_undefined_ID) + rewind(fileUnit) line = '' ! to have it initialized section = 0_pInt ! - " - @@ -821,6 +926,9 @@ subroutine material_parsePhase(fileUnit,myPart) if (echo) write(6,'(2x,a)') trim(line) ! echo back read lines if (IO_getTag(line,'[',']') /= '') then ! next section section = section + 1_pInt + sourceCtr = 0_pInt + kinematicsCtr = 0_pInt + stiffDegradationCtr = 0_pInt phase_name(section) = IO_getTag(line,'[',']') endif if (section > 0_pInt) then @@ -855,42 +963,47 @@ subroutine material_parsePhase(fileUnit,myPart) case default call IO_error(201_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) end select - case ('damage') + case ('(source)') + sourceCtr = sourceCtr + 1_pInt select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case (LOCAL_DAMAGE_none_label) - phase_damage(section) = LOCAL_DAMAGE_none_ID - case (LOCAL_DAMAGE_isoBrittle_label) - phase_damage(section) = LOCAL_DAMAGE_isoBrittle_ID - case (LOCAL_DAMAGE_isoDuctile_label) - phase_damage(section) = LOCAL_DAMAGE_isoDuctile_ID - case (LOCAL_DAMAGE_anisoBrittle_label) - phase_damage(section) = LOCAL_DAMAGE_anisoBrittle_ID - case (LOCAL_DAMAGE_anisoDuctile_label) - phase_damage(section) = LOCAL_DAMAGE_anisoDuctile_ID - case (LOCAL_DAMAGE_gurson_label) - phase_damage(section) = LOCAL_DAMAGE_gurson_ID - case (LOCAL_DAMAGE_phaseField_label) - phase_damage(section) = LOCAL_DAMAGE_phaseField_ID - case default - call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + case (SOURCE_thermal_dissipation_label) + phase_source(sourceCtr,section) = SOURCE_thermal_dissipation_ID + case (SOURCE_damage_isoBrittle_label) + phase_source(sourceCtr,section) = SOURCE_damage_isoBrittle_ID + case (SOURCE_damage_isoDuctile_label) + phase_source(sourceCtr,section) = SOURCE_damage_isoDuctile_ID + case (SOURCE_damage_anisoBrittle_label) + phase_source(sourceCtr,section) = SOURCE_damage_anisoBrittle_ID + case (SOURCE_damage_anisoDuctile_label) + phase_source(sourceCtr,section) = SOURCE_damage_anisoDuctile_ID + case (SOURCE_vacancy_phenoplasticity_label) + phase_source(sourceCtr,section) = SOURCE_vacancy_phenoplasticity_ID + case (SOURCE_vacancy_irradiation_label) + phase_source(sourceCtr,section) = SOURCE_vacancy_irradiation_ID + case (SOURCE_vacancy_thermalfluc_label) + phase_source(sourceCtr,section) = SOURCE_vacancy_thermalfluc_ID end select - case ('thermal') + case ('(kinematics)') + kinematicsCtr = kinematicsCtr + 1_pInt select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case (LOCAL_THERMAL_ISOTHERMAL_label) - phase_thermal(section) = LOCAL_THERMAL_isothermal_ID - case (LOCAL_THERMAL_ADIABATIC_label) - phase_thermal(section) = LOCAL_THERMAL_adiabatic_ID - case default - call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + case (KINEMATICS_cleavage_opening_label) + phase_kinematics(kinematicsCtr,section) = KINEMATICS_cleavage_opening_ID + case (KINEMATICS_slipplane_opening_label) + phase_kinematics(kinematicsCtr,section) = KINEMATICS_slipplane_opening_ID + case (KINEMATICS_thermal_expansion_label) + phase_kinematics(kinematicsCtr,section) = KINEMATICS_thermal_expansion_ID + case (KINEMATICS_vacancy_strain_label) + phase_kinematics(kinematicsCtr,section) = KINEMATICS_vacancy_strain_ID + case (KINEMATICS_hydrogen_strain_label) + phase_kinematics(kinematicsCtr,section) = KINEMATICS_hydrogen_strain_ID end select - case ('vacancy') + case ('(stiffness_degradation)') + stiffDegradationCtr = stiffDegradationCtr + 1_pInt select case (IO_lc(IO_stringValue(line,positions,2_pInt))) - case (LOCAL_VACANCY_CONSTANT_label) - phase_vacancy(section) = LOCAL_VACANCY_constant_ID - case (LOCAL_VACANCY_GENERATION_label) - phase_vacancy(section) = LOCAL_VACANCY_generation_ID - case default - call IO_error(200_pInt,ext_msg=trim(IO_stringValue(line,positions,2_pInt))) + case (STIFFNESS_DEGRADATION_damage_label) + phase_stiffnessDegradation(stiffDegradationCtr,section) = STIFFNESS_DEGRADATION_damage_ID + case (STIFFNESS_DEGRADATION_porosity_label) + phase_stiffnessDegradation(stiffDegradationCtr,section) = STIFFNESS_DEGRADATION_porosity_ID end select end select @@ -898,14 +1011,10 @@ subroutine material_parsePhase(fileUnit,myPart) enddo do p=1_pInt, Nsections - phase_elasticityInstance(p) = count(phase_elasticity(1:p) == phase_elasticity(p)) - phase_plasticityInstance(p) = count(phase_plasticity(1:p) == phase_plasticity(p)) - phase_damageInstance(p) = count(phase_damage(1:p) == phase_damage(p)) - phase_thermalInstance(p) = count(phase_thermal(1:p) == phase_thermal(p)) - phase_vacancyInstance(p) = count(phase_vacancy(1:p) == phase_vacancy(p)) + phase_elasticityInstance(p) = count(phase_elasticity(1:p) == phase_elasticity(p)) + phase_plasticityInstance(p) = count(phase_plasticity(1:p) == phase_plasticity(p)) enddo - end subroutine material_parsePhase !-------------------------------------------------------------------------------------------------- diff --git a/code/numerics.f90 b/code/numerics.f90 index 19d132f42..9ba61854b 100644 --- a/code/numerics.f90 +++ b/code/numerics.f90 @@ -70,6 +70,31 @@ module numerics usePingPong = .true., & numerics_timeSyncing = .false. !< flag indicating if time synchronization in crystallite is used for nonlocal plasticity +!-------------------------------------------------------------------------------------------------- +! field parameters: + real(pReal), protected, public :: & + err_struct_tolAbs = 1.0e-10_pReal, & !< absolute tolerance for mechanical equilibrium + err_struct_tolRel = 1.0e-4_pReal, & !< relative tolerance for mechanical equilibrium + err_thermal_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for thermal equilibrium + err_thermal_tolRel = 1.0e-6_pReal, & !< relative tolerance for thermal equilibrium + err_damage_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for damage evolution + err_damage_tolRel = 1.0e-6_pReal, & !< relative tolerance for damage evolution + err_vacancyflux_tolAbs = 1.0e-8_pReal, & !< absolute tolerance for vacancy transport + err_vacancyflux_tolRel = 1.0e-6_pReal, & !< relative tolerance for vacancy transport + err_porosity_tolAbs = 1.0e-2_pReal, & !< absolute tolerance for porosity evolution + err_porosity_tolRel = 1.0e-6_pReal, & !< relative tolerance for porosity evolution + err_hydrogenflux_tolAbs = 1.0e-8_pReal, & !< absolute tolerance for hydrogen transport + err_hydrogenflux_tolRel = 1.0e-6_pReal, & !< relative tolerance for hydrogen transport + vacancyBoundPenalty = 1.0e+4_pReal, & !< penalty to enforce 0 < Cv < 1 + hydrogenBoundPenalty = 1.0e+4_pReal !< penalty to enforce 0 < Ch < 1 + integer(pInt), protected, public :: & + itmax = 250_pInt, & !< maximum number of iterations + itmin = 1_pInt, & !< minimum number of iterations + stagItMax = 10_pInt, & !< max number of field level staggered iterations + maxCutBack = 3_pInt, & !< max number of cut backs + vacancyPolyOrder = 10_pInt, & !< order of polynomial approximation of entropic contribution to vacancy chemical potential + hydrogenPolyOrder = 10_pInt !< order of polynomial approximation of entropic contribution to hydrogen chemical potential + !-------------------------------------------------------------------------------------------------- ! spectral parameters: #ifdef Spectral @@ -94,9 +119,6 @@ module numerics &-snes_ngmres_anderson ' integer(pInt), protected, public :: & fftw_planner_flag = 32_pInt, & !< conversion of fftw_plan_mode to integer, basically what is usually done in the include file of fftw - itmax = 250_pInt, & !< maximum number of iterations - itmin = 2_pInt, & !< minimum number of iterations - maxCutBack = 3_pInt, & !< max number of cut backs continueCalculation = 0_pInt, & !< 0: exit if BVP solver does not converge, 1: continue calculation if BVP solver does not converge divergence_correction = 2_pInt !< correct divergence calculation in fourier space 0: no correction, 1: size scaled to 1, 2: size scaled to Npoints logical, protected, public :: & @@ -107,13 +129,16 @@ module numerics !-------------------------------------------------------------------------------------------------- ! FEM parameters: #ifdef FEM - real(pReal), protected, public :: & - err_struct_tolAbs = 1.0e-10_pReal, & !< absolute tolerance for equilibrium - err_struct_tolRel = 1.0e-4_pReal, & !< relative tolerance for equilibrium - err_thermal_tol = 1.0e-1_pReal, & - err_damage_tol = 1.0e-2_pReal, & - err_vacancydiffusion_tol = 1.0e-8_pReal, & - vacancyBoundPenalty = 1.0e+4_pReal !< penalty to enforce 0 < Cv < 1 + integer(pInt), protected, public :: & + integrationOrder = 2_pInt, & !< order of quadrature rule required + structOrder = 2_pInt, & !< order of displacement shape functions + thermalOrder = 2_pInt, & !< order of temperature field shape functions + damageOrder = 2_pInt, & !< order of damage field shape functions + vacancyfluxOrder = 2_pInt, & !< order of vacancy concentration and chemical potential field shape functions + porosityOrder = 2_pInt, & !< order of porosity field shape functions + hydrogenfluxOrder = 2_pInt !< order of hydrogen concentration and chemical potential field shape functions + logical, protected, public :: & + BBarStabilisation = .false. character(len=4096), protected, public :: & petsc_optionsFEM = '-mech_snes_type newtonls & &-mech_snes_linesearch_type cp & @@ -123,50 +148,43 @@ module numerics &-mech_ksp_type fgmres & &-mech_ksp_max_it 25 & &-mech_pc_type ml & - &-mech_pc_ml_maxNlevels 2 & - &-mech_mg_coarse_ksp_type preonly & - &-mech_mg_coarse_pc_type lu & - &-mech_mg_coarse_pc_factor_mat_solver_package superlu_dist & &-mech_mg_levels_ksp_type chebyshev & - &-mech_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 & &-mech_mg_levels_pc_type sor & &-mech_pc_ml_nullspace user & &-damage_snes_type newtonls & &-damage_snes_linesearch_type cp & &-damage_ksp_type fgmres & + &-damage_ksp_max_it 25 & &-damage_snes_atol 1e-8 & - &-damage_pc_type ml & - &-damage_mg_levels_ksp_type chebyshev & - &-damage_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 & - &-damage_mg_levels_pc_type sor & + &-damage_pc_type hypre & &-thermal_snes_type newtonls & &-thermal_snes_linesearch_type cp & &-thermal_ksp_type fgmres & + &-thermal_ksp_max_it 25 & &-thermal_snes_atol 1e-1 & - &-thermal_pc_type ml & - &-thermal_mg_levels_ksp_type chebyshev & - &-thermal_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 & - &-thermal_mg_levels_pc_type sor & + &-thermal_pc_type hypre & &-vacancy_snes_type newtonls & &-vacancy_snes_linesearch_type cp & - &-vacancy_ksp_type fgmres & &-vacancy_snes_atol 1e-9 & + &-vacancy_ksp_type fgmres & + &-vacancy_ksp_max_it 25 & &-vacancy_pc_type ml & &-vacancy_mg_levels_ksp_type chebyshev & - &-vacancy_mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.1,0,1.1 & - &-vacancy_mg_levels_pc_type sor ' - integer(pInt), protected, public :: & - itmaxFEM = 25_pInt, & !< maximum number of iterations - itminFEM = 1_pInt, & !< minimum number of iterations - stagItMax = 10_pInt, & !< max number of field level staggered iterations - maxCutBackFEM = 3_pInt, & !< max number of cut backs - integrationOrder = 2_pInt, & - structOrder = 2_pInt, & - thermalOrder = 2_pInt, & - damageOrder = 2_pInt, & - vacancyDiffusionOrder = 2_pInt - logical, protected, public :: & - BBarStabilisation = .false. + &-vacancy_mg_levels_pc_type sor & + &-porosity_snes_type newtonls & + &-porosity_snes_linesearch_type cp & + &-porosity_ksp_type fgmres & + &-porosity_ksp_max_it 25 & + &-porosity_snes_atol 1e-8 & + &-porosity_pc_type hypre & + &-hydrogen_snes_type newtonls & + &-hydrogen_snes_linesearch_type cp & + &-hydrogen_snes_atol 1e-9 & + &-hydrogen_ksp_type fgmres & + &-hydrogen_ksp_max_it 25 & + &-hydrogen_pc_type ml & + &-hydrogen_mg_levels_ksp_type chebyshev & + &-hydrogen_mg_levels_pc_type sor ' #endif public :: numerics_init @@ -350,6 +368,49 @@ subroutine numerics_init case ('residualstiffness') residualStiffness = IO_floatValue(line,positions,2_pInt) +!-------------------------------------------------------------------------------------------------- +! field parameters + case ('err_struct_tolabs') + err_struct_tolAbs = IO_floatValue(line,positions,2_pInt) + case ('err_struct_tolrel') + err_struct_tolRel = IO_floatValue(line,positions,2_pInt) + case ('err_thermal_tolabs') + err_thermal_tolabs = IO_floatValue(line,positions,2_pInt) + case ('err_thermal_tolrel') + err_thermal_tolrel = IO_floatValue(line,positions,2_pInt) + case ('err_damage_tolabs') + err_damage_tolabs = IO_floatValue(line,positions,2_pInt) + case ('err_damage_tolrel') + err_damage_tolrel = IO_floatValue(line,positions,2_pInt) + case ('err_vacancyflux_tolabs') + err_vacancyflux_tolabs = IO_floatValue(line,positions,2_pInt) + case ('err_vacancyflux_tolrel') + err_vacancyflux_tolrel = IO_floatValue(line,positions,2_pInt) + case ('err_porosity_tolabs') + err_porosity_tolabs = IO_floatValue(line,positions,2_pInt) + case ('err_porosity_tolrel') + err_porosity_tolrel = IO_floatValue(line,positions,2_pInt) + case ('err_hydrogenflux_tolabs') + err_hydrogenflux_tolabs = IO_floatValue(line,positions,2_pInt) + case ('err_hydrogenflux_tolrel') + err_hydrogenflux_tolrel = IO_floatValue(line,positions,2_pInt) + case ('vacancyboundpenalty') + vacancyBoundPenalty = IO_floatValue(line,positions,2_pInt) + case ('hydrogenboundpenalty') + hydrogenBoundPenalty = IO_floatValue(line,positions,2_pInt) + case ('itmax') + itmax = IO_intValue(line,positions,2_pInt) + case ('itmin') + itmin = IO_intValue(line,positions,2_pInt) + case ('maxcutback') + maxCutBack = IO_intValue(line,positions,2_pInt) + case ('maxstaggerediter') + stagItMax = IO_intValue(line,positions,2_pInt) + case ('vacancypolyorder') + vacancyPolyOrder = IO_intValue(line,positions,2_pInt) + case ('hydrogenpolyorder') + hydrogenPolyOrder = IO_intValue(line,positions,2_pInt) + !-------------------------------------------------------------------------------------------------- ! spectral parameters #ifdef Spectral @@ -361,12 +422,6 @@ subroutine numerics_init err_stress_tolrel = IO_floatValue(line,positions,2_pInt) case ('err_stress_tolabs') err_stress_tolabs = IO_floatValue(line,positions,2_pInt) - case ('itmax') - itmax = IO_intValue(line,positions,2_pInt) - case ('itmin') - itmin = IO_intValue(line,positions,2_pInt) - case ('maxcutback') - maxCutBack = IO_intValue(line,positions,2_pInt) case ('continuecalculation') continueCalculation = IO_intValue(line,positions,2_pInt) case ('memory_efficient') @@ -395,36 +450,16 @@ subroutine numerics_init polarBeta = IO_floatValue(line,positions,2_pInt) #else case ('err_div_tolabs','err_div_tolrel','err_stress_tolrel','err_stress_tolabs',& ! found spectral parameter for FEM build - 'itmax', 'itmin','memory_efficient','fftw_timelimit','fftw_plan_mode', & + 'memory_efficient','fftw_timelimit','fftw_plan_mode', & 'divergence_correction','update_gamma','spectralfilter','myfilter', & 'err_curl_tolabs','err_curl_tolrel', & - 'maxcutback','polaralpha','polarbeta') + 'polaralpha','polarbeta') call IO_warning(40_pInt,ext_msg=tag) #endif !-------------------------------------------------------------------------------------------------- ! FEM parameters #ifdef FEM - case ('err_struct_tolabs') - err_struct_tolAbs = IO_floatValue(line,positions,2_pInt) - case ('err_struct_tolrel') - err_struct_tolRel = IO_floatValue(line,positions,2_pInt) - case ('err_thermal_tol') - err_thermal_tol = IO_floatValue(line,positions,2_pInt) - case ('err_damage_tol') - err_damage_tol = IO_floatValue(line,positions,2_pInt) - case ('err_vacancydiffusion_tol') - err_vacancyDiffusion_tol = IO_floatValue(line,positions,2_pInt) - case ('vacancyboundpenalty') - vacancyBoundPenalty = IO_floatValue(line,positions,2_pInt) - case ('itmaxfem') - itmaxFEM = IO_intValue(line,positions,2_pInt) - case ('itminfem') - itminFEM = IO_intValue(line,positions,2_pInt) - case ('maxcutbackfem') - maxCutBackFEM = IO_intValue(line,positions,2_pInt) - case ('maxstaggerediter') - stagItMax = IO_intValue(line,positions,2_pInt) case ('integrationorder') integrationorder = IO_intValue(line,positions,2_pInt) case ('structorder') @@ -433,16 +468,19 @@ subroutine numerics_init thermalorder = IO_intValue(line,positions,2_pInt) case ('damageorder') damageorder = IO_intValue(line,positions,2_pInt) - case ('vacancydiffusionorder') - vacancyDiffusionOrder = IO_intValue(line,positions,2_pInt) + case ('vacancyfluxorder') + vacancyfluxOrder = IO_intValue(line,positions,2_pInt) + case ('porosityorder') + porosityOrder = IO_intValue(line,positions,2_pInt) + case ('hydrogenfluxorder') + hydrogenfluxOrder = IO_intValue(line,positions,2_pInt) case ('petsc_optionsfem') petsc_optionsFEM = trim(line(positions(4):)) case ('bbarstabilisation') BBarStabilisation = IO_intValue(line,positions,2_pInt) > 0_pInt #else - case ('err_struct_tolabs','err_struct_tolrel','err_thermal_tol','err_damage_tol','err_vacancydiffusion_tol',& ! found FEM parameter for spectral/Abaqus/Marc build - 'vacancyboundpenalty','itmaxfem', 'itminfem','maxcutbackfem','maxstaggerediter','integrationorder',& - 'structorder','thermalorder', 'damageorder','petsc_optionsfem','bbarstabilisation') + case ('integrationorder','structorder','thermalorder', 'damageorder','vacancyfluxorder', & + 'porosityorder','hydrogenfluxorder','petsc_optionsfem','bbarstabilisation') call IO_warning(40_pInt,ext_msg=tag) #endif case default ! found unknown keyword @@ -541,11 +579,31 @@ subroutine numerics_init !$ write(6,'(a24,1x,i8,/)') ' number of threads: ',DAMASK_NumThreadsInt !-------------------------------------------------------------------------------------------------- -! spectral parameters -#ifdef Spectral +! field parameters write(6,'(a24,1x,i8)') ' itmax: ',itmax write(6,'(a24,1x,i8)') ' itmin: ',itmin write(6,'(a24,1x,i8)') ' maxCutBack: ',maxCutBack + write(6,'(a24,1x,i8)') ' maxStaggeredIter: ',stagItMax + write(6,'(a24,1x,i8)') ' vacancyPolyOrder: ',vacancyPolyOrder + write(6,'(a24,1x,i8)') ' hydrogenPolyOrder: ',hydrogenPolyOrder + write(6,'(a24,1x,es8.1)') ' err_struct_tolAbs: ',err_struct_tolAbs + write(6,'(a24,1x,es8.1)') ' err_struct_tolRel: ',err_struct_tolRel + write(6,'(a24,1x,es8.1)') ' err_thermal_tolabs: ',err_thermal_tolabs + write(6,'(a24,1x,es8.1)') ' err_thermal_tolrel: ',err_thermal_tolrel + write(6,'(a24,1x,es8.1)') ' err_damage_tolabs: ',err_damage_tolabs + write(6,'(a24,1x,es8.1)') ' err_damage_tolrel: ',err_damage_tolrel + write(6,'(a24,1x,es8.1)') ' err_vacancyflux_tolabs: ',err_vacancyflux_tolabs + write(6,'(a24,1x,es8.1)') ' err_vacancyflux_tolrel: ',err_vacancyflux_tolrel + write(6,'(a24,1x,es8.1)') ' err_porosity_tolabs: ',err_porosity_tolabs + write(6,'(a24,1x,es8.1)') ' err_porosity_tolrel: ',err_porosity_tolrel + write(6,'(a24,1x,es8.1)') ' err_hydrogenflux_tolabs:',err_hydrogenflux_tolabs + write(6,'(a24,1x,es8.1)') ' err_hydrogenflux_tolrel:',err_hydrogenflux_tolrel + write(6,'(a24,1x,es8.1)') ' vacancyBoundPenalty: ',vacancyBoundPenalty + write(6,'(a24,1x,es8.1)') ' hydrogenBoundPenalty: ',hydrogenBoundPenalty + +!-------------------------------------------------------------------------------------------------- +! spectral parameters +#ifdef Spectral write(6,'(a24,1x,i8)') ' continueCalculation: ',continueCalculation write(6,'(a24,1x,L8)') ' memory_efficient: ',memory_efficient write(6,'(a24,1x,i8)') ' divergence_correction: ',divergence_correction @@ -573,21 +631,13 @@ subroutine numerics_init !-------------------------------------------------------------------------------------------------- ! spectral parameters #ifdef FEM - write(6,'(a24,1x,i8)') ' itmaxFEM: ',itmaxFEM - write(6,'(a24,1x,i8)') ' itminFEM: ',itminFEM - write(6,'(a24,1x,i8)') ' maxCutBackFEM: ',maxCutBackFEM - write(6,'(a24,1x,i8)') ' maxStaggeredIter: ',stagItMax write(6,'(a24,1x,i8)') ' integrationOrder: ',integrationOrder write(6,'(a24,1x,i8)') ' structOrder: ',structOrder write(6,'(a24,1x,i8)') ' thermalOrder: ',thermalOrder write(6,'(a24,1x,i8)') ' damageOrder: ',damageOrder - write(6,'(a24,1x,i8)') ' vacancyDiffusionOrder: ',vacancyDiffusionOrder - write(6,'(a24,1x,es8.1)') ' err_struct_tolAbs: ',err_struct_tolAbs - write(6,'(a24,1x,es8.1)') ' err_struct_tolRel: ',err_struct_tolRel - write(6,'(a24,1x,es8.1)') ' err_thermal_tol: ',err_thermal_tol - write(6,'(a24,1x,es8.1)') ' err_damage_tol: ',err_damage_tol - write(6,'(a24,1x,es8.1)') ' err_vacancyDiff_tol: ',err_vacancyDiffusion_tol - write(6,'(a24,1x,es8.1)') ' vacancyBoundPenalty: ',vacancyBoundPenalty + write(6,'(a24,1x,i8)') ' vacancyfluxOrder: ',vacancyfluxOrder + write(6,'(a24,1x,i8)') ' porosityOrder: ',porosityOrder + write(6,'(a24,1x,i8)') ' hydrogenfluxOrder: ',hydrogenfluxOrder write(6,'(a24,1x,a)') ' PETSc_optionsFEM: ',trim(petsc_optionsFEM) write(6,'(a24,1x,L8)') ' B-Bar stabilisation: ',BBarStabilisation #endif @@ -634,14 +684,28 @@ subroutine numerics_init if (volDiscrMod_RGC < 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrMod_RGC') if (volDiscrPow_RGC <= 0.0_pReal) call IO_error(301_pInt,ext_msg='volDiscrPw_RGC') if (residualStiffness <= 0.0_pReal) call IO_error(301_pInt,ext_msg='residualStiffness') -#ifdef Spectral if (itmax <= 1_pInt) call IO_error(301_pInt,ext_msg='itmax') if (itmin > itmax .or. itmin < 1_pInt) call IO_error(301_pInt,ext_msg='itmin') + if (maxCutBack < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBack') + if (stagItMax < 0_pInt) call IO_error(301_pInt,ext_msg='maxStaggeredIter') + if (vacancyPolyOrder < 0_pInt) call IO_error(301_pInt,ext_msg='vacancyPolyOrder') + if (err_struct_tolRel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolRel') + if (err_struct_tolAbs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolAbs') + if (err_thermal_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tolabs') + if (err_thermal_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tolrel') + if (err_damage_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tolabs') + if (err_damage_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tolrel') + if (err_vacancyflux_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_vacancyflux_tolabs') + if (err_vacancyflux_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_vacancyflux_tolrel') + if (err_porosity_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_porosity_tolabs') + if (err_porosity_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_porosity_tolrel') + if (err_hydrogenflux_tolabs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_hydrogenflux_tolabs') + if (err_hydrogenflux_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_hydrogenflux_tolrel') +#ifdef Spectral if (continueCalculation /= 0_pInt .and. & continueCalculation /= 1_pInt) call IO_error(301_pInt,ext_msg='continueCalculation') if (divergence_correction < 0_pInt .or. & divergence_correction > 2_pInt) call IO_error(301_pInt,ext_msg='divergence_correction') - if (maxCutBack < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBack') if (update_gamma .and. & .not. memory_efficient) call IO_error(error_ID = 847_pInt) if (err_stress_tolrel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_stress_tolRel') @@ -655,18 +719,6 @@ subroutine numerics_init if (polarBeta < 0.0_pReal .or. & polarBeta > 2.0_pReal) call IO_error(301_pInt,ext_msg='polarBeta') #endif -#ifdef FEM - if (itmaxFEM <= 1_pInt) call IO_error(301_pInt,ext_msg='itmaxFEM') - if (itminFEM > itmaxFEM .or. & - itminFEM < 0_pInt) call IO_error(301_pInt,ext_msg='itminFEM') - if (maxCutBackFEM < 0_pInt) call IO_error(301_pInt,ext_msg='maxCutBackFEM') - if (stagItMax < 0_pInt) call IO_error(301_pInt,ext_msg='maxStaggeredIter') - if (err_struct_tolRel <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolRel') - if (err_struct_tolAbs <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_struct_tolAbs') - if (err_thermal_tol <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_thermal_tol') - if (err_damage_tol <= 0.0_pReal) call IO_error(301_pInt,ext_msg='err_damage_tol') - if (err_vacancyDiffusion_tol <= 0.0_pReal)call IO_error(301_pInt,ext_msg='err_vacancydiffusion_tol') -#endif end subroutine numerics_init diff --git a/code/porosity_none.f90 b/code/porosity_none.f90 new file mode 100644 index 000000000..738104545 --- /dev/null +++ b/code/porosity_none.f90 @@ -0,0 +1,62 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for constant porosity +!-------------------------------------------------------------------------------------------------- +module porosity_none + + implicit none + private + + public :: & + porosity_none_init + +contains + +!-------------------------------------------------------------------------------------------------- +!> @brief allocates all neccessary fields, reads information from material configuration file +!-------------------------------------------------------------------------------------------------- +subroutine porosity_none_init() + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use prec, only: & + pReal, & + pInt + use IO, only: & + IO_timeStamp + use material + use numerics, only: & + worldrank + + implicit none + integer(pInt) :: & + homog, & + NofMyHomog + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- porosity_'//POROSITY_none_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + initializeInstances: do homog = 1_pInt, material_Nhomogenization + + myhomog: if (porosity_type(homog) == POROSITY_none_ID) then + NofMyHomog = count(material_homog == homog) + porosityState(homog)%sizeState = 0_pInt + porosityState(homog)%sizePostResults = 0_pInt + allocate(porosityState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal) + allocate(porosityState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal) + allocate(porosityState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal) + + deallocate(porosity(homog)%p) + allocate (porosity(homog)%p(1), source=1.0_pReal) + + endif myhomog + enddo initializeInstances + + +end subroutine porosity_none_init + +end module porosity_none diff --git a/code/porosity_phasefield.f90 b/code/porosity_phasefield.f90 new file mode 100644 index 000000000..3cf832319 --- /dev/null +++ b/code/porosity_phasefield.f90 @@ -0,0 +1,488 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for phase field modelling of pore nucleation and growth +!> @details phase field model for pore nucleation and growth based on vacancy clustering +!-------------------------------------------------------------------------------------------------- +module porosity_phasefield + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + porosity_phasefield_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + porosity_phasefield_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + porosity_phasefield_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + porosity_phasefield_Noutput !< number of outputs per instance of this porosity + + real(pReal), dimension(:), allocatable, private :: & + porosity_phasefield_specificFormationEnergy, & + porosity_phasefield_surfaceEnergy + + enum, bind(c) + enumerator :: undefined_ID, & + porosity_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + porosity_phasefield_outputID !< ID of each post result output + + + public :: & + porosity_phasefield_init, & + porosity_phasefield_getFormationEnergy, & + porosity_phasefield_getSurfaceEnergy, & + porosity_phasefield_getSourceAndItsTangent, & + porosity_phasefield_getDiffusion33, & + porosity_phasefield_getMobility, & + porosity_phasefield_putPorosity, & + porosity_phasefield_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine porosity_phasefield_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use lattice, only: & + lattice_vacancyVol + use material, only: & + porosity_type, & + porosity_typeInstance, & + homogenization_Noutput, & + POROSITY_phasefield_label, & + POROSITY_phasefield_ID, & + material_homog, & + material_Nphase, & + mappingHomogenization, & + porosityState, & + porosityMapping, & + porosity, & + material_partHomogenization, & + material_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- porosity_'//POROSITY_phasefield_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(porosity_type == POROSITY_phasefield_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(porosity_phasefield_sizePostResults(maxNinstance), source=0_pInt) + allocate(porosity_phasefield_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(porosity_phasefield_output (maxval(homogenization_Noutput),maxNinstance)) + porosity_phasefield_output = '' + allocate(porosity_phasefield_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(porosity_phasefield_Noutput (maxNinstance), source=0_pInt) + allocate(porosity_phasefield_specificFormationEnergy(material_Nphase), source=0.0_pReal) + allocate(porosity_phasefield_surfaceEnergy (material_Nphase), source=0.0_pReal) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (porosity_type(section) == POROSITY_phasefield_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = porosity_typeInstance(section) ! which instance of my porosity is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('porosity') + porosity_phasefield_Noutput(instance) = porosity_phasefield_Noutput(instance) + 1_pInt + porosity_phasefield_outputID(porosity_phasefield_Noutput(instance),instance) = porosity_ID + porosity_phasefield_output(porosity_phasefield_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingHomog + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (porosity_type(section) == POROSITY_phasefield_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('vacancyformationenergy') + porosity_phasefield_specificFormationEnergy(section) = IO_floatValue(line,positions,2_pInt)/& + lattice_vacancyVol(section) + + case ('voidsurfaceenergy') + porosity_phasefield_surfaceEnergy(section) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingPhase + + initializeInstances: do section = 1_pInt, size(porosity_type) + if (porosity_type(section) == POROSITY_phasefield_ID) then + NofMyHomog=count(material_homog==section) + instance = porosity_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,porosity_phasefield_Noutput(instance) + select case(porosity_phasefield_outputID(o,instance)) + case(porosity_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + porosity_phasefield_sizePostResult(o,instance) = mySize + porosity_phasefield_sizePostResults(instance) = porosity_phasefield_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 0_pInt + porosityState(section)%sizeState = sizeState + porosityState(section)%sizePostResults = porosity_phasefield_sizePostResults(instance) + allocate(porosityState(section)%state0 (sizeState,NofMyHomog)) + allocate(porosityState(section)%subState0(sizeState,NofMyHomog)) + allocate(porosityState(section)%state (sizeState,NofMyHomog)) + + nullify(porosityMapping(section)%p) + porosityMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(porosity(section)%p) + allocate(porosity(section)%p(NofMyHomog), source=1.0_pReal) + + endif + + enddo initializeInstances +end subroutine porosity_phasefield_init + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized vacancy formation energy +!-------------------------------------------------------------------------------------------------- +function porosity_phasefield_getFormationEnergy(ip,el) + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + porosity_phasefield_getFormationEnergy + integer(pInt) :: & + grain + + porosity_phasefield_getFormationEnergy = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + porosity_phasefield_getFormationEnergy = porosity_phasefield_getFormationEnergy + & + porosity_phasefield_specificFormationEnergy(material_phase(grain,ip,el)) + enddo + + porosity_phasefield_getFormationEnergy = & + porosity_phasefield_getFormationEnergy/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function porosity_phasefield_getFormationEnergy + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized pore surface energy (normalized by characteristic length) +!-------------------------------------------------------------------------------------------------- +function porosity_phasefield_getSurfaceEnergy(ip,el) + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + porosity_phasefield_getSurfaceEnergy + integer(pInt) :: & + grain + + porosity_phasefield_getSurfaceEnergy = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + porosity_phasefield_getSurfaceEnergy = porosity_phasefield_getSurfaceEnergy + & + porosity_phasefield_surfaceEnergy(material_phase(grain,ip,el)) + enddo + + porosity_phasefield_getSurfaceEnergy = & + porosity_phasefield_getSurfaceEnergy/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function porosity_phasefield_getSurfaceEnergy + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates homogenized local driving force for pore nucleation and growth +!-------------------------------------------------------------------------------------------------- +subroutine porosity_phasefield_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el) + use math, only : & + math_mul33x33, & + math_mul66x6, & + math_Mandel33to6, & + math_transpose33, & + math_I3 + use material, only: & + homogenization_Ngrains, & + material_homog, & + material_phase, & + phase_NstiffnessDegradations, & + phase_stiffnessDegradation, & + vacancyConc, & + vacancyfluxMapping, & + damage, & + damageMapping, & + STIFFNESS_DEGRADATION_damage_ID + use crystallite, only: & + crystallite_Fe + use constitutive, only: & + constitutive_homogenizedC + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + phi + integer(pInt) :: & + phase, & + grain, & + homog, & + mech + real(pReal) :: & + phiDot, dPhiDot_dPhi, Cv, W_e, strain(6), C(6,6) + + homog = material_homog(ip,el) + Cv = vacancyConc(homog)%p(vacancyfluxMapping(homog)%p(ip,el)) + + W_e = 0.0_pReal + do grain = 1, homogenization_Ngrains(homog) + phase = material_phase(grain,ip,el) + strain = math_Mandel33to6(math_mul33x33(math_transpose33(crystallite_Fe(1:3,1:3,grain,ip,el)), & + crystallite_Fe(1:3,1:3,grain,ip,el)) - math_I3)/2.0_pReal + C = constitutive_homogenizedC(grain,ip,el) + do mech = 1_pInt, phase_NstiffnessDegradations(phase) + select case(phase_stiffnessDegradation(mech,phase)) + case (STIFFNESS_DEGRADATION_damage_ID) + C = damage(homog)%p(damageMapping(homog)%p(ip,el))* & + damage(homog)%p(damageMapping(homog)%p(ip,el))* & + C + + end select + enddo + W_e = W_e + sum(abs(strain*math_mul66x6(C,strain))) + enddo + W_e = W_e/homogenization_Ngrains(homog) + + phiDot = 2.0_pReal*(1.0_pReal - phi)*(1.0_pReal - Cv)*(1.0_pReal - Cv) - & + 2.0_pReal*phi*(W_e + Cv*porosity_phasefield_getFormationEnergy(ip,el))/ & + porosity_phasefield_getSurfaceEnergy (ip,el) + dPhiDot_dPhi = - 2.0_pReal*(1.0_pReal - Cv)*(1.0_pReal - Cv) & + - 2.0_pReal*(W_e + Cv*porosity_phasefield_getFormationEnergy(ip,el))/ & + porosity_phasefield_getSurfaceEnergy (ip,el) + +end subroutine porosity_phasefield_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized nonlocal diffusion tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function porosity_phasefield_getDiffusion33(ip,el) + use lattice, only: & + lattice_PorosityDiffusion33 + use material, only: & + homogenization_Ngrains, & + material_phase, & + mappingHomogenization + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + porosity_phasefield_getDiffusion33 + integer(pInt) :: & + homog, & + grain + + homog = mappingHomogenization(2,ip,el) + porosity_phasefield_getDiffusion33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(homog) + porosity_phasefield_getDiffusion33 = porosity_phasefield_getDiffusion33 + & + crystallite_push33ToRef(grain,ip,el,lattice_PorosityDiffusion33(1:3,1:3,material_phase(grain,ip,el))) + enddo + + porosity_phasefield_getDiffusion33 = & + porosity_phasefield_getDiffusion33/ & + homogenization_Ngrains(homog) + +end function porosity_phasefield_getDiffusion33 + +!-------------------------------------------------------------------------------------------------- +!> @brief Returns homogenized phase field mobility +!-------------------------------------------------------------------------------------------------- +real(pReal) function porosity_phasefield_getMobility(ip,el) + use mesh, only: & + mesh_element + use lattice, only: & + lattice_PorosityMobility + use material, only: & + material_phase, & + homogenization_Ngrains + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + integer(pInt) :: & + ipc + + porosity_phasefield_getMobility = 0.0_pReal + + do ipc = 1, homogenization_Ngrains(mesh_element(3,el)) + porosity_phasefield_getMobility = porosity_phasefield_getMobility + lattice_PorosityMobility(material_phase(ipc,ip,el)) + enddo + + porosity_phasefield_getMobility = porosity_phasefield_getMobility/homogenization_Ngrains(mesh_element(3,el)) + +end function porosity_phasefield_getMobility + +!-------------------------------------------------------------------------------------------------- +!> @brief updates porosity with solution from phasefield PDE +!-------------------------------------------------------------------------------------------------- +subroutine porosity_phasefield_putPorosity(phi,ip,el) + use material, only: & + material_homog, & + porosityMapping, & + porosity + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + phi + integer(pInt) :: & + homog, & + offset + + homog = material_homog(ip,el) + offset = porosityMapping(homog)%p(ip,el) + porosity(homog)%p(offset) = phi + +end subroutine porosity_phasefield_putPorosity + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of porosity results +!-------------------------------------------------------------------------------------------------- +function porosity_phasefield_postResults(ip,el) + use material, only: & + mappingHomogenization, & + porosity_typeInstance, & + porosity + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(porosity_phasefield_sizePostResults(porosity_typeInstance(mappingHomogenization(2,ip,el)))) :: & + porosity_phasefield_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + instance = porosity_typeInstance(homog) + + c = 0_pInt + porosity_phasefield_postResults = 0.0_pReal + + do o = 1_pInt,porosity_phasefield_Noutput(instance) + select case(porosity_phasefield_outputID(o,instance)) + + case (porosity_ID) + porosity_phasefield_postResults(c+1_pInt) = porosity(homog)%p(offset) + c = c + 1 + end select + enddo +end function porosity_phasefield_postResults + +end module porosity_phasefield diff --git a/code/prec.f90 b/code/prec.f90 index 189b2c18e..97252c60e 100644 --- a/code/prec.f90 +++ b/code/prec.f90 @@ -58,11 +58,11 @@ use ifport real(pReal), parameter, public :: tol_math_check = 1.0e-8_pReal !< tolerance for internal math self-checks (rotation) type, public :: p_vec !< variable length datatype used for storage of state - real(pReal), dimension(:), allocatable :: p + real(pReal), dimension(:), pointer :: p end type p_vec -type, public :: p_intvec - integer(pInt), dimension(:), allocatable :: p + type, public :: p_intvec + integer(pInt), dimension(:), pointer :: p end type p_intvec !http://stackoverflow.com/questions/3948210/can-i-have-a-pointer-to-an-item-in-an-allocatable-array @@ -71,14 +71,11 @@ type, public :: p_intvec sizeState = 0_pInt , & !< size of state sizeDotState = 0_pInt, & !< size of dot state, i.e. parts of the state that are integrated sizePostResults = 0_pInt !< size of output data - logical :: & - nonlocal = .false. !< absolute tolerance for state integration real(pReal), allocatable, dimension(:) :: & atolState real(pReal), pointer, dimension(:,:), contiguous :: & ! a pointer is needed here because we might point to state/doState. However, they will never point to something, but are rather allocated and, hence, contiguous state, & !< state - dotState !< state rate - real(pReal), allocatable, dimension(:,:) :: & + dotState, & !< state rate state0, & partionedState0, & subState0, & @@ -97,17 +94,23 @@ type, public :: p_intvec nSlip = 0_pInt , & nTwin = 0_pInt, & nTrans = 0_pInt + logical :: & + nonlocal = .false. !< absolute tolerance for state integration real(pReal), pointer, dimension(:,:), contiguous :: & slipRate, & !< slip rate accumulatedSlip !< accumulated plastic slip end type - type, public :: tFieldData - integer(pInt) :: & - sizeField = 0_pInt , & - sizePostResults = 0_pInt - real(pReal), allocatable, dimension(:,:) :: & - field !< field data + type, public :: tSourceState + type(tState), dimension(:), allocatable :: p !< tState for each active source mechanism in a phase + end type + + type, public :: tHomogMapping + integer(pInt), pointer, dimension(:,:) :: p + end type + + type, public :: tPhaseMapping + integer(pInt), pointer, dimension(:,:,:) :: p end type #ifdef FEM diff --git a/code/source_damage_anisoBrittle.f90 b/code/source_damage_anisoBrittle.f90 new file mode 100644 index 000000000..6b05876cd --- /dev/null +++ b/code/source_damage_anisoBrittle.f90 @@ -0,0 +1,423 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @brief material subroutine incorporating anisotropic brittle damage source mechanism +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_damage_anisoBrittle + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_damage_anisoBrittle_sizePostResults, & !< cumulative size of post results + source_damage_anisoBrittle_offset, & !< which source is my current source mechanism? + source_damage_anisoBrittle_instance !< instance of source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_damage_anisoBrittle_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_damage_anisoBrittle_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_damage_anisoBrittle_Noutput !< number of outputs per instance of this source + + integer(pInt), dimension(:), allocatable, private :: & + source_damage_anisoBrittle_totalNcleavage !< total number of cleavage systems + + integer(pInt), dimension(:,:), allocatable, private :: & + source_damage_anisoBrittle_Ncleavage !< number of cleavage systems per family + + real(pReal), dimension(:), allocatable, private :: & + source_damage_anisoBrittle_aTol, & + source_damage_anisoBrittle_sdot_0, & + source_damage_anisoBrittle_N + + real(pReal), dimension(:,:), allocatable, private :: & + source_damage_anisoBrittle_critDisp, & + source_damage_anisoBrittle_critLoad + + enum, bind(c) + enumerator :: undefined_ID, & + damage_drivingforce_ID + end enum + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + source_damage_anisoBrittle_outputID !< ID of each post result output + + + public :: & + source_damage_anisoBrittle_init, & + source_damage_anisoBrittle_dotState, & + source_damage_anisobrittle_getRateAndItsTangent, & + source_damage_anisoBrittle_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisoBrittle_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_damage_anisoBrittle_label, & + SOURCE_damage_anisoBrittle_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + use lattice, only: & + lattice_maxNcleavageFamily, & + lattice_NcleavageSystem + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + integer(pInt) :: Nchunks_CleavageFamilies = 0_pInt, j + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_anisoBrittle_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_damage_anisoBrittle_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_damage_anisoBrittle_offset(material_Nphase), source=0_pInt) + allocate(source_damage_anisoBrittle_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_damage_anisoBrittle_instance(phase) = count(phase_source(:,1:phase) == source_damage_anisoBrittle_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_damage_anisoBrittle_ID) & + source_damage_anisoBrittle_offset(phase) = source + enddo + enddo + + allocate(source_damage_anisoBrittle_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_damage_anisoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance), source=0_pInt) + allocate(source_damage_anisoBrittle_output(maxval(phase_Noutput),maxNinstance)) + source_damage_anisoBrittle_output = '' + allocate(source_damage_anisoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) + allocate(source_damage_anisoBrittle_Noutput(maxNinstance), source=0_pInt) + allocate(source_damage_anisoBrittle_critDisp(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoBrittle_critLoad(lattice_maxNcleavageFamily,maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoBrittle_Ncleavage(lattice_maxNcleavageFamily,maxNinstance), source=0_pInt) + allocate(source_damage_anisoBrittle_totalNcleavage(maxNinstance), source=0_pInt) + allocate(source_damage_anisoBrittle_aTol(maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoBrittle_sdot_0(maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoBrittle_N(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = source_damage_anisoBrittle_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('anisobrittle_drivingforce') + source_damage_anisoBrittle_Noutput(instance) = source_damage_anisoBrittle_Noutput(instance) + 1_pInt + source_damage_anisoBrittle_outputID(source_damage_anisoBrittle_Noutput(instance),instance) = damage_drivingforce_ID + source_damage_anisoBrittle_output(source_damage_anisoBrittle_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + case ('anisobrittle_atol') + source_damage_anisoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisobrittle_sdot0') + source_damage_anisoBrittle_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisobrittle_ratesensitivity') + source_damage_anisoBrittle_N(instance) = IO_floatValue(line,positions,2_pInt) + + case ('ncleavage') ! + Nchunks_CleavageFamilies = positions(1) - 1_pInt + do j = 1_pInt, Nchunks_CleavageFamilies + source_damage_anisoBrittle_Ncleavage(j,instance) = IO_intValue(line,positions,1_pInt+j) + enddo + + case ('anisobrittle_criticaldisplacement') + do j = 1_pInt, Nchunks_CleavageFamilies + source_damage_anisoBrittle_critDisp(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + case ('anisobrittle_criticalload') + do j = 1_pInt, Nchunks_CleavageFamilies + source_damage_anisoBrittle_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + end select + endif; endif + enddo parsingFile + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, material_Nphase + myPhase: if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then + instance = source_damage_anisoBrittle_instance(phase) + source_damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance) = & + min(lattice_NcleavageSystem(1:lattice_maxNcleavageFamily,phase),& ! limit active cleavage systems per family to min of available and requested + source_damage_anisoBrittle_Ncleavage(1:lattice_maxNcleavageFamily,instance)) + source_damage_anisoBrittle_totalNcleavage(instance) = sum(source_damage_anisoBrittle_Ncleavage(:,instance)) ! how many cleavage systems altogether + if (source_damage_anisoBrittle_aTol(instance) < 0.0_pReal) & + source_damage_anisoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 + if (source_damage_anisoBrittle_sdot_0(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//SOURCE_damage_anisoBrittle_LABEL//')') + if (any(source_damage_anisoBrittle_critDisp(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='critical_displacement ('//SOURCE_damage_anisoBrittle_LABEL//')') + if (any(source_damage_anisoBrittle_critLoad(1:Nchunks_CleavageFamilies,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='critical_load ('//SOURCE_damage_anisoBrittle_LABEL//')') + if (source_damage_anisoBrittle_N(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//SOURCE_damage_anisoBrittle_LABEL//')') + endif myPhase + enddo sanityChecks + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_damage_anisoBrittle_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_damage_anisoBrittle_instance(phase) + sourceOffset = source_damage_anisoBrittle_offset(phase) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,source_damage_anisoBrittle_Noutput(instance) + select case(source_damage_anisoBrittle_outputID(o,instance)) + case(damage_drivingforce_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + source_damage_anisoBrittle_sizePostResult(o,instance) = mySize + source_damage_anisoBrittle_sizePostResults(instance) = source_damage_anisoBrittle_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +!-------------------------------------------------------------------------------------------------- +! Determine size of state array + sizeDotState = 1_pInt + sizeState = 1_pInt + + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_anisoBrittle_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), & + source=source_damage_anisoBrittle_aTol(instance)) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_damage_anisoBrittle_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisoBrittle_dotState(Tstar_v, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState, & + material_homog, & + damage, & + damageMapping + use lattice, only: & + lattice_Scleavage_v, & + lattice_maxNcleavageFamily, & + lattice_NcleavageSystem + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in), dimension(6) :: & + Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) + integer(pInt) :: & + phase, & + constituent, & + instance, & + sourceOffset, & + damageOffset, & + homog, & + f, i, index_myFamily + real(pReal) :: & + traction_d, traction_t, traction_n, traction_crit + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_anisoBrittle_instance(phase) + sourceOffset = source_damage_anisoBrittle_offset(phase) + homog = material_homog(ip,el) + damageOffset = damageMapping(homog)%p(ip,el) + + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = 0.0_pReal + do f = 1_pInt,lattice_maxNcleavageFamily + index_myFamily = sum(lattice_NcleavageSystem(1:f-1_pInt,phase)) ! at which index starts my family + do i = 1_pInt,source_damage_anisoBrittle_Ncleavage(f,instance) ! process each (active) cleavage system in family + traction_d = dot_product(Tstar_v,lattice_Scleavage_v(1:6,1,index_myFamily+i,phase)) + traction_t = dot_product(Tstar_v,lattice_Scleavage_v(1:6,2,index_myFamily+i,phase)) + traction_n = dot_product(Tstar_v,lattice_Scleavage_v(1:6,3,index_myFamily+i,phase)) + + traction_crit = source_damage_anisoBrittle_critLoad(f,instance)* & + damage(homog)%p(damageOffset) + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = & + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) + & + source_damage_anisoBrittle_sdot_0(instance)* & + ((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance) + & + (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance) + & + (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**source_damage_anisoBrittle_N(instance))/ & + source_damage_anisoBrittle_critDisp(f,instance) + + enddo + enddo + +end subroutine source_damage_anisoBrittle_dotState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local part of nonlocal damage driving force +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in) :: & + phi + real(pReal), intent(out) :: & + localphiDot, & + dLocalphiDot_dPhi + integer(pInt) :: & + phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_damage_anisoBrittle_offset(phase) + + localphiDot = 1.0_pReal - & + max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* & + phi + + dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent)) + +end subroutine source_damage_anisobrittle_getRateAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of local damage results +!-------------------------------------------------------------------------------------------------- +function source_damage_anisoBrittle_postResults(ipc,ip,el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), dimension(source_damage_anisoBrittle_sizePostResults( & + source_damage_anisoBrittle_instance(mappingConstitutive(2,ipc,ip,el)))) :: & + source_damage_anisoBrittle_postResults + + integer(pInt) :: & + instance, phase, constituent, sourceOffset, o, c + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_anisoBrittle_instance(phase) + sourceOffset = source_damage_anisoBrittle_offset(phase) + + c = 0_pInt + source_damage_anisoBrittle_postResults = 0.0_pReal + + do o = 1_pInt,source_damage_anisoBrittle_Noutput(instance) + select case(source_damage_anisoBrittle_outputID(o,instance)) + case (damage_drivingforce_ID) + source_damage_anisoBrittle_postResults(c+1_pInt) = & + sourceState(phase)%p(sourceOffset)%state(1,constituent) + c = c + 1_pInt + + end select + enddo +end function source_damage_anisoBrittle_postResults + +end module source_damage_anisoBrittle diff --git a/code/source_damage_anisoDuctile.f90 b/code/source_damage_anisoDuctile.f90 new file mode 100644 index 000000000..b78bcc08d --- /dev/null +++ b/code/source_damage_anisoDuctile.f90 @@ -0,0 +1,412 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incorporating anisotropic ductile damage source mechanism +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_damage_anisoDuctile + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_damage_anisoDuctile_sizePostResults, & !< cumulative size of post results + source_damage_anisoDuctile_offset, & !< which source is my current damage mechanism? + source_damage_anisoDuctile_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_damage_anisoDuctile_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_damage_anisoDuctile_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_damage_anisoDuctile_Noutput !< number of outputs per instance of this damage + + integer(pInt), dimension(:), allocatable, private :: & + source_damage_anisoDuctile_totalNslip !< total number of slip systems + + integer(pInt), dimension(:,:), allocatable, private :: & + source_damage_anisoDuctile_Nslip !< number of slip systems per family + + real(pReal), dimension(:), allocatable, private :: & + source_damage_anisoDuctile_aTol + + real(pReal), dimension(:,:), allocatable, private :: & + source_damage_anisoDuctile_critPlasticStrain + + real(pReal), dimension(:), allocatable, private :: & + source_damage_anisoDuctile_sdot_0, & + source_damage_anisoDuctile_N + + real(pReal), dimension(:,:), allocatable, private :: & + source_damage_anisoDuctile_critLoad + + enum, bind(c) + enumerator :: undefined_ID, & + damage_drivingforce_ID + end enum + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + source_damage_anisoDuctile_outputID !< ID of each post result output + + + public :: & + source_damage_anisoDuctile_init, & + source_damage_anisoDuctile_dotState, & + source_damage_anisoDuctile_getRateAndItsTangent, & + source_damage_anisoDuctile_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisoDuctile_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_damage_anisoDuctile_label, & + SOURCE_damage_anisoDuctile_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + use lattice, only: & + lattice_maxNslipFamily, & + lattice_NslipSystem + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + integer(pInt) :: Nchunks_SlipFamilies = 0_pInt, j + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_anisoDuctile_LABEL//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_damage_anisoDuctile_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_damage_anisoDuctile_offset(material_Nphase), source=0_pInt) + allocate(source_damage_anisoDuctile_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_damage_anisoDuctile_instance(phase) = count(phase_source(:,1:phase) == source_damage_anisoDuctile_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_damage_anisoDuctile_ID) & + source_damage_anisoDuctile_offset(phase) = source + enddo + enddo + + allocate(source_damage_anisoDuctile_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_damage_anisoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_damage_anisoDuctile_output(maxval(phase_Noutput),maxNinstance)) + source_damage_anisoDuctile_output = '' + allocate(source_damage_anisoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) + allocate(source_damage_anisoDuctile_Noutput(maxNinstance), source=0_pInt) + allocate(source_damage_anisoDuctile_critLoad(lattice_maxNslipFamily,maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoDuctile_critPlasticStrain(lattice_maxNslipFamily,maxNinstance),source=0.0_pReal) + allocate(source_damage_anisoDuctile_Nslip(lattice_maxNslipFamily,maxNinstance), source=0_pInt) + allocate(source_damage_anisoDuctile_totalNslip(maxNinstance), source=0_pInt) + allocate(source_damage_anisoDuctile_N(maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoDuctile_sdot_0(maxNinstance), source=0.0_pReal) + allocate(source_damage_anisoDuctile_aTol(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = source_damage_anisoDuctile_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('anisoductile_drivingforce') + source_damage_anisoDuctile_Noutput(instance) = source_damage_anisoDuctile_Noutput(instance) + 1_pInt + source_damage_anisoDuctile_outputID(source_damage_anisoDuctile_Noutput(instance),instance) = damage_drivingforce_ID + source_damage_anisoDuctile_output(source_damage_anisoDuctile_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + case ('anisoductile_atol') + source_damage_anisoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt) + + case ('nslip') ! + Nchunks_SlipFamilies = positions(1) - 1_pInt + do j = 1_pInt, Nchunks_SlipFamilies + source_damage_anisoDuctile_Nslip(j,instance) = IO_intValue(line,positions,1_pInt+j) + enddo + + case ('anisoductile_sdot0') + source_damage_anisoDuctile_sdot_0(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisoductile_criticalplasticstrain') + do j = 1_pInt, Nchunks_SlipFamilies + source_damage_anisoDuctile_critPlasticStrain(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + case ('anisoductile_ratesensitivity') + source_damage_anisoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt) + + case ('anisoductile_criticalload') + do j = 1_pInt, Nchunks_SlipFamilies + source_damage_anisoDuctile_critLoad(j,instance) = IO_floatValue(line,positions,1_pInt+j) + enddo + + end select + endif; endif + enddo parsingFile + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, size(phase_source) + myPhase: if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then + instance = source_damage_anisoDuctile_instance(phase) + source_damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance) = & + min(lattice_NslipSystem(1:lattice_maxNslipFamily,phase),& ! limit active cleavage systems per family to min of available and requested + source_damage_anisoDuctile_Nslip(1:lattice_maxNslipFamily,instance)) + source_damage_anisoDuctile_totalNslip(instance) = sum(source_damage_anisoDuctile_Nslip(:,instance)) + if (source_damage_anisoDuctile_aTol(instance) < 0.0_pReal) & + source_damage_anisoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 + if (source_damage_anisoDuctile_sdot_0(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='sdot_0 ('//SOURCE_damage_anisoDuctile_LABEL//')') + if (any(source_damage_anisoDuctile_critPlasticStrain(:,instance) < 0.0_pReal)) & + call IO_error(211_pInt,el=instance,ext_msg='criticaPlasticStrain ('//SOURCE_damage_anisoDuctile_LABEL//')') + if (source_damage_anisoDuctile_N(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='rate_sensitivity ('//SOURCE_damage_anisoDuctile_LABEL//')') + endif myPhase + enddo sanityChecks + + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_damage_anisoDuctile_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_damage_anisoDuctile_instance(phase) + sourceOffset = source_damage_anisoDuctile_offset(phase) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,source_damage_anisoDuctile_Noutput(instance) + select case(source_damage_anisoDuctile_outputID(o,instance)) + case(damage_drivingforce_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + source_damage_anisoDuctile_sizePostResult(o,instance) = mySize + source_damage_anisoDuctile_sizePostResults(instance) = source_damage_anisoDuctile_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +!-------------------------------------------------------------------------------------------------- +! Determine size of state array + sizeDotState = 1_pInt + sizeState = 1_pInt + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_anisoDuctile_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), & + source=source_damage_anisoDuctile_aTol(instance)) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_damage_anisoDuctile_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisoDuctile_dotState(ipc, ip, el) + use material, only: & + mappingConstitutive, & + plasticState, & + sourceState, & + material_homog, & + damage, & + damageMapping + use lattice, only: & + lattice_maxNslipFamily + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, & + constituent, & + sourceOffset, & + homog, damageOffset, & + instance, & + index, f, i + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_anisoDuctile_instance(phase) + sourceOffset = source_damage_anisoDuctile_offset(phase) + homog = material_homog(ip,el) + damageOffset = damageMapping(homog)%p(ip,el) + + index = 1_pInt + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = 0.0_pReal + do f = 1_pInt,lattice_maxNslipFamily + do i = 1_pInt,source_damage_anisoDuctile_Nslip(f,instance) ! process each (active) slip system in family + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = & + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) + & + plasticState(phase)%slipRate(index,constituent)/ & + ((damage(homog)%p(damageOffset))**source_damage_anisoDuctile_N(instance))/ & + source_damage_anisoDuctile_critPlasticStrain(f,instance) + + index = index + 1_pInt + enddo + enddo + +end subroutine source_damage_anisoDuctile_dotState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local part of nonlocal damage driving force +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_anisoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in) :: & + phi + real(pReal), intent(out) :: & + localphiDot, & + dLocalphiDot_dPhi + integer(pInt) :: & + phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_damage_anisoDuctile_offset(phase) + + localphiDot = 1.0_pReal - & + max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* & + phi + + dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent)) + +end subroutine source_damage_anisoDuctile_getRateAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of local damage results +!-------------------------------------------------------------------------------------------------- +function source_damage_anisoDuctile_postResults(ipc,ip,el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), dimension(source_damage_anisoDuctile_sizePostResults( & + source_damage_anisoDuctile_instance(mappingConstitutive(2,ipc,ip,el)))) :: & + source_damage_anisoDuctile_postResults + + integer(pInt) :: & + instance, phase, constituent, sourceOffset, o, c + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_anisoDuctile_instance(phase) + sourceOffset = source_damage_anisoDuctile_offset(phase) + + c = 0_pInt + source_damage_anisoDuctile_postResults = 0.0_pReal + + do o = 1_pInt,source_damage_anisoDuctile_Noutput(instance) + select case(source_damage_anisoDuctile_outputID(o,instance)) + case (damage_drivingforce_ID) + source_damage_anisoDuctile_postResults(c+1_pInt) = & + sourceState(phase)%p(sourceOffset)%state(1,constituent) + c = c + 1_pInt + + end select + enddo +end function source_damage_anisoDuctile_postResults + +end module source_damage_anisoDuctile diff --git a/code/source_damage_isoBrittle.f90 b/code/source_damage_isoBrittle.f90 new file mode 100644 index 000000000..cf560e1f4 --- /dev/null +++ b/code/source_damage_isoBrittle.f90 @@ -0,0 +1,362 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Luv Sharma, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine incoprorating isotropic brittle damage source mechanism +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_damage_isoBrittle + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_damage_isoBrittle_sizePostResults, & !< cumulative size of post results + source_damage_isoBrittle_offset, & !< which source is my current damage mechanism? + source_damage_isoBrittle_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_damage_isoBrittle_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_damage_isoBrittle_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_damage_isoBrittle_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + source_damage_isoBrittle_aTol, & + source_damage_isoBrittle_critStrainEnergy + + enum, bind(c) + enumerator :: undefined_ID, & + damage_drivingforce_ID + end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + source_damage_isoBrittle_outputID !< ID of each post result output + + + public :: & + source_damage_isoBrittle_init, & + source_damage_isoBrittle_deltaState, & + source_damage_isoBrittle_getRateAndItsTangent, & + source_damage_isoBrittle_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoBrittle_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_damage_isoBrittle_label, & + SOURCE_damage_isoBrittle_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_isoBrittle_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_damage_isoBrittle_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_damage_isoBrittle_offset(material_Nphase), source=0_pInt) + allocate(source_damage_isoBrittle_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_damage_isoBrittle_instance(phase) = count(phase_source(:,1:phase) == source_damage_isoBrittle_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_damage_isoBrittle_ID) & + source_damage_isoBrittle_offset(phase) = source + enddo + enddo + + allocate(source_damage_isoBrittle_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_damage_isoBrittle_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_damage_isoBrittle_output(maxval(phase_Noutput),maxNinstance)) + source_damage_isoBrittle_output = '' + allocate(source_damage_isoBrittle_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) + allocate(source_damage_isoBrittle_Noutput(maxNinstance), source=0_pInt) + allocate(source_damage_isoBrittle_critStrainEnergy(maxNinstance), source=0.0_pReal) + allocate(source_damage_isoBrittle_aTol(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = source_damage_isoBrittle_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('isobrittle_drivingforce') + source_damage_isoBrittle_Noutput(instance) = source_damage_isoBrittle_Noutput(instance) + 1_pInt + source_damage_isoBrittle_outputID(source_damage_isoBrittle_Noutput(instance),instance) = damage_drivingforce_ID + source_damage_isoBrittle_output(source_damage_isoBrittle_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + case ('isobrittle_criticalstrainenergy') + source_damage_isoBrittle_critStrainEnergy(instance) = IO_floatValue(line,positions,2_pInt) + + case ('isobrittle_atol') + source_damage_isoBrittle_aTol(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, material_Nphase + myPhase: if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then + instance = source_damage_isoBrittle_instance(phase) + if (source_damage_isoBrittle_aTol(instance) < 0.0_pReal) & + source_damage_isoBrittle_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 + if (source_damage_isoBrittle_critStrainEnergy(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='criticalStrainEnergy ('//SOURCE_damage_isoBrittle_LABEL//')') + endif myPhase + enddo sanityChecks + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_damage_isoBrittle_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_damage_isoBrittle_instance(phase) + sourceOffset = source_damage_isoBrittle_offset(phase) +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,source_damage_isoBrittle_Noutput(instance) + select case(source_damage_isoBrittle_outputID(o,instance)) + case(damage_drivingforce_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + source_damage_isoBrittle_sizePostResult(o,instance) = mySize + source_damage_isoBrittle_sizePostResults(instance) = source_damage_isoBrittle_sizePostResults(instance) + mySize + endif + enddo outputsLoop +! Determine size of state array + sizeDotState = 1_pInt + sizeState = 1_pInt + + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_isoBrittle_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), & + source=source_damage_isoBrittle_aTol(instance)) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_damage_isoBrittle_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoBrittle_deltaState(C, Fe, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState, & + material_homog, & + phase_NstiffnessDegradations, & + phase_stiffnessDegradation, & + porosity, & + porosityMapping, & + STIFFNESS_DEGRADATION_porosity_ID + use math, only : & + math_mul33x33, & + math_mul66x6, & + math_Mandel33to6, & + math_transpose33, & + math_I3 + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in), dimension(3,3) :: & + Fe + integer(pInt) :: & + phase, constituent, instance, sourceOffset, mech + real(pReal) :: & + strain(6), & + C(6,6) + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_isoBrittle_instance(phase) + sourceOffset = source_damage_isoBrittle_offset(phase) + + do mech = 1_pInt, phase_NstiffnessDegradations(phase) + select case(phase_stiffnessDegradation(mech,phase)) + case (STIFFNESS_DEGRADATION_porosity_ID) + C = porosity(material_homog(ip,el))%p(porosityMapping(material_homog(ip,el))%p(ip,el))* & + porosity(material_homog(ip,el))%p(porosityMapping(material_homog(ip,el))%p(ip,el))* & + C + end select + enddo + strain = 0.5_pReal*math_Mandel33to6(math_mul33x33(math_transpose33(Fe),Fe)-math_I3) + + sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = & + 2.0_pReal*sum(strain*math_mul66x6(C,strain))/source_damage_isoBrittle_critStrainEnergy(instance) - & + sourceState(phase)%p(sourceOffset)%state(1,constituent) + +end subroutine source_damage_isoBrittle_deltaState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local part of nonlocal damage driving force +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoBrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in) :: & + phi + real(pReal), intent(out) :: & + localphiDot, & + dLocalphiDot_dPhi + integer(pInt) :: & + phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_damage_isoBrittle_offset(phase) + + localphiDot = 1.0_pReal - & + max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* & + phi + + dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent)) + +end subroutine source_damage_isoBrittle_getRateAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of local damage results +!-------------------------------------------------------------------------------------------------- +function source_damage_isoBrittle_postResults(ipc,ip,el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), dimension(source_damage_isoBrittle_sizePostResults( & + source_damage_isoBrittle_instance(mappingConstitutive(2,ipc,ip,el)))) :: & + source_damage_isoBrittle_postResults + + integer(pInt) :: & + instance, phase, constituent, sourceOffset, o, c + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_isoBrittle_instance(phase) + sourceOffset = source_damage_isoBrittle_offset(phase) + + c = 0_pInt + source_damage_isoBrittle_postResults = 0.0_pReal + + do o = 1_pInt,source_damage_isoBrittle_Noutput(instance) + select case(source_damage_isoBrittle_outputID(o,instance)) + case (damage_drivingforce_ID) + source_damage_isoBrittle_postResults(c+1_pInt) = sourceState(phase)%p(sourceOffset)%state(1,constituent) + c = c + 1 + + end select + enddo +end function source_damage_isoBrittle_postResults + +end module source_damage_isoBrittle diff --git a/code/source_damage_isoDuctile.f90 b/code/source_damage_isoDuctile.f90 new file mode 100644 index 000000000..af547aaa7 --- /dev/null +++ b/code/source_damage_isoDuctile.f90 @@ -0,0 +1,347 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @author Luv Sharma, Max-Planck-Institut fŸr Eisenforschung GmbH +!> @brief material subroutine incoprorating isotropic ductile damage source mechanism +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_damage_isoDuctile + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_damage_isoDuctile_sizePostResults, & !< cumulative size of post results + source_damage_isoDuctile_offset, & !< which source is my current damage mechanism? + source_damage_isoDuctile_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_damage_isoDuctile_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_damage_isoDuctile_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_damage_isoDuctile_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + source_damage_isoDuctile_aTol, & + source_damage_isoDuctile_critPlasticStrain, & + source_damage_isoDuctile_N + + enum, bind(c) + enumerator :: undefined_ID, & + damage_drivingforce_ID + end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo + + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + source_damage_isoDuctile_outputID !< ID of each post result output + + + public :: & + source_damage_isoDuctile_init, & + source_damage_isoDuctile_dotState, & + source_damage_isoDuctile_getRateAndItsTangent, & + source_damage_isoDuctile_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoDuctile_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_damage_isoDuctile_label, & + SOURCE_damage_isoDuctile_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,source,sourceOffset,o + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_damage_isoDuctile_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_damage_isoDuctile_ID),pInt) + if (maxNinstance == 0_pInt) return + + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_damage_isoDuctile_offset(material_Nphase), source=0_pInt) + allocate(source_damage_isoDuctile_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_damage_isoDuctile_instance(phase) = count(phase_source(:,1:phase) == source_damage_isoDuctile_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_damage_isoDuctile_ID) & + source_damage_isoDuctile_offset(phase) = source + enddo + enddo + + allocate(source_damage_isoDuctile_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_damage_isoDuctile_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_damage_isoDuctile_output(maxval(phase_Noutput),maxNinstance)) + source_damage_isoDuctile_output = '' + allocate(source_damage_isoDuctile_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) + allocate(source_damage_isoDuctile_Noutput(maxNinstance), source=0_pInt) + allocate(source_damage_isoDuctile_critPlasticStrain(maxNinstance), source=0.0_pReal) + allocate(source_damage_isoDuctile_N(maxNinstance), source=0.0_pReal) + allocate(source_damage_isoDuctile_aTol(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + instance = source_damage_isoDuctile_instance(phase) ! which instance of my damage is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('isoductile_drivingforce') + source_damage_isoDuctile_Noutput(instance) = source_damage_isoDuctile_Noutput(instance) + 1_pInt + source_damage_isoDuctile_outputID(source_damage_isoDuctile_Noutput(instance),instance) = damage_drivingforce_ID + source_damage_isoDuctile_output(source_damage_isoDuctile_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + case ('isoductile_criticalplasticstrain') + source_damage_isoDuctile_critPlasticStrain(instance) = IO_floatValue(line,positions,2_pInt) + + case ('isoductile_ratesensitivity') + source_damage_isoDuctile_N(instance) = IO_floatValue(line,positions,2_pInt) + + case ('isoductile_atol') + source_damage_isoDuctile_aTol(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + +!-------------------------------------------------------------------------------------------------- +! sanity checks + sanityChecks: do phase = 1_pInt, material_Nphase + myPhase: if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then + instance = source_damage_isoDuctile_instance(phase) + if (source_damage_isoDuctile_aTol(instance) < 0.0_pReal) & + source_damage_isoDuctile_aTol(instance) = 1.0e-3_pReal ! default absolute tolerance 1e-3 + if (source_damage_isoDuctile_critPlasticStrain(instance) <= 0.0_pReal) & + call IO_error(211_pInt,el=instance,ext_msg='critical plastic strain ('//SOURCE_damage_isoDuctile_LABEL//')') + endif myPhase + enddo sanityChecks + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_damage_isoDuctile_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_damage_isoDuctile_instance(phase) + sourceOffset = source_damage_isoDuctile_offset(phase) +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,source_damage_isoDuctile_Noutput(instance) + select case(source_damage_isoDuctile_outputID(o,instance)) + case(damage_drivingforce_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + source_damage_isoDuctile_sizePostResult(o,instance) = mySize + source_damage_isoDuctile_sizePostResults(instance) = source_damage_isoDuctile_sizePostResults(instance) + mySize + endif + enddo outputsLoop +! Determine size of state array + sizeDotState = 0_pInt + sizeState = 1_pInt + + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_damage_isoDuctile_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), & + source=source_damage_isoDuctile_aTol(instance)) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_damage_isoDuctile_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoDuctile_dotState(ipc, ip, el) + use material, only: & + mappingConstitutive, & + plasticState, & + sourceState, & + material_homog, & + damage, & + damageMapping + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, constituent, instance, homog, sourceOffset, damageOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_isoDuctile_instance(phase) + sourceOffset = source_damage_isoDuctile_offset(phase) + homog = material_homog(ip,el) + damageOffset = damageMapping(homog)%p(ip,el) + + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = & + sum(plasticState(phase)%slipRate(:,constituent))/ & + ((damage(homog)%p(damageOffset))**source_damage_isoDuctile_N(instance))/ & + source_damage_isoDuctile_critPlasticStrain(instance) + +end subroutine source_damage_isoDuctile_dotState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local part of nonlocal damage driving force +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), intent(in) :: & + phi + real(pReal), intent(out) :: & + localphiDot, & + dLocalphiDot_dPhi + integer(pInt) :: & + phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_damage_isoDuctile_offset(phase) + + localphiDot = 1.0_pReal - & + max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent))* & + phi + + dLocalphiDot_dPhi = -max(1.0_pReal,sourceState(phase)%p(sourceOffset)%state(1,constituent)) + +end subroutine source_damage_isoDuctile_getRateAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of local damage results +!-------------------------------------------------------------------------------------------------- +function source_damage_isoDuctile_postResults(ipc,ip,el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + real(pReal), dimension(source_damage_isoDuctile_sizePostResults( & + source_damage_isoDuctile_instance(mappingConstitutive(2,ipc,ip,el)))) :: & + source_damage_isoDuctile_postResults + + integer(pInt) :: & + instance, phase, constituent, sourceOffset, o, c + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_damage_isoDuctile_instance(phase) + sourceOffset = source_damage_isoDuctile_offset(phase) + + c = 0_pInt + source_damage_isoDuctile_postResults = 0.0_pReal + + do o = 1_pInt,source_damage_isoDuctile_Noutput(instance) + select case(source_damage_isoDuctile_outputID(o,instance)) + case (damage_drivingforce_ID) + source_damage_isoDuctile_postResults(c+1_pInt) = sourceState(phase)%p(sourceOffset)%state(1,constituent) + c = c + 1 + + end select + enddo +end function source_damage_isoDuctile_postResults + +end module source_damage_isoDuctile diff --git a/code/source_thermal_dissipation.f90 b/code/source_thermal_dissipation.f90 new file mode 100644 index 000000000..04e8c8690 --- /dev/null +++ b/code/source_thermal_dissipation.f90 @@ -0,0 +1,217 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for thermal source due to plastic dissipation +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_thermal_dissipation + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_thermal_dissipation_sizePostResults, & !< cumulative size of post results + source_thermal_dissipation_offset, & !< which source is my current thermal dissipation mechanism? + source_thermal_dissipation_instance !< instance of thermal dissipation source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_thermal_dissipation_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_thermal_dissipation_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_thermal_dissipation_Noutput !< number of outputs per instance of this source + + real(pReal), dimension(:), allocatable, private :: & + source_thermal_dissipation_coldworkCoeff + + public :: & + source_thermal_dissipation_init, & + source_thermal_dissipation_getRateAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_thermal_dissipation_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_thermal_dissipation_label, & + SOURCE_thermal_dissipation_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_dissipation_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_thermal_dissipation_ID),pInt) + if (maxNinstance == 0_pInt) return + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_thermal_dissipation_offset(material_Nphase), source=0_pInt) + allocate(source_thermal_dissipation_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_thermal_dissipation_instance(phase) = count(phase_source(:,1:phase) == SOURCE_thermal_dissipation_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == SOURCE_thermal_dissipation_ID) & + source_thermal_dissipation_offset(phase) = source + enddo + enddo + + allocate(source_thermal_dissipation_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_thermal_dissipation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_thermal_dissipation_output (maxval(phase_Noutput),maxNinstance)) + source_thermal_dissipation_output = '' + allocate(source_thermal_dissipation_Noutput(maxNinstance), source=0_pInt) + allocate(source_thermal_dissipation_coldworkCoeff(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_thermal_dissipation_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = source_thermal_dissipation_instance(phase) ! which instance of my source is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('dissipation_coldworkcoeff') + source_thermal_dissipation_coldworkCoeff(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_thermal_dissipation_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_thermal_dissipation_instance(phase) + sourceOffset = source_thermal_dissipation_offset(phase) + + sizeDotState = 0_pInt + sizeState = 0_pInt + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_thermal_dissipation_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_thermal_dissipation_init + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local vacancy generation rate +!-------------------------------------------------------------------------------------------------- +subroutine source_thermal_dissipation_getRateAndItsTangent(TDot, dTDOT_dT, Tstar_v, Lp, ipc, ip, el) + use math, only: & + math_Mandel6to33 + use material, only: & + mappingConstitutive + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(in), dimension(6) :: & + Tstar_v !< 2nd Piola Kirchhoff stress tensor (Mandel) + real(pReal), intent(in), dimension(3,3) :: & + Lp + real(pReal), intent(out) :: & + TDot, & + dTDOT_dT + integer(pInt) :: & + instance, phase, constituent + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_thermal_dissipation_instance(phase) + + TDot = source_thermal_dissipation_coldworkCoeff(instance)* & + sum(abs(math_Mandel6to33(Tstar_v)*Lp)) + dTDOT_dT = 0.0_pReal + +end subroutine source_thermal_dissipation_getRateAndItsTangent + +end module source_thermal_dissipation diff --git a/code/source_vacancy_irradiation.f90 b/code/source_vacancy_irradiation.f90 new file mode 100644 index 000000000..07798df29 --- /dev/null +++ b/code/source_vacancy_irradiation.f90 @@ -0,0 +1,250 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for vacancy generation due to irradiation +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_vacancy_irradiation + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_vacancy_irradiation_sizePostResults, & !< cumulative size of post results + source_vacancy_irradiation_offset, & !< which source is my current damage mechanism? + source_vacancy_irradiation_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_vacancy_irradiation_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_vacancy_irradiation_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_vacancy_irradiation_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + source_vacancy_irradiation_cascadeProb, & + source_vacancy_irradiation_cascadeVolume + + public :: & + source_vacancy_irradiation_init, & + source_vacancy_irradiation_deltaState, & + source_vacancy_irradiation_getRateAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_irradiation_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_vacancy_irradiation_label, & + SOURCE_vacancy_irradiation_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_irradiation_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_vacancy_irradiation_ID),pInt) + if (maxNinstance == 0_pInt) return + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_vacancy_irradiation_offset(material_Nphase), source=0_pInt) + allocate(source_vacancy_irradiation_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_vacancy_irradiation_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_irradiation_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_vacancy_irradiation_ID) & + source_vacancy_irradiation_offset(phase) = source + enddo + enddo + + allocate(source_vacancy_irradiation_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_vacancy_irradiation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_vacancy_irradiation_output(maxval(phase_Noutput),maxNinstance)) + source_vacancy_irradiation_output = '' + allocate(source_vacancy_irradiation_Noutput(maxNinstance), source=0_pInt) + allocate(source_vacancy_irradiation_cascadeProb(maxNinstance), source=0.0_pReal) + allocate(source_vacancy_irradiation_cascadeVolume(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_irradiation_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = source_vacancy_irradiation_instance(phase) ! which instance of my vacancy is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('irradiation_cascadeprobability') + source_vacancy_irradiation_cascadeProb(instance) = IO_floatValue(line,positions,2_pInt) + + case ('irradiation_cascadevolume') + source_vacancy_irradiation_cascadeVolume(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_vacancy_irradiation_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_vacancy_irradiation_instance(phase) + sourceOffset = source_vacancy_irradiation_offset(phase) + + sizeDotState = 2_pInt + sizeState = 2_pInt + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_irradiation_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.1_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_vacancy_irradiation_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_irradiation_deltaState(ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, constituent, sourceOffset + real(pReal) :: & + randNo + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_vacancy_irradiation_offset(phase) + + call random_number(randNo) + sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = & + randNo - sourceState(phase)%p(sourceOffset)%state(1,constituent) + call random_number(randNo) + sourceState(phase)%p(sourceOffset)%deltaState(2,constituent) = & + randNo - sourceState(phase)%p(sourceOffset)%state(2,constituent) + +end subroutine source_vacancy_irradiation_deltaState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local vacancy generation rate +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_irradiation_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out) :: & + CvDot, dCvDot_dCv + integer(pInt) :: & + instance, phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_vacancy_irradiation_instance(phase) + sourceOffset = source_vacancy_irradiation_offset(phase) + + CvDot = 0.0_pReal + dCvDot_dCv = 0.0_pReal + if (sourceState(phase)%p(sourceOffset)%state0(1,constituent) < source_vacancy_irradiation_cascadeProb(instance)) & + CvDot = sourceState(phase)%p(sourceOffset)%state0(2,constituent)*source_vacancy_irradiation_cascadeVolume(instance) + +end subroutine source_vacancy_irradiation_getRateAndItsTangent + +end module source_vacancy_irradiation diff --git a/code/source_vacancy_phenoplasticity.f90 b/code/source_vacancy_phenoplasticity.f90 new file mode 100644 index 000000000..8fca355ea --- /dev/null +++ b/code/source_vacancy_phenoplasticity.f90 @@ -0,0 +1,212 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for vacancy generation due to plasticity +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_vacancy_phenoplasticity + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_vacancy_phenoplasticity_sizePostResults, & !< cumulative size of post results + source_vacancy_phenoplasticity_offset, & !< which source is my current damage mechanism? + source_vacancy_phenoplasticity_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_vacancy_phenoplasticity_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_vacancy_phenoplasticity_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_vacancy_phenoplasticity_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + source_vacancy_phenoplasticity_rateCoeff + + public :: & + source_vacancy_phenoplasticity_init, & + source_vacancy_phenoplasticity_getRateAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_phenoplasticity_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_vacancy_phenoplasticity_label, & + SOURCE_vacancy_phenoplasticity_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_phenoplasticity_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_vacancy_phenoplasticity_ID),pInt) + if (maxNinstance == 0_pInt) return + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_vacancy_phenoplasticity_offset(material_Nphase), source=0_pInt) + allocate(source_vacancy_phenoplasticity_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_vacancy_phenoplasticity_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_phenoplasticity_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_vacancy_phenoplasticity_ID) & + source_vacancy_phenoplasticity_offset(phase) = source + enddo + enddo + + allocate(source_vacancy_phenoplasticity_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_vacancy_phenoplasticity_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_vacancy_phenoplasticity_output(maxval(phase_Noutput),maxNinstance)) + source_vacancy_phenoplasticity_output = '' + allocate(source_vacancy_phenoplasticity_Noutput(maxNinstance), source=0_pInt) + allocate(source_vacancy_phenoplasticity_rateCoeff(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_phenoplasticity_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = source_vacancy_phenoplasticity_instance(phase) ! which instance of my vacancy is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('phenoplasticity_ratecoeff') + source_vacancy_phenoplasticity_rateCoeff(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_vacancy_phenoplasticity_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_vacancy_phenoplasticity_instance(phase) + sourceOffset = source_vacancy_phenoplasticity_offset(phase) + + sizeDotState = 0_pInt + sizeState = 0_pInt + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_phenoplasticity_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_vacancy_phenoplasticity_init + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local vacancy generation rate +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_phenoplasticity_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el) + use material, only: & + mappingConstitutive, & + plasticState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out) :: & + CvDot, dCvDot_dCv + integer(pInt) :: & + instance, phase, constituent + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_vacancy_phenoplasticity_instance(phase) + + CvDot = & + source_vacancy_phenoplasticity_rateCoeff(instance)* & + sum(plasticState(phase)%slipRate(:,constituent)) + dCvDot_dCv = 0.0_pReal + +end subroutine source_vacancy_phenoplasticity_getRateAndItsTangent + +end module source_vacancy_phenoplasticity diff --git a/code/source_vacancy_thermalfluc.f90 b/code/source_vacancy_thermalfluc.f90 new file mode 100644 index 000000000..3bfc05884 --- /dev/null +++ b/code/source_vacancy_thermalfluc.f90 @@ -0,0 +1,240 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for vacancy generation due to thermal fluctuations +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module source_vacancy_thermalfluc + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + source_vacancy_thermalfluc_sizePostResults, & !< cumulative size of post results + source_vacancy_thermalfluc_offset, & !< which source is my current damage mechanism? + source_vacancy_thermalfluc_instance !< instance of damage source mechanism + + integer(pInt), dimension(:,:), allocatable, target, public :: & + source_vacancy_thermalfluc_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + source_vacancy_thermalfluc_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + source_vacancy_thermalfluc_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + source_vacancy_thermalfluc_amplitude + + public :: & + source_vacancy_thermalfluc_init, & + source_vacancy_thermalfluc_deltaState, & + source_vacancy_thermalfluc_getRateAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_thermalfluc_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use debug, only: & + debug_level,& + debug_constitutive,& + debug_levelBasic + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + phase_source, & + phase_Nsources, & + phase_Noutput, & + SOURCE_vacancy_thermalfluc_label, & + SOURCE_vacancy_thermalfluc_ID, & + material_Nphase, & + material_phase, & + sourceState, & + MATERIAL_partPhase + use numerics,only: & + worldrank, & + numerics_integrator + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,phase,instance,source,sourceOffset + integer(pInt) :: sizeState, sizeDotState + integer(pInt) :: NofMyPhase + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- source_'//SOURCE_vacancy_thermalfluc_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(phase_source == SOURCE_vacancy_thermalfluc_ID),pInt) + if (maxNinstance == 0_pInt) return + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & + write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance + + allocate(source_vacancy_thermalfluc_offset(material_Nphase), source=0_pInt) + allocate(source_vacancy_thermalfluc_instance(material_Nphase), source=0_pInt) + do phase = 1, material_Nphase + source_vacancy_thermalfluc_instance(phase) = count(phase_source(:,1:phase) == source_vacancy_thermalfluc_ID) + do source = 1, phase_Nsources(phase) + if (phase_source(source,phase) == source_vacancy_thermalfluc_ID) & + source_vacancy_thermalfluc_offset(phase) = source + enddo + enddo + + allocate(source_vacancy_thermalfluc_sizePostResults(maxNinstance), source=0_pInt) + allocate(source_vacancy_thermalfluc_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) + allocate(source_vacancy_thermalfluc_output(maxval(phase_Noutput),maxNinstance)) + source_vacancy_thermalfluc_output = '' + allocate(source_vacancy_thermalfluc_Noutput(maxNinstance), source=0_pInt) + allocate(source_vacancy_thermalfluc_amplitude(maxNinstance), source=0.0_pReal) + + rewind(fileUnit) + phase = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next phase section + phase = phase + 1_pInt ! advance phase section counter + cycle ! skip to next line + endif + + if (phase > 0_pInt ) then; if (any(phase_source(:,phase) == SOURCE_vacancy_thermalfluc_ID)) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = source_vacancy_thermalfluc_instance(phase) ! which instance of my vacancy is present phase + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('thermalfluctuation_amplitude') + source_vacancy_thermalfluc_amplitude(instance) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingFile + + initializeInstances: do phase = 1_pInt, material_Nphase + if (any(phase_source(:,phase) == SOURCE_vacancy_thermalfluc_ID)) then + NofMyPhase=count(material_phase==phase) + instance = source_vacancy_thermalfluc_instance(phase) + sourceOffset = source_vacancy_thermalfluc_offset(phase) + + sizeDotState = 1_pInt + sizeState = 1_pInt + sourceState(phase)%p(sourceOffset)%sizeState = sizeState + sourceState(phase)%p(sourceOffset)%sizeDotState = sizeDotState + sourceState(phase)%p(sourceOffset)%sizePostResults = source_vacancy_thermalfluc_sizePostResults(instance) + allocate(sourceState(phase)%p(sourceOffset)%aTolState (sizeState), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(sourceOffset)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 1_pInt)) then + allocate(sourceState(phase)%p(sourceOffset)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(sourceOffset)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + endif + if (any(numerics_integrator == 4_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + if (any(numerics_integrator == 5_pInt)) & + allocate(sourceState(phase)%p(sourceOffset)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine source_vacancy_thermalfluc_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates derived quantities from state +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_thermalfluc_deltaState(ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< component-ID of integration point + ip, & !< integration point + el !< element + integer(pInt) :: & + phase, constituent, sourceOffset + real(pReal) :: & + randNo + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + sourceOffset = source_vacancy_thermalfluc_offset(phase) + + call random_number(randNo) + sourceState(phase)%p(sourceOffset)%deltaState(1,constituent) = & + randNo - sourceState(phase)%p(sourceOffset)%state(1,constituent) + +end subroutine source_vacancy_thermalfluc_deltaState + +!-------------------------------------------------------------------------------------------------- +!> @brief returns local vacancy generation rate +!-------------------------------------------------------------------------------------------------- +subroutine source_vacancy_thermalfluc_getRateAndItsTangent(CvDot, dCvDot_dCv, ipc, ip, el) + use material, only: & + mappingConstitutive, & + sourceState + + implicit none + integer(pInt), intent(in) :: & + ipc, & !< grain number + ip, & !< integration point number + el !< element number + real(pReal), intent(out) :: & + CvDot, dCvDot_dCv + integer(pInt) :: & + instance, phase, constituent, sourceOffset + + phase = mappingConstitutive(2,ipc,ip,el) + constituent = mappingConstitutive(1,ipc,ip,el) + instance = source_vacancy_thermalfluc_instance(phase) + sourceOffset = source_vacancy_thermalfluc_offset(phase) + + CvDot = source_vacancy_thermalfluc_amplitude(instance)*(sourceState(phase)%p(sourceOffset)%state0(2,constituent) - 0.5_pReal) + dCvDot_dCv = 0.0_pReal + +end subroutine source_vacancy_thermalfluc_getRateAndItsTangent + +end module source_vacancy_thermalfluc diff --git a/code/thermal_adiabatic.f90 b/code/thermal_adiabatic.f90 index e137e1039..3c7888331 100644 --- a/code/thermal_adiabatic.f90 +++ b/code/thermal_adiabatic.f90 @@ -2,7 +2,7 @@ ! $Id$ !-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine incoprorating local heat generation due to plastic dissipation +!> @brief material subroutine for adiabatic temperature evolution !> @details to be done !-------------------------------------------------------------------------------------------------- module thermal_adiabatic @@ -22,10 +22,7 @@ module thermal_adiabatic thermal_adiabatic_output !< name of each post result output integer(pInt), dimension(:), allocatable, target, public :: & - thermal_adiabatic_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, public :: & - thermal_adiabatic_aTol + thermal_adiabatic_Noutput !< number of outputs per instance of this thermal model enum, bind(c) enumerator :: undefined_ID, & @@ -37,14 +34,10 @@ module thermal_adiabatic public :: & thermal_adiabatic_init, & - thermal_adiabatic_stateInit, & - thermal_adiabatic_aTolState, & - thermal_adiabatic_microstructure, & - thermal_adiabatic_LTAndItsTangent, & - thermal_adiabatic_getTemperature, & - thermal_adiabatic_getLocalTemperature, & - thermal_adiabatic_putLocalTemperature, & - thermal_adiabatic_getHeatGeneration, & + thermal_adiabatic_updateState, & + thermal_adiabatic_getSourceAndItsTangent, & + thermal_adiabatic_getSpecificHeat, & + thermal_adiabatic_getMassDensity, & thermal_adiabatic_postResults contains @@ -56,10 +49,6 @@ contains !-------------------------------------------------------------------------------------------------- subroutine thermal_adiabatic_init(fileUnit,temperature_init) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic use IO, only: & IO_read, & IO_lc, & @@ -74,17 +63,20 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init) IO_timeStamp, & IO_EOF use material, only: & - phase_thermal, & - phase_thermalInstance, & - phase_Noutput, & - LOCAL_THERMAL_ADIABATIC_label, & - LOCAL_THERMAL_adiabatic_ID, & - material_phase, & + thermal_type, & + thermal_typeInstance, & + homogenization_Noutput, & + THERMAL_ADIABATIC_label, & + THERMAL_adiabatic_ID, & + material_homog, & + mappingHomogenization, & thermalState, & - MATERIAL_partPhase + thermalMapping, & + temperature, & + temperatureRate, & + material_partHomogenization use numerics,only: & - worldrank, & - numerics_integrator + worldrank implicit none real(pReal), intent(in) :: temperature_init !< initial temperature @@ -92,54 +84,51 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init) integer(pInt), parameter :: MAXNCHUNKS = 7_pInt integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog character(len=65536) :: & tag = '', & line = '' mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- thermal_'//LOCAL_THERMAL_ADIABATIC_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_ADIABATIC_label//' init -+>>>' write(6,'(a)') ' $Id$' write(6,'(a15,a)') ' Current time: ',IO_timeStamp() #include "compilation_info.f90" endif mainProcess - maxNinstance = int(count(phase_thermal == LOCAL_THERMAL_adiabatic_ID),pInt) + maxNinstance = int(count(thermal_type == THERMAL_adiabatic_ID),pInt) if (maxNinstance == 0_pInt) return - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - allocate(thermal_adiabatic_sizePostResults(maxNinstance), source=0_pInt) - allocate(thermal_adiabatic_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(thermal_adiabatic_output(maxval(phase_Noutput),maxNinstance)) + allocate(thermal_adiabatic_sizePostResults(maxNinstance), source=0_pInt) + allocate(thermal_adiabatic_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(thermal_adiabatic_output (maxval(homogenization_Noutput),maxNinstance)) thermal_adiabatic_output = '' - allocate(thermal_adiabatic_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(thermal_adiabatic_Noutput(maxNinstance), source=0_pInt) - allocate(thermal_adiabatic_aTol(maxNinstance), source=0.0_pReal) + allocate(thermal_adiabatic_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(thermal_adiabatic_Noutput (maxNinstance), source=0_pInt) rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to line = IO_read(fileUnit) enddo - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part line = IO_read(fileUnit) 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 + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter cycle ! skip to next line endif - if (phase > 0_pInt ) then; if (phase_thermal(phase) == LOCAL_THERMAL_adiabatic_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + if (section > 0_pInt ) then; if (thermal_type(section) == THERMAL_adiabatic_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - instance = phase_thermalInstance(phase) ! which instance of my thermal is present phase + instance = thermal_typeInstance(section) ! which instance of my thermal is present homog positions = IO_stringPos(line,MAXNCHUNKS) tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key select case(tag) @@ -152,17 +141,14 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init) IO_lc(IO_stringValue(line,positions,2_pInt)) end select - case ('atol_adiabatic') - thermal_adiabatic_aTol(instance) = IO_floatValue(line,positions,2_pInt) - end select endif; endif enddo parsingFile - initializeInstances: do phase = 1_pInt, size(phase_thermal) - if (phase_thermal(phase) == LOCAL_THERMAL_adiabatic_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_thermalInstance(phase) + initializeInstances: do section = 1_pInt, size(thermal_type) + if (thermal_type(section) == THERMAL_adiabatic_ID) then + NofMyHomog=count(material_homog==section) + instance = thermal_typeInstance(section) !-------------------------------------------------------------------------------------------------- ! Determine size of postResults array @@ -177,280 +163,243 @@ subroutine thermal_adiabatic_init(fileUnit,temperature_init) thermal_adiabatic_sizePostResults(instance) = thermal_adiabatic_sizePostResults(instance) + mySize endif enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = 1_pInt - thermalState(phase)%sizeState = sizeState - thermalState(phase)%sizeDotState = sizeDotState - thermalState(phase)%sizePostResults = thermal_adiabatic_sizePostResults(instance) - allocate(thermalState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(thermalState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(thermalState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(thermalState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(thermalState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(thermalState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) +! allocate state arrays + sizeState = 1_pInt + thermalState(section)%sizeState = sizeState + thermalState(section)%sizePostResults = thermal_adiabatic_sizePostResults(instance) + allocate(thermalState(section)%state0 (sizeState,NofMyHomog), source=temperature_init) + allocate(thermalState(section)%subState0(sizeState,NofMyHomog), source=temperature_init) + allocate(thermalState(section)%state (sizeState,NofMyHomog), source=temperature_init) - call thermal_adiabatic_stateInit(phase,temperature_init) - call thermal_adiabatic_aTolState(phase,instance) + nullify(thermalMapping(section)%p) + thermalMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(temperature(section)%p) + temperature(section)%p => thermalState(section)%state(1,:) + deallocate(temperatureRate(section)%p) + allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal) + endif enddo initializeInstances end subroutine thermal_adiabatic_init !-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant NEW state values for a given instance of this thermal +!> @brief calculates adiabatic change in temperature based on local heat generation model !-------------------------------------------------------------------------------------------------- -subroutine thermal_adiabatic_stateInit(phase,temperature_init) - use material, only: & - thermalState - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the thermal - real(pReal), intent(in) :: temperature_init !< initial temperature - - real(pReal), dimension(thermalState(phase)%sizeState) :: tempState - - tempState(1) = temperature_init - thermalState(phase)%state = spread(tempState,2,size(thermalState(phase)%state(1,:))) - thermalState(phase)%state0 = thermalState(phase)%state - thermalState(phase)%partionedState0 = thermalState(phase)%state -end subroutine thermal_adiabatic_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this thermal -!-------------------------------------------------------------------------------------------------- -subroutine thermal_adiabatic_aTolState(phase,instance) - use material, only: & - thermalState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the thermal - real(pReal), dimension(thermalState(phase)%sizeState) :: tempTol - - tempTol = thermal_adiabatic_aTol(instance) - thermalState(phase)%aTolState = tempTol -end subroutine thermal_adiabatic_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine thermal_adiabatic_microstructure(Tstar_v, Lp, subdt, ipc, ip, el) - use lattice, only: & - lattice_massDensity, & - lattice_specificHeat - use material, only: & - mappingConstitutive, & - thermalState - use math, only: & - math_Mandel6to33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(in), dimension(3,3) :: & - Lp !< plastic velocity gradient - real(pReal), intent(in) :: & - subdt - integer(pInt) :: & - phase, & - constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - - thermalState(phase)%state(1,constituent) = & - thermalState(phase)%subState0(1,constituent) + & - subdt* & - 0.95_pReal*sum(abs(math_Mandel6to33(Tstar_v))*Lp)/ & - (lattice_massDensity(phase)*lattice_specificHeat(phase)) - -end subroutine thermal_adiabatic_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief contains the constitutive equation for calculating the velocity gradient -!-------------------------------------------------------------------------------------------------- -subroutine thermal_adiabatic_LTAndItsTangent(LT, dLT_dTstar3333, Tstar_v, Lp, ipc, ip, el) - use lattice, only: & - lattice_massDensity, & - lattice_specificHeat, & - lattice_thermalExpansion33 - use material, only: & - mappingConstitutive - use math, only: & - math_Plain3333to99, & - math_Mandel6to33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(in), dimension(3,3) :: & - Lp !< plastic velocity gradient - real(pReal), intent(out), dimension(3,3) :: & - LT !< thermal velocity gradient - real(pReal), intent(out), dimension(3,3,3,3) :: & - dLT_dTstar3333 !< derivative of LT with respect to Tstar (4th-order tensor) - integer(pInt) :: & - phase, & - constituent, & - i, j, k, l - real(pReal) :: & - Tdot - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - - Tdot = 0.95_pReal & - * sum(abs(math_Mandel6to33(Tstar_v))*Lp) & - / (lattice_massDensity(phase)*lattice_specificHeat(phase)) - - LT = Tdot*lattice_thermalExpansion33(1:3,1:3,phase) - dLT_dTstar3333 = 0.0_pReal - forall (i=1_pInt:3_pInt,j=1_pInt:3_pInt,k=1_pInt:3_pInt,l=1_pInt:3_pInt) & - dLT_dTstar3333(i,j,k,l) = Lp(k,l)*lattice_thermalExpansion33(i,j,phase) - - dLT_dTstar3333 = 0.95_pReal*dLT_dTstar3333/(lattice_massDensity(phase)*lattice_specificHeat(phase)) - -end subroutine thermal_adiabatic_LTAndItsTangent - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -pure function thermal_adiabatic_getTemperature(ipc, ip, el) +function thermal_adiabatic_updateState(subdt, ip, el) + use numerics, only: & + err_thermal_tolAbs, & + err_thermal_tolRel use material, only: & mappingHomogenization, & - fieldThermal, & - field_thermal_type, & - FIELD_THERMAL_nonlocal_ID, & - material_homog, & - mappingConstitutive, & - thermalState - + thermalState, & + temperature, & + temperatureRate, & + thermalMapping + implicit none integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: thermal_adiabatic_getTemperature - - select case(field_thermal_type(material_homog(ip,el))) - case (FIELD_THERMAL_nonlocal_ID) - thermal_adiabatic_getTemperature = fieldThermal(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - - case default - thermal_adiabatic_getTemperature = thermalState(mappingConstitutive(2,ipc,ip,el))% & - state(1,mappingConstitutive(1,ipc,ip,el)) - - end select - -end function thermal_adiabatic_getTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -pure function thermal_adiabatic_getLocalTemperature(ipc, ip, el) - use material, only: & - mappingConstitutive, & - ThermalState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: & - thermal_adiabatic_getLocalTemperature - - thermal_adiabatic_getLocalTemperature = & - thermalState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function thermal_adiabatic_getLocalTemperature - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -subroutine thermal_adiabatic_putLocalTemperature(ipc, ip, el, localTemperature) - use material, only: & - mappingConstitutive, & - ThermalState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number ip, & !< integration point number el !< element number real(pReal), intent(in) :: & - localTemperature + subdt + logical, dimension(2) :: & + thermal_adiabatic_updateState + integer(pInt) :: & + homog, & + offset + real(pReal) :: & + T, Tdot, dTdot_dT + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) - thermalState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))= & - localTemperature + T = thermalState(homog)%subState0(1,offset) + call thermal_adiabatic_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el) + T = T + subdt*thermal_adiabatic_getSpecificHeat(ip,el)*thermal_adiabatic_getMassDensity(ip,el)*Tdot -end subroutine thermal_adiabatic_putLocalTemperature + thermal_adiabatic_updateState = [ abs(T - thermalState(homog)%state(1,offset)) & + <= err_thermal_tolAbs & + .or. abs(T - thermalState(homog)%state(1,offset)) & + <= err_thermal_tolRel*abs(thermalState(homog)%state(1,offset)), & + .true.] + + temperature (homog)%p(thermalMapping(homog)%p(ip,el)) = T + temperatureRate(homog)%p(thermalMapping(homog)%p(ip,el)) = & + (thermalState(homog)%state(1,offset) - thermalState(homog)%subState0(1,offset))/subdt +end function thermal_adiabatic_updateState + !-------------------------------------------------------------------------------------------------- !> @brief returns heat generation rate !-------------------------------------------------------------------------------------------------- -pure function thermal_adiabatic_getHeatGeneration(Tstar_v, Lp) +subroutine thermal_adiabatic_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el) use math, only: & math_Mandel6to33 + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + thermal_typeInstance, & + phase_Nsources, & + phase_source, & + SOURCE_thermal_dissipation_ID + use source_thermal_dissipation, only: & + source_thermal_dissipation_getRateAndItsTangent + use crystallite, only: & + crystallite_Tstar_v, & + crystallite_Lp implicit none - real(pReal), intent(in), dimension(6) :: & - Tstar_v !< 2nd Piola-Kirchhoff stress - real(pReal), intent(in), dimension(3,3) :: & - Lp !< plastic velocity gradient - real(pReal) :: thermal_adiabatic_getHeatGeneration + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + T + real(pReal), intent(out) :: & + Tdot, dTdot_dT + real(pReal) :: & + my_Tdot, my_dTdot_dT + integer(pInt) :: & + phase, & + homog, & + offset, & + instance, & + grain, & + source + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + instance = thermal_typeInstance(homog) - thermal_adiabatic_getHeatGeneration = 0.95_pReal & - * sum(abs(math_Mandel6to33(Tstar_v))*Lp) + Tdot = 0.0_pReal + dTdot_dT = 0.0_pReal + do grain = 1, homogenization_Ngrains(homog) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_thermal_dissipation_ID) + call source_thermal_dissipation_getRateAndItsTangent(my_Tdot, my_dTdot_dT, & + crystallite_Tstar_v(1:6,grain,ip,el), & + crystallite_Lp(1:3,1:3,grain,ip,el), & + grain, ip, el) + + case default + my_Tdot = 0.0_pReal + my_dTdot_dT = 0.0_pReal + end select + Tdot = Tdot + my_Tdot + dTdot_dT = dTdot_dT + my_dTdot_dT + enddo + enddo -end function thermal_adiabatic_getHeatGeneration + Tdot = Tdot/homogenization_Ngrains(homog) + dTdot_dT = dTdot_dT/homogenization_Ngrains(homog) + +end subroutine thermal_adiabatic_getSourceAndItsTangent !-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results +!> @brief returns homogenized specific heat capacity !-------------------------------------------------------------------------------------------------- -function thermal_adiabatic_postResults(ipc,ip,el) +function thermal_adiabatic_getSpecificHeat(ip,el) + use lattice, only: & + lattice_specificHeat use material, only: & - mappingConstitutive, & - phase_thermalInstance, & - thermalState + homogenization_Ngrains, & + mappingHomogenization, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + thermal_adiabatic_getSpecificHeat + integer(pInt) :: & + homog, grain + + thermal_adiabatic_getSpecificHeat = 0.0_pReal + + homog = mappingHomogenization(2,ip,el) + + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + thermal_adiabatic_getSpecificHeat = thermal_adiabatic_getSpecificHeat + & + lattice_specificHeat(material_phase(grain,ip,el)) + enddo + + thermal_adiabatic_getSpecificHeat = & + thermal_adiabatic_getSpecificHeat/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function thermal_adiabatic_getSpecificHeat + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized mass density +!-------------------------------------------------------------------------------------------------- +function thermal_adiabatic_getMassDensity(ip,el) + use lattice, only: & + lattice_massDensity + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + thermal_adiabatic_getMassDensity + integer(pInt) :: & + homog, grain + + thermal_adiabatic_getMassDensity = 0.0_pReal + + homog = mappingHomogenization(2,ip,el) + + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + thermal_adiabatic_getMassDensity = thermal_adiabatic_getMassDensity + & + lattice_massDensity(material_phase(grain,ip,el)) + enddo + + thermal_adiabatic_getMassDensity = & + thermal_adiabatic_getMassDensity/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function thermal_adiabatic_getMassDensity + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of thermal results +!-------------------------------------------------------------------------------------------------- +function thermal_adiabatic_postResults(ip,el) + use material, only: & + mappingHomogenization, & + thermal_typeInstance, & + thermalMapping, & + temperature implicit none integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point ip, & !< integration point el !< element - real(pReal), dimension(thermal_adiabatic_sizePostResults(phase_thermalInstance(mappingConstitutive(2,ipc,ip,el)))) :: & + real(pReal), dimension(thermal_adiabatic_sizePostResults(thermal_typeInstance(mappingHomogenization(2,ip,el)))) :: & thermal_adiabatic_postResults integer(pInt) :: & - instance, phase, constituent, o, c + instance, homog, offset, o, c - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_thermalInstance(phase) + homog = mappingHomogenization(2,ip,el) + offset = thermalMapping(homog)%p(ip,el) + instance = thermal_typeInstance(homog) c = 0_pInt thermal_adiabatic_postResults = 0.0_pReal @@ -459,7 +408,7 @@ function thermal_adiabatic_postResults(ipc,ip,el) select case(thermal_adiabatic_outputID(o,instance)) case (temperature_ID) - thermal_adiabatic_postResults(c+1_pInt) = thermalState(phase)%state(1,constituent) + thermal_adiabatic_postResults(c+1_pInt) = temperature(homog)%p(offset) c = c + 1 end select enddo diff --git a/code/thermal_conduction.f90 b/code/thermal_conduction.f90 new file mode 100644 index 000000000..570abe8ae --- /dev/null +++ b/code/thermal_conduction.f90 @@ -0,0 +1,439 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for temperature evolution from heat conduction +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module thermal_conduction + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + thermal_conduction_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + thermal_conduction_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + thermal_conduction_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + thermal_conduction_Noutput !< number of outputs per instance of this damage + + enum, bind(c) + enumerator :: undefined_ID, & + temperature_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + thermal_conduction_outputID !< ID of each post result output + + + public :: & + thermal_conduction_init, & + thermal_conduction_getSourceAndItsTangent, & + thermal_conduction_getConductivity33, & + thermal_conduction_getSpecificHeat, & + thermal_conduction_getMassDensity, & + thermal_conduction_putTemperatureAndItsRate, & + thermal_conduction_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine thermal_conduction_init(fileUnit,temperature_init) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + thermal_type, & + thermal_typeInstance, & + homogenization_Noutput, & + THERMAL_conduction_label, & + THERMAL_conduction_ID, & + material_homog, & + mappingHomogenization, & + thermalState, & + thermalMapping, & + temperature, & + temperatureRate, & + material_partHomogenization + use numerics,only: & + worldrank + + implicit none + real(pReal), intent(in) :: temperature_init !< initial temperature + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_CONDUCTION_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(thermal_type == THERMAL_conduction_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(thermal_conduction_sizePostResults(maxNinstance), source=0_pInt) + allocate(thermal_conduction_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(thermal_conduction_output (maxval(homogenization_Noutput),maxNinstance)) + thermal_conduction_output = '' + allocate(thermal_conduction_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(thermal_conduction_Noutput (maxNinstance), source=0_pInt) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (thermal_type(section) == THERMAL_conduction_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = thermal_typeInstance(section) ! which instance of my thermal is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('temperature') + thermal_conduction_Noutput(instance) = thermal_conduction_Noutput(instance) + 1_pInt + thermal_conduction_outputID(thermal_conduction_Noutput(instance),instance) = temperature_ID + thermal_conduction_output(thermal_conduction_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingFile + + initializeInstances: do section = 1_pInt, size(thermal_type) + if (thermal_type(section) == THERMAL_conduction_ID) then + NofMyHomog=count(material_homog==section) + instance = thermal_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,thermal_conduction_Noutput(instance) + select case(thermal_conduction_outputID(o,instance)) + case(temperature_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + thermal_conduction_sizePostResult(o,instance) = mySize + thermal_conduction_sizePostResults(instance) = thermal_conduction_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 0_pInt + thermalState(section)%sizeState = sizeState + thermalState(section)%sizePostResults = thermal_conduction_sizePostResults(instance) + allocate(thermalState(section)%state0 (sizeState,NofMyHomog)) + allocate(thermalState(section)%subState0(sizeState,NofMyHomog)) + allocate(thermalState(section)%state (sizeState,NofMyHomog)) + + nullify(thermalMapping(section)%p) + thermalMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(temperature (section)%p) + allocate (temperature (section)%p(NofMyHomog), source=temperature_init) + deallocate(temperatureRate(section)%p) + allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine thermal_conduction_init + +!-------------------------------------------------------------------------------------------------- +!> @brief returns heat generation rate +!-------------------------------------------------------------------------------------------------- +subroutine thermal_conduction_getSourceAndItsTangent(Tdot, dTdot_dT, T, ip, el) + use math, only: & + math_Mandel6to33 + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + thermal_typeInstance, & + phase_Nsources, & + phase_source, & + SOURCE_thermal_dissipation_ID + use source_thermal_dissipation, only: & + source_thermal_dissipation_getRateAndItsTangent + use crystallite, only: & + crystallite_Tstar_v, & + crystallite_Lp + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + T + real(pReal), intent(out) :: & + Tdot, dTdot_dT + real(pReal) :: & + my_Tdot, my_dTdot_dT + integer(pInt) :: & + phase, & + homog, & + offset, & + instance, & + grain, & + source + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + instance = thermal_typeInstance(homog) + + Tdot = 0.0_pReal + dTdot_dT = 0.0_pReal + do grain = 1, homogenization_Ngrains(homog) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_thermal_dissipation_ID) + call source_thermal_dissipation_getRateAndItsTangent(my_Tdot, my_dTdot_dT, & + crystallite_Tstar_v(1:6,grain,ip,el), & + crystallite_Lp(1:3,1:3,grain,ip,el), & + grain, ip, el) + + case default + my_Tdot = 0.0_pReal + my_dTdot_dT = 0.0_pReal + + end select + Tdot = Tdot + my_Tdot + dTdot_dT = dTdot_dT + my_dTdot_dT + enddo + enddo + + Tdot = Tdot/homogenization_Ngrains(homog) + dTdot_dT = dTdot_dT/homogenization_Ngrains(homog) + +end subroutine thermal_conduction_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized thermal conductivity in reference configuration +!-------------------------------------------------------------------------------------------------- +function thermal_conduction_getConductivity33(ip,el) + use lattice, only: & + lattice_thermalConductivity33 + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + thermal_conduction_getConductivity33 + integer(pInt) :: & + homog, & + grain + + homog = mappingHomogenization(2,ip,el) + + thermal_conduction_getConductivity33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + thermal_conduction_getConductivity33 = thermal_conduction_getConductivity33 + & + crystallite_push33ToRef(grain,ip,el,lattice_thermalConductivity33(:,:,material_phase(grain,ip,el))) + enddo + + thermal_conduction_getConductivity33 = & + thermal_conduction_getConductivity33/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function thermal_conduction_getConductivity33 + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized specific heat capacity +!-------------------------------------------------------------------------------------------------- +function thermal_conduction_getSpecificHeat(ip,el) + use lattice, only: & + lattice_specificHeat + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + thermal_conduction_getSpecificHeat + integer(pInt) :: & + homog, grain + + thermal_conduction_getSpecificHeat = 0.0_pReal + + homog = mappingHomogenization(2,ip,el) + + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + thermal_conduction_getSpecificHeat = thermal_conduction_getSpecificHeat + & + lattice_specificHeat(material_phase(grain,ip,el)) + enddo + + thermal_conduction_getSpecificHeat = & + thermal_conduction_getSpecificHeat/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function thermal_conduction_getSpecificHeat + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized mass density +!-------------------------------------------------------------------------------------------------- +function thermal_conduction_getMassDensity(ip,el) + use lattice, only: & + lattice_massDensity + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + thermal_conduction_getMassDensity + integer(pInt) :: & + homog, grain + + thermal_conduction_getMassDensity = 0.0_pReal + + homog = mappingHomogenization(2,ip,el) + + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + thermal_conduction_getMassDensity = thermal_conduction_getMassDensity + & + lattice_massDensity(material_phase(grain,ip,el)) + enddo + + thermal_conduction_getMassDensity = & + thermal_conduction_getMassDensity/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function thermal_conduction_getMassDensity + +!-------------------------------------------------------------------------------------------------- +!> @brief updates thermal state with solution from heat conduction PDE +!-------------------------------------------------------------------------------------------------- +subroutine thermal_conduction_putTemperatureAndItsRate(T,Tdot,ip,el) + use material, only: & + mappingHomogenization, & + temperature, & + temperatureRate, & + thermalMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + T, & + Tdot + integer(pInt) :: & + homog, & + offset + + homog = mappingHomogenization(2,ip,el) + offset = thermalMapping(homog)%p(ip,el) + temperature (homog)%p(offset) = T + temperatureRate(homog)%p(offset) = Tdot + +end subroutine thermal_conduction_putTemperatureAndItsRate + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of thermal results +!-------------------------------------------------------------------------------------------------- +function thermal_conduction_postResults(ip,el) + use material, only: & + mappingHomogenization, & + thermal_typeInstance, & + temperature, & + thermalMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(thermal_conduction_sizePostResults(thermal_typeInstance(mappingHomogenization(2,ip,el)))) :: & + thermal_conduction_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = thermalMapping(homog)%p(ip,el) + instance = thermal_typeInstance(homog) + + c = 0_pInt + thermal_conduction_postResults = 0.0_pReal + + do o = 1_pInt,thermal_conduction_Noutput(instance) + select case(thermal_conduction_outputID(o,instance)) + + case (temperature_ID) + thermal_conduction_postResults(c+1_pInt) = temperature(homog)%p(offset) + c = c + 1 + end select + enddo +end function thermal_conduction_postResults + +end module thermal_conduction diff --git a/code/thermal_isothermal.f90 b/code/thermal_isothermal.f90 index dca088708..d3d033c17 100644 --- a/code/thermal_isothermal.f90 +++ b/code/thermal_isothermal.f90 @@ -1,107 +1,66 @@ !-------------------------------------------------------------------------------------------------- ! $Id$ !-------------------------------------------------------------------------------------------------- -!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH -!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine for purely elastic material +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for isothermal temperature field !-------------------------------------------------------------------------------------------------- module thermal_isothermal - use prec, only: & - pInt, & - pReal implicit none private - integer(pInt), dimension(:), allocatable, public, protected :: & - thermal_isothermal_sizePostResults - - integer(pInt), dimension(:,:), allocatable, target, public :: & - thermal_isothermal_sizePostResult !< size of each post result output - - real(pReal), dimension(:), allocatable, public :: & - thermal_isothermal_temperature - + public :: & thermal_isothermal_init contains - !-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks +!> @brief allocates all neccessary fields, reads information from material configuration file !-------------------------------------------------------------------------------------------------- subroutine thermal_isothermal_init(temperature_init) use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level, & - debug_constitutive, & - debug_levelBasic + use prec, only: & + pReal, & + pInt use IO, only: & IO_timeStamp + use material use numerics, only: & - worldrank, & - numerics_integrator - use material, only: & - phase_thermal, & - LOCAL_THERMAL_ISOTHERMAL_label, & - LOCAL_THERMAL_ISOTHERMAL_ID, & - material_phase, & - thermalState, & - MATERIAL_partPhase - + worldrank + implicit none - real(pReal), intent(in) :: temperature_init !< initial temperature integer(pInt) :: & - maxNinstance, & - phase, & - NofMyPhase, & - sizeState, & - sizeDotState + homog, & + NofMyHomog, & + sizeState mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- thermal_'//LOCAL_THERMAL_ISOTHERMAL_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_isothermal_label//' init -+>>>' write(6,'(a)') ' $Id$' write(6,'(a15,a)') ' Current time: ',IO_timeStamp() #include "compilation_info.f90" endif mainProcess - maxNinstance = int(count(phase_thermal == LOCAL_THERMAL_ISOTHERMAL_ID),pInt) - if (maxNinstance == 0_pInt) return + initializeInstances: do homog = 1_pInt, material_Nhomogenization + + myhomog: if (thermal_type(homog) == THERMAL_isothermal_ID) then + NofMyHomog = count(material_homog == homog) + sizeState = 0_pInt + thermalState(homog)%sizeState = sizeState + thermalState(homog)%sizePostResults = sizeState + allocate(thermalState(homog)%state0 (sizeState,NofMyHomog), source=0.0_pReal) + allocate(thermalState(homog)%subState0(sizeState,NofMyHomog), source=0.0_pReal) + allocate(thermalState(homog)%state (sizeState,NofMyHomog), source=0.0_pReal) + + deallocate(temperature (homog)%p) + allocate (temperature (homog)%p(1), source=temperature_init) + deallocate(temperatureRate(homog)%p) + allocate (temperatureRate(homog)%p(1), source=0.0_pReal) - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - initializeInstances: do phase = 1_pInt, size(phase_thermal) - NofMyPhase=count(material_phase==phase) - - if (phase_thermal(phase) == LOCAL_THERMAL_ISOTHERMAL_ID) then - sizeState = 0_pInt - thermalState(phase)%sizeState = sizeState - sizeDotState = sizeState - thermalState(phase)%sizeDotState = sizeDotState - thermalState(phase)%sizePostResults = 0_pInt - allocate(thermalState(phase)%state0 (sizeState,NofMyPhase)) - allocate(thermalState(phase)%partionedState0(sizeState,NofMyPhase)) - allocate(thermalState(phase)%subState0 (sizeState,NofMyPhase)) - allocate(thermalState(phase)%state (sizeState,NofMyPhase)) - allocate(thermalState(phase)%state_backup (sizeState,NofMyPhase)) - allocate(thermalState(phase)%aTolState (NofMyPhase)) - allocate(thermalState(phase)%dotState (sizeDotState,NofMyPhase)) - allocate(thermalState(phase)%dotState_backup(sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 1_pInt)) then - allocate(thermalState(phase)%previousDotState (sizeDotState,NofMyPhase)) - allocate(thermalState(phase)%previousDotState2 (sizeDotState,NofMyPhase)) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(thermalState(phase)%RK4dotState (sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 5_pInt)) & - allocate(thermalState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase)) - endif + endif myhomog enddo initializeInstances - allocate(thermal_isothermal_sizePostResults(maxNinstance), source=0_pInt) - allocate(thermal_isothermal_temperature(maxNinstance), source=temperature_init) + end subroutine thermal_isothermal_init diff --git a/code/vacancy_constant.f90 b/code/vacancy_constant.f90 deleted file mode 100644 index 5f9913f2b..000000000 --- a/code/vacancy_constant.f90 +++ /dev/null @@ -1,101 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine for constant vacancy concentration -!-------------------------------------------------------------------------------------------------- -module vacancy_constant - use prec, only: & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - vacancy_constant_sizePostResults - - integer(pInt), dimension(:,:), allocatable, target, public :: & - vacancy_constant_sizePostResult !< size of each post result output - - public :: & - vacancy_constant_init - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_constant_init - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level, & - debug_constitutive, & - debug_levelBasic - use IO, only: & - IO_timeStamp - use numerics, only: & - worldrank, & - numerics_integrator - use material, only: & - phase_vacancy, & - LOCAL_VACANCY_CONSTANT_label, & - LOCAL_VACANCY_CONSTANT_ID, & - material_phase, & - vacancyState, & - MATERIAL_partPhase - - implicit none - - integer(pInt) :: & - maxNinstance, & - phase, & - NofMyPhase, & - sizeState, & - sizeDotState - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- vacancy_'//LOCAL_VACANCY_CONSTANT_label//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_vacancy == LOCAL_VACANCY_CONSTANT_ID),pInt) - if (maxNinstance == 0_pInt) return - - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - initializeInstances: do phase = 1_pInt, size(phase_vacancy) - NofMyPhase=count(material_phase==phase) - - if (phase_vacancy(phase) == LOCAL_VACANCY_CONSTANT_ID) then - sizeState = 0_pInt - vacancyState(phase)%sizeState = sizeState - sizeDotState = sizeState - vacancyState(phase)%sizeDotState = sizeDotState - vacancyState(phase)%sizePostResults = 0_pInt - allocate(vacancyState(phase)%state0 (sizeState,NofMyPhase)) - allocate(vacancyState(phase)%partionedState0(sizeState,NofMyPhase)) - allocate(vacancyState(phase)%subState0 (sizeState,NofMyPhase)) - allocate(vacancyState(phase)%state (sizeState,NofMyPhase)) - allocate(vacancyState(phase)%state_backup (sizeState,NofMyPhase)) - allocate(vacancyState(phase)%aTolState (NofMyPhase)) - allocate(vacancyState(phase)%dotState (sizeDotState,NofMyPhase)) - allocate(vacancyState(phase)%dotState_backup(sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 1_pInt)) then - allocate(vacancyState(phase)%previousDotState (sizeDotState,NofMyPhase)) - allocate(vacancyState(phase)%previousDotState2 (sizeDotState,NofMyPhase)) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(vacancyState(phase)%RK4dotState (sizeDotState,NofMyPhase)) - if (any(numerics_integrator == 5_pInt)) & - allocate(vacancyState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase)) - endif - enddo initializeInstances - allocate(vacancy_constant_sizePostResults(maxNinstance), source=0_pInt) - -end subroutine vacancy_constant_init - -end module vacancy_constant diff --git a/code/vacancy_generation.f90 b/code/vacancy_generation.f90 deleted file mode 100644 index 2e8053cca..000000000 --- a/code/vacancy_generation.f90 +++ /dev/null @@ -1,534 +0,0 @@ -!-------------------------------------------------------------------------------------------------- -! $Id$ -!-------------------------------------------------------------------------------------------------- -!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH -!> @brief material subroutine for plastically generated vacancy concentrations -!> @details to be done -!-------------------------------------------------------------------------------------------------- -module vacancy_generation - use prec, only: & - pReal, & - pInt - - implicit none - private - integer(pInt), dimension(:), allocatable, public, protected :: & - vacancy_generation_sizePostResults !< cumulative size of post results - - integer(pInt), dimension(:,:), allocatable, target, public :: & - vacancy_generation_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - vacancy_generation_output !< name of each post result output - - integer(pInt), dimension(:), allocatable, target, public :: & - vacancy_generation_Noutput !< number of outputs per instance of this damage - - real(pReal), dimension(:), allocatable, private :: & - vacancy_generation_aTol, & - vacancy_generation_freq, & - vacancy_generation_formationEnergy, & - vacancy_generation_specificFormationEnergy, & - vacancy_generation_migrationEnergy, & - vacancy_generation_diffusionCoeff0, & !< the temperature-independent diffusion coefficient D_0 - vacancy_generation_atomicVol, & - vacancy_generation_surfaceEnergy, & - vacancy_generation_plasticityCoeff, & - vacancy_generation_kBCoeff - - real(pReal), parameter, private :: & - kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin - - enum, bind(c) - enumerator :: undefined_ID, & - vacancy_concentration_ID - end enum - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - vacancy_generation_outputID !< ID of each post result output - - - public :: & - vacancy_generation_init, & - vacancy_generation_stateInit, & - vacancy_generation_aTolState, & - vacancy_generation_microstructure, & - vacancy_generation_getLocalConcentration, & - vacancy_generation_putLocalConcentration, & - vacancy_generation_getConcentration, & - vacancy_generation_getVacancyDiffusion33, & - vacancy_generation_getVacancyMobility33, & - vacancy_generation_getVacancyEnergy, & - vacancy_generation_postResults - -contains - - -!-------------------------------------------------------------------------------------------------- -!> @brief module initialization -!> @details reads in material parameters, allocates arrays, and does sanity checks -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_generation_init(fileUnit) - use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) - use debug, only: & - debug_level,& - debug_constitutive,& - debug_levelBasic - use mesh, only: & - mesh_maxNips, & - mesh_NcpElems - use IO, only: & - IO_read, & - IO_lc, & - IO_getTag, & - IO_isBlank, & - IO_stringPos, & - IO_stringValue, & - IO_floatValue, & - IO_intValue, & - IO_warning, & - IO_error, & - IO_timeStamp, & - IO_EOF - use material, only: & - homogenization_maxNgrains, & - phase_vacancy, & - phase_vacancyInstance, & - phase_Noutput, & - LOCAL_VACANCY_GENERATION_label, & - LOCAL_VACANCY_generation_ID, & - material_phase, & - vacancyState, & - MATERIAL_partPhase - use numerics,only: & - worldrank, & - numerics_integrator - - implicit none - integer(pInt), intent(in) :: fileUnit - - integer(pInt), parameter :: MAXNCHUNKS = 7_pInt - integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions - integer(pInt) :: maxNinstance,mySize=0_pInt,phase,instance,o - integer(pInt) :: sizeState, sizeDotState - integer(pInt) :: NofMyPhase - character(len=65536) :: & - tag = '', & - line = '' - - mainProcess: if (worldrank == 0) then - write(6,'(/,a)') ' <<<+- vacancy_'//LOCAL_VACANCY_GENERATION_label//' init -+>>>' - write(6,'(a)') ' $Id$' - write(6,'(a15,a)') ' Current time: ',IO_timeStamp() -#include "compilation_info.f90" - endif mainProcess - - maxNinstance = int(count(phase_vacancy == LOCAL_VACANCY_generation_ID),pInt) - if (maxNinstance == 0_pInt) return - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0_pInt) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstance - - allocate(vacancy_generation_sizePostResults(maxNinstance), source=0_pInt) - allocate(vacancy_generation_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0_pInt) - allocate(vacancy_generation_output(maxval(phase_Noutput),maxNinstance)) - vacancy_generation_output = '' - allocate(vacancy_generation_outputID(maxval(phase_Noutput),maxNinstance), source=undefined_ID) - allocate(vacancy_generation_Noutput(maxNinstance), source=0_pInt) - allocate(vacancy_generation_aTol(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_freq(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_formationEnergy(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_specificFormationEnergy(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_migrationEnergy(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_diffusionCoeff0(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_atomicVol(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_surfaceEnergy(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_plasticityCoeff(maxNinstance), source=0.0_pReal) - allocate(vacancy_generation_kBCoeff(maxNinstance), source=0.0_pReal) - - rewind(fileUnit) - phase = 0_pInt - do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= MATERIAL_partPhase) ! wind forward to - line = IO_read(fileUnit) - enddo - - parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of phase part - line = IO_read(fileUnit) - if (IO_isBlank(line)) cycle ! skip empty lines - if (IO_getTag(line,'<','>') /= '') then ! stop at next part - line = IO_read(fileUnit, .true.) ! reset IO_read - exit - endif - if (IO_getTag(line,'[',']') /= '') then ! next phase section - phase = phase + 1_pInt ! advance phase section counter - cycle ! skip to next line - endif - - if (phase > 0_pInt ) then; if (phase_vacancy(phase) == LOCAL_VACANCY_generation_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran - - instance = phase_vacancyInstance(phase) ! which instance of my vacancy is present phase - positions = IO_stringPos(line,MAXNCHUNKS) - tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key - select case(tag) - case ('(output)') - select case(IO_lc(IO_stringValue(line,positions,2_pInt))) - case ('vacancy_concentration') - vacancy_generation_Noutput(instance) = vacancy_generation_Noutput(instance) + 1_pInt - vacancy_generation_outputID(vacancy_generation_Noutput(instance),instance) = vacancy_concentration_ID - vacancy_generation_output(vacancy_generation_Noutput(instance),instance) = & - IO_lc(IO_stringValue(line,positions,2_pInt)) - end select - - case ('atolvacancygeneration') - vacancy_generation_aTol(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancyformationfreq') - vacancy_generation_freq(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancyformationenergy') - vacancy_generation_formationEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancymigrationenergy') - vacancy_generation_migrationEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancydiffusioncoeff0') - vacancy_generation_diffusionCoeff0(instance) = IO_floatValue(line,positions,2_pInt) - - case ('atomicvolume') - vacancy_generation_atomicVol(instance) = IO_floatValue(line,positions,2_pInt) - - case ('surfaceenergy') - vacancy_generation_surfaceEnergy(instance) = IO_floatValue(line,positions,2_pInt) - - case ('vacancyplasticitycoeff') - vacancy_generation_plasticityCoeff(instance) = IO_floatValue(line,positions,2_pInt) - - end select - endif; endif - enddo parsingFile - - initializeInstances: do phase = 1_pInt, size(phase_vacancy) - if (phase_vacancy(phase) == LOCAL_VACANCY_generation_ID) then - NofMyPhase=count(material_phase==phase) - instance = phase_vacancyInstance(phase) - -!-------------------------------------------------------------------------------------------------- -! pre-calculating derived material parameters - vacancy_generation_kBCoeff(instance) = kB/vacancy_generation_atomicVol(instance) - vacancy_generation_specificFormationEnergy(instance) = & - vacancy_generation_formationEnergy(instance)/vacancy_generation_atomicVol(instance) - -!-------------------------------------------------------------------------------------------------- -! Determine size of postResults array - outputsLoop: do o = 1_pInt,vacancy_generation_Noutput(instance) - select case(vacancy_generation_outputID(o,instance)) - case(vacancy_concentration_ID) - mySize = 1_pInt - end select - - if (mySize > 0_pInt) then ! any meaningful output found - vacancy_generation_sizePostResult(o,instance) = mySize - vacancy_generation_sizePostResults(instance) = vacancy_generation_sizePostResults(instance) + mySize - endif - enddo outputsLoop -! Determine size of state array - sizeDotState = 0_pInt - sizeState = 1_pInt - vacancyState(phase)%sizeState = sizeState - vacancyState(phase)%sizeDotState = sizeDotState - vacancyState(phase)%sizePostResults = vacancy_generation_sizePostResults(instance) - allocate(vacancyState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(vacancyState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%state_backup (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(vacancyState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%deltaState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%dotState_backup (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 1_pInt)) then - allocate(vacancyState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(vacancyState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) - endif - if (any(numerics_integrator == 4_pInt)) & - allocate(vacancyState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) - if (any(numerics_integrator == 5_pInt)) & - allocate(vacancyState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase),source=0.0_pReal) - - call vacancy_generation_stateInit(phase) - call vacancy_generation_aTolState(phase,instance) - endif - - enddo initializeInstances -end subroutine vacancy_generation_init - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant NEW state values for a given instance of this vacancy model -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_generation_stateInit(phase) - use material, only: & - vacancyState - use lattice, only: & - lattice_equilibriumVacancyConcentration - - implicit none - integer(pInt), intent(in) :: phase !< number specifying the phase of the vacancy - real(pReal), dimension(vacancyState(phase)%sizeState) :: tempState - - tempState(1) = lattice_equilibriumVacancyConcentration(phase) - vacancyState(phase)%state0 = spread(tempState,2,size(vacancyState(phase)%state(1,:))) - -end subroutine vacancy_generation_stateInit - -!-------------------------------------------------------------------------------------------------- -!> @brief sets the relevant state values for a given instance of this vacancy model -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_generation_aTolState(phase,instance) - use material, only: & - vacancyState - - implicit none - integer(pInt), intent(in) :: & - phase, & - instance ! number specifying the current instance of the vacancy - real(pReal), dimension(vacancyState(phase)%sizeState) :: tempTol - - tempTol = vacancy_generation_aTol(instance) - vacancyState(phase)%aTolState = tempTol -end subroutine vacancy_generation_aTolState - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates derived quantities from state -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_generation_microstructure(Tstar_v, temperature, damage, subdt, & - ipc, ip, el) - use material, only: & - mappingConstitutive, & - phase_vacancyInstance, & - plasticState, & - vacancyState - use math, only : & - math_Mandel6to33, & - math_trace33 - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), intent(in) :: & - Tstar_v(6), & - temperature, & !< 2nd Piola Kirchhoff stress tensor (Mandel) - damage, & - subdt - real(pReal) :: & - pressure, & - stressBarrier - integer(pInt) :: & - instance, phase, constituent - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_vacancyInstance(phase) - - pressure = math_trace33(math_Mandel6to33(Tstar_v))/3.0_pReal - stressBarrier = max(0.0_pReal, & - vacancy_generation_specificFormationEnergy(instance) - & - pressure - & - vacancy_generation_plasticityCoeff(instance)* & - sum(plasticState(phase)%accumulatedSlip(:,constituent))) - - vacancyState(phase)%state(1,constituent) = & - vacancyState(phase)%subState0(1,constituent) + & - subdt* & - damage*damage* & - vacancy_generation_freq(instance)* & - exp(-stressBarrier/(vacancy_generation_kBCoeff(instance)*temperature)) - -end subroutine vacancy_generation_microstructure - -!-------------------------------------------------------------------------------------------------- -!> @brief returns vacancy concentration based on state layout -!-------------------------------------------------------------------------------------------------- -pure function vacancy_generation_getLocalConcentration(ipc, ip, el) - use material, only: & - mappingConstitutive, & - vacancyState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: vacancy_generation_getLocalConcentration - - vacancy_generation_getLocalConcentration = & - vacancyState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el)) - -end function vacancy_generation_getLocalConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns temperature based on local damage model state layout -!-------------------------------------------------------------------------------------------------- -subroutine vacancy_generation_putLocalConcentration(ipc, ip, el, localVacancyConcentration) - use material, only: & - mappingConstitutive, & - vacancyState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), intent(in) :: & - localVacancyConcentration - - vacancyState(mappingConstitutive(2,ipc,ip,el))%state(1,mappingConstitutive(1,ipc,ip,el))= & - localVacancyConcentration - -end subroutine vacancy_generation_putLocalConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns vacancy concentration based on state layout -!-------------------------------------------------------------------------------------------------- -pure function vacancy_generation_getConcentration(ipc, ip, el) - use material, only: & - mappingHomogenization, & - material_phase, & - fieldVacancy, & - field_vacancy_type, & - FIELD_VACANCY_local_ID, & - FIELD_VACANCY_nonlocal_ID, & - material_homog - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal) :: vacancy_generation_getConcentration - - select case(field_vacancy_type(material_homog(ip,el))) - case (FIELD_VACANCY_local_ID) - vacancy_generation_getConcentration = vacancy_generation_getLocalConcentration(ipc, ip, el) - - case (FIELD_VACANCY_nonlocal_ID) - vacancy_generation_getConcentration = fieldVacancy(material_homog(ip,el))% & - field(1,mappingHomogenization(1,ip,el)) ! Taylor type - end select - -end function vacancy_generation_getConcentration - -!-------------------------------------------------------------------------------------------------- -!> @brief returns generation vacancy diffusion tensor -!-------------------------------------------------------------------------------------------------- -pure function vacancy_generation_getVacancyDiffusion33(ipc,ip,el) - use lattice, only: & - lattice_VacancyDiffusion33 - use material, only: & - mappingConstitutive - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - vacancy_generation_getVacancyDiffusion33 - - vacancy_generation_getVacancyDiffusion33 = & - lattice_VacancyDiffusion33(1:3,1:3,mappingConstitutive(2,ipc,ip,el)) - -end function vacancy_generation_getVacancyDiffusion33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns generation vacancy mobility tensor -!-------------------------------------------------------------------------------------------------- -pure function vacancy_generation_getVacancyMobility33(temperature,ipc,ip,el) - use math, only: & - math_I3 - use material, only: & - mappingConstitutive, & - phase_vacancyInstance, & - plasticState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - real(pReal), dimension(3,3) :: & - vacancy_generation_getVacancyMobility33 - real(pReal), intent(in) :: & - temperature - integer(pInt) :: & - phase, constituent, instance - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_vacancyInstance(phase) - - vacancy_generation_getVacancyMobility33 = & - math_I3*(1.0_pReal + sum(plasticState(phase)%accumulatedSlip(:,constituent))) - -end function vacancy_generation_getVacancyMobility33 - -!-------------------------------------------------------------------------------------------------- -!> @brief returns generation vacancy mobility tensor -!-------------------------------------------------------------------------------------------------- -pure real(pReal) function vacancy_generation_getVacancyEnergy(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_vacancyInstance - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< grain number - ip, & !< integration point number - el !< element number - integer(pInt) :: & - instance - - instance = phase_vacancyInstance(mappingConstitutive(2,ipc,ip,el)) - vacancy_generation_getVacancyEnergy = & - vacancy_generation_specificFormationEnergy(instance)/vacancy_generation_surfaceEnergy(instance) - -end function vacancy_generation_getVacancyEnergy - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function vacancy_generation_postResults(ipc,ip,el) - use material, only: & - mappingConstitutive, & - phase_vacancyInstance, & - vacancyState - - implicit none - integer(pInt), intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(vacancy_generation_sizePostResults(phase_vacancyInstance(mappingConstitutive(2,ipc,ip,el)))) :: & - vacancy_generation_postResults - - integer(pInt) :: & - instance, phase, constituent, o, c - - phase = mappingConstitutive(2,ipc,ip,el) - constituent = mappingConstitutive(1,ipc,ip,el) - instance = phase_vacancyInstance(phase) - - c = 0_pInt - vacancy_generation_postResults = 0.0_pReal - - do o = 1_pInt,vacancy_generation_Noutput(instance) - select case(vacancy_generation_outputID(o,instance)) - - case (vacancy_concentration_ID) - vacancy_generation_postResults(c+1_pInt) = vacancyState(phase)%state(1,constituent) - c = c + 1 - end select - enddo -end function vacancy_generation_postResults - -end module vacancy_generation diff --git a/code/vacancyflux_cahnhilliard.f90 b/code/vacancyflux_cahnhilliard.f90 new file mode 100644 index 000000000..c20a4ad97 --- /dev/null +++ b/code/vacancyflux_cahnhilliard.f90 @@ -0,0 +1,637 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for conservative transport of vacancy concentration field +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module vacancyflux_cahnhilliard + use prec, only: & + pReal, & + pInt, & + p_vec + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + vacancyflux_cahnhilliard_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + vacancyflux_cahnhilliard_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + vacancyflux_cahnhilliard_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + vacancyflux_cahnhilliard_Noutput !< number of outputs per instance of this damage + + real(pReal), dimension(:), allocatable, private :: & + vacancyflux_cahnhilliard_formationEnergyCoeff, & + vacancyflux_cahnhilliard_surfaceEnergy, & + vacancyflux_cahnhilliard_kBCoeff + + type(p_vec), dimension(:), allocatable, private :: & + vacancyflux_cahnhilliard_thermalFluc + + real(pReal), parameter, private :: & + kB = 1.3806488e-23_pReal !< Boltzmann constant in J/Kelvin + + enum, bind(c) + enumerator :: undefined_ID, & + vacancyConc_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + vacancyflux_cahnhilliard_outputID !< ID of each post result output + + + public :: & + vacancyflux_cahnhilliard_init, & + vacancyflux_cahnhilliard_getSourceAndItsTangent, & + vacancyflux_cahnhilliard_getMobility33, & + vacancyflux_cahnhilliard_getDiffusion33, & + vacancyflux_cahnhilliard_getChemPotAndItsTangent, & + vacancyflux_cahnhilliard_putVacancyConcAndItsRate, & + vacancyflux_cahnhilliard_postResults + private :: & + vacancyflux_cahnhilliard_getFormationEnergy, & + vacancyflux_cahnhilliard_getEntropicCoeff, & + vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_cahnhilliard_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use lattice, only: & + lattice_vacancyVol + use material, only: & + vacancyflux_type, & + vacancyflux_typeInstance, & + homogenization_Noutput, & + VACANCYFLUX_cahnhilliard_label, & + VACANCYFLUX_cahnhilliard_ID, & + material_homog, & + material_Nphase, & + mappingHomogenization, & + vacancyfluxState, & + vacancyfluxMapping, & + vacancyConc, & + vacancyConcRate, & + material_partHomogenization, & + material_partPhase + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o,offset + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_cahnhilliard_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(vacancyflux_type == VACANCYFLUX_cahnhilliard_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(vacancyflux_cahnhilliard_sizePostResults(maxNinstance), source=0_pInt) + allocate(vacancyflux_cahnhilliard_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(vacancyflux_cahnhilliard_output (maxval(homogenization_Noutput),maxNinstance)) + vacancyflux_cahnhilliard_output = '' + allocate(vacancyflux_cahnhilliard_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(vacancyflux_cahnhilliard_Noutput (maxNinstance), source=0_pInt) + + allocate(vacancyflux_cahnhilliard_formationEnergyCoeff(material_Nphase), source=0.0_pReal) + allocate(vacancyflux_cahnhilliard_kBCoeff (material_Nphase), source=0.0_pReal) + allocate(vacancyflux_cahnhilliard_surfaceEnergy (material_Nphase), source=0.0_pReal) + + allocate(vacancyflux_cahnhilliard_thermalFluc(maxNinstance)) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingHomog: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = vacancyflux_typeInstance(section) ! which instance of my vacancyflux is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('vacancyconc') + vacancyflux_cahnhilliard_Noutput(instance) = vacancyflux_cahnhilliard_Noutput(instance) + 1_pInt + vacancyflux_cahnhilliard_outputID(vacancyflux_cahnhilliard_Noutput(instance),instance) = vacancyConc_ID + vacancyflux_cahnhilliard_output(vacancyflux_cahnhilliard_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingHomog + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partPhase) ! wind forward to + line = IO_read(fileUnit) + enddo + + parsingPhase: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('vacancyformationenergy') + vacancyflux_cahnhilliard_formationEnergyCoeff(section) = IO_floatValue(line,positions,2_pInt) + + case ('voidsurfaceenergy') + vacancyflux_cahnhilliard_surfaceEnergy(section) = IO_floatValue(line,positions,2_pInt) + + end select + endif; endif + enddo parsingPhase + + initializeInstances: do section = 1_pInt, size(vacancyflux_type) + if (vacancyflux_type(section) == VACANCYFLUX_cahnhilliard_ID) then + NofMyHomog=count(material_homog==section) + instance = vacancyflux_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,vacancyflux_cahnhilliard_Noutput(instance) + select case(vacancyflux_cahnhilliard_outputID(o,instance)) + case(vacancyConc_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + vacancyflux_cahnhilliard_sizePostResult(o,instance) = mySize + vacancyflux_cahnhilliard_sizePostResults(instance) = vacancyflux_cahnhilliard_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 0_pInt + vacancyfluxState(section)%sizeState = sizeState + vacancyfluxState(section)%sizePostResults = vacancyflux_cahnhilliard_sizePostResults(instance) + allocate(vacancyfluxState(section)%state0 (sizeState,NofMyHomog)) + allocate(vacancyfluxState(section)%subState0(sizeState,NofMyHomog)) + allocate(vacancyfluxState(section)%state (sizeState,NofMyHomog)) + + allocate(vacancyflux_cahnhilliard_thermalFluc(instance)%p(NofMyHomog)) + do offset = 1_pInt, NofMyHomog + call random_number(vacancyflux_cahnhilliard_thermalFluc(instance)%p(offset)) + enddo + + nullify(vacancyfluxMapping(section)%p) + vacancyfluxMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(vacancyConc (section)%p) + allocate (vacancyConc (section)%p(NofMyHomog), source=0.0_pReal) + deallocate(vacancyConcRate(section)%p) + allocate (vacancyConcRate(section)%p(NofMyHomog), source=0.0_pReal) + + endif + + enddo initializeInstances + + initializeParams: do section = 1_pInt, material_Nphase + vacancyflux_cahnhilliard_formationEnergyCoeff(section) = & + vacancyflux_cahnhilliard_formationEnergyCoeff(section)/ & + lattice_vacancyVol(section)/ & + vacancyflux_cahnhilliard_surfaceEnergy(section) + vacancyflux_cahnhilliard_kBCoeff(section) = & + kB/ & + lattice_vacancyVol(section)/ & + vacancyflux_cahnhilliard_surfaceEnergy(section) + enddo initializeParams + +end subroutine vacancyflux_cahnhilliard_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates homogenized vacancy driving forces +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_cahnhilliard_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el) + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + phase_source, & + phase_Nsources, & + SOURCE_vacancy_phenoplasticity_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID + use source_vacancy_phenoplasticity, only: & + source_vacancy_phenoplasticity_getRateAndItsTangent + use source_vacancy_irradiation, only: & + source_vacancy_irradiation_getRateAndItsTangent + use source_vacancy_thermalfluc, only: & + source_vacancy_thermalfluc_getRateAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Cv + integer(pInt) :: & + phase, & + grain, & + source + real(pReal) :: & + CvDot, dCvDot_dCv, localCvDot, dLocalCvDot_dCv + + CvDot = 0.0_pReal + dCvDot_dCv = 0.0_pReal + do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el)) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1_pInt, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_vacancy_phenoplasticity_ID) + call source_vacancy_phenoplasticity_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el) + + case (SOURCE_vacancy_irradiation_ID) + call source_vacancy_irradiation_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el) + + case (SOURCE_vacancy_thermalfluc_ID) + call source_vacancy_thermalfluc_getRateAndItsTangent(localCvDot, dLocalCvDot_dCv, grain, ip, el) + + end select + CvDot = CvDot + localCvDot + dCvDot_dCv = dCvDot_dCv + dLocalCvDot_dCv + enddo + enddo + + CvDot = CvDot/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + dCvDot_dCv = dCvDot_dCv/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + +end subroutine vacancyflux_cahnhilliard_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized vacancy mobility tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function vacancyflux_cahnhilliard_getMobility33(ip,el) + use lattice, only: & + lattice_vacancyfluxMobility33 + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + vacancyflux_cahnhilliard_getMobility33 + integer(pInt) :: & + grain + + vacancyflux_cahnhilliard_getMobility33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + vacancyflux_cahnhilliard_getMobility33 = vacancyflux_cahnhilliard_getMobility33 + & + crystallite_push33ToRef(grain,ip,el,lattice_vacancyfluxMobility33(:,:,material_phase(grain,ip,el))) + enddo + + vacancyflux_cahnhilliard_getMobility33 = & + vacancyflux_cahnhilliard_getMobility33/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function vacancyflux_cahnhilliard_getMobility33 + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized vacancy diffusion tensor in reference configuration +!-------------------------------------------------------------------------------------------------- +function vacancyflux_cahnhilliard_getDiffusion33(ip,el) + use lattice, only: & + lattice_vacancyfluxDiffusion33 + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + use crystallite, only: & + crystallite_push33ToRef + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), dimension(3,3) :: & + vacancyflux_cahnhilliard_getDiffusion33 + integer(pInt) :: & + grain + + vacancyflux_cahnhilliard_getDiffusion33 = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + vacancyflux_cahnhilliard_getDiffusion33 = vacancyflux_cahnhilliard_getDiffusion33 + & + crystallite_push33ToRef(grain,ip,el,lattice_vacancyfluxDiffusion33(:,:,material_phase(grain,ip,el))) + enddo + + vacancyflux_cahnhilliard_getDiffusion33 = & + vacancyflux_cahnhilliard_getDiffusion33/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function vacancyflux_cahnhilliard_getDiffusion33 + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized vacancy formation energy +!-------------------------------------------------------------------------------------------------- +function vacancyflux_cahnhilliard_getFormationEnergy(ip,el) + use material, only: & + homogenization_Ngrains, & + material_phase + use mesh, only: & + mesh_element + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + vacancyflux_cahnhilliard_getFormationEnergy + integer(pInt) :: & + grain + + vacancyflux_cahnhilliard_getFormationEnergy = 0.0_pReal + do grain = 1, homogenization_Ngrains(mesh_element(3,el)) + vacancyflux_cahnhilliard_getFormationEnergy = vacancyflux_cahnhilliard_getFormationEnergy + & + vacancyflux_cahnhilliard_formationEnergyCoeff(material_phase(grain,ip,el)) + enddo + + vacancyflux_cahnhilliard_getFormationEnergy = & + vacancyflux_cahnhilliard_getFormationEnergy/ & + homogenization_Ngrains(mesh_element(3,el)) + +end function vacancyflux_cahnhilliard_getFormationEnergy + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized vacancy entropy coefficient +!-------------------------------------------------------------------------------------------------- +function vacancyflux_cahnhilliard_getEntropicCoeff(ip,el) + use material, only: & + homogenization_Ngrains, & + material_homog, & + material_phase, & + temperature, & + thermalMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal) :: & + vacancyflux_cahnhilliard_getEntropicCoeff + integer(pInt) :: & + grain + + vacancyflux_cahnhilliard_getEntropicCoeff = 0.0_pReal + do grain = 1, homogenization_Ngrains(material_homog(ip,el)) + vacancyflux_cahnhilliard_getEntropicCoeff = vacancyflux_cahnhilliard_getEntropicCoeff + & + vacancyflux_cahnhilliard_kBCoeff(material_phase(grain,ip,el)) + enddo + + vacancyflux_cahnhilliard_getEntropicCoeff = & + vacancyflux_cahnhilliard_getEntropicCoeff* & + temperature(material_homog(ip,el))%p(thermalMapping(material_homog(ip,el))%p(ip,el))/ & + homogenization_Ngrains(material_homog(ip,el)) + +end function vacancyflux_cahnhilliard_getEntropicCoeff + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized kinematic contribution to chemical potential +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCv, Cv, ip, el) + use material, only: & + homogenization_Ngrains, & + material_homog, & + phase_kinematics, & + phase_Nkinematics, & + material_phase, & + KINEMATICS_vacancy_strain_ID + use crystallite, only: & + crystallite_Tstar_v, & + crystallite_Fi0, & + crystallite_Fi + use kinematics_vacancy_strain, only: & + kinematics_vacancy_strain_ChemPotAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Cv + real(pReal), intent(out) :: & + KPot, dKPot_dCv + real(pReal) :: & + my_KPot, my_dKPot_dCv + integer(pInt) :: & + grain, kinematics + + KPot = 0.0_pReal + dKPot_dCv = 0.0_pReal + do grain = 1_pInt,homogenization_Ngrains(material_homog(ip,el)) + do kinematics = 1_pInt, phase_Nkinematics(material_phase(grain,ip,el)) + select case (phase_kinematics(kinematics,material_phase(grain,ip,el))) + case (KINEMATICS_vacancy_strain_ID) + call kinematics_vacancy_strain_ChemPotAndItsTangent(my_KPot, my_dKPot_dCv, & + crystallite_Tstar_v(1:6,grain,ip,el), & + crystallite_Fi0(1:3,1:3,grain,ip,el), & + crystallite_Fi (1:3,1:3,grain,ip,el), & + grain,ip, el) + + case default + my_KPot = 0.0_pReal + my_dKPot_dCv = 0.0_pReal + + end select + KPot = KPot + my_KPot/vacancyflux_cahnhilliard_surfaceEnergy(material_phase(grain,ip,el)) + dKPot_dCv = dKPot_dCv + my_dKPot_dCv/vacancyflux_cahnhilliard_surfaceEnergy(material_phase(grain,ip,el)) + enddo + enddo + + KPot = KPot/homogenization_Ngrains(material_homog(ip,el)) + dKPot_dCv = dKPot_dCv/homogenization_Ngrains(material_homog(ip,el)) + +end subroutine vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief returns homogenized chemical potential and its tangent +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_cahnhilliard_getChemPotAndItsTangent(ChemPot,dChemPot_dCv,Cv,ip,el) + use numerics, only: & + vacancyBoundPenalty, & + vacancyPolyOrder + use material, only: & + mappingHomogenization, & + porosity, & + porosityMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Cv + real(pReal), intent(out) :: & + ChemPot, & + dChemPot_dCv + real(pReal) :: & + VoidPhaseFrac, kBT, KPot, dKPot_dCv + integer(pInt) :: & + homog, o + + homog = mappingHomogenization(2,ip,el) + VoidPhaseFrac = porosity(homog)%p(porosityMapping(homog)%p(ip,el)) + kBT = vacancyflux_cahnhilliard_getEntropicCoeff(ip,el) + + ChemPot = vacancyflux_cahnhilliard_getFormationEnergy(ip,el) + dChemPot_dCv = 0.0_pReal + do o = 1_pInt, vacancyPolyOrder + ChemPot = ChemPot + kBT*((2.0_pReal*Cv - 1.0_pReal)**real(2_pInt*o-1_pInt,pReal))/ & + real(2_pInt*o-1_pInt,pReal) + dChemPot_dCv = dChemPot_dCv + 2.0_pReal*kBT*(2.0_pReal*Cv - 1.0_pReal)**real(2_pInt*o-2_pInt,pReal) + enddo + + ChemPot = VoidPhaseFrac*VoidPhaseFrac*ChemPot & + - 2.0_pReal*(1.0_pReal - Cv)*(1.0_pReal - VoidPhaseFrac)*(1.0_pReal - VoidPhaseFrac) + + dChemPot_dCv = VoidPhaseFrac*VoidPhaseFrac*dChemPot_dCv & + + 2.0_pReal*(1.0_pReal - VoidPhaseFrac)*(1.0_pReal - VoidPhaseFrac) + + call vacancyflux_cahnhilliard_KinematicChemPotAndItsTangent(KPot, dKPot_dCv, Cv, ip, el) + ChemPot = ChemPot + KPot + dChemPot_dCv = dChemPot_dCv + dKPot_dCv + + if (Cv < 0.0_pReal) then + ChemPot = ChemPot - 3.0_pReal*vacancyBoundPenalty*Cv*Cv + dChemPot_dCv = dChemPot_dCv - 6.0_pReal*vacancyBoundPenalty*Cv + elseif (Cv > 1.0_pReal) then + ChemPot = ChemPot + 3.0_pReal*vacancyBoundPenalty*(1.0_pReal - Cv)*(1.0_pReal - Cv) + dChemPot_dCv = dChemPot_dCv - 6.0_pReal*vacancyBoundPenalty*(1.0_pReal - Cv) + endif + +end subroutine vacancyflux_cahnhilliard_getChemPotAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief updated vacancy concentration and its rate with solution from transport PDE +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_cahnhilliard_putVacancyConcAndItsRate(Cv,Cvdot,ip,el) + use material, only: & + mappingHomogenization, & + vacancyConc, & + vacancyConcRate, & + vacancyfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Cv, & + Cvdot + integer(pInt) :: & + homog, & + offset + + homog = mappingHomogenization(2,ip,el) + offset = vacancyfluxMapping(homog)%p(ip,el) + vacancyConc (homog)%p(offset) = Cv + vacancyConcRate(homog)%p(offset) = Cvdot + +end subroutine vacancyflux_cahnhilliard_putVacancyConcAndItsRate + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of vacancy transport results +!-------------------------------------------------------------------------------------------------- +function vacancyflux_cahnhilliard_postResults(ip,el) + use material, only: & + mappingHomogenization, & + vacancyflux_typeInstance, & + vacancyConc, & + vacancyfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(vacancyflux_cahnhilliard_sizePostResults(vacancyflux_typeInstance(mappingHomogenization(2,ip,el)))) :: & + vacancyflux_cahnhilliard_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = vacancyfluxMapping(homog)%p(ip,el) + instance = vacancyflux_typeInstance(homog) + + c = 0_pInt + vacancyflux_cahnhilliard_postResults = 0.0_pReal + + do o = 1_pInt,vacancyflux_cahnhilliard_Noutput(instance) + select case(vacancyflux_cahnhilliard_outputID(o,instance)) + + case (vacancyConc_ID) + vacancyflux_cahnhilliard_postResults(c+1_pInt) = vacancyConc(homog)%p(offset) + c = c + 1 + end select + enddo +end function vacancyflux_cahnhilliard_postResults + +end module vacancyflux_cahnhilliard diff --git a/code/vacancyflux_isochempot.f90 b/code/vacancyflux_isochempot.f90 new file mode 100644 index 000000000..44ccb13e6 --- /dev/null +++ b/code/vacancyflux_isochempot.f90 @@ -0,0 +1,330 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for locally evolving vacancy concentration +!> @details to be done +!-------------------------------------------------------------------------------------------------- +module vacancyflux_isochempot + use prec, only: & + pReal, & + pInt + + implicit none + private + integer(pInt), dimension(:), allocatable, public, protected :: & + vacancyflux_isochempot_sizePostResults !< cumulative size of post results + + integer(pInt), dimension(:,:), allocatable, target, public :: & + vacancyflux_isochempot_sizePostResult !< size of each post result output + + character(len=64), dimension(:,:), allocatable, target, public :: & + vacancyflux_isochempot_output !< name of each post result output + + integer(pInt), dimension(:), allocatable, target, public :: & + vacancyflux_isochempot_Noutput !< number of outputs per instance of this damage + + enum, bind(c) + enumerator :: undefined_ID, & + vacancyconc_ID + end enum + integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + vacancyflux_isochempot_outputID !< ID of each post result output + + + public :: & + vacancyflux_isochempot_init, & + vacancyflux_isochempot_updateState, & + vacancyflux_isochempot_getSourceAndItsTangent, & + vacancyflux_isochempot_postResults + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief module initialization +!> @details reads in material parameters, allocates arrays, and does sanity checks +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_isochempot_init(fileUnit) + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use IO, only: & + IO_read, & + IO_lc, & + IO_getTag, & + IO_isBlank, & + IO_stringPos, & + IO_stringValue, & + IO_floatValue, & + IO_intValue, & + IO_warning, & + IO_error, & + IO_timeStamp, & + IO_EOF + use material, only: & + vacancyflux_type, & + vacancyflux_typeInstance, & + homogenization_Noutput, & + VACANCYFLUX_isochempot_label, & + VACANCYFLUX_isochempot_ID, & + material_homog, & + mappingHomogenization, & + vacancyfluxState, & + vacancyfluxMapping, & + vacancyConc, & + vacancyConcRate, & + material_partHomogenization + use numerics,only: & + worldrank + + implicit none + integer(pInt), intent(in) :: fileUnit + + integer(pInt), parameter :: MAXNCHUNKS = 7_pInt + integer(pInt), dimension(1+2*MAXNCHUNKS) :: positions + integer(pInt) :: maxNinstance,mySize=0_pInt,section,instance,o + integer(pInt) :: sizeState + integer(pInt) :: NofMyHomog + character(len=65536) :: & + tag = '', & + line = '' + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_isochempot_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + maxNinstance = int(count(vacancyflux_type == VACANCYFLUX_isochempot_ID),pInt) + if (maxNinstance == 0_pInt) return + + allocate(vacancyflux_isochempot_sizePostResults(maxNinstance), source=0_pInt) + allocate(vacancyflux_isochempot_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0_pInt) + allocate(vacancyflux_isochempot_output (maxval(homogenization_Noutput),maxNinstance)) + vacancyflux_isochempot_output = '' + allocate(vacancyflux_isochempot_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) + allocate(vacancyflux_isochempot_Noutput (maxNinstance), source=0_pInt) + + rewind(fileUnit) + section = 0_pInt + do while (trim(line) /= IO_EOF .and. IO_lc(IO_getTag(line,'<','>')) /= material_partHomogenization)! wind forward to + line = IO_read(fileUnit) + enddo + + parsingFile: do while (trim(line) /= IO_EOF) ! read through sections of homog part + line = IO_read(fileUnit) + if (IO_isBlank(line)) cycle ! skip empty lines + if (IO_getTag(line,'<','>') /= '') then ! stop at next part + line = IO_read(fileUnit, .true.) ! reset IO_read + exit + endif + if (IO_getTag(line,'[',']') /= '') then ! next homog section + section = section + 1_pInt ! advance homog section counter + cycle ! skip to next line + endif + + if (section > 0_pInt ) then; if (vacancyflux_type(section) == VACANCYFLUX_isochempot_ID) then ! do not short-circuit here (.and. with next if statemen). It's not safe in Fortran + + instance = vacancyflux_typeInstance(section) ! which instance of my vacancyflux is present homog + positions = IO_stringPos(line,MAXNCHUNKS) + tag = IO_lc(IO_stringValue(line,positions,1_pInt)) ! extract key + select case(tag) + case ('(output)') + select case(IO_lc(IO_stringValue(line,positions,2_pInt))) + case ('vacancyconc') + vacancyflux_isochempot_Noutput(instance) = vacancyflux_isochempot_Noutput(instance) + 1_pInt + vacancyflux_isochempot_outputID(vacancyflux_isochempot_Noutput(instance),instance) = vacancyconc_ID + vacancyflux_isochempot_output(vacancyflux_isochempot_Noutput(instance),instance) = & + IO_lc(IO_stringValue(line,positions,2_pInt)) + end select + + end select + endif; endif + enddo parsingFile + + initializeInstances: do section = 1_pInt, size(vacancyflux_type) + if (vacancyflux_type(section) == VACANCYFLUX_isochempot_ID) then + NofMyHomog=count(material_homog==section) + instance = vacancyflux_typeInstance(section) + +!-------------------------------------------------------------------------------------------------- +! Determine size of postResults array + outputsLoop: do o = 1_pInt,vacancyflux_isochempot_Noutput(instance) + select case(vacancyflux_isochempot_outputID(o,instance)) + case(vacancyconc_ID) + mySize = 1_pInt + end select + + if (mySize > 0_pInt) then ! any meaningful output found + vacancyflux_isochempot_sizePostResult(o,instance) = mySize + vacancyflux_isochempot_sizePostResults(instance) = vacancyflux_isochempot_sizePostResults(instance) + mySize + endif + enddo outputsLoop + +! allocate state arrays + sizeState = 1_pInt + vacancyfluxState(section)%sizeState = sizeState + vacancyfluxState(section)%sizePostResults = vacancyflux_isochempot_sizePostResults(instance) + allocate(vacancyfluxState(section)%state0 (sizeState,NofMyHomog), source=0.0_pReal) + allocate(vacancyfluxState(section)%subState0(sizeState,NofMyHomog), source=0.0_pReal) + allocate(vacancyfluxState(section)%state (sizeState,NofMyHomog), source=0.0_pReal) + + nullify(vacancyfluxMapping(section)%p) + vacancyfluxMapping(section)%p => mappingHomogenization(1,:,:) + deallocate(vacancyConc(section)%p) + vacancyConc(section)%p => vacancyfluxState(section)%state(1,:) + deallocate(vacancyConcRate(section)%p) + allocate(vacancyConcRate(section)%p(NofMyHomog), source=0.0_pReal) + + endif + + enddo initializeInstances +end subroutine vacancyflux_isochempot_init + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates change in vacancy concentration based on local vacancy generation model +!-------------------------------------------------------------------------------------------------- +function vacancyflux_isochempot_updateState(subdt, ip, el) + use numerics, only: & + err_vacancyflux_tolAbs, & + err_vacancyflux_tolRel + use material, only: & + mappingHomogenization, & + vacancyflux_typeInstance, & + vacancyfluxState, & + vacancyConc, & + vacancyConcRate, & + vacancyfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + subdt + logical, dimension(2) :: & + vacancyflux_isochempot_updateState + integer(pInt) :: & + homog, & + offset, & + instance + real(pReal) :: & + Cv, Cvdot, dCvDot_dCv + + homog = mappingHomogenization(2,ip,el) + offset = mappingHomogenization(1,ip,el) + instance = vacancyflux_typeInstance(homog) + + Cv = vacancyfluxState(homog)%subState0(1,offset) + call vacancyflux_isochempot_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el) + Cv = Cv + subdt*Cvdot + + vacancyflux_isochempot_updateState = [ abs(Cv - vacancyfluxState(homog)%state(1,offset)) & + <= err_vacancyflux_tolAbs & + .or. abs(Cv - vacancyfluxState(homog)%state(1,offset)) & + <= err_vacancyflux_tolRel*abs(vacancyfluxState(homog)%state(1,offset)), & + .true.] + + vacancyConc (homog)%p(vacancyfluxMapping(homog)%p(ip,el)) = Cv + vacancyConcRate(homog)%p(vacancyfluxMapping(homog)%p(ip,el)) = & + (vacancyfluxState(homog)%state(1,offset) - vacancyfluxState(homog)%subState0(1,offset))/subdt + +end function vacancyflux_isochempot_updateState + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates homogenized vacancy driving forces +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_isochempot_getSourceAndItsTangent(CvDot, dCvDot_dCv, Cv, ip, el) + use material, only: & + homogenization_Ngrains, & + mappingHomogenization, & + mappingConstitutive, & + phase_source, & + phase_Nsources, & + SOURCE_vacancy_phenoplasticity_ID, & + SOURCE_vacancy_irradiation_ID, & + SOURCE_vacancy_thermalfluc_ID + use source_vacancy_phenoplasticity, only: & + source_vacancy_phenoplasticity_getRateAndItsTangent + use source_vacancy_irradiation, only: & + source_vacancy_irradiation_getRateAndItsTangent + use source_vacancy_thermalfluc, only: & + source_vacancy_thermalfluc_getRateAndItsTangent + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point number + el !< element number + real(pReal), intent(in) :: & + Cv + integer(pInt) :: & + phase, & + grain, & + source + real(pReal) :: & + CvDot, dCvDot_dCv, localCvDot, dLocalCvDot_dCv + + CvDot = 0.0_pReal + dCvDot_dCv = 0.0_pReal + do grain = 1, homogenization_Ngrains(mappingHomogenization(2,ip,el)) + phase = mappingConstitutive(2,grain,ip,el) + do source = 1_pInt, phase_Nsources(phase) + select case(phase_source(source,phase)) + case (SOURCE_vacancy_phenoplasticity_ID) + call source_vacancy_phenoplasticity_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el) + + case (SOURCE_vacancy_irradiation_ID) + call source_vacancy_irradiation_getRateAndItsTangent (localCvDot, dLocalCvDot_dCv, grain, ip, el) + + case (SOURCE_vacancy_thermalfluc_ID) + call source_vacancy_thermalfluc_getRateAndItsTangent(localCvDot, dLocalCvDot_dCv, grain, ip, el) + + end select + CvDot = CvDot + localCvDot + dCvDot_dCv = dCvDot_dCv + dLocalCvDot_dCv + enddo + enddo + + CvDot = CvDot/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + dCvDot_dCv = dCvDot_dCv/homogenization_Ngrains(mappingHomogenization(2,ip,el)) + +end subroutine vacancyflux_isochempot_getSourceAndItsTangent + +!-------------------------------------------------------------------------------------------------- +!> @brief return array of vacancy transport results +!-------------------------------------------------------------------------------------------------- +function vacancyflux_isochempot_postResults(ip,el) + use material, only: & + mappingHomogenization, & + vacancyflux_typeInstance, & + vacancyConc, & + vacancyfluxMapping + + implicit none + integer(pInt), intent(in) :: & + ip, & !< integration point + el !< element + real(pReal), dimension(vacancyflux_isochempot_sizePostResults(vacancyflux_typeInstance(mappingHomogenization(2,ip,el)))) :: & + vacancyflux_isochempot_postResults + + integer(pInt) :: & + instance, homog, offset, o, c + + homog = mappingHomogenization(2,ip,el) + offset = vacancyfluxMapping(homog)%p(ip,el) + instance = vacancyflux_typeInstance(homog) + + c = 0_pInt + vacancyflux_isochempot_postResults = 0.0_pReal + + do o = 1_pInt,vacancyflux_isochempot_Noutput(instance) + select case(vacancyflux_isochempot_outputID(o,instance)) + + case (vacancyconc_ID) + vacancyflux_isochempot_postResults(c+1_pInt) = vacancyConc(homog)%p(offset) + c = c + 1 + end select + enddo +end function vacancyflux_isochempot_postResults + +end module vacancyflux_isochempot diff --git a/code/vacancyflux_isoconc.f90 b/code/vacancyflux_isoconc.f90 new file mode 100644 index 000000000..c66a8f55f --- /dev/null +++ b/code/vacancyflux_isoconc.f90 @@ -0,0 +1,64 @@ +!-------------------------------------------------------------------------------------------------- +! $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @brief material subroutine for constant vacancy concentration +!-------------------------------------------------------------------------------------------------- +module vacancyflux_isoconc + + implicit none + private + + public :: & + vacancyflux_isoconc_init + +contains + +!-------------------------------------------------------------------------------------------------- +!> @brief allocates all neccessary fields, reads information from material configuration file +!-------------------------------------------------------------------------------------------------- +subroutine vacancyflux_isoconc_init() + use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran 4.6 at the moment) + use prec, only: & + pReal, & + pInt + use IO, only: & + IO_timeStamp + use material + use numerics, only: & + worldrank + + implicit none + integer(pInt) :: & + homog, & + NofMyHomog + + mainProcess: if (worldrank == 0) then + write(6,'(/,a)') ' <<<+- vacancyflux_'//VACANCYFLUX_isoconc_label//' init -+>>>' + write(6,'(a)') ' $Id$' + write(6,'(a15,a)') ' Current time: ',IO_timeStamp() +#include "compilation_info.f90" + endif mainProcess + + initializeInstances: do homog = 1_pInt, material_Nhomogenization + + myhomog: if (vacancyflux_type(homog) == VACANCYFLUX_isoconc_ID) then + NofMyHomog = count(material_homog == homog) + vacancyfluxState(homog)%sizeState = 0_pInt + vacancyfluxState(homog)%sizePostResults = 0_pInt + allocate(vacancyfluxState(homog)%state0 (0_pInt,NofMyHomog), source=0.0_pReal) + allocate(vacancyfluxState(homog)%subState0(0_pInt,NofMyHomog), source=0.0_pReal) + allocate(vacancyfluxState(homog)%state (0_pInt,NofMyHomog), source=0.0_pReal) + + deallocate(vacancyConc (homog)%p) + allocate (vacancyConc (homog)%p(1), source=0.0_pReal) + deallocate(vacancyConcRate(homog)%p) + allocate (vacancyConcRate(homog)%p(1), source=0.0_pReal) + + endif myhomog + enddo initializeInstances + + +end subroutine vacancyflux_isoconc_init + +end module vacancyflux_isoconc