diff --git a/code/DAMASK_spectral_Driver.f90 b/code/DAMASK_spectral_Driver.f90 index 235e74ece..720972d64 100644 --- a/code/DAMASK_spectral_Driver.f90 +++ b/code/DAMASK_spectral_Driver.f90 @@ -1,40 +1,11 @@ -! Copyright 2012 Max-Planck-Institut für Eisenforschung GmbH -! -! This file is part of DAMASK, -! the Düsseldorf Advanced Material Simulation Kit. -! -! DAMASK is free software: you can redistribute it and/or modify -! it under the terms of the GNU General Public License as published by -! the Free Software Foundation, either version 3 of the License, or -! (at your option) any later version. -! -! DAMASK is distributed in the hope that it will be useful, -! but WITHOUT ANY WARRANTY; without even the implied warranty of -! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -! GNU General Public License for more details. -! -! You should have received a copy of the GNU General Public License -! along with DAMASK. If not, see . -! -!################################################################################################## +!-------------------------------------------------------------------------------------------------- !* $Id$ -!################################################################################################## -! Material subroutine for BVP solution using spectral method -! -! Run 'DAMASK_spectral.exe --help' to get usage hints -! -! written by P. Eisenlohr, -! F. Roters, -! L. Hantcherli, -! W.A. Counts, -! D.D. Tjahjanto, -! C. Kords, -! M. Diehl, -! R. Lebensohn -! -! MPI fuer Eisenforschung, Duesseldorf - - +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Driver controlling inner and outer load case looping of the various spectral solvers +!-------------------------------------------------------------------------------------------------- program DAMASK_spectral_Driver use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran >4.6 at the moment) @@ -85,7 +56,7 @@ program DAMASK_spectral_Driver materialpoint_sizeResults, & materialpoint_results - use DAMASK_spectral_SolverAL + !use DAMASK_spectral_SolverAL use DAMASK_spectral_SolverBasic use DAMASK_spectral_Utilities @@ -110,8 +81,8 @@ program DAMASK_spectral_Driver !-------------------------------------------------------------------------------------------------- ! variables related to information from load case and geom file - real(pReal), dimension(9) :: temp_valueVector !> temporarily from loadcase file when reading in tensors - logical, dimension(9) :: temp_maskVector !> temporarily from loadcase file when reading in tensors + real(pReal), dimension(9) :: temp_valueVector !> temporarily from loadcase file when reading in tensors + logical, dimension(9) :: temp_maskVector !> temporarily from loadcase file when reading in tensors integer(pInt), parameter :: maxNchunksLoadcase = (1_pInt + 9_pInt)*3_pInt +& ! deformation, rotation, and stress (1_pInt + 1_pInt)*5_pInt +& ! time, (log)incs, temp, restartfrequency, and outputfrequency 1_pInt, & ! dropguessing @@ -130,27 +101,35 @@ program DAMASK_spectral_Driver type(loadcase), allocatable, dimension(:) :: bc type(solutionState) solres - + type(BC_type) :: stress !-------------------------------------------------------------------------------------------------- ! loop variables, convergence etc. real(pReal) :: time = 0.0_pReal, time0 = 0.0_pReal, timeinc = 1.0_pReal, timeinc_old = 0.0_pReal ! elapsed time, begin of interval, time interval real(pReal) :: guessmode - real(pReal), dimension(3,3) :: temp33_Real + real(pReal), dimension(3,3) :: temp33_Real integer(pInt) :: i, j, k, l, errorID integer(pInt) :: currentLoadcase = 0_pInt, inc, & totalIncsCounter = 0_pInt,& notConvergedCounter = 0_pInt, convergedCounter = 0_pInt character(len=6) :: loadcase_string - call DAMASK_interface_init - + call CPFEM_initAll(temperature = 300.0_pReal, element = 1_pInt, IP= 1_pInt) + write(6,'(a)') '' write(6,'(a)') ' <<<+- DAMASK_spectral_Driver init -+>>>' write(6,'(a)') ' $Id$' #include "compilation_info.f90" - write(6,'(a)') ' Working Directory: ',trim(getSolverWorkingDirectoryName()) - write(6,'(a)') ' Solver Job Name: ',trim(getSolverJobName()) + write(6,'(a,a)') ' Working Directory: ',trim(getSolverWorkingDirectoryName()) + write(6,'(a,a)') ' Solver Job Name: ',trim(getSolverJobName()) + write(6,'(a)') '' + write(6,'(a,a)') ' geometry file: ',trim(geometryFile) + write(6,'(a)') '=============================================================' + write(6,'(a,3(i12 ))') ' resolution a b c:', mesh_spectral_getResolution() + write(6,'(a,3(f12.5))') ' dimension x y z:', mesh_spectral_getDimension() + write(6,'(a,i5)') ' homogenization: ', mesh_spectral_getHomogenization() + write(6,'(a)') '=============================================================' + write(6,'(a,a)') 'Loadcase file: ',trim(loadCaseFile) write(6,'(a)') '' !-------------------------------------------------------------------------------------------------- @@ -248,27 +227,6 @@ program DAMASK_spectral_Driver end select enddo; enddo 101 close(myUnit) -print*, 'my Unit closed' -!-------------------------------------------------------------------------------------------------- ToDo: if temperature at CPFEM is treated properly, move this up immediately after interface init -! initialization of all related DAMASK modules (e.g. mesh.f90 reads in geometry) - call CPFEM_initAll(bc(1)%temperature,1_pInt,1_pInt) - -!-------------------------------------------------------------------------------------------------- -! output of geometry information - write(6,'(a)') '' - write(6,'(a)') '#############################################################' - write(6,'(a)') 'DAMASK spectral:' - write(6,'(a)') 'The spectral method boundary value problem solver for' - write(6,'(a)') 'the Duesseldorf Advanced Material Simulation Kit' - write(6,'(a)') '#############################################################' - write(6,'(a)') 'geometry file: ',trim(geometryFile) - write(6,'(a)') '=============================================================' - write(6,'(a,3(i12 ))') 'resolution a b c:', mesh_spectral_getResolution() - write(6,'(a,3(f12.5))') 'dimension x y z:', mesh_spectral_getDimension() - write(6,'(a,i5)') 'homogenization: ', mesh_spectral_getHomogenization() - write(6,'(a)') '#############################################################' - write(6,'(a)') 'currentLoadcase file: ',trim(loadCaseFile) - !-------------------------------------------------------------------------------------------------- ! consistency checks and output of load case bc(1)%followFormerTrajectory = .false. ! cannot guess along trajectory for first inc of first currentLoadcase @@ -347,8 +305,8 @@ print*, 'my Unit closed' case (DAMASK_spectral_SolverBasic_label) call basic_init() - case (DAMASK_spectral_SolverAL_label) - call AL_init() + !case (DAMASK_spectral_SolverAL_label) + ! call AL_init() end select @@ -409,15 +367,15 @@ print*, 'my Unit closed' velgrad = bc(currentLoadcase)%velGradApplied, & rotation_BC = bc(currentLoadcase)%rotation) - case (DAMASK_spectral_SolverAL_label) - solres = AL_solution (& - guessmode,timeinc,timeinc_old, & - P_BC = bc(currentLoadcase)%stress, & - F_BC = bc(currentLoadcase)%deformation, & - ! temperature_bc = bc(currentLoadcase)%temperature, & - mask_stressVector = bc(currentLoadcase)%maskStressVector, & - velgrad = bc(currentLoadcase)%velGradApplied, & - rotation_BC = bc(currentLoadcase)%rotation) + ! case (DAMASK_spectral_SolverAL_label) + ! solres = AL_solution (& + ! guessmode,timeinc,timeinc_old, & + ! P_BC = bc(currentLoadcase)%stress, & + ! F_BC = bc(currentLoadcase)%deformation, & + ! ! temperature_bc = bc(currentLoadcase)%temperature, & + ! mask_stressVector = bc(currentLoadcase)%maskStressVector, & + ! velgrad = bc(currentLoadcase)%velGradApplied, & + ! rotation_BC = bc(currentLoadcase)%rotation) end select @@ -447,9 +405,9 @@ print*, 'my Unit closed' case (DAMASK_spectral_SolverBasic_label) call basic_destroy() - case (DAMASK_spectral_SolverAL_label) - call AL_destroy() - + ! case (DAMASK_spectral_SolverAL_label) + ! call AL_destroy() + ! end select write(6,'(a)') '' write(6,'(a)') '##################################################################' diff --git a/code/DAMASK_spectral_SolverBasic.f90 b/code/DAMASK_spectral_SolverBasic.f90 index 53fdba661..363b0c0b3 100644 --- a/code/DAMASK_spectral_SolverBasic.f90 +++ b/code/DAMASK_spectral_SolverBasic.f90 @@ -1,19 +1,31 @@ +!-------------------------------------------------------------------------------------------------- +!* $Id$ +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Basic scheme solver +!-------------------------------------------------------------------------------------------------- module DAMASK_spectral_SolverBasic use, intrinsic :: iso_fortran_env ! to get compiler_version and compiler_options (at least for gfortran >4.6 at the moment) use DAMASK_spectral_Utilities - use math + use math, only: & + math_I3, & + math_mul33x33, use mesh, only : & mesh_spectral_getResolution, & - mesh_spectral_getDimension + mesh_spectral_getDimension, & + math_rotate_backward33, & + math_transpose33,& + math_mul3333xx33, & + math_eigenvalues33 implicit none - real(pReal), dimension(3,3) :: temp33_Real - character (len=*), parameter, public :: & DAMASK_spectral_SolverBasic_label = 'basic' @@ -28,7 +40,6 @@ module DAMASK_spectral_SolverBasic real(pReal), dimension(3,3) :: & F_aim = math_I3, & F_aim_lastInc = math_I3 - real(pReal), dimension(3,3,3,3) :: & C = 0.0_pReal @@ -50,7 +61,14 @@ module DAMASK_spectral_SolverBasic implicit none integer(pInt) :: i,j,k - call Utilities_Init() + real(pReal), dimension(3,3) :: temp33_Real + + write(6,'(a)') '' + write(6,'(a)') ' <<<+- DAMASK_spectral_solverBasic init -+>>>' + write(6,'(a)') ' $Id$' +#include "compilation_info.f90" + write(6,'(a)') '' + call Utilities_Init() allocate (F ( res(1), res(2),res(3),3,3), source = 0.0_pReal) allocate (F_lastInc ( res(1), res(2),res(3),3,3), source = 0.0_pReal) @@ -193,121 +211,128 @@ type(solutionState) function basic_solution(guessmode,timeinc,timeinc_old,P_BC,F 1.0_pReal,F_lastInc,coordinates) iter = 0_pInt - S = Utilities_stressBC(rotation_BC,mask_stressVector,C) + S = Utilities_maskedCompliance(rotation_BC,mask_stressVector,C) if (update_gamma) call Utilities_updateGamma(C) - convergenceLoop: do while(.not. basic_convergenced(err_div,P_av,err_stress,P_av,iter)) + convergenceLoop: do iter = iter + 1_pInt !-------------------------------------------------------------------------------------------------- ! report begin of new iteration write(6,'(a)') '' write(6,'(a)') '==================================================================' - write(6,'(3(a,i6.6))') ' @ Iter. ',itmin,' < ',iter,' < ',itmax + write(6,'(3(a,i6.6))') ' Iter. ',itmin,' < ',iter,' < ',itmax + 1_pInt write(6,'(a,/,3(3(f12.7,1x)/))',advance='no') 'deformation gradient aim =',& math_transpose33(F_aim) F_aim_lab_lastIter = math_rotate_backward33(F_aim,rotation_BC) !-------------------------------------------------------------------------------------------------- ! evaluate constitutive response - call Utilities_constitutiveResponse(coordinates,F,F_lastInc,temperature,timeinc,& +print*, 'FLast 111', F_lastInc(1,1,1,1:3,1:3) + call Utilities_constitutiveResponse(coordinates,F_lastInc,F,temperature,timeinc,& P,C,P_av,ForwardData,rotation_BC) ForwardData = .False. !-------------------------------------------------------------------------------------------------- ! stress BC handling - if(any(mask_stressVector)) then ! calculate stress BC if applied - F_aim = F_aim - math_mul3333xx33(S, ((P_av - P_BC))) - err_stress = mask_stress * (P_av - P_BC))) - else - err_stress = 0.0_pReal - endif + F_aim = F_aim - math_mul3333xx33(S, ((P_av - P_BC))) !S = 0.0 for no bc + err_stress = maxval(mask_stress * (P_av - P_BC)) ! mask = 0.0 for no bc + F_aim_lab = math_rotate_backward33(F_aim,rotation_BC) ! boundary conditions from load frame into lab (Fourier) frame !-------------------------------------------------------------------------------------------------- ! updated deformation gradient + field_real = 0.0_pReal field_real(1:res(1),1:res(2),1:res(3),1:3,1:3) = P call Utilities_forwardFFT() err_div = Utilities_divergenceRMS() call Utilities_fourierConvolution(F_aim_lab_lastIter - F_aim_lab) call Utilities_backwardFFT() + temp33_real =0.0_pReal + do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt, res(1) F(i,j,k,1:3,1:3) = F(i,j,k,1:3,1:3) - field_real(i,j,k,1:3,1:3) ! F(x)^(n+1) = F(x)^(n) + correction; *wgt: correcting for missing normalization + temp33_real = temp33_real + field_real(i,j,k,1:3,1:3) enddo; enddo; enddo - -!-------------------------------------------------------------------------------------------------- -! calculate some additional output - if(debugGeneral) then - maxCorrectionSkew = 0.0_pReal - maxCorrectionSym = 0.0_pReal - temp33_Real = 0.0_pReal - do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt, res(1) - maxCorrectionSym = max(maxCorrectionSym,& - maxval(math_symmetric33(field_real(i,j,k,1:3,1:3)))) - maxCorrectionSkew = max(maxCorrectionSkew,& - maxval(math_skew33(field_real(i,j,k,1:3,1:3)))) - temp33_Real = temp33_Real + field_real(i,j,k,1:3,1:3) - enddo; enddo; enddo - write(6,'(a,1x,es11.4)') 'max symmetric correction of deformation =',& - maxCorrectionSym*wgt - write(6,'(a,1x,es11.4)') 'max skew correction of deformation =',& - maxCorrectionSkew*wgt - write(6,'(a,1x,es11.4)') 'max sym/skew of avg correction = ',& - maxval(math_symmetric33(temp33_real))/& - maxval(math_skew33(temp33_real)) - endif - -!-------------------------------------------------------------------------------------------------- -! calculate bounds of det(F) and report - if(debugGeneral) then - defgradDetMax = -huge(1.0_pReal) - defgradDetMin = +huge(1.0_pReal) - do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt, res(1) - defgradDet = math_det33(F(i,j,k,1:3,1:3)) - defgradDetMax = max(defgradDetMax,defgradDet) - defgradDetMin = min(defgradDetMin,defgradDet) - enddo; enddo; enddo - - write(6,'(a,1x,es11.4)') 'max determinant of deformation =', defgradDetMax - write(6,'(a,1x,es11.4)') 'min determinant of deformation =', defgradDetMin - endif + if (Convergenced(err_div,P_av,err_stress,P_av,iter)) exit enddo convergenceLoop end function basic_solution -logical function basic_convergenced(err_div,P_av,err_stress,P_av,iter) +logical function Convergenced(err_div,P_av,err_stress,P_av2,iter) - use numerics, only: & - itmax, & - itmin, & - err_div_tol, & - err_stress_tolrel, & - err_stress_tolabs + use numerics, only: & + itmax, & + itmin, & + err_div_tol, & + err_stress_tolrel, & + err_stress_tolabs - implicit none + implicit none - real(pReal), dimension(3,3) :: P_av - real(pReal) :: err_div, err_stress, field_av_L2 - integer(pInt) :: iter + real(pReal), dimension(3,3) :: P_av, P_av2 + real(pReal) :: err_div, err_stress, field_av_L2 + integer(pInt) :: iter - field_av_L2 = sqrt(maxval(math_eigenvalues33(math_mul33x33(P_av,& ! L_2 norm of average stress (http://mathworld.wolfram.com/SpectralNorm.html) + field_av_L2 = sqrt(maxval(math_eigenvalues33(math_mul33x33(P_av,& ! L_2 norm of average stress (http://mathworld.wolfram.com/SpectralNorm.html) math_transpose33(P_av))))) - basic_convergenced = (iter < itmax) .and. (iter > itmin) .and. & - (err_div/field_av_L2/err_div_tol < 1.0_pReal) .and. & - (err_stress/min(maxval(abs(P_av))*err_stress_tolrel,err_stress_tolabs) < 1.0_pReal) + Convergenced = (iter < itmax) .and. (iter > itmin) .and. & + all([err_div/field_av_L2/err_div_tol,& + err_stress/min(maxval(abs(P_av2))*err_stress_tolrel,err_stress_tolabs)] < 1.0_pReal) -end function basic_convergenced + write(6,'(a,f6.2,a,es11.4,a)') 'error stress = ', err_stress/min(maxval(abs(P_av2))*err_stress_tolrel,err_stress_tolabs), & + ' (',err_stress,' Pa)' + write(6,'(a,f6.2,a,es11.4,a)') 'error divergence = ', err_div/field_av_L2/err_div_tol,& + ' (',err_div,' N/m³)' +end function Convergenced subroutine basic_destroy() implicit none - call Utilities_destroy() end subroutine basic_destroy end module DAMASK_spectral_SolverBasic + + +!-------------------------------------------------------------------------------------------------- +! calculate some additional output + ! if(debugGeneral) then + ! maxCorrectionSkew = 0.0_pReal + ! maxCorrectionSym = 0.0_pReal + ! temp33_Real = 0.0_pReal + ! do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt, res(1) + ! maxCorrectionSym = max(maxCorrectionSym,& + ! maxval(math_symmetric33(field_real(i,j,k,1:3,1:3)))) + ! maxCorrectionSkew = max(maxCorrectionSkew,& + ! maxval(math_skew33(field_real(i,j,k,1:3,1:3)))) + ! temp33_Real = temp33_Real + field_real(i,j,k,1:3,1:3) + ! enddo; enddo; enddo + ! write(6,'(a,1x,es11.4)') 'max symmetric correction of deformation =',& + ! maxCorrectionSym*wgt + ! write(6,'(a,1x,es11.4)') 'max skew correction of deformation =',& + ! maxCorrectionSkew*wgt + ! write(6,'(a,1x,es11.4)') 'max sym/skew of avg correction = ',& + ! maxval(math_symmetric33(temp33_real))/& + ! maxval(math_skew33(temp33_real)) + ! endif + +!-------------------------------------------------------------------------------------------------- +! calculate bounds of det(F) and report + ! if(debugGeneral) then + ! defgradDetMax = -huge(1.0_pReal) + ! defgradDetMin = +huge(1.0_pReal) + ! do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt, res(1) + ! defgradDet = math_det33(F(i,j,k,1:3,1:3)) + ! defgradDetMax = max(defgradDetMax,defgradDet) + ! defgradDetMin = min(defgradDetMin,defgradDet) + ! enddo; enddo; enddo + + ! write(6,'(a,1x,es11.4)') 'max determinant of deformation =', defgradDetMax + ! write(6,'(a,1x,es11.4)') 'min determinant of deformation =', defgradDetMin + ! endif diff --git a/code/DAMASK_spectral_Utilities.f90 b/code/DAMASK_spectral_Utilities.f90 index 14dfa7e89..8987b96b3 100644 --- a/code/DAMASK_spectral_Utilities.f90 +++ b/code/DAMASK_spectral_Utilities.f90 @@ -1,39 +1,11 @@ -! Copyright 2012 Max-Planck-Institut für Eisenforschung GmbH -! -! This file is part of DAMASK, -! the Düsseldorf Advanced Material Simulation Kit. -! -! DAMASK is free software: you can redistribute it and/or modify -! it under the terms of the GNU General Public License as published by -! the Free Software Foundation, either version 3 of the License, or -! (at your option) any later version. -! -! DAMASK is distributed in the hope that it will be useful, -! but WITHOUT ANY WARRANTY; without even the implied warranty of -! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -! GNU General Public License for more details. -! -! You should have received a copy of the GNU General Public License -! along with DAMASK. If not, see . -! -!################################################################################################## +!-------------------------------------------------------------------------------------------------- !* $Id$ -!################################################################################################## -! Material subroutine for BVP solution using spectral method -! -! Run 'DAMASK_spectral.exe --help' to get usage hints -! -! written by P. Eisenlohr, -! F. Roters, -! L. Hantcherli, -! W.A. Counts, -! D.D. Tjahjanto, -! C. Kords, -! M. Diehl, -! R. Lebensohn -! -! MPI fuer Eisenforschung, Duesseldorf - +!-------------------------------------------------------------------------------------------------- +!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH +!> @brief Utilities used by the different spectral solver variants +!-------------------------------------------------------------------------------------------------- module DAMASK_spectral_Utilities use prec, only: & @@ -49,26 +21,33 @@ module DAMASK_spectral_Utilities !-------------------------------------------------------------------------------------------------- ! variables storing information for spectral method and FFTW - type(C_PTR) :: plan_forward, plan_backward ! plans for fftw - real(pReal), dimension(:,:,:,:,:,:,:), allocatable :: gamma_hat ! gamma operator (field) for spectral method - real(pReal), dimension(3,3,3,3) :: C_ref - real(pReal), dimension(:,:,:,:), allocatable :: xi ! wave vector field for divergence and for gamma operator - real(pReal), dimension(:,:,:,:,:), pointer :: field_real - complex(pReal), dimension(:,:,:,:,:), pointer :: field_fourier + type(C_PTR) , private :: plan_forward, plan_backward ! plans for fftw + real(pReal), private, dimension(:,:,:,:,:,:,:), allocatable :: gamma_hat ! gamma operator (field) for spectral method + real(pReal), private, dimension(3,3,3,3) :: C_ref + real(pReal), private, dimension(:,:,:,:), allocatable :: xi ! wave vector field for divergence and for gamma operator + real(pReal), public, dimension(:,:,:,:,:), pointer :: field_real + complex(pReal),private, dimension(:,:,:,:,:), pointer :: field_fourier !-------------------------------------------------------------------------------------------------- ! debug fftw - type(C_PTR) :: plan_scalarField_forth, plan_scalarField_back - complex(pReal), dimension(:,:,:), pointer :: scalarField_real - complex(pReal), dimension(:,:,:), pointer :: scalarField_fourier + type(C_PTR), private :: plan_scalarField_forth, plan_scalarField_back + complex(pReal),private, dimension(:,:,:), pointer :: scalarField_real + complex(pReal),private, dimension(:,:,:), pointer :: scalarField_fourier !-------------------------------------------------------------------------------------------------- ! debug divergence - type(C_PTR) :: plan_divergence - real(pReal), dimension(:,:,:,:), pointer :: divergence_real - complex(pReal), dimension(:,:,:,:), pointer :: divergence_fourier + type(C_PTR), private :: plan_divergence + real(pReal), private, dimension(:,:,:,:), pointer :: divergence_real + complex(pReal), private, dimension(:,:,:,:), pointer :: divergence_fourier real(pReal), dimension(:,:,:,:), allocatable :: divergence_post + type BC_type + real(pReal), dimension(3,3) :: values + real(pReal), dimension(3,3) :: maskFloat + logical, dimension(3,3) :: maskLogical + character(20) :: myType + end type BC_type + !-------------------------------------------------------------------------------------------------- !variables controlling debugging logical :: debugGeneral, debugDivergence, debugRestart, debugFFTW @@ -98,7 +77,8 @@ subroutine Utilities_init() divergence_correction, & DAMASK_NumThreadsInt, & fftw_planner_flag, & - fftw_timelimit + fftw_timelimit, & + memory_efficient use debug, only: & debug_level, & @@ -233,7 +213,7 @@ subroutine Utilities_updateGamma(C) real(pReal), dimension(3,3,3,3) :: C real(pReal), dimension(3,3) :: temp33_Real, xiDyad - integer(pInt) :: i, j, k, l, m, n, q + integer(pInt) :: i, j, k, l, m, n, o C_ref = C if(.not. memory_efficient) then @@ -244,8 +224,8 @@ subroutine Utilities_updateGamma(C) forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & temp33_Real(l,m) = sum(C_ref(l,m,1:3,1:3)*xiDyad) temp33_Real = math_inv33(temp33_Real) - forall(l=1_pInt:3_pInt, m=1_pInt:3_pInt, n=1_pInt:3_pInt, q=1_pInt:3_pInt)& - gamma_hat(i,j,k, l,m,n,q) = temp33_Real(l,n)*xiDyad(m,q) + forall(l=1_pInt:3_pInt, m=1_pInt:3_pInt, n=1_pInt:3_pInt, o=1_pInt:3_pInt)& + gamma_hat(i,j,k, l,m,n,o) = temp33_Real(l,n)*xiDyad(m,o) endif enddo; enddo; enddo gamma_hat(1,1,1, 1:3,1:3,1:3,1:3) = 0.0_pReal ! singular point at xi=(0.0,0.0,0.0) i.e. i=j=k=1 @@ -290,7 +270,15 @@ subroutine Utilities_forwardFFT() field_fourier(1:res1_red,1:res(2),1:res(3),row,column))/& scalarField_fourier(1:res1_red,1:res(2),1:res(3)))) endif - +!-------------------------------------------------------------------------------------------------- +! removing highest frequencies + field_fourier ( res1_red,1:res(2) , 1:res(3) ,1:3,1:3)& + = cmplx(0.0_pReal,0.0_pReal,pReal) + field_fourier (1:res1_red, res(2)/2_pInt+1_pInt,1:res(3) ,1:3,1:3)& + = cmplx(0.0_pReal,0.0_pReal,pReal) + if(res(3)>1_pInt) & + field_fourier (1:res1_red,1:res(2), res(3)/2_pInt+1_pInt,1:3,1:3)& + = cmplx(0.0_pReal,0.0_pReal,pReal) end subroutine Utilities_forwardFFT subroutine Utilities_backwardFFT() @@ -322,8 +310,9 @@ subroutine Utilities_backwardFFT() endif !-------------------------------------------------------------------------------------------------- ! doing the inverse FT + print*, 'field fourier 111', field_fourier(1,1,1,1:3,1:3) call fftw_execute_dft_c2r(plan_backward,field_fourier,field_real) ! back transform of fluct deformation gradient - + print*, 'field real 111', field_real(1,1,1,1:3,1:3) !-------------------------------------------------------------------------------------------------- ! comparing 1 and 3x3 inverse FT results if (debugFFTW) then @@ -334,96 +323,84 @@ subroutine Utilities_backwardFFT() field_real(1:res(1),1:res(2),1:res(3),row,column))/& real(scalarField_real(1:res(1),1:res(2),1:res(3)))) endif - + field_real = field_real * wgt end subroutine Utilities_backwardFFT -subroutine Utilities_fourierConvolution(field_aim) - use numerics, only: & - memory_efficient +!-------------------------------------------------------------------------------------------------- +!> @brief doing convolution gamma_hat * field_real with average value given by fieldAim +!-------------------------------------------------------------------------------------------------- +subroutine Utilities_fourierConvolution(fieldAim) + + use numerics, only: & + memory_efficient - implicit none + implicit none - real(pReal), dimension(3,3) :: xiDyad, temp33_Real, field_aim - integer(pInt) :: i, j, k, l, m, n, q - complex(pReal), dimension(3,3) :: temp33_complex + real(pReal), dimension(3,3), intent(in) :: fieldAim + real(pReal), dimension(3,3) :: xiDyad, temp33_Real + integer(pInt) :: i, j, k, l, m, n, o + complex(pReal), dimension(3,3) :: temp33_complex -!-------------------------------------------------------------------------------------------------- -! actual spectral method - write(6,'(a)') '' - write(6,'(a)') '... doing convolution .................' + write(6,'(a)') '' + write(6,'(a)') '... doing convolution .................' -!-------------------------------------------------------------------------------------------------- -! removing highest frequencies - field_fourier ( res1_red,1:res(2) , 1:res(3) ,1:3,1:3)& - = cmplx(0.0_pReal,0.0_pReal,pReal) - field_fourier (1:res1_red, res(2)/2_pInt+1_pInt,1:res(3) ,1:3,1:3)& - = cmplx(0.0_pReal,0.0_pReal,pReal) - if(res(3)>1_pInt) & - field_fourier (1:res1_red,1:res(2), res(3)/2_pInt+1_pInt,1:3,1:3)& - = cmplx(0.0_pReal,0.0_pReal,pReal) - !-------------------------------------------------------------------------------------------------- ! to the actual spectral method calculation (mechanical equilibrium) - if(memory_efficient) then ! memory saving version, on-the-fly calculation of gamma_hat - do k = 1_pInt, res(3); do j = 1_pInt, res(2) ;do i = 1_pInt, res1_red - if(any([i,j,k] /= 1_pInt)) then ! singular point at xi=(0.0,0.0,0.0) i.e. i=j=k=1 - forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & - xiDyad(l,m) = xi(l, i,j,k)*xi(m, i,j,k) - forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & - temp33_Real(l,m) = sum(C_ref(l,m,1:3,1:3)*xiDyad) - temp33_Real = math_inv33(temp33_Real) - forall(l=1_pInt:3_pInt, m=1_pInt:3_pInt, n=1_pInt:3_pInt, q=1_pInt:3_pInt)& - gamma_hat(1,1,1, l,m,n,q) = temp33_Real(l,n)*xiDyad(m,q) - forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & - temp33_Complex(l,m) = sum(gamma_hat(1,1,1, l,m, 1:3,1:3) *& - field_fourier(i,j,k,1:3,1:3)) - field_fourier(i,j,k,1:3,1:3) = temp33_Complex - endif - enddo; enddo; enddo - else ! use precalculated gamma-operator - do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt,res1_red - forall( m = 1_pInt:3_pInt, n = 1_pInt:3_pInt) & - temp33_Complex(m,n) = sum(gamma_hat(i,j,k, m,n, 1:3,1:3) *& - field_fourier(i,j,k,1:3,1:3)) - field_fourier(i,j,k, 1:3,1:3) = temp33_Complex - enddo; enddo; enddo - endif - field_fourier(1,1,1,1:3,1:3) = cmplx(field_aim,0.0_pReal,pReal) ! singular point at xi=(0.0,0.0,0.0) i.e. i=j=k=1 + if(memory_efficient) then ! memory saving version, on-the-fly calculation of gamma_hat + do k = 1_pInt, res(3); do j = 1_pInt, res(2) ;do i = 1_pInt, res1_red + if(any([i,j,k] /= 1_pInt)) then ! singular point at xi=(0.0,0.0,0.0) i.e. i=j=k=1 + forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & + xiDyad(l,m) = xi(l, i,j,k)*xi(m, i,j,k) + forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & + temp33_Real(l,m) = sum(C_ref(l,m,1:3,1:3)*xiDyad) + temp33_Real = math_inv33(temp33_Real) + forall(l=1_pInt:3_pInt, m=1_pInt:3_pInt, n=1_pInt:3_pInt, o=1_pInt:3_pInt)& + gamma_hat(1,1,1, l,m,n,o) = temp33_Real(l,n)*xiDyad(m,o) + forall(l = 1_pInt:3_pInt, m = 1_pInt:3_pInt) & + temp33_Complex(l,m) = sum(gamma_hat(1,1,1, l,m, 1:3,1:3) * field_fourier(i,j,k,1:3,1:3)) + field_fourier(i,j,k,1:3,1:3) = temp33_Complex + endif + enddo; enddo; enddo + else ! use precalculated gamma-operator + do k = 1_pInt, res(3); do j = 1_pInt, res(2); do i = 1_pInt,res1_red + forall( m = 1_pInt:3_pInt, n = 1_pInt:3_pInt) & + temp33_Complex(m,n) = sum(gamma_hat(i,j,k, m,n, 1:3,1:3) * field_fourier(i,j,k,1:3,1:3)) + field_fourier(i,j,k, 1:3,1:3) = temp33_Complex + enddo; enddo; enddo + endif + + field_fourier(1,1,1,1:3,1:3) = cmplx(fieldAim*real(Npoints,pReal),0.0_pReal,pReal) ! singular point at xi=(0.0,0.0,0.0) i.e. i=j=k=1 end subroutine Utilities_fourierConvolution + +!-------------------------------------------------------------------------------------------------- +!> @brief calculate root mean square of divergence of field_fourier +!-------------------------------------------------------------------------------------------------- real(pReal) function Utilities_divergenceRMS() - use numerics, only: err_div_tol - - integer(pInt) :: i, j, k, l, m, n, q - -!-------------------------------------------------------------------------------------------------- -!variables for additional output due to general debugging - real(pReal), dimension(3,3) :: field_avg - real(pReal) :: field_av_L2, err_div_RMS, err_real_div_RMS, err_post_div_RMS,& + integer(pInt) :: i, j, k + real(pReal) :: err_div_RMS, err_real_div_RMS, err_post_div_RMS,& err_div_max, err_real_div_max complex(pReal), dimension(3) :: temp3_complex - -!-------------------------------------------------------------------------------------------------- -! actual spectral method + write(6,'(a)') '' write(6,'(a)') '... calculating divergence .................' !-------------------------------------------------------------------------------------------------- ! calculating RMS divergence criterion in Fourier space - err_div_RMS = 0.0_pReal + Utilities_divergenceRMS = 0.0_pReal do k = 1_pInt, res(3); do j = 1_pInt, res(2) do i = 2_pInt, res1_red -1_pInt ! Has somewhere a conj. complex counterpart. Therefore count it twice. - err_div_RMS = err_div_RMS & + Utilities_divergenceRMS = Utilities_divergenceRMS & + 2.0_pReal*(sum (real(math_mul33x3_complex(field_fourier(i,j,k,1:3,1:3),& ! (sqrt(real(a)**2 + aimag(a)**2))**2 = real(a)**2 + aimag(a)**2. do not take square root and square again xi(1:3,i,j,k))*TWOPIIMG)**2.0_pReal)& ! --> sum squared L_2 norm of vector +sum(aimag(math_mul33x3_complex(field_fourier(i,j,k,1:3,1:3),& xi(1:3,i,j,k))*TWOPIIMG)**2.0_pReal)) enddo - err_div_RMS = err_div_RMS & ! Those two layers (DC and Nyquist) do not have a conjugate complex counterpart + Utilities_divergenceRMS = Utilities_divergenceRMS & ! Those two layers (DC and Nyquist) do not have a conjugate complex counterpart + sum( real(math_mul33x3_complex(field_fourier(1 ,j,k,1:3,1:3),& xi(1:3,1 ,j,k))*TWOPIIMG)**2.0_pReal)& + sum(aimag(math_mul33x3_complex(field_fourier(1 ,j,k,1:3,1:3),& @@ -434,8 +411,7 @@ real(pReal) function Utilities_divergenceRMS() xi(1:3,res1_red,j,k))*TWOPIIMG)**2.0_pReal) enddo; enddo - err_div_RMS = sqrt(err_div_RMS)*wgt ! RMS in real space calculated with Parsevals theorem from Fourier space - Utilities_divergenceRMS = err_div_RMS ! criterion to stop iterations + Utilities_divergenceRMS = sqrt(Utilities_divergenceRMS) *wgt ! RMS in real space calculated with Parsevals theorem from Fourier space !-------------------------------------------------------------------------------------------------- ! calculate additional divergence criteria and report @@ -474,39 +450,30 @@ real(pReal) function Utilities_divergenceRMS() end function Utilities_divergenceRMS -function Utilities_stressBC(rot_BC,mask_stressVector,C) +!-------------------------------------------------------------------------------------------------- +!> @brief calculates mask compliance +!-------------------------------------------------------------------------------------------------- +function Utilities_maskedCompliance(rot_BC,mask_stressVector,C) + + real(pReal), dimension(3,3,3,3) :: Utilities_maskedCompliance + real(pReal), dimension(3,3,3,3), intent(in) :: C + integer(pInt) :: i, j, k, m, n + real(pReal), dimension(3,3), intent(in) :: rot_BC + logical, dimension(9), intent(in) :: mask_stressVector + real(pReal), dimension(3,3,3,3) :: C_lastInc + real(pReal), dimension(9,9) :: temp99_Real + integer(pInt) :: size_reduced = 0_pInt + real(pReal), dimension(:,:), allocatable :: s_reduced, c_reduced ! reduced compliance and stiffness (only for stress BC) + logical :: errmatinv - real(pReal), dimension(3,3,3,3) :: Utilities_stressBC - real(pReal), dimension(3,3,3,3), intent(in) :: C - integer(pInt) :: i, j, k, m, n - real(pReal), dimension(3,3), intent(in) :: rot_BC - logical, dimension(9), intent(in) :: mask_stressVector - real(pReal), dimension(3,3,3,3) :: C_lastInc - real(pReal), dimension(9,9) :: temp99_Real - integer(pInt) :: size_reduced = 0_pInt - real(pReal), dimension(:,:), allocatable :: s_reduced, c_reduced ! reduced compliance and stiffness (only for stress BC) - logical :: errmatinv - - size_reduced = count(mask_stressVector) - allocate (c_reduced(size_reduced,size_reduced), source =0.0_pReal) - allocate (s_reduced(size_reduced,size_reduced), source =0.0_pReal) - - C_lastInc = math_rotate_forward3333(C,rot_BC) ! calculate stiffness from former inc - temp99_Real = math_Plain3333to99(C_lastInc) - k = 0_pInt ! build reduced stiffness - do n = 1_pInt,9_pInt - if(mask_stressVector(n)) then - k = k + 1_pInt - j = 0_pInt - do m = 1_pInt,9_pInt - if(mask_stressVector(m)) then - j = j + 1_pInt - c_reduced(k,j) = temp99_Real(n,m) - endif; enddo; endif; enddo - call math_invert(size_reduced, c_reduced, s_reduced, i, errmatinv) ! invert reduced stiffness - if(errmatinv) call IO_error(error_ID=400_pInt) - temp99_Real = 0.0_pReal ! build full compliance - k = 0_pInt + size_reduced = count(mask_stressVector) + if(size_reduced > 0_pInt )then + allocate (c_reduced(size_reduced,size_reduced), source =0.0_pReal) + allocate (s_reduced(size_reduced,size_reduced), source =0.0_pReal) + + C_lastInc = math_rotate_forward3333(C,rot_BC) ! calculate stiffness from former inc + temp99_Real = math_Plain3333to99(C_lastInc) + k = 0_pInt ! build reduced stiffness do n = 1_pInt,9_pInt if(mask_stressVector(n)) then k = k + 1_pInt @@ -514,13 +481,32 @@ function Utilities_stressBC(rot_BC,mask_stressVector,C) do m = 1_pInt,9_pInt if(mask_stressVector(m)) then j = j + 1_pInt - temp99_Real(n,m) = s_reduced(k,j) - endif; enddo; endif; enddo - Utilities_stressBC = math_Plain99to3333(temp99_Real) + c_reduced(k,j) = temp99_Real(n,m) + endif; enddo; endif; enddo + call math_invert(size_reduced, c_reduced, s_reduced, i, errmatinv) ! invert reduced stiffness + if(errmatinv) call IO_error(error_ID=400_pInt) + temp99_Real = 0.0_pReal ! build full compliance + k = 0_pInt + do n = 1_pInt,9_pInt + if(mask_stressVector(n)) then + k = k + 1_pInt + j = 0_pInt + do m = 1_pInt,9_pInt + if(mask_stressVector(m)) then + j = j + 1_pInt + temp99_Real(n,m) = s_reduced(k,j) + endif; enddo; endif; enddo + deallocate(c_reduced) + deallocate(s_reduced) + else + temp99_real = 0.0_pReal + endif -end function Utilities_stressBC + Utilities_maskedCompliance = math_Plain99to3333(temp99_Real) -subroutine Utilities_constitutiveResponse(coordinates,F,F_lastInc,temperature,timeinc,& +end function Utilities_maskedCompliance + +subroutine Utilities_constitutiveResponse(coordinates,F_lastInc,F,temperature,timeinc,& P,C,P_av,ForwardData,rotation_BC) use debug, only: & debug_reset, & @@ -549,6 +535,7 @@ subroutine Utilities_constitutiveResponse(coordinates,F,F_lastInc,temperature,ti else CPFEM_mode = 2_pInt endif + write(6,'(a)') '' write(6,'(a)') '... update stress field P(F) .....................................' ielem = 0_pInt @@ -583,6 +570,7 @@ subroutine Utilities_constitutiveResponse(coordinates,F,F_lastInc,temperature,ti end subroutine Utilities_constitutiveResponse + subroutine Utilities_destroy() implicit none