Merge remote-tracking branch 'origin/development' into config_from_dream3D

This commit is contained in:
Martin Diehl 2021-03-12 08:09:25 +01:00
commit 3b27c64709
144 changed files with 7801 additions and 7780 deletions

View File

@ -95,7 +95,7 @@ checkout:
- release - release
################################################################################################### ###################################################################################################
Pytest_python: pytest_python:
stage: python stage: python
script: script:
- cd $DAMASKROOT/python - cd $DAMASKROOT/python
@ -252,7 +252,7 @@ setup_mesh:
- release - release
################################################################################################### ###################################################################################################
Pytest_grid: pytest_fortran:
stage: grid stage: grid
script: script:
- module load $IntelCompiler $MPI_Intel $PETSc_Intel - module load $IntelCompiler $MPI_Intel $PETSc_Intel
@ -287,14 +287,6 @@ J2_plasticBehavior:
- master - master
- release - release
Marc_elementLib:
stage: marc
script:
- module load $IntelMarc $HDF5Marc $MSC
- Marc_elementLib/test.py
except:
- master
- release
################################################################################################### ###################################################################################################
SpectralRuntime: SpectralRuntime:

4
.gitmodules vendored
View File

@ -1,5 +1,5 @@
[submodule "PRIVATE"] [submodule "PRIVATE"]
path = PRIVATE path = PRIVATE
url = ../PRIVATE.git url = ../PRIVATE.git
branch = master branch = master
shallow = true shallow = true

View File

@ -84,7 +84,7 @@ for executable in python python3; do
done done
secondLevel "Details on $DEFAULT_PYTHON:" secondLevel "Details on $DEFAULT_PYTHON:"
echo $(ls -la $(which $DEFAULT_PYTHON)) echo $(ls -la $(which $DEFAULT_PYTHON))
for module in numpy scipy pandas;do for module in numpy scipy pandas matplotlib yaml h5py;do
thirdLevel $module thirdLevel $module
$DEFAULT_PYTHON -c "import $module; \ $DEFAULT_PYTHON -c "import $module; \
print('Version: {}'.format($module.__version__)); \ print('Version: {}'.format($module.__version__)); \
@ -94,10 +94,6 @@ thirdLevel vtk
$DEFAULT_PYTHON -c "import vtk; \ $DEFAULT_PYTHON -c "import vtk; \
print('Version: {}'.format(vtk.vtkVersion.GetVTKVersion())); \ print('Version: {}'.format(vtk.vtkVersion.GetVTKVersion())); \
print('Location: {}'.format(vtk.__file__))" print('Location: {}'.format(vtk.__file__))"
thirdLevel h5py
$DEFAULT_PYTHON -c "import h5py; \
print('Version: {}'.format(h5py.version.version)); \
print('Location: {}'.format(h5py.__file__))"
firstLevel "GNU Compiler Collection" firstLevel "GNU Compiler Collection"
for executable in gcc g++ gfortran ;do for executable in gcc g++ gfortran ;do

View File

@ -1,4 +1,4 @@
Copyright 2011-20 Max-Planck-Institut für Eisenforschung GmbH Copyright 2011-21 Max-Planck-Institut für Eisenforschung GmbH
DAMASK is free software: you can redistribute it and/or modify DAMASK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

@ -1 +1 @@
Subproject commit 45ef93dbfa3e0e6fa830914b3632e188c308a099 Subproject commit 13dfa0ee9d702782f0b7999f3f7fb2384f58d768

View File

@ -1 +1 @@
v3.0.0-alpha2-173-g584c7cc3a v3.0.0-alpha2-602-ge2d4ab427

6
env/CONFIG vendored
View File

@ -1,5 +1,5 @@
# "set"-syntax needed only for tcsh (but works with bash and zsh) # "set"-syntax needed only for tcsh (but works with bash and zsh)
set DAMASK_NUM_THREADS = 4 set OMP_NUM_THREADS = 4
set MSC_ROOT = /opt/msc set MSC_ROOT = /opt/msc
set MSC_VERSION = 2020 set MSC_VERSION = 2020

54
env/DAMASK.csh vendored
View File

@ -1,54 +0,0 @@
# sets up an environment for DAMASK on tcsh
# usage: source DAMASK_env.csh
set CALLED=($_)
set ENV_ROOT=`dirname $CALLED[2]`
set DAMASK_ROOT=`python3 -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" $ENV_ROOT"/../"`
source $ENV_ROOT/CONFIG
set path = ($DAMASK_ROOT/bin $path)
set SOLVER=`which DAMASK_grid`
if ( "x$DAMASK_NUM_THREADS" == "x" ) then
set DAMASK_NUM_THREADS=1
endif
# currently, there is no information that unlimited stack size causes problems
# still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it
# more info https://jblevins.org/log/segfault
# https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
# http://superuser.com/questions/220059/what-parameters-has-ulimit
limit stacksize unlimited # maximum stack size (kB)
# disable output in case of scp
if ( $?prompt ) then
echo ''
echo Düsseldorf Advanced Materials Simulation Kit --- DAMASK
echo Max-Planck-Institut für Eisenforschung GmbH, Düsseldorf
echo https://damask.mpie.de
echo
echo Using environment with ...
echo "DAMASK $DAMASK_ROOT"
echo "Grid Solver $SOLVER"
if ( $?PETSC_DIR) then
echo "PETSc location $PETSC_DIR"
endif
if ( $?MSC_ROOT) then
echo "MSC.Marc/Mentat $MSC_ROOT"
endif
echo
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS"
echo `limit datasize`
echo `limit stacksize`
echo
endif
setenv DAMASK_NUM_THREADS $DAMASK_NUM_THREADS
if ( ! $?PYTHONPATH ) then
setenv PYTHONPATH $DAMASK_ROOT/python
else
setenv PYTHONPATH $DAMASK_ROOT/python:$PYTHONPATH
endif
setenv MSC_ROOT
setenv MSC_VERSION

10
env/DAMASK.sh vendored
View File

@ -38,7 +38,7 @@ PATH=${DAMASK_ROOT}/bin:$PATH
SOLVER=$(type -p DAMASK_grid || true 2>/dev/null) SOLVER=$(type -p DAMASK_grid || true 2>/dev/null)
[ "x$SOLVER" == "x" ] && SOLVER=$(blink 'Not found!') [ "x$SOLVER" == "x" ] && SOLVER=$(blink 'Not found!')
[ "x$DAMASK_NUM_THREADS" == "x" ] && DAMASK_NUM_THREADS=1 [ "x$OMP_NUM_THREADS" == "x" ] && OMP_NUM_THREADS=1
# currently, there is no information that unlimited stack size causes problems # currently, there is no information that unlimited stack size causes problems
# still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it
@ -66,7 +66,7 @@ if [ ! -z "$PS1" ]; then
echo -n "MSC.Marc/Mentat " echo -n "MSC.Marc/Mentat "
[ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT [ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT
echo echo
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" echo "Multithreading OMP_NUM_THREADS=$OMP_NUM_THREADS"
echo -n "heap size " echo -n "heap size "
[[ "$(ulimit -d)" == "unlimited" ]] \ [[ "$(ulimit -d)" == "unlimited" ]] \
&& echo "unlimited" \ && echo "unlimited" \
@ -86,11 +86,13 @@ if [ ! -z "$PS1" ]; then
echo echo
fi fi
export DAMASK_NUM_THREADS export OMP_NUM_THREADS
export MSC_ROOT
export MSC_VERSION
export DAMASK_ROOT
export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH
for var in BASE STAT SOLVER BRANCH; do for var in BASE STAT SOLVER BRANCH; do
unset "${var}" unset "${var}"
done done
unset "ENV_ROOT" unset "ENV_ROOT"
unset "DAMASK_ROOT"

10
env/DAMASK.zsh vendored
View File

@ -30,7 +30,7 @@ PATH=${DAMASK_ROOT}/bin:$PATH
SOLVER=$(which DAMASK_grid || true 2>/dev/null) SOLVER=$(which DAMASK_grid || true 2>/dev/null)
[[ "x$SOLVER" == "x" ]] && SOLVER=$(blink 'Not found!') [[ "x$SOLVER" == "x" ]] && SOLVER=$(blink 'Not found!')
[[ "x$DAMASK_NUM_THREADS" == "x" ]] && DAMASK_NUM_THREADS=1 [[ "x$OMP_NUM_THREADS" == "x" ]] && OMP_NUM_THREADS=1
# currently, there is no information that unlimited stack size causes problems # currently, there is no information that unlimited stack size causes problems
# still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it
@ -60,7 +60,7 @@ if [ ! -z "$PS1" ]; then
echo -n "MSC.Marc/Mentat " echo -n "MSC.Marc/Mentat "
[ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT [ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT
echo echo
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS" echo "Multithreading OMP_NUM_THREADS=$OMP_NUM_THREADS"
echo -n "heap size " echo -n "heap size "
[[ "$(ulimit -d)" == "unlimited" ]] \ [[ "$(ulimit -d)" == "unlimited" ]] \
&& echo "unlimited" \ && echo "unlimited" \
@ -80,11 +80,13 @@ if [ ! -z "$PS1" ]; then
echo echo
fi fi
export DAMASK_NUM_THREADS export OMP_NUM_THREADS
export MSC_ROOT
export MSC_VERSION
export DAMASK_ROOT
export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH
for var in SOLVER BRANCH; do for var in SOLVER BRANCH; do
unset "${var}" unset "${var}"
done done
unset "ENV_ROOT" unset "ENV_ROOT"
unset "DAMASK_ROOT"

View File

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

View File

@ -1,4 +0,0 @@
[DP_Steel]
crystallite 1
(constituent) phase 1 texture 1 fraction 0.82
(constituent) phase 2 texture 2 fraction 0.18

View File

@ -1,64 +0,0 @@
[TWIP_Steel_FeMnC]
elasticity hooke
plasticity dislotwin
(output) rho_mob
(output) rho_dip
(output) gamma_sl
(output) lambda_sl
(output) tau_pass
(output) f_tw
(output) lambda_tw
(output) tau_hat_tw
(output) f_tr
### Material parameters ###
lattice_structure fcc
C11 175.0e9 # From Music et al. Applied Physics Letters 91, 191904 (2007)
C12 115.0e9
C44 135.0e9
grainsize 2.0e-5 # Average grain size [m]
SolidSolutionStrength 1.5e8 # Strength due to elements in solid solution
### Dislocation glide parameters ###
Nslip 12
slipburgers 2.56e-10 # Burgers vector of slip system [m]
rhoedgedip0 1.0 # Initial dislocation density [m/m**3]
rhoedge0 1.0e12 # Initial dislocation density [m/m**3]
v0 1.0e-4 # Initial glide velocity [m/s]
Qedge 3.7e-19 # Activation energy for dislocation glide [J]
p_slip 1.0 # p-exponent in glide velocity
q_slip 1.0 # q-exponent in glide velocity
# hardening of glide
CLambdaSlip 10.0 # Adj. parameter controlling dislocation mean free path
D0 4.0e-5 # Vacancy diffusion prefactor [m**2/s]
Qsd 4.5e-19 # Activation energy for climb [J]
Catomicvolume 1.0 # Adj. parameter controlling the atomic volume [in b^3]
Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b]
interactionSlipSlip 0.122 0.122 0.625 0.07 0.137 0.122 # Interaction coefficients (Kubin et al. 2008)
### Shearband parameters ###
shearbandresistance 180e6
shearbandvelocity 0e-4 # set to zero to turn shear banding of
QedgePerSbSystem 3.7e-19 # Activation energy for shear banding [J]
p_shearband 1.0 # p-exponent in glide velocity
q_shearband 1.0 # q-exponent in glide velocity
### Twinning parameters ###
Ntwin 12
twinburgers 1.47e-10 # Burgers vector of twin system [m]
twinsize 5.0e-8 # Twin stack mean thickness [m]
L0_twin 442.0 # Length of twin nuclei in Burgers vectors
maxtwinfraction 1.0 # Maximum admissible twin volume fraction
xc_twin 1.0e-9 # critical distance for formation of twin nucleus
VcrossSlip 1.67e-29 # cross slip volume
r_twin 10.0 # r-exponent in twin formation probability
Cmfptwin 1.0 # Adj. parameter controlling twin mean free path
Cthresholdtwin 1.0 # Adj. parameter controlling twin threshold stress
interactionSlipTwin 0.0 1.0 1.0 # Dislocation-Twin interaction coefficients
interactionTwinTwin 0.0 1.0 # Twin-Twin interaction coefficients
SFE_0K -0.0396 # stacking fault energy at zero K; TWIP steel: -0.0526; Cu: -0.0396
dSFE_dT 0.0002 # temperature dependance of stacking fault energy

View File

@ -0,0 +1,41 @@
TWIP_Steel_FeMnC:
lattice: cF
mechanics:
elasticity: {type: hooke, C_11: 175.0e9, C_12: 115.0e9, C_44: 135.0e9}
plasticity:
type: dislotwin
output: [rho_mob, rho_dip, gamma_sl, Lambda_sl, tau_pass, f_tw, Lambda_tw, tau_hat_tw, f_tr]
D: 2.0e-5
N_sl: [12]
b_sl: [2.56e-10]
rho_mob_0: [1.0e12]
rho_dip_0: [1.0]
v_0: [1.0e4]
Q_s: [3.7e-19]
p_sl: [1.0]
q_sl: [1.0]
tau_0: [1.5e8]
i_sl: [10.0] # Adj. parameter controlling dislocation mean free path
D_0: 4.0e-5 # Vacancy diffusion prefactor / m^2/s
D_a: 1.0 # minimum dipole distance / b
Q_cl: 4.5e-19 # Activation energy for climb / J
h_sl_sl: [0.122, 0.122, 0.625, 0.07, 0.137, 0.122] # Interaction coefficients (Kubin et al. 2008)
# shear band parameters
xi_sb: 180.0e6
Q_sb: 3.7e-19
p_sb: 1.0
q_sb: 1.0
v_sb: 0.0 # set to 0, to turn it off
# twinning parameters
N_tw: [12]
b_tw: [1.47e-10] # Burgers vector length of twin system / b
t_tw: [5.0e-8] # Twin stack mean thickness / m
L_tw: 442.0 # Length of twin nuclei / b
x_c_tw: 1.0e-9 # critical distance for formation of twin nucleus / m
V_cs: 1.67e-29 # cross slip volume / m^3
p_tw: [10.0] # r-exponent in twin formation probability
i_tw: 1.0 # Adj. parameter controlling twin mean free path
h_sl_tw: [0.0, 1.0, 1.0] # dislocation-twin interaction coefficients
h_tw_tw: [0.0, 1.0] # twin-twin interaction coefficients
Gamma_sf_0K: -0.0396 # stacking fault energy / J/m^2 at zero K; TWIP steel: -0.0526; Cu: -0.0396
dGamma_sf_dT: 0.0002 # temperature dependence / J/(m^2 K) of stacking fault energy

View File

@ -1,36 +0,0 @@
[Tungsten]
elasticity hooke
plasticity dislotwin
### Material parameters ###
lattice_structure bcc
C11 523.0e9 # From Marinica et al. Journal of Physics: Condensed Matter(2013)
C12 202.0e9
C44 161.0e9
grainsize 2.0e-5 # Average grain size [m]
SolidSolutionStrength 1.5e8 # Strength due to elements in solid solution
### Dislocation glide parameters ###
#per family
Nslip 12
slipburgers 2.72e-10 # Burgers vector of slip system [m]
rhoedge0 1.0e12 # Initial edge dislocation density [m/m**3]
rhoedgedip0 1.0 # Initial edged dipole dislocation density [m/m**3]
v0 1.0e-4 # Initial glide velocity [m/s]
Qedge 2.725e-19 # Activation energy for dislocation glide [J]
p_slip 0.78 # p-exponent in glide velocity
q_slip 1.58 # q-exponent in glide velocity
tau_peierls 2.03e9 # peierls stress (for bcc)
dipoleformationfactor 0 # to have hardening due to dipole formation off
#hardening
CLambdaSlip 10.0 # Adj. parameter controlling dislocation mean free path
D0 4.0e-5 # Vacancy diffusion prefactor [m**2/s]
Qsd 4.5e-19 # Activation energy for climb [J]
Catomicvolume 1.0 # Adj. parameter controlling the atomic volume [in b]
Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b]
interaction_slipslip 1 1 1.4 1.4 1.4 1.4

View File

@ -0,0 +1,21 @@
Tungsten:
lattice: cI
mechanics:
elasticity: {type: hooke, C_11: 523.0e9, C_12: 202.0e9, C_44: 161.0e9} # Marinica et al. Journal of Physics: Condensed Matter(2013)
plasticity:
type: dislotwin
D: 2.0e-5 # Average grain size / m
N_sl: [12]
b_sl: [2.72e-10] # Burgers vector length of slip families / m
rho_mob_0: [1.0e12]
rho_dip_0: [1.0]
v_0: [1.0e4] # Initial glide velocity / m/s
Q_s: [2.725e-19] # Activation energy for dislocation glide / J
p_sl: [0.78] # p-exponent in glide velocity
q_sl: [1.58] # q-exponent in glide velocity
tau_0: [1.5e8] # solid solution strength / Pa
i_sl: [10.0] # Adj. parameter controlling dislocation mean free path
D_0: 4.0e-5 # Vacancy diffusion prefactor / m^2/s
D_a: 1.0 # minimum dipole distance / b
Q_cl: 4.5e-19 # Activation energy for climb / J
h_sl_sl: [1, 1, 1.4, 1.4, 1.4, 1.4]

View File

@ -1,3 +0,0 @@
hydrogenflux_diffusion11 1.0
hydrogenflux_mobility11 1.0
hydrogenVolume 1e-28

View File

@ -1,9 +1,9 @@
# Kuo, J. C., Mikrostrukturmechanik von Bikristallen mit Kippkorngrenzen. Shaker-Verlag 2004. http://edoc.mpg.de/204079 # Kuo, J. C., Mikrostrukturmechanik von Bikristallen mit Kippkorngrenzen. Shaker-Verlag 2004. http://edoc.mpg.de/204079
Aluminum: Aluminum:
lattice: aP
mechanics: mechanics:
lattice: aP output: [F, P, F_e, F_p, L_p]
elasticity: {C_11: 110.9e9, C_12: 58.34e9, type: hooke} elasticity: {type: hooke, C_11: 110.9e9, C_12: 58.34e9}
output: [F, P, Fe, Fp, Lp]
plasticity: plasticity:
type: isotropic type: isotropic
output: [xi] output: [xi]

View File

@ -1,9 +1,8 @@
# Maiti and Eisenlohr 2018 Scripta Materialia
Air: Air:
lattice: aP
mechanics: mechanics:
lattice: aP output: [F, P, F_e, F_p, L_p]
elasticity: {C_11: 10e9, C_12: 0.0, type: hooke} elasticity: {type: hooke, C_11: 1e8, C_12: 1e6}
output: [F, P, Fe, Fp, Lp]
plasticity: plasticity:
type: isotropic type: isotropic
output: [xi] output: [xi]
@ -14,4 +13,4 @@ Air:
M: 3 M: 3
h_0: 1e6 h_0: 1e6
a: 2 a: 2
dilatation: true dilatation: True

View File

@ -1,21 +0,0 @@
[Aluminum]
elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
(output) accumulatedshear_slip
lattice_structure fcc
Nslip 12 # 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
h0_slipslip 75e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4

View File

@ -0,0 +1,16 @@
Aluminum:
lattice: cF
mechanics:
output: [F, P, F_e, F_p, L_p, O]
elasticity: {C_11: 106.75e9, C_12: 60.41e9, C_44: 28.34e9, type: hooke}
plasticity:
N_sl: [12]
a_sl: 2.25
dot_gamma_0_sl: 0.001
h_0_sl_sl: 75e6
h_sl_sl: [1, 1, 1.4, 1.4, 1.4, 1.4]
n_sl: 20
output: [xi_sl, gamma_sl]
type: phenopowerlaw
xi_0_sl: [31e6]
xi_inf_sl: [63e6]

View File

@ -2,8 +2,8 @@
# Tasan et.al. 2015 International Journal of Plasticity # Tasan et.al. 2015 International Journal of Plasticity
# Diehl et.al. 2015 Meccanica # Diehl et.al. 2015 Meccanica
Ferrite: Ferrite:
lattice: cI
mechanics: mechanics:
lattice: cI
elasticity: {C_11: 233.3e9, C_12: 135.5e9, C_44: 118.0e9, type: hooke} elasticity: {C_11: 233.3e9, C_12: 135.5e9, C_44: 118.0e9, type: hooke}
plasticity: plasticity:
N_sl: [12, 12] N_sl: [12, 12]

View File

@ -2,8 +2,8 @@
# Tasan et.al. 2015 International Journal of Plasticity # Tasan et.al. 2015 International Journal of Plasticity
# Diehl et.al. 2015 Meccanica # Diehl et.al. 2015 Meccanica
Martensite: Martensite:
lattice: cI
mechanics: mechanics:
lattice: cI
elasticity: {C_11: 417.4e9, C_12: 242.4e9, C_44: 211.1e9, type: hooke} elasticity: {C_11: 417.4e9, C_12: 242.4e9, C_44: 211.1e9, type: hooke}
plasticity: plasticity:
N_sl: [12, 12] N_sl: [12, 12]

View File

@ -1,27 +0,0 @@
# parameters fitted by D. Ma to:
# I. Kovács, G. Vörös
# On the mathematical description of the tensile stress-strain curves of polycrystalline face centered cubic metals
# International Journal of Plasticity, Volume 12, Issue 1, 1996, Pages 3543
# DOI: 10.1016/S0749-6419(95)00043-7
[gold_phenopowerlaw]
elasticity hooke
plasticity phenopowerlaw
(output) resistance_slip
lattice_structure fcc
Nslip 12 # per family
c11 191.0e9
c12 162.0e9
c44 42.20e9
gdot0_slip 0.001
n_slip 83.3
tau0_slip 26.25e6 # per family
tausat_slip 53.00e6 # per family
a_slip 1.0
h0_slipslip 75e6
interaction_slipslip 1 1 1.4 1.4 1.4 1.4

View File

@ -0,0 +1,21 @@
# parameters fitted by D. Ma to:
# On the mathematical description of the tensile stress-strain curves of polycrystalline face centered cubic metals
# International Journal of Plasticity, Volume 12, Issue 1, 1996, Pages 35-43
# DOI: 10.1016/S0749-6419(95)00043-7
Gold:
lattice: cF
mechanics:
output: [F, P, F_e, F_p, L_p, O]
elasticity: {type: hooke, C_11: 191e9, C_12: 162e9, C_44: 42.2e9}
plasticity:
type: phenopowerlaw
output: [xi_sl]
N_sl: [12]
n_sl: 83
dot_gamma_0_sl: 0.001
h_0_sl_sl: 75e6
h_sl_sl: [1, 1, 1.4, 1.4, 1.4, 1.4]
a_sl: 1.0
xi_0_sl: [26e6]
xi_inf_sl: [53e6]

View File

@ -1,56 +0,0 @@
#-------------------#
<phase>
#-------------------#
/echo/
[Mg]
plasticity phenopowerlaw
elasticity hooke
(output) resistance_slip
(output) resistance_twin
lattice_structure hex
c/a 1.62350 # from Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals
c11 59.3e9 # - " -
c33 61.5e9 # - " -
c44 16.4e9 # - " -
c12 25.7e9 # - " -
c13 21.4e9 # - " -
# basal prism prism pyr(a) pyr(c+a) pyr(c+a)
Nslip 3 3 0 6 0 6 # from Agnew et al 2006, Validating a polycrystal model for the elastoplastic response of mg alloy AZ32 using in situ neutron diffraction
# T1 C1 T2 C2
Ntwin 6 0 0 6 # - " -
# basal prism prism pyr(a) pyr(c+a) pyr(c+a)
tau0_slip 10.0e6 55.0e6 0 60.0e6 0.0 60.0e6 # - " - table 1, pyr(a) set to pyr(c+a)
tausat_slip 40.0e6 135.0e6 0 150.0e6 0.0 150.0e6 # - " - table 1, pyr(a) set to pyr(c+a)
# T1 C1 T2 C2
tau0_twin 40e6 0.0 0.0 60.0e6 # - " - table 1, compressive twin guessed by Steffi, tensile twin modified to match experimental results
h0_twintwin 50.0e6 # - " - table 1, same range as theta_0
h0_slipslip 500.0e6 # - " - table 1, same range as theta_0
h0_twinslip 150.0e6 # guessing
interaction_slipslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 # just guessing
interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 # - " -
interaction_sliptwin 1 1 1 1 1 1 1 1 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 1 1 1 1 1 1 1 1 # - " -
####################################################
# open for discussion
####################################################
n_twin 20
n_slip 20
gdot0_twin 0.001
gdot0_slip 0.001
twin_b 0
twin_c 0
twin_d 20
twin_e 20
a_slip 2.25
s_pr 10.0 # push-up factor for slip saturation due to twinning

View File

@ -0,0 +1,31 @@
# Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals
Magnesium:
lattice: hP
c/a: 1.62350
mechanics:
output: [F, P, F_e, F_p, L_p, O]
elasticity: {C_11: 59.3e9, C_12: 25.7e9, C_13: 21.4e9, C_33: 61.5e9, C_44: 16.4e9, type: hooke}
plasticity:
N_sl: [3, 3, 0, 6, 0, 6]
N_tw: [6, 0, 0, 6]
h_0_tw_tw: 50.0e6
h_0_sl_sl: 500.0e6
h_0_tw_sl: 150.0e6
h_sl_sl: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
h_tw_tw: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
h_sl_tw: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
h_tw_sl: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
output: [xi_sl, xi_tw]
type: phenopowerlaw
xi_0_sl: [10.0e6, 55.0e6, 0, 60.0e6, 0.0, 60.0e6]
xi_inf_sl: [40.0e6, 135.0e6, 0, 150.0e6, 0.0, 150.0e6]
xi_0_tw: [40e6, 0.0, 0.0, 60.0e6]
####################################################
# open for discussion
####################################################
a_sl: 2.25
dot_gamma_0_sl: 0.001
dot_gamma_0_tw: 0.001
n_sl: 20
n_tw: 20
f_sl_sat_tw: 10.0

View File

@ -1,23 +0,0 @@
[cpTi-alpha]
plasticity phenopowerlaw
elasticity hooke
lattice_structure hex
covera_ratio 1.587
# M. Levy, Handbook of Elastic Properties of Solids, Liquids, and Gases (2001)
c11 160.0e9
c12 90.0e9
c13 66.0e9
c33 181.7e9
c44 46.5e9
# C. Zambaldi, "Orientation informed nanoindentation of a-titanium: Indentation pileup in hexagonal metals deforming by prismatic slip", J. Mater. Res., Vol. 27, No. 1, Jan 14, 2012
gdot0_slip 0.001
n_slip 20
nslip 3 3 0 6
tau0_slip 349.3e6 150e6 0 1107.9e6
tausat_slip 568.6e6 1502.2e6 0 3420.1e6
a_slip 2
h0_slipslip 15e6
interaction_slipslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

View File

@ -0,0 +1,20 @@
# M. Levy, Handbook of Elastic Properties of Solids, Liquids, and Gases (2001)
# C. Zambaldi, "Orientation informed nanoindentation of a-titanium: Indentation pileup in hexagonal metals deforming by prismatic slip", J. Mater. Res., Vol. 27, No. 1, Jan 14, 2012
# Better use values from L. Wang, Z. Zheng, H. Phukan, P. Kenesei, J.-S. Park, J. Lind, R.M. Suter, T.R. Bieler, Direct measurement of critical resolved shear stress of prismatic and basal slip in polycrystalline Ti using high energy X-ray diffraction microscopy, Acta Mater 2017
cpTi:
lattice: hP
c/a: 1.587
mechanics:
output: [F, P, F_e, F_p, L_p, O]
elasticity: {C_11: 160.0e9, C_12: 90.0e9, C_13: 66.0e9, C_33: 181.7e9, C_44: 46.5e9, type: hooke}
plasticity:
N_sl: [3, 3, 0, 6, 12]
a_sl: 2.0
dot_gamma_0_sl: 0.001
h_0_sl_sl: 200e6
h_sl_sl: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
n_sl: 20
output: [gamma_sl]
type: phenopowerlaw
xi_0_sl: [0.15e9, 0.09e9, 0, 0.20e9, 0.25e9]
xi_inf_sl: [0.24e9, 0.5e9, 0, 0.6e9, 0.8e9]

View File

@ -1,2 +0,0 @@
[001]
(gauss) phi1 0.000 Phi 0.000 phi2 0.000

View File

@ -1,2 +0,0 @@
[101]
(gauss) phi1 0.000 Phi 45.000 phi2 90.000

View File

@ -1,2 +0,0 @@
[111]
(gauss) phi1 0.000 Phi 54.7356 phi2 45.000

View File

@ -1,2 +0,0 @@
[123]
(gauss) phi1 209.805 Phi 29.206 phi2 63.435

View File

@ -1,20 +0,0 @@
# The material.config file needs to specify five parts:
# homogenization, microstructure, crystallite, phase, and texture.
# You can either put the full text in here or include suited separate files
<homogenization>
{./Homogenization_Isostrain_SX.config}
<microstructure>
[one_only]
crystallite 1
(constituent) phase 1 texture 1 fraction 1.0
<crystallite>
{./Crystallite_All.config}
<phase>
{./Phase_Phenopowerlaw_Aluminum.config}
<texture>
{./Texture_Gauss_001.config}

View File

@ -1,9 +0,0 @@
step:
- mechanics:
dot_F: [0, 0, 0,
1e-3, 0, 0,
0, 0, 0]
discretization:
t: 60
N: 120
f_out: 20

View File

@ -1,10 +0,0 @@
---
step:
- mechanics:
dot_F: [0, 0, 1e-3,
0, 0, 0,
0, 0, 0]
discretization:
t: 60
N: 120
f_out: 20

View File

@ -1,25 +0,0 @@
---
step:
- mechanics:
dot_F: [1.0e-3, 0, 0,
0, x, 0,
0, 0, x]
P: [x, x, x,
x, 0, x,
x, x, 0]
discretization:
t: 10
N: 40
f_out: 4
- mechanics:
dot_F: [1.0e-3, 0, 0,
0, x, 0,
0, 0, x]
P: [x, x, x,
x, 0, x,
x, x, 0]
discretization:
t: 60
N: 60
f_out: 4

View File

@ -2,108 +2,108 @@
homogenization: homogenization:
SX: SX:
N_constituents: 1 N_constituents: 1
mechanics: {type: none} mechanics: {type: pass}
material: material:
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [1.0, 0.0, 0.0, 0.0] O: [1.0, 0.0, 0.0, 0.0]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434] O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945] O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106] O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.33012772942625784, -0.6781865350268957, 0.6494525351030648, 0.09638521992649676] O: [0.33012772942625784, -0.6781865350268957, 0.6494525351030648, 0.09638521992649676]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.43596817439583935, -0.5982537129781701, 0.046599032277502436, 0.6707106499919265] O: [0.43596817439583935, -0.5982537129781701, 0.046599032277502436, 0.6707106499919265]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.169734823419553, -0.699615227367322, -0.6059581215838098, -0.33844257746495854] O: [0.169734823419553, -0.699615227367322, -0.6059581215838098, -0.33844257746495854]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.9698864809294915, 0.1729052643205874, -0.15948307917616958, 0.06315956884687175] O: [0.9698864809294915, 0.1729052643205874, -0.15948307917616958, 0.06315956884687175]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.46205660912967883, 0.3105054068891252, -0.617849551030653, 0.555294529545738] O: [0.46205660912967883, 0.3105054068891252, -0.617849551030653, 0.555294529545738]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.4512443497461787, -0.7636045534540555, -0.04739348426715133, -0.45939142396805815] O: [0.4512443497461787, -0.7636045534540555, -0.04739348426715133, -0.45939142396805815]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.2161856212656443, -0.6581450184826598, -0.5498086209601588, 0.4667112513346289] O: [0.2161856212656443, -0.6581450184826598, -0.5498086209601588, 0.4667112513346289]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.8753220715350803, -0.4561599367657419, -0.13298279533852678, -0.08969369719975541] O: [0.8753220715350803, -0.4561599367657419, -0.13298279533852678, -0.08969369719975541]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.11908260752431069, 0.18266024809834172, -0.7144822594012615, -0.664807992845101] O: [0.11908260752431069, 0.18266024809834172, -0.7144822594012615, -0.664807992845101]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.751104669484278, 0.5585633382623958, -0.34579336397009175, 0.06538900566860861] O: [0.751104669484278, 0.5585633382623958, -0.34579336397009175, 0.06538900566860861]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.08740438971703973, 0.8991264096610437, -0.4156704205935976, 0.10559485570696363] O: [0.08740438971703973, 0.8991264096610437, -0.4156704205935976, 0.10559485570696363]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.5584325870096193, 0.6016408353068798, -0.14280340445801173, 0.5529814994483859] O: [0.5584325870096193, 0.6016408353068798, -0.14280340445801173, 0.5529814994483859]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.4052725440888093, 0.25253073423599154, 0.5693263597910454, -0.669215876471182] O: [0.4052725440888093, 0.25253073423599154, 0.5693263597910454, -0.669215876471182]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.7570164606888676, 0.15265448024694664, -0.5998021466848317, 0.20942796551297105] O: [0.7570164606888676, 0.15265448024694664, -0.5998021466848317, 0.20942796551297105]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.6987659297138081, -0.132172211261028, -0.19693254724422338, 0.6748883269678543] O: [0.6987659297138081, -0.132172211261028, -0.19693254724422338, 0.6748883269678543]
- homogenization: SX - homogenization: SX
constituents: constituents:
- phase: Aluminum - phase: Aluminum
fraction: 1.0 v: 1.0
O: [0.7729330445886478, 0.21682179052722322, -0.5207379472917645, 0.2905078484066341] O: [0.7729330445886478, 0.21682179052722322, -0.5207379472917645, 0.2905078484066341]
phase: phase:

View File

@ -0,0 +1,15 @@
---
solver:
mechanical: spectral_basic
loadstep:
- boundary_conditions:
mechanical:
dot_F: [0, 0, 0,
1e-3, 0, 0,
0, 0, 0]
discretization:
t: 60
N: 120
f_out: 20

View File

@ -0,0 +1,15 @@
---
solver:
mechanical: spectral_basic
loadstep:
- boundary_conditions:
mechanical:
dot_F: [0, 0, 1e-3,
0, 0, 0,
0, 0, 0]
discretization:
t: 60
N: 120
f_out: 20

View File

@ -0,0 +1,30 @@
---
solver:
mechanical: spectral_basic
loadstep:
- boundary_conditions:
mechanical:
dot_F: [1.0e-3, 0, 0,
0, x, 0,
0, 0, x]
P: [x, x, x,
x, 0, x,
x, x, 0]
discretization:
t: 10
N: 40
f_out: 4
- boundary_conditions:
mechanical:
dot_F: [1.0e-3, 0, 0,
0, x, 0,
0, 0, x]
P: [x, x, x,
x, 0, x,
x, x, 0]
discretization:
t: 60
N: 60
f_out: 4

View File

@ -5,13 +5,9 @@ import glob
import argparse import argparse
from pathlib import Path from pathlib import Path
import damask msc_version = os.environ['MSC_VERSION']
msc_root = Path(os.environ['MSC_ROOT'])
msc_version = float(damask.environment.options['MSC_VERSION']) damask_root = Path(os.environ['DAMASK_ROOT'])
if int(msc_version) == msc_version:
msc_version = int(msc_version)
msc_root = Path(damask.environment.options['MSC_ROOT'])
damask_root = damask.environment.root_dir
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Apply DAMASK modification to MSC.Marc/Mentat', description='Apply DAMASK modification to MSC.Marc/Mentat',
@ -24,7 +20,7 @@ def copy_and_replace(in_file,dst):
with open(in_file) as f: with open(in_file) as f:
content = f.read() content = f.read()
content = content.replace('%INSTALLDIR%',str(msc_root)) content = content.replace('%INSTALLDIR%',str(msc_root))
content = content.replace('%VERSION%',str(msc_version)) content = content.replace('%VERSION%', msc_version)
content = content.replace('%EDITOR%', parser.parse_args().editor) content = content.replace('%EDITOR%', parser.parse_args().editor)
with open(dst/Path(in_file).name,'w') as f: with open(dst/Path(in_file).name,'w') as f:
f.write(content) f.write(content)
@ -53,8 +49,8 @@ for in_file in glob.glob(str(src/'job_run.ms')):
print('compiling Mentat menu binaries...') print('compiling Mentat menu binaries...')
executable = str(msc_root/f'mentat{msc_version}/bin/mentat') executable = msc_root/f'mentat{msc_version}/bin/mentat'
menu_file = str(msc_root/f'mentat{msc_version}/menus/linux64/main.msb') menu_file = msc_root/f'mentat{msc_version}/menus/linux64/main.msb'
os.system(f'xvfb-run {executable} -compile {menu_file}') os.system(f'xvfb-run {executable} -compile {menu_file}')

View File

@ -3,11 +3,9 @@
# Makes postprocessing routines accessible from everywhere. # Makes postprocessing routines accessible from everywhere.
import sys import sys
from pathlib import Path from pathlib import Path
import os
import damask bin_dir = Path(os.environ['DAMASK_ROOT'])/'bin'
env = damask.Environment()
bin_dir = env.root_dir/Path('bin')
if not bin_dir.exists(): if not bin_dir.exists():
bin_dir.mkdir() bin_dir.mkdir()
@ -15,7 +13,7 @@ if not bin_dir.exists():
sys.stdout.write('\nsymbolic linking...\n') sys.stdout.write('\nsymbolic linking...\n')
for sub_dir in ['pre','post']: for sub_dir in ['pre','post']:
the_dir = env.root_dir/Path('processing')/Path(sub_dir) the_dir = Path(os.environ['DAMASK_ROOT'])/'processing'/sub_dir
for the_file in the_dir.glob('*.py'): for the_file in the_dir.glob('*.py'):
src = the_dir/the_file src = the_dir/the_file

View File

@ -41,15 +41,15 @@ for filename in options.filenames:
table = damask.Table(np.ones(np.product(results.cells),dtype=int)*int(inc[3:]),{'inc':(1,)})\ table = damask.Table(np.ones(np.product(results.cells),dtype=int)*int(inc[3:]),{'inc':(1,)})\
.add('pos',coords.reshape(-1,3)) .add('pos',coords.reshape(-1,3))
results.pick('homogenizations',False) results.view('homogenizations',False)
results.pick('phases',True) results.view('phases',True)
for label in options.con: for label in options.con:
x = results.get_dataset_location(label) x = results.get_dataset_location(label)
if len(x) != 0: if len(x) != 0:
table = table.add(label,results.read_dataset(x,0,plain=True).reshape(results.cells.prod(),-1)) table = table.add(label,results.read_dataset(x,0,plain=True).reshape(results.cells.prod(),-1))
results.pick('phases',False) results.view('phases',False)
results.pick('homogenizations',True) results.view('homogenizations',True)
for label in options.mat: for label in options.mat:
x = results.get_dataset_location(label) x = results.get_dataset_location(label)
if len(x) != 0: if len(x) != 0:

View File

@ -16,8 +16,6 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
__version__ = version __version__ = version
# make classes directly accessible as damask.Class # make classes directly accessible as damask.Class
from ._environment import Environment as _ # noqa
environment = _()
from . import util # noqa from . import util # noqa
from . import seeds # noqa from . import seeds # noqa
from . import tensor # noqa from . import tensor # noqa
@ -38,7 +36,6 @@ from ._result import Result # noqa
# deprecated # deprecated
Environment = _
from ._asciitable import ASCIItable # noqa from ._asciitable import ASCIItable # noqa
from ._test import Test # noqa from ._test import Test # noqa
from .util import extendableOption # noqa from .util import extendableOption # noqa

View File

@ -223,25 +223,46 @@ class Colormap(mpl.colors.ListedColormap):
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name) return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
def _get_file_handle(self,fname,extension):
"""
Provide file handle.
Parameters
----------
fname : file, str, pathlib.Path, or None
Filename or filehandle, will be name of the colormap+extension if None.
extension: str
Extension of the filename.
Returns
-------
f
File handle
"""
if fname is None:
fhandle = open(self.name.replace(' ','_')+'.'+extension,'w',newline='\n')
else:
try:
fhandle = open(fname,'w',newline='\n')
except TypeError:
fhandle = fname
return fhandle
def save_paraview(self,fname=None): def save_paraview(self,fname=None):
""" """
Save as JSON file for use in Paraview. Save as JSON file for use in Paraview.
Parameters Parameters
---------- ----------
fname : file, str, or pathlib.Path, optional. fname : file, str, or pathlib.Path, optional
Filename to store results. If not given, the filename will Filename to store results. If not given, the filename will
consist of the name of the colormap and extension '.json'. consist of the name of the colormap and extension '.json'.
""" """
if fname is None:
fhandle = None
else:
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
colors = [] colors = []
for i,c in enumerate(np.round(self.colors,6).tolist()): for i,c in enumerate(np.round(self.colors,6).tolist()):
colors+=[i]+c colors+=[i]+c
@ -254,8 +275,7 @@ class Colormap(mpl.colors.ListedColormap):
'RGBPoints':colors 'RGBPoints':colors
}] }]
with open(self.name.replace(' ','_')+'.json', 'w') if fhandle is None else fhandle as f: json.dump(out,self._get_file_handle(fname,'json'),indent=4)
json.dump(out, f,indent=4)
def save_ASCII(self,fname=None): def save_ASCII(self,fname=None):
@ -264,24 +284,14 @@ class Colormap(mpl.colors.ListedColormap):
Parameters Parameters
---------- ----------
fname : file, str, or pathlib.Path, optional. fname : file, str, or pathlib.Path, optional
Filename to store results. If not given, the filename will Filename to store results. If not given, the filename will
consist of the name of the colormap and extension '.txt'. consist of the name of the colormap and extension '.txt'.
""" """
if fname is None:
fhandle = None
else:
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3} labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3}
t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}') t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}')
t.save(self._get_file_handle(fname,'txt'))
with open(self.name.replace(' ','_')+'.txt', 'w') if fhandle is None else fhandle as f:
t.save(f)
def save_GOM(self,fname=None): def save_GOM(self,fname=None):
@ -290,26 +300,19 @@ class Colormap(mpl.colors.ListedColormap):
Parameters Parameters
---------- ----------
fname : file, str, or pathlib.Path, optional. fname : file, str, or pathlib.Path, optional
Filename to store results. If not given, the filename will Filename to store results. If not given, the filename will
consist of the name of the colormap and extension '.legend'. consist of the name of the colormap and extension '.legend'.
""" """
if fname is None:
fhandle = None
else:
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
# ToDo: test in GOM # ToDo: test in GOM
GOM_str = '1 1 {name} 9 {name} '.format(name=self.name.replace(" ","_")) \ GOM_str = '1 1 {name} 9 {name} '.format(name=self.name.replace(" ","_")) \
+ '0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' \ + '0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' \
+ f'30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 {len(self.colors)}' \ + f'30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 {len(self.colors)}' \
+ ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((self.colors*255).astype(int))]) \ + ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((self.colors*255).astype(int))]) \
+ '\n' + '\n'
with open(self.name.replace(' ','_')+'.legend', 'w') if fhandle is None else fhandle as f:
f.write(GOM_str) self._get_file_handle(fname,'legend').write(GOM_str)
def save_gmsh(self,fname=None): def save_gmsh(self,fname=None):
@ -318,24 +321,16 @@ class Colormap(mpl.colors.ListedColormap):
Parameters Parameters
---------- ----------
fname : file, str, or pathlib.Path, optional. fname : file, str, or pathlib.Path, optional
Filename to store results. If not given, the filename will Filename to store results. If not given, the filename will
consist of the name of the colormap and extension '.msh'. consist of the name of the colormap and extension '.msh'.
""" """
if fname is None:
fhandle = None
else:
try:
fhandle = open(fname,'w')
except TypeError:
fhandle = fname
# ToDo: test in gmsh # ToDo: test in gmsh
gmsh_str = 'View.ColorTable = {\n' \ gmsh_str = 'View.ColorTable = {\n' \
+'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \ +'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \
+'\n}\n' +'\n}\n'
with open(self.name.replace(' ','_')+'.msh', 'w') if fhandle is None else fhandle as f: self._get_file_handle(fname,'msh').write(gmsh_str)
f.write(gmsh_str)
@staticmethod @staticmethod

View File

@ -1,4 +1,6 @@
import copy
from io import StringIO from io import StringIO
from collections.abc import Iterable
import abc import abc
import numpy as np import numpy as np
@ -35,6 +37,50 @@ class Config(dict):
output.seek(0) output.seek(0)
return ''.join(output.readlines()) return ''.join(output.readlines())
def __copy__(self):
"""Create deep copy."""
return copy.deepcopy(self)
copy = __copy__
def __or__(self,other):
"""
Update configuration with contents of other.
Parameters
----------
other : damask.Config or dict
Key-value pairs that update self.
"""
duplicate = self.copy()
duplicate.update(other)
return duplicate
def __ior__(self,other):
"""Update configuration with contents of other."""
return self.__or__(other)
def delete(self,keys):
"""
Remove configuration keys.
Parameters
----------
keys : iterable or scalar
Label of the key(s) to remove.
"""
duplicate = self.copy()
for k in keys if isinstance(keys, Iterable) and not isinstance(keys, str) else [keys]:
del duplicate[k]
return duplicate
@classmethod @classmethod
def load(cls,fname): def load(cls,fname):
""" """
@ -52,6 +98,7 @@ class Config(dict):
fhandle = fname fhandle = fname
return cls(yaml.safe_load(fhandle)) return cls(yaml.safe_load(fhandle))
def save(self,fname,**kwargs): def save(self,fname,**kwargs):
""" """
Save to yaml file. Save to yaml file.
@ -65,7 +112,7 @@ class Config(dict):
""" """
try: try:
fhandle = open(fname,'w') fhandle = open(fname,'w',newline='\n')
except TypeError: except TypeError:
fhandle = fname fhandle = fname
@ -95,6 +142,7 @@ class Config(dict):
"""Check for completeness.""" """Check for completeness."""
pass pass
@property @property
@abc.abstractmethod @abc.abstractmethod
def is_valid(self): def is_valid(self):

View File

@ -1,4 +1,3 @@
import copy
from os import path from os import path
import numpy as np import numpy as np
@ -7,6 +6,7 @@ import h5py
from . import Config from . import Config
from . import Rotation from . import Rotation
from . import Orientation from . import Orientation
from . import util
class ConfigMaterial(Config): class ConfigMaterial(Config):
"""Material configuration.""" """Material configuration."""
@ -15,11 +15,10 @@ class ConfigMaterial(Config):
'homogenization': {}, 'homogenization': {},
'phase': {}} 'phase': {}}
def __init__(self,d={}): def __init__(self,d=_defaults):
"""Initialize object with default dictionary keys.""" """Initialize object with default dictionary keys."""
super().__init__(d) super().__init__(d)
for k,v in self._defaults.items():
if k not in self: self[k] = v
def save(self,fname='material.yaml',**kwargs): def save(self,fname='material.yaml',**kwargs):
""" """
@ -51,7 +50,7 @@ class ConfigMaterial(Config):
@staticmethod @staticmethod
def from_table(table,constituents={},**kwargs): def from_table(table,**kwargs):
""" """
Load from an ASCII table. Load from an ASCII table.
@ -59,12 +58,9 @@ class ConfigMaterial(Config):
---------- ----------
table : damask.Table table : damask.Table
Table that contains material information. Table that contains material information.
constituents : dict, optional
Entries for 'constituents'. The key is the name and the value specifies
the label of the data column in the table
**kwargs **kwargs
Keyword arguments where the key is the name and the value specifies Keyword arguments where the key is the name and the value specifies
the label of the data column in the table the label of the data column in the table.
Examples Examples
-------- --------
@ -75,32 +71,30 @@ class ConfigMaterial(Config):
pos pos pos qu qu qu qu phase homog pos pos pos qu qu qu qu phase homog
0 0 0 0 0.19 0.8 0.24 -0.51 Aluminum SX 0 0 0 0 0.19 0.8 0.24 -0.51 Aluminum SX
1 1 0 0 0.8 0.19 0.24 -0.51 Steel SX 1 1 0 0 0.8 0.19 0.24 -0.51 Steel SX
>>> cm.from_table(t,{'O':'qu','phase':'phase'},homogenization='homog') 1 1 1 0 0.8 0.19 0.24 -0.51 Steel SX
>>> cm.from_table(t,O='qu',phase='phase',homogenization='homog')
material: material:
- constituents: - constituents:
- O: [0.19, 0.8, 0.24, -0.51] - O: [0.19, 0.8, 0.24, -0.51]
fraction: 1.0 v: 1.0
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- O: [0.8, 0.19, 0.24, -0.51] - O: [0.8, 0.19, 0.24, -0.51]
fraction: 1.0 v: 1.0
phase: Steel phase: Steel
homogenization: SX homogenization: SX
homogenization: {} homogenization: {}
phase: {} phase: {}
""" """
constituents_ = {k:table.get(v) for k,v in constituents.items()}
kwargs_ = {k:table.get(v) for k,v in kwargs.items()} kwargs_ = {k:table.get(v) for k,v in kwargs.items()}
_,idx = np.unique(np.hstack(list({**constituents_,**kwargs_}.values())),return_index=True,axis=0) _,idx = np.unique(np.hstack(list(kwargs_.values())),return_index=True,axis=0)
idx = np.sort(idx) idx = np.sort(idx)
constituents_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in constituents_.items()} kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()}
kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()}
return ConfigMaterial().material_add(constituents_,**kwargs_) return ConfigMaterial().material_add(**kwargs_)
@staticmethod @staticmethod
@ -108,11 +102,11 @@ class ConfigMaterial(Config):
r""" r"""
Load material data from DREAM3D file. Load material data from DREAM3D file.
The parts of homogenization and phase need to be added by the user. The parts of homogenization and phase need to be added by the user.
Parameters Parameters
---------- ----------
fname : str fname : str
path to the DREAM3D file. path to the DREAM3D file.
base_group : str base_group : str
Name of the group (folder) below 'DataContainers', Name of the group (folder) below 'DataContainers',
@ -126,7 +120,7 @@ class ConfigMaterial(Config):
phase_id : str phase_id : str
Name of the dataset containing phase IDs for each grain, Name of the dataset containing phase IDs for each grain,
for example 'Phases'. for example 'Phases'.
phase_name : list phase_name : list
List with name of the phases. List with name of the phases.
Examples Examples
@ -135,25 +129,25 @@ class ConfigMaterial(Config):
>>> import damask >>> import damask
>>> import damask.ConfigMaterial as cm >>> import damask.ConfigMaterial as cm
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\ >>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\
'EulerAngles','Phases',['Ferrite']) 'EulerAngles','Phases',['Ferrite'])
for point based data with single phase for point based data with single phase
>>> import damask >>> import damask
>>> import damask.ConfigMaterial as cm >>> import damask.ConfigMaterial as cm
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\ >>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\
'EulerAngles','Phases',['Ferrite']) 'EulerAngles','Phases',['Ferrite'])
for grain based data with dual phase for grain based data with dual phase
>>> import damask >>> import damask
>>> import damask.ConfigMaterial as cm >>> import damask.ConfigMaterial as cm
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\ >>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\
'EulerAngles','Phases',['Ferrite','Martensite']) 'EulerAngles','Phases',['Ferrite','Martensite'])
for point based data with dual phase for point based data with dual phase
>>> import damask >>> import damask
>>> import damask.ConfigMaterial as cm >>> import damask.ConfigMaterial as cm
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\ >>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\
'EulerAngles','Phases',['Ferrite','Martensite']) 'EulerAngles','Phases',['Ferrite','Martensite'])
""" """
root_dir = 'DataContainers' root_dir = 'DataContainers'
@ -162,13 +156,13 @@ class ConfigMaterial(Config):
config_info = ConfigMaterial() # empty yaml dictionary config_info = ConfigMaterial() # empty yaml dictionary
orientation_path = path.join(root_dir,base_group,data_group,ori_data) orientation_path = path.join(root_dir,base_group,data_group,ori_data)
if hdf[orientation_path].attrs['TupleDimensions'].shape == (3,): if hdf[orientation_path].attrs['TupleDimensions'].shape == (3,):
grain_orientations = np.array(hdf[orientation_path]).reshape(cells.prod(),3,order='F') grain_orientations = np.array(hdf[orientation_path]).reshape(cells.prod(),3,order='F')
else: else:
grain_orientations = np.array(hdf[orientation_path])[1:] grain_orientations = np.array(hdf[orientation_path])[1:]
grain_quats = Rotation.from_Euler_angles(grain_orientations).as_quaternion() grain_quats = Rotation.from_Euler_angles(grain_orientations).as_quaternion()
phase_path = path.join(root_dir,base_group,data_group,phase_id) phase_path = path.join(root_dir,base_group,data_group,phase_id)
if hdf[phase_path].attrs['TupleDimensions'].shape == (3,): if hdf[phase_path].attrs['TupleDimensions'].shape == (3,):
@ -181,13 +175,12 @@ class ConfigMaterial(Config):
material_dict = config_info.material_add(constituents={'phase':phase_name_list,'O':grain_quats},homogenization='SX') material_dict = config_info.material_add(constituents={'phase':phase_name_list,'O':grain_quats},homogenization='SX')
material_dict.save() material_dict.save()
@property @property
def is_complete(self): def is_complete(self):
"""Check for completeness.""" """Check for completeness."""
ok = True ok = True
for top_level in ['homogenization','phase','material']: for top_level in ['homogenization','phase','material']:
# ToDo: With python 3.8 as prerequisite we can shorten with :=
ok &= top_level in self ok &= top_level in self
if top_level not in self: print(f'{top_level} entry missing') if top_level not in self: print(f'{top_level} entry missing')
@ -238,7 +231,7 @@ class ConfigMaterial(Config):
@property @property
def is_valid(self): def is_valid(self):
"""Check for valid file layout.""" """Check for valid content."""
ok = True ok = True
if 'phase' in self: if 'phase' in self:
@ -247,25 +240,23 @@ class ConfigMaterial(Config):
try: try:
Orientation(lattice=v['lattice']) Orientation(lattice=v['lattice'])
except KeyError: except KeyError:
s = v['lattice'] print(f"Invalid lattice '{v['lattice']}' in phase '{k}'")
print(f"Invalid lattice: '{s}' in phase '{k}'")
ok = False ok = False
if 'material' in self: if 'material' in self:
for i,v in enumerate(self['material']): for i,m in enumerate(self['material']):
if 'constituents' in v: if 'constituents' in m:
f = 0.0 v = 0.0
for c in v['constituents']: for c in m['constituents']:
f+= float(c['fraction']) v += float(c['v'])
if 'O' in c: if 'O' in c:
try: try:
Rotation.from_quaternion(c['O']) Rotation.from_quaternion(c['O'])
except ValueError: except ValueError:
o = c['O'] print(f"Invalid orientation '{c['O']}' in material '{i}'")
print(f"Invalid orientation: '{o}' in material '{i}'")
ok = False ok = False
if not np.isclose(f,1.0): if not np.isclose(v,1.0):
print(f"Invalid total fraction '{f}' in material '{i}'") print(f"Total fraction v = {v} ≠ 1 in material '{i}'")
ok = False ok = False
return ok return ok
@ -284,10 +275,15 @@ class ConfigMaterial(Config):
constituent: list of ints, optional constituent: list of ints, optional
Limit renaming to selected constituents. Limit renaming to selected constituents.
Returns
-------
cfg : damask.ConfigMaterial
Updated material configuration.
""" """
dup = copy.deepcopy(self) dup = self.copy()
for i,m in enumerate(dup['material']): for i,m in enumerate(dup['material']):
if ID and i not in ID: continue if ID is not None and i not in ID: continue
for c in m['constituents']: for c in m['constituents']:
if constituent is not None and c not in constituent: continue if constituent is not None and c not in constituent: continue
try: try:
@ -308,10 +304,15 @@ class ConfigMaterial(Config):
ID: list of ints, optional ID: list of ints, optional
Limit renaming to selected homogenization IDs. Limit renaming to selected homogenization IDs.
Returns
-------
cfg : damask.ConfigMaterial
Updated material configuration.
""" """
dup = copy.deepcopy(self) dup = self.copy()
for i,m in enumerate(dup['material']): for i,m in enumerate(dup['material']):
if ID and i not in ID: continue if ID is not None and i not in ID: continue
try: try:
m['homogenization'] = mapping[m['homogenization']] m['homogenization'] = mapping[m['homogenization']]
except KeyError: except KeyError:
@ -319,93 +320,92 @@ class ConfigMaterial(Config):
return dup return dup
def material_add(self,constituents=None,**kwargs): def material_add(self,**kwargs):
""" """
Add material entries. Add material entries.
Parameters Parameters
---------- ----------
constituents : dict, optional
Entries for 'constituents' as key-value pair.
**kwargs **kwargs
Key-value pairs. Key-value pairs.
Returns
-------
cfg : damask.ConfigMaterial
Updated material configuration.
Examples Examples
-------- --------
>>> import numpy as np
>>> import damask >>> import damask
>>> O = damask.Rotation.from_random(3).as_quaternion() >>> m = damask.ConfigMaterial().material_add(phase = ['Aluminum','Steel'],
>>> phase = ['Aluminum','Steel','Aluminum'] ... O = damask.Rotation.from_random(2),
>>> m = damask.ConfigMaterial().material_add(constituents={'phase':phase,'O':O}, ... homogenization = 'SX')
... homogenization='SX')
>>> m >>> m
material: material:
- constituents: - constituents:
- O: [0.577764, -0.146299, -0.617669, 0.513010] - O: [0.577764, -0.146299, -0.617669, 0.513010]
fraction: 1.0 v: 1.0
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- O: [0.184176, 0.340305, 0.737247, 0.553840] - O: [0.184176, 0.340305, 0.737247, 0.553840]
fraction: 1.0 v: 1.0
phase: Steel phase: Steel
homogenization: SX homogenization: SX
- constituents: homogenization: {}
- O: [0.0886257, -0.144848, 0.615674, -0.769487] phase: {}
fraction: 1.0
phase: Aluminum >>> m = damask.ConfigMaterial().material_add(phase = np.array(['Austenite','Martensite']).reshape(1,2),
homogenization: SX ... O = damask.Rotation.from_random((2,2)),
... v = np.array([0.2,0.8]).reshape(1,2),
... homogenization = ['A','B'])
>>> m
material:
- constituents:
- phase: Austenite
O: [0.659802978293224, 0.6953785848195171, 0.22426295326327111, -0.17554139512785227]
v: 0.2
- phase: Martensite
O: [0.49356745891301596, 0.2841806579193434, -0.7487679215072818, -0.339085707289975]
v: 0.8
homogenization: A
- constituents:
- phase: Austenite
O: [0.26542221365204055, 0.7268854930702071, 0.4474726435701472, -0.44828201137283735]
v: 0.2
- phase: Martensite
O: [0.6545817158479885, -0.08004812803625233, -0.6226561293931374, 0.4212059104577611]
v: 0.8
homogenization: B
homogenization: {} homogenization: {}
phase: {} phase: {}
""" """
length = -1 N,n,shaped = 1,1,{}
for v in kwargs.values():
if hasattr(v,'__len__') and not isinstance(v,str):
if length != -1 and len(v) != length:
raise ValueError('Cannot add entries of different length')
else:
length = len(v)
length = max(1,length)
c = [{} for _ in range(length)] if constituents is None else \
[{'constituents':u} for u in ConfigMaterial._constituents(**constituents)]
if len(c) == 1: c = [copy.deepcopy(c[0]) for _ in range(length)]
if length != 1 and length != len(c):
raise ValueError('Cannot add entries of different length')
for k,v in kwargs.items(): for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str): shaped[k] = np.array(v)
for i,vv in enumerate(v): s = shaped[k].shape[:-1] if k=='O' else shaped[k].shape
c[i][k] = vv.item() if isinstance(vv,np.generic) else vv N = max(N,s[0]) if len(s)>0 else N
else: n = max(n,s[1]) if len(s)>1 else n
for i in range(len(c)):
c[i][k] = v mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
dup = copy.deepcopy(self)
dup['material'] = dup['material'] + c if 'material' in dup else c if 'v' not in kwargs:
shaped['v'] = np.broadcast_to(1/n,(N,n))
for k,v in shaped.items():
target = (N,n,4) if k=='O' else (N,n)
obj = np.broadcast_to(v.reshape(util.shapeshifter(v.shape,target,mode='right')),target)
for i in range(N):
if k in ['phase','O','v']:
for j in range(n):
mat[i]['constituents'][j][k] = obj[i,j].item() if isinstance(obj[i,j],np.generic) else obj[i,j]
else:
mat[i][k] = obj[i,0].item() if isinstance(obj[i,0],np.generic) else obj[i,0]
dup = self.copy()
dup['material'] = dup['material'] + mat if 'material' in dup else mat
return dup return dup
@staticmethod
def _constituents(N=1,**kwargs):
"""Construct list of constituents."""
N_material=1
for v in kwargs.values():
if hasattr(v,'__len__') and not isinstance(v,str): N_material = len(v)
if N == 1:
m = [[{'fraction':1.0}] for _ in range(N_material)]
for k,v in kwargs.items():
if hasattr(v,'__len__') and not isinstance(v,str):
if len(v) != N_material:
raise ValueError('Cannot add entries of different length')
for i,vv in enumerate(np.array(v)):
m[i][0][k] = vv.item() if isinstance(vv,np.generic) else vv
else:
for i in range(N_material):
m[i][0][k] = v
return m
else:
raise NotImplementedError

View File

@ -1,41 +0,0 @@
import os
from pathlib import Path
class Environment:
@property
def screen_size(self):
try:
import wx
_ = wx.App(False) # noqa
width, height = wx.GetDisplaySize()
except ImportError:
try:
import tkinter
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.destroy()
except Exception as e:
width = 1024
height = 768
return (width,height)
@property
def options(self):
options = {}
for item in ['DAMASK_NUM_THREADS',
'MSC_ROOT',
'MSC_VERSION',
]:
options[item] = os.environ[item] if item in os.environ else None
return options
@property
def root_dir(self):
"""Return DAMASK root path."""
return Path(__file__).parents[2]

View File

@ -1,7 +1,7 @@
import copy import copy
import multiprocessing as mp import multiprocessing as mp
from functools import partial from functools import partial
from os import path import os
import warnings import warnings
import numpy as np import numpy as np
@ -10,7 +10,6 @@ import h5py
from scipy import ndimage, spatial from scipy import ndimage, spatial
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
from . import environment
from . import VTK from . import VTK
from . import util from . import util
from . import grid_filters from . import grid_filters
@ -57,13 +56,10 @@ class Grid:
def __copy__(self): def __copy__(self):
"""Copy grid.""" """Create deep copy."""
return copy.deepcopy(self) return copy.deepcopy(self)
copy = __copy__
def copy(self):
"""Copy grid."""
return self.__copy__()
def diff(self,other): def diff(self,other):
@ -126,7 +122,7 @@ class Grid:
@size.setter @size.setter
def size(self,size): def size(self,size):
if len(size) != 3 or any(np.array(size) <= 0): if len(size) != 3 or any(np.array(size) < 0):
raise ValueError(f'invalid size {size}') raise ValueError(f'invalid size {size}')
else: else:
self._size = np.array(size) self._size = np.array(size)
@ -206,7 +202,7 @@ class Grid:
Geometry file to read. Geometry file to read.
""" """
warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning) warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning,2)
try: try:
f = open(fname) f = open(fname)
except TypeError: except TypeError:
@ -281,14 +277,14 @@ class Grid:
""" """
root_dir ='DataContainers' root_dir ='DataContainers'
f = h5py.File(fname, 'r') f = h5py.File(fname, 'r')
g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY') g = os.path.join(root_dir,base_group,'_SIMPL_GEOMETRY')
cells = f[path.join(g,'DIMENSIONS')][()] cells = f[os.path.join(g,'DIMENSIONS')][()]
size = f[path.join(g,'SPACING')][()] * cells size = f[os.path.join(g,'SPACING')][()] * cells
origin = f[path.join(g,'ORIGIN')][()] origin = f[os.path.join(g,'ORIGIN')][()]
ma = np.arange(cells.prod(),dtype=int) \ ma = np.arange(cells.prod(),dtype=int) \
if point_data is None else \ if point_data is None else \
np.reshape(f[path.join(root_dir,base_group,point_data,material)],cells.prod()) np.reshape(f[os.path.join(root_dir,base_group,point_data,material)],cells.prod())
return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','load_DREAM3D')) return Grid(ma.reshape(cells,order='F'),size,origin,util.execution_stamp('Grid','load_DREAM3D'))
@ -307,7 +303,7 @@ class Grid:
Need to be ordered (1./x fast, 3./z slow). Need to be ordered (1./x fast, 3./z slow).
labels : str or list of str labels : str or list of str
Label(s) of the columns containing the material definition. Label(s) of the columns containing the material definition.
Each unique combintation of values results in one material ID. Each unique combination of values results in one material ID.
""" """
cells,size,origin = grid_filters.cellsSizeOrigin_coordinates0_point(table.get(coordinates)) cells,size,origin = grid_filters.cellsSizeOrigin_coordinates0_point(table.get(coordinates))
@ -358,7 +354,7 @@ class Grid:
seeds_p = seeds seeds_p = seeds
coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3)
pool = mp.Pool(processes = int(environment.options['DAMASK_NUM_THREADS'])) pool = mp.Pool(int(os.environ.get('OMP_NUM_THREADS',1)))
result = pool.map_async(partial(Grid._find_closest_seed,seeds_p,weights_p), [coord for coord in coords]) result = pool.map_async(partial(Grid._find_closest_seed,seeds_p,weights_p), [coord for coord in coords])
pool.close() pool.close()
pool.join() pool.join()
@ -545,7 +541,7 @@ class Grid:
Compress geometry with 'x of y' and 'a to b'. Compress geometry with 'x of y' and 'a to b'.
""" """
warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning) warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning,2)
header = [f'{len(self.comments)+4} header'] + self.comments \ header = [f'{len(self.comments)+4} header'] + self.comments \
+ ['grid a {} b {} c {}'.format(*self.cells), + ['grid a {} b {} c {}'.format(*self.cells),
'size x {} y {} z {}'.format(*self.size), 'size x {} y {} z {}'.format(*self.size),
@ -764,26 +760,21 @@ class Grid:
""" """
if fill is None: fill = np.nanmax(self.material) + 1 if fill is None: fill = np.nanmax(self.material) + 1
dtype = float if np.isnan(fill) or int(fill) != fill or self.material.dtype==np.float else int dtype = float if isinstance(fill,float) or self.material.dtype in np.sctypes['float'] else int
Eulers = R.as_Euler_angles(degrees=True)
material_in = self.material.copy()
material = self.material
# These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'') # These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'')
# see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf # see https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
for angle,axes in zip(Eulers[::-1], [(0,1),(1,2),(0,1)]): for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]):
material_out = ndimage.rotate(material_in,angle,axes,order=0, material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,output=dtype,cval=fill)
prefilter=False,output=dtype,cval=fill) # avoid scipy interpolation errors for rotations close to multiples of 90°
if np.prod(material_in.shape) == np.prod(material_out.shape): material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \
# avoid scipy interpolation errors for rotations close to multiples of 90° np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes)
material_in = np.rot90(material_in,k=np.rint(angle/90.).astype(int),axes=axes)
else:
material_in = material_out
origin = self.origin-(np.asarray(material_in.shape)-self.cells)*.5 * self.size/self.cells origin = self.origin-(np.asarray(material.shape)-self.cells)*.5 * self.size/self.cells
return Grid(material = material_in, return Grid(material = material,
size = self.size/self.cells*np.asarray(material_in.shape), size = self.size/self.cells*np.asarray(material.shape),
origin = origin, origin = origin,
comments = self.comments+[util.execution_stamp('Grid','rotate')], comments = self.comments+[util.execution_stamp('Grid','rotate')],
) )

View File

@ -1,3 +1,5 @@
import inspect
import numpy as np import numpy as np
from . import Rotation from . import Rotation
@ -7,7 +9,7 @@ from . import tensor
_parameter_doc = \ _parameter_doc = \
"""lattice : str """lattice : str
Either a crystal family out of [triclinic, monoclinic, orthorhombic, tetragonal, hexagonal, cubic] Either a crystal family out of [triclinic, monoclinic, orthorhombic, tetragonal, hexagonal, cubic]
or a Bravais lattice out of [aP, mP, mS, oP, oS, oI, oF, tP, tI, hP, cP, cI, cF]. or a Bravais lattice out of [aP, mP, mS, oP, oS, oI, oF, tP, tI, hP, cP, cI, cF].
When specifying a Bravais lattice, additional lattice parameters might be required: When specifying a Bravais lattice, additional lattice parameters might be required:
a : float, optional a : float, optional
Length of lattice parameter "a". Length of lattice parameter "a".
@ -107,8 +109,7 @@ class Orientation(Rotation):
lattice = None, lattice = None,
a = None,b = None,c = None, a = None,b = None,c = None,
alpha = None,beta = None,gamma = None, alpha = None,beta = None,gamma = None,
degrees = False, degrees = False):
**kwargs):
""" """
Initialize orientation object. Initialize orientation object.
@ -199,7 +200,7 @@ class Orientation(Rotation):
def __copy__(self,**kwargs): def __copy__(self,**kwargs):
"""Copy.""" """Create deep copy."""
return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion, return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion,
lattice =kwargs['lattice'] if 'lattice' in kwargs else self.lattice lattice =kwargs['lattice'] if 'lattice' in kwargs else self.lattice
if self.lattice is not None else self.family, if self.lattice is not None else self.family,
@ -225,96 +226,150 @@ class Orientation(Rotation):
Orientation to check for equality. Orientation to check for equality.
""" """
return super().__eq__(other) \ matching_type = all([hasattr(other,attr) and getattr(self,attr) == getattr(other,attr)
and hasattr(other, 'family') and self.family == other.family \ for attr in ['family','lattice','parameters']])
and hasattr(other, 'lattice') and self.lattice == other.lattice \ return np.logical_and(super().__eq__(other),matching_type)
and hasattr(other, 'parameters') and self.parameters == other.parameters
def __ne__(self,other):
def __matmul__(self,other):
""" """
Rotation of vector, second or fourth order tensor, or rotation object. Not equal to other.
Parameters Parameters
---------- ----------
other : numpy.ndarray, Rotation, or Orientation other : Orientation
Vector, second or fourth order tensor, or rotation object that is rotated. Orientation to check for equality.
"""
return np.logical_not(self==other)
def __mul__(self,other):
"""
Compose this orientation with other.
Parameters
----------
other : Rotation or Orientation
Object for composition.
Returns Returns
------- -------
other_rot : numpy.ndarray or Rotation composition : Orientation
Rotated vector, second or fourth order tensor, or rotation object. Compound rotation self*other, i.e. first other then self rotation.
""" """
return self.copy(rotation=Rotation.__matmul__(self,Rotation(other.quaternion))) \ if isinstance(other,Orientation) or isinstance(other,Rotation):
if isinstance(other,self.__class__) else \ return self.copy(rotation=Rotation.__mul__(self,Rotation(other.quaternion)))
Rotation.__matmul__(self,other) else:
raise TypeError('Use "O@b", i.e. matmul, to apply Orientation "O" to object "b"')
@staticmethod
def _split_kwargs(kwargs,target):
"""
Separate keyword arguments in 'kwargs' targeted at 'target' from general keyword arguments of Orientation objects.
Parameters
----------
kwargs : dictionary
Contains all **kwargs.
target: method
Function to scan for kwarg signature.
Returns
-------
rot_kwargs: dictionary
Valid keyword arguments of 'target' function of Rotation class.
ori_kwargs: dictionary
Valid keyword arguments of Orientation object.
"""
kws = ()
for t in (target,Orientation.__init__):
kws += ({key: kwargs[key] for key in set(inspect.signature(t).parameters) & set(kwargs)},)
invalid_keys = set(kwargs)-(set(kws[0])|set(kws[1]))
if invalid_keys:
raise TypeError(f"{inspect.stack()[1][3]}() got an unexpected keyword argument '{invalid_keys.pop()}'")
return kws
@classmethod @classmethod
@util.extended_docstring(Rotation.from_random,_parameter_doc) @util.extended_docstring(Rotation.from_random,_parameter_doc)
def from_random(cls,**kwargs): def from_random(cls,**kwargs):
return cls(rotation=Rotation.from_random(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_random)
return cls(rotation=Rotation.from_random(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_quaternion,_parameter_doc) @util.extended_docstring(Rotation.from_quaternion,_parameter_doc)
def from_quaternion(cls,**kwargs): def from_quaternion(cls,**kwargs):
return cls(rotation=Rotation.from_quaternion(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_quaternion)
return cls(rotation=Rotation.from_quaternion(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc) @util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc)
def from_Euler_angles(cls,**kwargs): def from_Euler_angles(cls,**kwargs):
return cls(rotation=Rotation.from_Euler_angles(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Euler_angles)
return cls(rotation=Rotation.from_Euler_angles(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_axis_angle,_parameter_doc) @util.extended_docstring(Rotation.from_axis_angle,_parameter_doc)
def from_axis_angle(cls,**kwargs): def from_axis_angle(cls,**kwargs):
return cls(rotation=Rotation.from_axis_angle(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_axis_angle)
return cls(rotation=Rotation.from_axis_angle(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_basis,_parameter_doc) @util.extended_docstring(Rotation.from_basis,_parameter_doc)
def from_basis(cls,**kwargs): def from_basis(cls,**kwargs):
return cls(rotation=Rotation.from_basis(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_basis)
return cls(rotation=Rotation.from_basis(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_matrix,_parameter_doc) @util.extended_docstring(Rotation.from_matrix,_parameter_doc)
def from_matrix(cls,**kwargs): def from_matrix(cls,**kwargs):
return cls(rotation=Rotation.from_matrix(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_matrix)
return cls(rotation=Rotation.from_matrix(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc) @util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc)
def from_Rodrigues_vector(cls,**kwargs): def from_Rodrigues_vector(cls,**kwargs):
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Rodrigues_vector)
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_homochoric,_parameter_doc) @util.extended_docstring(Rotation.from_homochoric,_parameter_doc)
def from_homochoric(cls,**kwargs): def from_homochoric(cls,**kwargs):
return cls(rotation=Rotation.from_homochoric(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_homochoric)
return cls(rotation=Rotation.from_homochoric(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_cubochoric,_parameter_doc) @util.extended_docstring(Rotation.from_cubochoric,_parameter_doc)
def from_cubochoric(cls,**kwargs): def from_cubochoric(cls,**kwargs):
return cls(rotation=Rotation.from_cubochoric(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_cubochoric)
return cls(rotation=Rotation.from_cubochoric(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_spherical_component,_parameter_doc) @util.extended_docstring(Rotation.from_spherical_component,_parameter_doc)
def from_spherical_component(cls,**kwargs): def from_spherical_component(cls,**kwargs):
return cls(rotation=Rotation.from_spherical_component(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_spherical_component)
return cls(rotation=Rotation.from_spherical_component(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@util.extended_docstring(Rotation.from_fiber_component,_parameter_doc) @util.extended_docstring(Rotation.from_fiber_component,_parameter_doc)
def from_fiber_component(cls,**kwargs): def from_fiber_component(cls,**kwargs):
return cls(rotation=Rotation.from_fiber_component(**kwargs),**kwargs) kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_fiber_component)
return cls(rotation=Rotation.from_fiber_component(**kwargs_rot),**kwargs_ori)
@classmethod @classmethod
@ -429,7 +484,7 @@ class Orientation(Rotation):
raise ValueError('Missing crystal symmetry') raise ValueError('Missing crystal symmetry')
o = self.symmetry_operations.broadcast_to(self.symmetry_operations.shape+self.shape,mode='right') o = self.symmetry_operations.broadcast_to(self.symmetry_operations.shape+self.shape,mode='right')
return self.copy(rotation=o@Rotation(self.quaternion).broadcast_to(o.shape,mode='left')) return self.copy(rotation=o*Rotation(self.quaternion).broadcast_to(o.shape,mode='left'))
@property @property
@ -469,26 +524,26 @@ class Orientation(Rotation):
if self.family is None: if self.family is None:
raise ValueError('Missing crystal symmetry') raise ValueError('Missing crystal symmetry')
rho_abs = np.abs(self.as_Rodrigues_vector(compact=True)) rho_abs = np.abs(self.as_Rodrigues_vector(compact=True))*(1.-1.e-9)
with np.errstate(invalid='ignore'): with np.errstate(invalid='ignore'):
# using '*'/prod for 'and' # using '*'/prod for 'and'
if self.family == 'cubic': if self.family == 'cubic':
return (np.prod(np.sqrt(2)-1. >= rho_abs,axis=-1) * return (np.prod(np.sqrt(2)-1. >= rho_abs,axis=-1) *
(1. >= np.sum(rho_abs,axis=-1))).astype(np.bool) (1. >= np.sum(rho_abs,axis=-1))).astype(bool)
elif self.family == 'hexagonal': elif self.family == 'hexagonal':
return (np.prod(1. >= rho_abs,axis=-1) * return (np.prod(1. >= rho_abs,axis=-1) *
(2. >= np.sqrt(3)*rho_abs[...,0] + rho_abs[...,1]) * (2. >= np.sqrt(3)*rho_abs[...,0] + rho_abs[...,1]) *
(2. >= np.sqrt(3)*rho_abs[...,1] + rho_abs[...,0]) * (2. >= np.sqrt(3)*rho_abs[...,1] + rho_abs[...,0]) *
(2. >= np.sqrt(3) + rho_abs[...,2])).astype(np.bool) (2. >= np.sqrt(3) + rho_abs[...,2])).astype(bool)
elif self.family == 'tetragonal': elif self.family == 'tetragonal':
return (np.prod(1. >= rho_abs[...,:2],axis=-1) * return (np.prod(1. >= rho_abs[...,:2],axis=-1) *
(np.sqrt(2) >= rho_abs[...,0] + rho_abs[...,1]) * (np.sqrt(2) >= rho_abs[...,0] + rho_abs[...,1]) *
(np.sqrt(2) >= rho_abs[...,2] + 1.)).astype(np.bool) (np.sqrt(2) >= rho_abs[...,2] + 1.)).astype(bool)
elif self.family == 'orthorhombic': elif self.family == 'orthorhombic':
return (np.prod(1. >= rho_abs,axis=-1)).astype(np.bool) return (np.prod(1. >= rho_abs,axis=-1)).astype(bool)
elif self.family == 'monoclinic': elif self.family == 'monoclinic':
return (1. >= rho_abs[...,1]).astype(np.bool) return (1. >= rho_abs[...,1]).astype(bool)
else: else:
return np.all(np.isfinite(rho_abs),axis=-1) return np.all(np.isfinite(rho_abs),axis=-1)
@ -512,28 +567,28 @@ class Orientation(Rotation):
if self.family is None: if self.family is None:
raise ValueError('Missing crystal symmetry') raise ValueError('Missing crystal symmetry')
rho = self.as_Rodrigues_vector(compact=True) rho = self.as_Rodrigues_vector(compact=True)*(1.0-1.0e-9)
with np.errstate(invalid='ignore'): with np.errstate(invalid='ignore'):
if self.family == 'cubic': if self.family == 'cubic':
return ((rho[...,0] >= rho[...,1]) & return ((rho[...,0] >= rho[...,1]) &
(rho[...,1] >= rho[...,2]) & (rho[...,1] >= rho[...,2]) &
(rho[...,2] >= 0)).astype(np.bool) (rho[...,2] >= 0)).astype(bool)
elif self.family == 'hexagonal': elif self.family == 'hexagonal':
return ((rho[...,0] >= rho[...,1]*np.sqrt(3)) & return ((rho[...,0] >= rho[...,1]*np.sqrt(3)) &
(rho[...,1] >= 0) & (rho[...,1] >= 0) &
(rho[...,2] >= 0)).astype(np.bool) (rho[...,2] >= 0)).astype(bool)
elif self.family == 'tetragonal': elif self.family == 'tetragonal':
return ((rho[...,0] >= rho[...,1]) & return ((rho[...,0] >= rho[...,1]) &
(rho[...,1] >= 0) & (rho[...,1] >= 0) &
(rho[...,2] >= 0)).astype(np.bool) (rho[...,2] >= 0)).astype(bool)
elif self.family == 'orthorhombic': elif self.family == 'orthorhombic':
return ((rho[...,0] >= 0) & return ((rho[...,0] >= 0) &
(rho[...,1] >= 0) & (rho[...,1] >= 0) &
(rho[...,2] >= 0)).astype(np.bool) (rho[...,2] >= 0)).astype(bool)
elif self.family == 'monoclinic': elif self.family == 'monoclinic':
return ((rho[...,1] >= 0) & return ((rho[...,1] >= 0) &
(rho[...,2] >= 0)).astype(np.bool) (rho[...,2] >= 0)).astype(bool)
else: else:
return np.ones_like(rho[...,0],dtype=bool) return np.ones_like(rho[...,0],dtype=bool)
@ -608,7 +663,7 @@ class Orientation(Rotation):
o,lattice = self.relation_operations(model,return_lattice=True) o,lattice = self.relation_operations(model,return_lattice=True)
target = Orientation(lattice=lattice) target = Orientation(lattice=lattice)
o = o.broadcast_to(o.shape+self.shape,mode='right') o = o.broadcast_to(o.shape+self.shape,mode='right')
return self.copy(rotation=o@Rotation(self.quaternion).broadcast_to(o.shape,mode='left'), return self.copy(rotation=o*Rotation(self.quaternion).broadcast_to(o.shape,mode='left'),
lattice=lattice, lattice=lattice,
b = self.b if target.ratio['b'] is None else self.a*target.ratio['b'], b = self.b if target.ratio['b'] is None else self.a*target.ratio['b'],
c = self.c if target.ratio['c'] is None else self.a*target.ratio['c'], c = self.c if target.ratio['c'] is None else self.a*target.ratio['c'],

View File

@ -80,12 +80,12 @@ class Result:
self.out_type_ho += f['/'.join([self.increments[0],'homogenization',m])].keys() self.out_type_ho += f['/'.join([self.increments[0],'homogenization',m])].keys()
self.out_type_ho = list(set(self.out_type_ho)) # make unique self.out_type_ho = list(set(self.out_type_ho)) # make unique
self.selection = {'increments': self.increments, self.visible = {'increments': self.increments,
'phases': self.phases, 'phases': self.phases,
'homogenizations': self.homogenizations, 'homogenizations': self.homogenizations,
'out_type_ph': self.out_type_ph, 'out_type_ph': self.out_type_ph,
'out_type_ho': self.out_type_ho 'out_type_ho': self.out_type_ho
} }
self.fname = Path(fname).absolute() self.fname = Path(fname).absolute()
@ -94,23 +94,23 @@ class Result:
def __repr__(self): def __repr__(self):
"""Show summary of file content.""" """Show summary of file content."""
all_selected_increments = self.selection['increments'] visible_increments = self.visible['increments']
self.pick('increments',all_selected_increments[0:1]) self.view('increments',visible_increments[0:1])
first = self.list_data() first = self.list_data()
self.pick('increments',all_selected_increments[-1:]) self.view('increments',visible_increments[-1:])
last = '' if len(all_selected_increments) < 2 else self.list_data() last = '' if len(visible_increments) < 2 else self.list_data()
self.pick('increments',all_selected_increments) self.view('increments',visible_increments)
in_between = '' if len(all_selected_increments) < 3 else \ in_between = '' if len(visible_increments) < 3 else \
''.join([f'\n{inc}\n ...\n' for inc in all_selected_increments[1:-2]]) ''.join([f'\n{inc}\n ...\n' for inc in visible_increments[1:-1]])
return util.srepr(first + in_between + last) return util.srepr(first + in_between + last)
def _manage_selection(self,action,what,datasets): def _manage_view(self,action,what,datasets):
""" """
Manages the visibility of the groups. Manages the visibility of the groups.
@ -119,10 +119,10 @@ class Result:
action : str action : str
Select from 'set', 'add', and 'del'. Select from 'set', 'add', and 'del'.
what : str what : str
Attribute to change (must be from self.selection). Attribute to change (must be from self.visible).
datasets : list of str or bool datasets : list of str or bool
Name of datasets as list, supports ? and * wildcards. Name of datasets as list; supports ? and * wildcards.
True is equivalent to [*], False is equivalent to [] True is equivalent to [*], False is equivalent to [].
""" """
def natural_sort(key): def natural_sort(key):
@ -156,18 +156,18 @@ class Result:
choice.append(self.increments[idx+1]) choice.append(self.increments[idx+1])
valid = [e for e_ in [glob.fnmatch.filter(getattr(self,what),s) for s in choice] for e in e_] valid = [e for e_ in [glob.fnmatch.filter(getattr(self,what),s) for s in choice] for e in e_]
existing = set(self.selection[what]) existing = set(self.visible[what])
if action == 'set': if action == 'set':
self.selection[what] = valid self.visible[what] = valid
elif action == 'add': elif action == 'add':
add = existing.union(valid) add = existing.union(valid)
add_sorted = sorted(add, key=natural_sort) add_sorted = sorted(add, key=natural_sort)
self.selection[what] = add_sorted self.visible[what] = add_sorted
elif action == 'del': elif action == 'del':
diff = existing.difference(valid) diff = existing.difference(valid)
diff_sorted = sorted(diff, key=natural_sort) diff_sorted = sorted(diff, key=natural_sort)
self.selection[what] = diff_sorted self.visible[what] = diff_sorted
def _get_attribute(self,path,attr): def _get_attribute(self,path,attr):
@ -200,7 +200,7 @@ class Result:
self._allow_modification = True self._allow_modification = True
def disallow_modification(self): def disallow_modification(self):
"""Disllow to overwrite existing data (default case).""" """Disallow to overwrite existing data (default case)."""
self._allow_modification = False self._allow_modification = False
@ -245,84 +245,84 @@ class Result:
def iterate(self,what): def iterate(self,what):
""" """
Iterate over selection items by setting each one selected. Iterate over visible items and view them independently.
Parameters Parameters
---------- ----------
what : str what : str
Attribute to change (must be from self.selection). Attribute to change (must be from self.visible).
""" """
datasets = self.selection[what] datasets = self.visible[what]
last_selection = datasets.copy() last_view = datasets.copy()
for dataset in datasets: for dataset in datasets:
if last_selection != self.selection[what]: if last_view != self.visible[what]:
self._manage_selection('set',what,datasets) self._manage_view('set',what,datasets)
raise Exception raise Exception
self._manage_selection('set',what,dataset) self._manage_view('set',what,dataset)
last_selection = self.selection[what] last_view = self.visible[what]
yield dataset yield dataset
self._manage_selection('set',what,datasets) self._manage_view('set',what,datasets)
def pick(self,what,datasets): def view(self,what,datasets):
""" """
Set selection. Set view.
Parameters Parameters
---------- ----------
what : str what : str
attribute to change (must be from self.selection) Attribute to change (must be from self.visible).
datasets : list of str or bool datasets : list of str or bool
name of datasets as list, supports ? and * wildcards. Name of datasets as list; supports ? and * wildcards.
True is equivalent to [*], False is equivalent to [] True is equivalent to [*], False is equivalent to [].
""" """
self._manage_selection('set',what,datasets) self._manage_view('set',what,datasets)
def pick_more(self,what,datasets): def view_more(self,what,datasets):
""" """
Add to selection. Add to view.
Parameters Parameters
---------- ----------
what : str what : str
attribute to change (must be from self.selection) Attribute to change (must be from self.visible).
datasets : list of str or bool datasets : list of str or bool
name of datasets as list, supports ? and * wildcards. Name of datasets as list; supports ? and * wildcards.
True is equivalent to [*], False is equivalent to [] True is equivalent to [*], False is equivalent to [].
""" """
self._manage_selection('add',what,datasets) self._manage_view('add',what,datasets)
def pick_less(self,what,datasets): def view_less(self,what,datasets):
""" """
Delete from selection. Delete from view.
Parameters Parameters
---------- ----------
what : str what : str
attribute to change (must be from self.selection) Attribute to change (must be from self.visible).
datasets : list of str or bool datasets : list of str or bool
name of datasets as list, supports ? and * wildcards. Name of datasets as list; supports ? and * wildcards.
True is equivalent to [*], False is equivalent to [] True is equivalent to [*], False is equivalent to [].
""" """
self._manage_selection('del',what,datasets) self._manage_view('del',what,datasets)
def rename(self,name_old,name_new): def rename(self,name_old,name_new):
""" """
Rename datasets. Rename dataset.
Parameters Parameters
---------- ----------
name_old : str name_old : str
name of the datasets to be renamed Name of the dataset to be renamed.
name_new : str name_new : str
new name of the datasets New name of the dataset.
""" """
if self._allow_modification: if self._allow_modification:
@ -353,13 +353,13 @@ class Result:
---------- ----------
datasets : iterable or str datasets : iterable or str
constituent : int constituent : int
Constituent to consider for phase data Constituent to consider for phase data.
tagged : bool tagged : bool
tag Table.column name with '#constituent' Tag Table.column name with '#constituent'.
defaults to False Defaults to False.
split : bool split : bool
split Table by increment and return dictionary of Tables Split Table by increment and return dictionary of Tables.
defaults to True Defaults to True.
""" """
sets = datasets if hasattr(datasets,'__iter__') and not isinstance(datasets,str) else \ sets = datasets if hasattr(datasets,'__iter__') and not isinstance(datasets,str) else \
@ -371,7 +371,7 @@ class Result:
with h5py.File(self.fname,'r') as f: with h5py.File(self.fname,'r') as f:
for dataset in sets: for dataset in sets:
for group in self.groups_with_datasets(dataset): for group in self.groups_with_datasets(dataset):
path = os.path.join(group,dataset) path = '/'.join([group,dataset])
inc,prop,name,cat,item = (path.split('/') + ['']*5)[:5] inc,prop,name,cat,item = (path.split('/') + ['']*5)[:5]
key = '/'.join([prop,name+tag]) key = '/'.join([prop,name+tag])
if key not in inGeom: if key not in inGeom:
@ -388,15 +388,15 @@ class Result:
np.nan, np.nan,
dtype=np.dtype(f[path])) dtype=np.dtype(f[path]))
data[inGeom[key]] = (f[path] if len(shape)>1 else np.expand_dims(f[path],1))[inData[key]] data[inGeom[key]] = (f[path] if len(shape)>1 else np.expand_dims(f[path],1))[inData[key]]
path = (os.path.join(*([prop,name]+([cat] if cat else [])+([item] if item else []))) if split else path)+tag path = ('/'.join([prop,name]+([cat] if cat else [])+([item] if item else [])) if split else path)+tag
if split: if split:
try: try:
tbl[inc].add(path,data) tbl[inc] = tbl[inc].add(path,data)
except KeyError: except KeyError:
tbl[inc] = Table(data.reshape(self.N_materialpoints,-1),{path:data.shape[1:]}) tbl[inc] = Table(data.reshape(self.N_materialpoints,-1),{path:data.shape[1:]})
else: else:
try: try:
tbl.add(path,data) tbl = tbl.add(path,data)
except AttributeError: except AttributeError:
tbl = Table(data.reshape(self.N_materialpoints,-1),{path:data.shape[1:]}) tbl = Table(data.reshape(self.N_materialpoints,-1),{path:data.shape[1:]})
@ -415,7 +415,7 @@ class Result:
are considered as they contain user-relevant data. are considered as they contain user-relevant data.
Single strings will be treated as list with one entry. Single strings will be treated as list with one entry.
Wild card matching is allowed, but the number of arguments need to fit. Wild card matching is allowed, but the number of arguments needs to fit.
Parameters Parameters
---------- ----------
@ -1134,8 +1134,7 @@ class Result:
""" """
chunk_size = 1024**2//8 chunk_size = 1024**2//8
num_threads = damask.environment.options['DAMASK_NUM_THREADS'] pool = mp.Pool(int(os.environ.get('OMP_NUM_THREADS',1)))
pool = mp.Pool(int(num_threads) if num_threads is not None else None)
lock = mp.Manager().Lock() lock = mp.Manager().Lock()
groups = self.groups_with_datasets(datasets.values()) groups = self.groups_with_datasets(datasets.values())
@ -1190,8 +1189,8 @@ class Result:
""" """
Write XDMF file to directly visualize data in DADF5 file. Write XDMF file to directly visualize data in DADF5 file.
This works only for scalar, 3-vector and 3x3-tensor data. The view is not taken into account, i.e. the content of the
Selection is not taken into account. whole file will be included.
""" """
if self.N_constituents != 1 or len(self.phases) != 1 or not self.structured: if self.N_constituents != 1 or len(self.phases) != 1 or not self.structured:
raise TypeError('XDMF output requires homogeneous grid') raise TypeError('XDMF output requires homogeneous grid')
@ -1288,7 +1287,7 @@ class Result:
np.prod(shape))} np.prod(shape))}
data_items[-1].text=f'{os.path.split(self.fname)[1]}:{name}' data_items[-1].text=f'{os.path.split(self.fname)[1]}:{name}'
with open(self.fname.with_suffix('.xdmf').name,'w') as f: with open(self.fname.with_suffix('.xdmf').name,'w',newline='\n') as f:
f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml()) f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml())
@ -1320,10 +1319,10 @@ class Result:
N_digits = int(np.floor(np.log10(max(1,int(self.increments[-1][3:])))))+1 N_digits = int(np.floor(np.log10(max(1,int(self.increments[-1][3:])))))+1
for inc in util.show_progress(self.iterate('increments'),len(self.selection['increments'])): for inc in util.show_progress(self.iterate('increments'),len(self.visible['increments'])):
picked_backup_ho = self.selection['homogenizations'].copy() viewed_backup_ho = self.visible['homogenizations'].copy()
self.pick('homogenizations',False) self.view('homogenizations',False)
for label in (labels if isinstance(labels,list) else [labels]): for label in (labels if isinstance(labels,list) else [labels]):
for o in self.iterate('out_type_ph'): for o in self.iterate('out_type_ph'):
for c in range(self.N_constituents): for c in range(self.N_constituents):
@ -1343,10 +1342,10 @@ class Result:
ph_name = re.compile(r'(?<=(phase\/))(.*?)(?=(mechanics))') # identify phase name ph_name = re.compile(r'(?<=(phase\/))(.*?)(?=(mechanics))') # identify phase name
dset_name = prefix+re.sub(ph_name,r'',paths[0].split('/',1)[1]) # remove phase name dset_name = prefix+re.sub(ph_name,r'',paths[0].split('/',1)[1]) # remove phase name
v.add(array,dset_name+f' / {self._get_attribute(paths[0],"Unit")}') v.add(array,dset_name+f' / {self._get_attribute(paths[0],"Unit")}')
self.pick('homogenizations',picked_backup_ho) self.view('homogenizations',viewed_backup_ho)
picked_backup_ph = self.selection['phases'].copy() viewed_backup_ph = self.visible['phases'].copy()
self.pick('phases',False) self.view('phases',False)
for label in (labels if isinstance(labels,list) else [labels]): for label in (labels if isinstance(labels,list) else [labels]):
for _ in self.iterate('out_type_ho'): for _ in self.iterate('out_type_ho'):
paths = self.get_dataset_location(label) paths = self.get_dataset_location(label)
@ -1354,7 +1353,7 @@ class Result:
continue continue
array = self.read_dataset(paths) array = self.read_dataset(paths)
v.add(array,paths[0].split('/',1)[1]+f' / {self._get_attribute(paths[0],"Unit")}') v.add(array,paths[0].split('/',1)[1]+f' / {self._get_attribute(paths[0],"Unit")}')
self.pick('phases',picked_backup_ph) self.view('phases',viewed_backup_ph)
u = self.read_dataset(self.get_dataset_location('u_n' if mode.lower() == 'cell' else 'u_p')) u = self.read_dataset(self.get_dataset_location('u_n' if mode.lower() == 'cell' else 'u_p'))
v.add(u,'u') v.add(u,'u')

View File

@ -35,6 +35,11 @@ class Rotation:
- b = Q @ a - b = Q @ a
- b = np.dot(Q.as_matrix(),a) - b = np.dot(Q.as_matrix(),a)
Compound rotations R1 (first) and R2 (second):
- R = R2 * R1
- R = Rotation.from_matrix(np.dot(R2.as_matrix(),R1.as_matrix())
References References
---------- ----------
D. Rowenhorst et al., Modelling and Simulation in Materials Science and Engineering 23:083501, 2015 D. Rowenhorst et al., Modelling and Simulation in Materials Science and Engineering 23:083501, 2015
@ -65,22 +70,13 @@ class Rotation:
def __repr__(self): def __repr__(self):
"""Represent rotation as unit quaternion, rotation matrix, and Bunge-Euler angles.""" """Represent rotation as unit quaternion(s)."""
if self == Rotation(): return f'Quaternion{" " if self.quaternion.shape == (4,) else "s of shape "+str(self.quaternion.shape)+chr(10)}'\
return 'Rotation()' + str(self.quaternion)
else:
return f'Quaternions {self.shape}:\n'+str(self.quaternion) \
if self.quaternion.shape != (4,) else \
'\n'.join([
'Quaternion: (real={:.3f}, imag=<{:+.3f}, {:+.3f}, {:+.3f}>)'.format(*(self.quaternion)),
'Matrix:\n{}'.format(np.round(self.as_matrix(),8)),
'Bunge Eulers / deg: ({:3.2f}, {:3.2f}, {:3.2f})'.format(*self.as_Euler_angles(degrees=True)),
])
# ToDo: Check difference __copy__ vs __deepcopy__
def __copy__(self,**kwargs): def __copy__(self,**kwargs):
"""Copy.""" """Create deep copy."""
return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion) return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion)
copy = __copy__ copy = __copy__
@ -97,6 +93,26 @@ class Rotation:
""" """
Equal to other. Equal to other.
Equality is determined taking limited floating point precision into account.
See numpy.allclose for details.
Parameters
----------
other : Rotation
Rotation to check for equality.
"""
s = self.quaternion
o = other.quaternion
if self.shape == () == other.shape:
return np.allclose(s,o) or (np.isclose(s[0],0.0) and np.allclose(s,-1.0*o))
else:
return np.all(np.isclose(s,o),-1) + np.all(np.isclose(s,-1.0*o),-1) * np.isclose(s[...,0],0.0)
def __ne__(self,other):
"""
Not equal to other.
Equality is determined taking limited floating point precision into Equality is determined taking limited floating point precision into
account. See numpy.allclose for details. account. See numpy.allclose for details.
@ -106,13 +122,21 @@ class Rotation:
Rotation to check for equality. Rotation to check for equality.
""" """
return np.prod(self.shape,dtype=int) == np.prod(other.shape,dtype=int) \ return np.logical_not(self==other)
and np.allclose(self.quaternion,other.quaternion)
def __array__(self):
"""Initializer for numpy."""
return self.quaternion
@property
def size(self):
return self.quaternion[...,0].size
@property @property
def shape(self): def shape(self):
return self.quaternion.shape[:-1] return self.quaternion[...,0].shape
def __len__(self): def __len__(self):
@ -127,41 +151,46 @@ class Rotation:
return dup return dup
def __pow__(self,pwr): def __pow__(self,exp):
""" """
Raise quaternion to power. Perform the rotation 'exp' times.
Equivalent to performing the rotation 'pwr' times.
Parameters Parameters
---------- ----------
pwr : float exp : float
Power to raise quaternion to. Exponent.
""" """
phi = np.arccos(self.quaternion[...,0:1]) phi = np.arccos(self.quaternion[...,0:1])
p = self.quaternion[...,1:]/np.linalg.norm(self.quaternion[...,1:],axis=-1,keepdims=True) p = self.quaternion[...,1:]/np.linalg.norm(self.quaternion[...,1:],axis=-1,keepdims=True)
return self.copy(rotation=Rotation(np.block([np.cos(pwr*phi),np.sin(pwr*phi)*p]))._standardize()) return self.copy(rotation=Rotation(np.block([np.cos(exp*phi),np.sin(exp*phi)*p]))._standardize())
def __ipow__(self,exp):
def __mul__(self,other):
"""Standard multiplication is not implemented."""
raise NotImplementedError('Use "R@b", i.e. matmul, to apply rotation "R" to object "b"')
def __matmul__(self,other):
""" """
Rotation of vector, second or fourth order tensor, or rotation object. Perform the rotation 'exp' times (in-place).
Parameters Parameters
---------- ----------
other : numpy.ndarray or Rotation exp : float
Vector, second or fourth order tensor, or rotation object that is rotated. Exponent.
"""
return self**exp
def __mul__(self,other):
"""
Compose this rotation with other.
Parameters
----------
other : Rotation of shape(self.shape)
Rotation for composition.
Returns Returns
------- -------
other_rot : numpy.ndarray or Rotation composition : Rotation
Rotated vector, second or fourth order tensor, or rotation object. Compound rotation self*other, i.e. first other then self rotation.
""" """
if isinstance(other,Rotation): if isinstance(other,Rotation):
@ -172,8 +201,71 @@ class Rotation:
q = (q_m*q_o - np.einsum('...i,...i',p_m,p_o).reshape(self.shape+(1,))) q = (q_m*q_o - np.einsum('...i,...i',p_m,p_o).reshape(self.shape+(1,)))
p = q_m*p_o + q_o*p_m + _P * np.cross(p_m,p_o) p = q_m*p_o + q_o*p_m + _P * np.cross(p_m,p_o)
return Rotation(np.block([q,p]))._standardize() return Rotation(np.block([q,p]))._standardize()
else:
raise TypeError('Use "R@b", i.e. matmul, to apply rotation "R" to object "b"')
elif isinstance(other,np.ndarray): def __imul__(self,other):
"""
Compose this rotation with other (in-place).
Parameters
----------
other : Rotation of shape(self.shape)
Rotation for composition.
"""
return self*other
def __truediv__(self,other):
"""
Compose this rotation with inverse of other.
Parameters
----------
other : damask.Rotation of shape (self.shape)
Rotation to inverse composition.
Returns
-------
composition : Rotation
Compound rotation self*(~other), i.e. first inverse of other then self rotation.
"""
if isinstance(other,Rotation):
return self*~other
else:
raise TypeError('Use "R@b", i.e. matmul, to apply rotation "R" to object "b"')
def __itruediv__(self,other):
"""
Compose this rotation with inverse of other (in-place).
Parameters
----------
other : Rotation of shape (self.shape)
Rotation to inverse composition.
"""
return self/other
def __matmul__(self,other):
"""
Rotation of vector, second order tensor, or fourth order tensor.
Parameters
----------
other : numpy.ndarray of shape (...,3), (...,3,3), or (...,3,3,3,3)
Vector or tensor on which to apply the rotation.
Returns
-------
rotated : numpy.ndarray of shape (...,3), (...,3,3), or (...,3,3,3,3)
Rotated vector or tensor, i.e. transformed to frame defined by rotation.
"""
if isinstance(other,np.ndarray):
if self.shape + (3,) == other.shape: if self.shape + (3,) == other.shape:
q_m = self.quaternion[...,0] q_m = self.quaternion[...,0]
p_m = self.quaternion[...,1:] p_m = self.quaternion[...,1:]
@ -193,9 +285,13 @@ class Rotation:
return np.einsum('...im,...jn,...ko,...lp,...mnop',R,R,R,R,other) return np.einsum('...im,...jn,...ko,...lp,...mnop',R,R,R,R,other)
else: else:
raise ValueError('Can only rotate vectors, 2nd order tensors, and 4th order tensors') raise ValueError('Can only rotate vectors, 2nd order tensors, and 4th order tensors')
elif isinstance(other,Rotation):
raise TypeError('Use "R1*R2", i.e. multiplication, to compose rotations "R1" and "R2"')
else: else:
raise TypeError(f'Cannot rotate {type(other)}') raise TypeError(f'Cannot rotate {type(other)}')
apply = __matmul__
def _standardize(self): def _standardize(self):
"""Standardize quaternion (ensure positive real hemisphere).""" """Standardize quaternion (ensure positive real hemisphere)."""
@ -296,7 +392,7 @@ class Rotation:
Rotation to which the misorientation is computed. Rotation to which the misorientation is computed.
""" """
return other@~self return other*~self
################################################################################################ ################################################################################################
@ -379,15 +475,17 @@ class Rotation:
Parameters Parameters
---------- ----------
vector : bool, optional compact : bool, optional
Return as actual Rodrigues-Frank vector, i.e. axis Return as actual Rodrigues-Frank vector,
and angle argument are not separated. i.e. axis and angle argument are not separated.
Returns Returns
------- -------
rho : numpy.ndarray of shape (...,4) unless vector == True: rho : numpy.ndarray of shape (...,4) containing
numpy.ndarray of shape (...,3) [n_1, n_2, n_3, tan(ω/2)], ǀnǀ = 1 and ω [0,π]
Rodrigues-Frank vector: [n_1, n_2, n_3, tan(ω/2)], ǀnǀ = 1 and ω [0,π]. unless compact == True:
numpy.ndarray of shape (...,3) containing
tan(ω/2) [n_1, n_2, n_3], ω [0,π].
""" """
ro = Rotation._qu2ro(self.quaternion) ro = Rotation._qu2ro(self.quaternion)
@ -415,8 +513,8 @@ class Rotation:
Returns Returns
------- -------
c : numpy.ndarray of shape (...,3) x : numpy.ndarray of shape (...,3)
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3). Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
""" """
return Rotation._qu2cu(self.quaternion) return Rotation._qu2cu(self.quaternion)
@ -427,8 +525,7 @@ class Rotation:
@staticmethod @staticmethod
def from_quaternion(q, def from_quaternion(q,
accept_homomorph = False, accept_homomorph = False,
P = -1, P = -1):
**kwargs):
""" """
Initialize from quaternion. Initialize from quaternion.
@ -463,8 +560,7 @@ class Rotation:
@staticmethod @staticmethod
def from_Euler_angles(phi, def from_Euler_angles(phi,
degrees = False, degrees = False):
**kwargs):
""" """
Initialize from Bunge-Euler angles. Initialize from Bunge-Euler angles.
@ -491,8 +587,7 @@ class Rotation:
def from_axis_angle(axis_angle, def from_axis_angle(axis_angle,
degrees = False, degrees = False,
normalize = False, normalize = False,
P = -1, P = -1):
**kwargs):
""" """
Initialize from Axis angle pair. Initialize from Axis angle pair.
@ -529,8 +624,7 @@ class Rotation:
@staticmethod @staticmethod
def from_basis(basis, def from_basis(basis,
orthonormal = True, orthonormal = True,
reciprocal = False, reciprocal = False):
**kwargs):
""" """
Initialize from lattice basis vectors. Initialize from lattice basis vectors.
@ -564,7 +658,7 @@ class Rotation:
return Rotation(Rotation._om2qu(om)) return Rotation(Rotation._om2qu(om))
@staticmethod @staticmethod
def from_matrix(R,**kwargs): def from_matrix(R):
""" """
Initialize from rotation matrix. Initialize from rotation matrix.
@ -608,8 +702,7 @@ class Rotation:
@staticmethod @staticmethod
def from_Rodrigues_vector(rho, def from_Rodrigues_vector(rho,
normalize = False, normalize = False,
P = -1, P = -1):
**kwargs):
""" """
Initialize from Rodrigues-Frank vector (angle separated from axis). Initialize from Rodrigues-Frank vector (angle separated from axis).
@ -640,8 +733,7 @@ class Rotation:
@staticmethod @staticmethod
def from_homochoric(h, def from_homochoric(h,
P = -1, P = -1):
**kwargs):
""" """
Initialize from homochoric vector. Initialize from homochoric vector.
@ -667,21 +759,20 @@ class Rotation:
return Rotation(Rotation._ho2qu(ho)) return Rotation(Rotation._ho2qu(ho))
@staticmethod @staticmethod
def from_cubochoric(c, def from_cubochoric(x,
P = -1, P = -1):
**kwargs):
""" """
Initialize from cubochoric vector. Initialize from cubochoric vector.
Parameters Parameters
---------- ----------
c : numpy.ndarray of shape (...,3) x : numpy.ndarray of shape (...,3)
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3). Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Convention used. Defaults to -1.
""" """
cu = np.array(c,dtype=float) cu = np.array(x,dtype=float)
if cu.shape[:-2:-1] != (3,): if cu.shape[:-2:-1] != (3,):
raise ValueError('Invalid shape.') raise ValueError('Invalid shape.')
if abs(P) != 1: if abs(P) != 1:
@ -697,8 +788,7 @@ class Rotation:
@staticmethod @staticmethod
def from_random(shape = None, def from_random(shape = None,
rng_seed = None, rng_seed = None):
**kwargs):
""" """
Draw random rotation. Draw random rotation.
@ -791,8 +881,7 @@ class Rotation:
sigma, sigma,
N = 500, N = 500,
degrees = True, degrees = True,
rng_seed = None, rng_seed = None):
**kwargs):
""" """
Calculate set of rotations with Gaussian distribution around center. Calculate set of rotations with Gaussian distribution around center.
@ -819,7 +908,7 @@ class Rotation:
np.sqrt(1-u**2)*np.sin(Theta), np.sqrt(1-u**2)*np.sin(Theta),
u, omega]) u, omega])
return Rotation.from_axis_angle(p) @ center return Rotation.from_axis_angle(p) * center
@staticmethod @staticmethod
@ -828,8 +917,7 @@ class Rotation:
sigma = 0.0, sigma = 0.0,
N = 500, N = 500,
degrees = True, degrees = True,
rng_seed = None, rng_seed = None):
**kwargs):
""" """
Calculate set of rotations with Gaussian distribution around direction. Calculate set of rotations with Gaussian distribution around direction.
@ -870,8 +958,8 @@ class Rotation:
f[::2,:3] *= -1 # flip half the rotation axes to negative sense f[::2,:3] *= -1 # flip half the rotation axes to negative sense
return R_align.broadcast_to(N) \ return R_align.broadcast_to(N) \
@ Rotation.from_axis_angle(p,normalize=True) \ * Rotation.from_axis_angle(p,normalize=True) \
@ Rotation.from_axis_angle(f) * Rotation.from_axis_angle(f)
#################################################################################################### ####################################################################################################
@ -1060,7 +1148,6 @@ class Rotation:
@staticmethod @staticmethod
def _om2ax(om): def _om2ax(om):
"""Rotation matrix to axis angle pair.""" """Rotation matrix to axis angle pair."""
#return Rotation._qu2ax(Rotation._om2qu(om)) # HOTFIX
diag_delta = -_P*np.block([om[...,1,2:3]-om[...,2,1:2], diag_delta = -_P*np.block([om[...,1,2:3]-om[...,2,1:2],
om[...,2,0:1]-om[...,0,2:3], om[...,2,0:1]-om[...,0,2:3],
om[...,0,1:2]-om[...,1,0:1] om[...,0,1:2]-om[...,1,0:1]

View File

@ -26,7 +26,7 @@ class Table:
comments_ = [comments] if isinstance(comments,str) else comments comments_ = [comments] if isinstance(comments,str) else comments
self.comments = [] if comments_ is None else [c for c in comments_] self.comments = [] if comments_ is None else [c for c in comments_]
self.data = pd.DataFrame(data=data) self.data = pd.DataFrame(data=data)
self.shapes = { k:(v,) if isinstance(v,(np.int,int)) else v for k,v in shapes.items() } self.shapes = { k:(v,) if isinstance(v,(np.int64,np.int32,int)) else v for k,v in shapes.items() }
self._label_uniform() self._label_uniform()
def __repr__(self): def __repr__(self):
@ -42,12 +42,10 @@ class Table:
return len(self.data) return len(self.data)
def __copy__(self): def __copy__(self):
"""Copy Table.""" """Create deep copy."""
return copy.deepcopy(self) return copy.deepcopy(self)
def copy(self): copy = __copy__
"""Copy Table."""
return self.__copy__()
def _label_discrete(self): def _label_discrete(self):
@ -191,6 +189,11 @@ class Table:
label : str label : str
Column label. Column label.
Returns
-------
data : numpy.ndarray
Array of column data.
""" """
if re.match(r'[0-9]*?_',label): if re.match(r'[0-9]*?_',label):
idx,key = label.split('_',1) idx,key = label.split('_',1)
@ -214,6 +217,11 @@ class Table:
info : str, optional info : str, optional
Human-readable information about the new data. Human-readable information about the new data.
Returns
-------
table : Table
Updated table.
""" """
dup = self.copy() dup = self.copy()
dup._add_comment(label,data.shape[1:],info) dup._add_comment(label,data.shape[1:],info)
@ -240,6 +248,11 @@ class Table:
info : str, optional info : str, optional
Human-readable information about the modified data. Human-readable information about the modified data.
Returns
-------
table : Table
Updated table.
""" """
dup = self.copy() dup = self.copy()
dup._add_comment(label,data.shape[1:],info) dup._add_comment(label,data.shape[1:],info)
@ -263,6 +276,11 @@ class Table:
label : str label : str
Column label. Column label.
Returns
-------
table : Table
Updated table.
""" """
dup = self.copy() dup = self.copy()
dup.data.drop(columns=label,inplace=True) dup.data.drop(columns=label,inplace=True)
@ -281,6 +299,11 @@ class Table:
label_new : str or iterable of str label_new : str or iterable of str
New column label(s). New column label(s).
Returns
-------
table : Table
Updated table.
""" """
dup = self.copy() dup = self.copy()
columns = dict(zip([old] if isinstance(old,str) else old, columns = dict(zip([old] if isinstance(old,str) else old,
@ -302,6 +325,11 @@ class Table:
ascending : bool or list, optional ascending : bool or list, optional
Set sort order. Set sort order.
Returns
-------
table : Table
Updated table.
""" """
dup = self.copy() dup = self.copy()
dup._label_discrete() dup._label_discrete()
@ -322,6 +350,11 @@ class Table:
other : Table other : Table
Table to append. Table to append.
Returns
-------
table : Table
Concatenated table.
""" """
if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns): if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns):
raise KeyError('Labels or shapes or order do not match') raise KeyError('Labels or shapes or order do not match')
@ -342,6 +375,11 @@ class Table:
other : Table other : Table
Table to join. Table to join.
Returns
-------
table : Table
Joined table.
""" """
if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]: if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]:
raise KeyError('Dublicated keys or row count mismatch') raise KeyError('Dublicated keys or row count mismatch')
@ -382,7 +420,7 @@ class Table:
[f'# {comment}' for comment in self.comments] [f'# {comment}' for comment in self.comments]
try: try:
fhandle = open(fname,'w') fhandle = open(fname,'w',newline='\n')
except TypeError: except TypeError:
fhandle = fname fhandle = fname

View File

@ -5,6 +5,7 @@ import logging
import logging.config import logging.config
from collections.abc import Iterable from collections.abc import Iterable
from optparse import OptionParser from optparse import OptionParser
from pathlib import Path
import numpy as np import numpy as np
@ -180,7 +181,7 @@ class Test:
def fileInRoot(self,dir,file): def fileInRoot(self,dir,file):
"""Path to a file in the root directory of DAMASK.""" """Path to a file in the root directory of DAMASK."""
return str(damask.environment.root_dir/dir/file) return str(Path(os.environ['DAMASK_ROOT'])/dir/file)
def fileInReference(self,file): def fileInReference(self,file):
@ -282,40 +283,6 @@ class Test:
return out,error return out,error
def compare_Array(self,File1,File2):
import numpy as np
logging.info('\n '.join(['comparing',File1,File2]))
table = damask.Table.load(File1)
len1 = len(table.comments)+2
table = damask.Table.load(File2)
len2 = len(table.comments)+2
refArray = np.nan_to_num(np.genfromtxt(File1,missing_values='n/a',skip_header = len1,autostrip=True))
curArray = np.nan_to_num(np.genfromtxt(File2,missing_values='n/a',skip_header = len2,autostrip=True))
if len(curArray) == len(refArray):
refArrayNonZero = refArray[refArray.nonzero()]
curArray = curArray[refArray.nonzero()]
max_err = np. max(abs(refArrayNonZero[curArray.nonzero()]/curArray[curArray.nonzero()]-1.))
max_loc = np.argmax(abs(refArrayNonZero[curArray.nonzero()]/curArray[curArray.nonzero()]-1.))
refArrayNonZero = refArrayNonZero[curArray.nonzero()]
curArray = curArray[curArray.nonzero()]
print(f' ********\n * maximum relative error {max_err} between {refArrayNonZero[max_loc]} and {curArray[max_loc]}\n ********')
return max_err
else:
raise Exception(f'mismatch in array sizes ({len(refArray)} and {len(curArray)}) to compare')
def compare_ArrayRefCur(self,ref,cur=''):
if cur == '': cur = ref
refName = self.fileInReference(ref)
curName = self.fileInCurrent(cur)
return self.compare_Array(refName,curName)
def compare_Table(self,headings0,file0, def compare_Table(self,headings0,file0,
headings1,file1, headings1,file1,
normHeadings='',normType=None, normHeadings='',normType=None,
@ -468,101 +435,6 @@ class Test:
return (mean < meanTol) & (std < stdTol) return (mean < meanTol) & (std < stdTol)
def compare_Tables(self,
files = [None,None], # list of file names
columns = [None], # list of list of column labels (per file)
rtol = 1e-5,
atol = 1e-8,
debug = False):
"""Compare multiple tables with np.allclose."""
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)]
if len(files) < 2: return True # single table is always close to itself...
tables = [damask.Table.load(filename) for filename in files]
columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files
columns = columns[:len(files)] # truncate to same length as files
for i,column in enumerate(columns):
if column is None: columns[i] = list(tables[i].shapes.keys()) # if no column is given, use all
logging.info('comparing ASCIItables')
for i in range(len(columns)):
columns[i] = columns[0] if not columns[i] else \
([columns[i]] if not (isinstance(columns[i], Iterable) and not isinstance(columns[i], str)) else \
columns[i]
)
logging.info(files[i]+': '+','.join(columns[i]))
dimensions = [np.prod(tables[0].shapes[c]) for c in columns[0]] # width of each requested column
maximum = np.zeros_like(columns[0],dtype=float) # one magnitude per column entry
data = [] # list of feature table extracted from each file (ASCII table)
for i,(table,labels) in enumerate(zip(tables,columns)):
if np.any(dimensions != [np.prod(table.shapes[c]) for c in labels]): # check data object consistency
logging.critical(f'Table {files[i]} differs in data layout.')
return False
data.append(np.hstack(list(table.get(label) for label in labels)).astype(np.float)) # store
for j,label in enumerate(labels): # iterate over object labels
maximum[j] = np.maximum(
maximum[j],
np.amax(np.linalg.norm(table.get(label),
axis=1))
) # find maximum Euclidean norm across rows
maximum = np.where(maximum > 0.0, maximum, 1.0) # avoid div by zero for zero columns
maximum = np.repeat(maximum,dimensions) # spread maximum over columns of each object
for i in range(len(data)):
data[i] /= maximum # normalize each table
logging.info(f'shape of data {i}: {data[i].shape}')
if debug:
violators = np.absolute(data[0]-data[1]) > atol + rtol*np.absolute(data[1])
logging.info(f'shape of violators: {violators.shape}')
for j,culprits in enumerate(violators):
goodguys = np.logical_not(culprits)
if culprits.any():
logging.info(f'{j} has {np.sum(culprits)}')
logging.info(f'deviation: {np.absolute(data[0][j]-data[1][j])[culprits]}')
logging.info(f'data : {np.absolute(data[1][j])[culprits]}')
logging.info(f'deviation: {np.absolute(data[0][j]-data[1][j])[goodguys]}')
logging.info(f'data : {np.absolute(data[1][j])[goodguys]}')
allclose = True # start optimistic
for i in range(1,len(data)):
allclose &= np.allclose(data[i-1],data[i],rtol,atol) # accumulate "pessimism"
return allclose
def compare_TableRefCur(self,headingsRef,ref,headingsCur='',cur='',
normHeadings='',normType=None,
absoluteTolerance=False,perLine=False,skipLines=[]):
return self.compare_Table(headingsRef,
self.fileInReference(ref),
headingsRef if headingsCur == '' else headingsCur,
self.fileInCurrent(ref if cur == '' else cur),
normHeadings,normType,
absoluteTolerance,perLine,skipLines)
def compare_TableCurCur(self,headingsCur0,Cur0,Cur1,
headingsCur1='',
normHeadings='',normType=None,
absoluteTolerance=False,perLine=False,skipLines=[]):
return self.compare_Table(headingsCur0,
self.fileInCurrent(Cur0),
headingsCur0 if headingsCur1 == '' else headingsCur1,
self.fileInCurrent(Cur1),
normHeadings,normType,absoluteTolerance,perLine,skipLines)
def report_Success(self,culprit): def report_Success(self,culprit):
ret = culprit ret = culprit

View File

@ -10,7 +10,6 @@ from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArr
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
from . import util from . import util
from . import environment
from . import Table from . import Table
@ -247,8 +246,8 @@ class VTK:
raise ValueError('No label defined for numpy.ndarray') raise ValueError('No label defined for numpy.ndarray')
N_data = data.shape[0] N_data = data.shape[0]
d = np_to_vtk((data.astype(np.float32) if data.dtype in [np.float64, np.float128] d = np_to_vtk((data.astype(np.single) if data.dtype in [np.double, np.longdouble] else
else data).reshape(N_data,-1),deep=True) # avoid large files data).reshape(N_data,-1),deep=True) # avoid large files
d.SetName(label) d.SetName(label)
if N_data == N_points: if N_data == N_points:
@ -348,6 +347,21 @@ class VTK:
See http://compilatrix.com/article/vtk-1 for further ideas. See http://compilatrix.com/article/vtk-1 for further ideas.
""" """
try:
import wx
_ = wx.App(False) # noqa
width, height = wx.GetDisplaySize()
except ImportError:
try:
import tkinter
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.destroy()
except Exception as e:
width = 1024
height = 768
mapper = vtk.vtkDataSetMapper() mapper = vtk.vtkDataSetMapper()
mapper.SetInputData(self.vtk_data) mapper.SetInputData(self.vtk_data)
actor = vtk.vtkActor() actor = vtk.vtkActor()
@ -361,7 +375,7 @@ class VTK:
ren.AddActor(actor) ren.AddActor(actor)
ren.SetBackground(0.2,0.2,0.2) ren.SetBackground(0.2,0.2,0.2)
window.SetSize(environment.screen_size[0],environment.screen_size[1]) window.SetSize(width,height)
iren = vtk.vtkRenderWindowInteractor() iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(window) iren.SetRenderWindow(window)

View File

@ -2,14 +2,13 @@ import subprocess
import shlex import shlex
import re import re
import io import io
import os
from pathlib import Path from pathlib import Path
from .. import environment
class Marc: class Marc:
"""Wrapper to run DAMASK with MSCMarc.""" """Wrapper to run DAMASK with MSCMarc."""
def __init__(self,version=environment.options['MSC_VERSION']): def __init__(self,version=os.environ['MSC_VERSION']):
""" """
Create a Marc solver object. Create a Marc solver object.
@ -25,9 +24,7 @@ class Marc:
@property @property
def library_path(self): def library_path(self):
path_MSC = environment.options['MSC_ROOT'] path_lib = Path(f'{os.environ["MSC_ROOT"]}/mentat{self.version}/shlib/linux64')
path_lib = Path(f'{path_MSC}/mentat{self.version}/shlib/linux64')
if not path_lib.is_dir(): if not path_lib.is_dir():
raise FileNotFoundError(f'library path "{path_lib}" not found') raise FileNotFoundError(f'library path "{path_lib}" not found')
@ -37,9 +34,7 @@ class Marc:
@property @property
def tools_path(self): def tools_path(self):
path_MSC = environment.options['MSC_ROOT'] path_tools = Path(f'{os.environ["MSC_ROOT"]}/marc{self.version}/tools')
path_tools = Path(f'{path_MSC}/marc{self.version}/tools')
if not path_tools.is_dir(): if not path_tools.is_dir():
raise FileNotFoundError(f'tools path "{path_tools}" not found') raise FileNotFoundError(f'tools path "{path_tools}" not found')
@ -54,7 +49,7 @@ class Marc:
optimization = '', optimization = '',
): ):
usersub = environment.root_dir/'src/DAMASK_marc' usersub = Path(os.environ['DAMASK_ROOT'])/'src/DAMASK_marc'
usersub = usersub.parent/(usersub.name + ('.f90' if compile else '.marc')) usersub = usersub.parent/(usersub.name + ('.f90' if compile else '.marc'))
if not usersub.is_file(): if not usersub.is_file():
raise FileNotFoundError(f'subroutine ({"source" if compile else "binary"}) "{usersub}" not found') raise FileNotFoundError(f'subroutine ({"source" if compile else "binary"}) "{usersub}" not found')
@ -71,7 +66,7 @@ class Marc:
if logfile is not None: if logfile is not None:
try: try:
f = open(logfile,'w+') f = open(logfile,'w+',newline='\n')
except TypeError: except TypeError:
f = logfile f = logfile
else: else:

View File

@ -133,6 +133,8 @@ def execute(cmd,
stdout = stdout.decode('utf-8').replace('\x08','') stdout = stdout.decode('utf-8').replace('\x08','')
stderr = stderr.decode('utf-8').replace('\x08','') stderr = stderr.decode('utf-8').replace('\x08','')
if process.returncode != 0: if process.returncode != 0:
print(stdout)
print(stderr)
raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}") raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}")
return stdout, stderr return stdout, stderr
@ -183,7 +185,7 @@ def scale_to_coprime(v):
# Python 3.9 provides math.lcm, see https://stackoverflow.com/questions/51716916. # Python 3.9 provides math.lcm, see https://stackoverflow.com/questions/51716916.
return a * b // np.gcd(a, b) return a * b // np.gcd(a, b)
m = (np.array(v) * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v)) ** 0.5).astype(np.int) m = (np.array(v) * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v)) ** 0.5).astype(int)
m = m//reduce(np.gcd,m) m = m//reduce(np.gcd,m)
with np.errstate(invalid='ignore'): with np.errstate(invalid='ignore'):
@ -193,7 +195,7 @@ def scale_to_coprime(v):
return m return m
def project_stereographic(vector,normalize=False): def project_stereographic(vector,direction='z',normalize=True,keepdims=False):
""" """
Apply stereographic projection to vector. Apply stereographic projection to vector.
@ -201,18 +203,37 @@ def project_stereographic(vector,normalize=False):
---------- ----------
vector : numpy.ndarray of shape (...,3) vector : numpy.ndarray of shape (...,3)
Vector coordinates to be projected. Vector coordinates to be projected.
direction : str
Projection direction 'x', 'y', or 'z'.
Defaults to 'z'.
normalize : bool normalize : bool
Ensure unit length for vector. Defaults to False. Ensure unit length of input vector. Defaults to True.
keepdims : bool
Maintain three-dimensional output coordinates.
Default two-dimensional output uses right-handed frame spanned by
the next and next-next axis relative to the projection direction,
e.g. x-y when projecting along z and z-x when projecting along y.
Returns Returns
------- -------
coordinates : numpy.ndarray of shape (...,2) coordinates : numpy.ndarray of shape (...,2 | 3)
Projected coordinates. Projected coordinates.
Examples
--------
>>> project_stereographic(np.ones(3))
[0.3660254, 0.3660254]
>>> project_stereographic(np.ones(3),direction='x',normalize=False,keepdims=True)
[0, 0.5, 0.5]
>>> project_stereographic([0,1,1],direction='y',normalize=True,keepdims=False)
[0.41421356, 0]
""" """
v_ = vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector shift = 'zyx'.index(direction)
return np.block([v_[...,:2]/(1+np.abs(v_[...,2:3])), v_ = np.roll(vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector,
np.zeros_like(v_[...,2:3])]) shift,axis=-1)
return np.roll(np.block([v_[...,:2]/(1+np.abs(v_[...,2:3])),np.zeros_like(v_[...,2:3])]),
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
def execution_stamp(class_name,function_name=None): def execution_stamp(class_name,function_name=None):
@ -418,7 +439,7 @@ class _ProgressBar:
bar = '' * filled_length + '' * (self.bar_length - filled_length) bar = '' * filled_length + '' * (self.bar_length - filled_length)
delta_time = datetime.datetime.now() - self.start_time delta_time = datetime.datetime.now() - self.start_time
remaining_time = (self.total - (iteration+1)) * delta_time / (iteration+1) remaining_time = (self.total - (iteration+1)) * delta_time / (iteration+1)
remaining_time -= datetime.timedelta(microseconds=remaining_time.microseconds) # remove μs remaining_time -= datetime.timedelta(microseconds=remaining_time.microseconds) # remove μs
sys.stderr.write(f'\r{self.prefix} {bar} {fraction:>4.0%} ETA {remaining_time}') sys.stderr.write(f'\r{self.prefix} {bar} {fraction:>4.0%} ETA {remaining_time}')
sys.stderr.flush() sys.stderr.flush()

View File

@ -6,28 +6,29 @@ with open(Path(__file__).parent/'damask/VERSION') as f:
version = re.sub(r'(-([^-]*)).*$',r'.\2',re.sub(r'^v(\d+\.\d+(\.\d+)?)',r'\1',f.readline().strip())) version = re.sub(r'(-([^-]*)).*$',r'.\2',re.sub(r'^v(\d+\.\d+(\.\d+)?)',r'\1',f.readline().strip()))
setuptools.setup( setuptools.setup(
name="damask", name='damask',
version=version, version=version,
author="The DAMASK team", author='The DAMASK team',
author_email="damask@mpie.de", author_email='damask@mpie.de',
description="DAMASK library", description='DAMASK library',
long_description="Python library for pre and post processing of DAMASK simulations", long_description='Python library for pre and post processing of DAMASK simulations',
url="https://damask.mpie.de", url='https://damask.mpie.de',
packages=setuptools.find_packages(), packages=setuptools.find_packages(),
include_package_data=True, include_package_data=True,
python_requires = '>=3.6',
install_requires = [ install_requires = [
"pandas", # requires numpy 'pandas>=0.24', # requires numpy
"scipy", 'scipy>=1.2',
"h5py", # requires numpy 'h5py>=2.9', # requires numpy
"vtk", 'vtk>=8.1',
"matplotlib", # requires numpy, pillow 'matplotlib>=3.0', # requires numpy, pillow
"pyaml" 'pyaml>=3.12'
], ],
classifiers = [ classifiers = [
"Intended Audience :: Science/Research", 'Intended Audience :: Science/Research',
"Topic :: Scientific/Engineering", 'Topic :: Scientific/Engineering',
"Programming Language :: Python :: 3", 'Programming Language :: Python :: 3',
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
"Operating System :: OS Independent", 'Operating System :: OS Independent',
], ],
) )

View File

@ -1,32 +1,32 @@
homogenization: homogenization:
SX: SX:
N_constituents: 1 N_constituents: 1
mechanics: {type: none} mechanics: {type: pass}
Taylor: Taylor:
N_constituents: 2 N_constituents: 2
mechanics: {type: isostrain} mechanics: {type: isostrain}
material: material:
- constituents: - constituents:
- fraction: 1.0 - v: 1.0
O: [1.0, 0.0, 0.0, 0.0] O: [1.0, 0.0, 0.0, 0.0]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- fraction: 1.0 - v: 1.0
O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434] O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- fraction: 1.0 - v: 1.0
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945] O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
phase: Aluminum phase: Aluminum
homogenization: SX homogenization: SX
- constituents: - constituents:
- fraction: 0.5 - v: 0.5
O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106] O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
phase: Aluminum phase: Aluminum
- fraction: 0.5 - v: 0.5
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945] O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
phase: Steel phase: Steel
homogenization: Taylor homogenization: Taylor

View File

@ -22,6 +22,19 @@ class TestConfig:
with open(tmp_path/'config.yaml') as f: with open(tmp_path/'config.yaml') as f:
assert Config.load(f) == config assert Config.load(f) == config
def test_add_remove(self):
dummy = {'hello':'world','foo':'bar'}
config = Config()
config |= dummy
assert config == Config() | dummy
config = config.delete(dummy)
assert config == Config()
assert (config | dummy ).delete( 'hello' ) == config | {'foo':'bar'}
assert (config | dummy ).delete([ 'hello', 'foo' ]) == config
assert (config | Config(dummy)).delete({ 'hello':1,'foo':2 }) == config
assert (config | Config(dummy)).delete(Config({'hello':1 })) == config | {'foo':'bar'}
def test_repr(self,tmp_path): def test_repr(self,tmp_path):
config = Config() config = Config()
config['A'] = 1 config['A'] = 1

View File

@ -5,6 +5,7 @@ import numpy as np
from damask import ConfigMaterial from damask import ConfigMaterial
from damask import Table from damask import Table
from damask import Rotation
@pytest.fixture @pytest.fixture
def ref_path(ref_path_base): def ref_path(ref_path_base):
@ -42,7 +43,7 @@ class TestConfigMaterial:
def test_invalid_fraction(self,ref_path): def test_invalid_fraction(self,ref_path):
material_config = ConfigMaterial.load(ref_path/'material.yaml') material_config = ConfigMaterial.load(ref_path/'material.yaml')
material_config['material'][0]['constituents'][0]['fraction']=.9 material_config['material'][0]['constituents'][0]['v']=.9
assert not material_config.is_valid assert not material_config.is_valid
@pytest.mark.parametrize('item',['homogenization','phase','material']) @pytest.mark.parametrize('item',['homogenization','phase','material'])
@ -85,42 +86,25 @@ class TestConfigMaterial:
def test_from_table(self): def test_from_table(self):
N = np.random.randint(3,10) N = np.random.randint(3,10)
a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])),np.ones(N*2),np.zeros(N*2),np.ones(N*2))).T a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])),np.ones(N*2),np.zeros(N*2),np.ones(N*2),np.ones(N*2))).T
t = Table(a,{'varying':2,'constant':2}) t = Table(a,{'varying':1,'constant':4})
c = ConfigMaterial.from_table(t,constituents={'a':'varying','b':'1_constant'},c='2_constant') c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':'4_constant'})
assert len(c['material']) == N assert len(c['material']) == N
for i,m in enumerate(c['material']): for i,m in enumerate(c['material']):
c = m['constituents'][0] assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all()
assert m['c'] == 1 and c['b'] == 0 and (c['a'] == [i,1]).all()
def test_constituents(self): @pytest.mark.parametrize('N,n,kw',[
c = ConfigMaterial._constituents(c=1,v=[2,3]) (1,1,{'phase':'Gold',
assert c[0][0]['c'] == c[1][0]['c'] == 1 'O':[1,0,0,0],
assert c[0][0]['v'] == c[1][0]['v'] -1 ==2 'homogenization':'SX'}),
(3,1,{'phase':'Gold',
@pytest.mark.parametrize('constituents',[{'W':1,'X':[2,3]},{'Y':4},{'Z':[5,6]}]) 'O':Rotation.from_random(3),
@pytest.mark.parametrize('a',[[7.,8.],9.]) 'homogenization':'SX'}),
@pytest.mark.parametrize('b',['bd',['efg','hi']]) (2,3,{'phase':np.broadcast_to(['a','b','c'],(2,3)),
def test_material_add(self,tmp_path,constituents,a,b): 'O':Rotation.from_random((2,3)),
len_c = len(ConfigMaterial()._constituents(1,**constituents)) 'homogenization':['SX','PX']}),
len_a = len(a) if isinstance(a,list) else 1 ])
len_b = len(b) if isinstance(b,list) else 1 def test_material_add(self,kw,N,n):
m = ConfigMaterial().material_add(constituents,a=a,b=b) m = ConfigMaterial().material_add(**kw)
m.save() assert len(m['material']) == N
assert len(m['material']) == np.max([len_a,len_b,len_c]) assert len(m['material'][0]['constituents']) == n
@pytest.mark.parametrize('constituents',[{'W':1,'X':np.array([2,3])},{'Y':4},{'Z':np.array([5,6])}])
@pytest.mark.parametrize('a',[np.array([7,8]),9])
def test_material_add_np(self,tmp_path,constituents,a):
len_c = len(ConfigMaterial()._constituents(1,**constituents))
len_a = len(a) if isinstance(a,np.ndarray) else 1
m = ConfigMaterial().material_add(constituents,ld=a)
m.save()
assert len(m['material']) == np.max([len_a,len_c])
@pytest.mark.parametrize('constituents',[{'X':np.array([2,3,4,5])},{'Y':4}])
@pytest.mark.parametrize('a',[np.array([1,2,3]),[4,5,6]])
@pytest.mark.parametrize('b',[np.array([6.,7.]),[8.,9.]])
def test_material_add_invalid(self,constituents,a,b):
with pytest.raises(ValueError):
ConfigMaterial().material_add(constituents,a=a,u=b)

View File

@ -347,7 +347,7 @@ class TestGrid:
@pytest.mark.parametrize('approach',['Laguerre','Voronoi']) @pytest.mark.parametrize('approach',['Laguerre','Voronoi'])
def test_tessellate_bicrystal(self,approach): def test_tessellate_bicrystal(self,approach):
cells = np.random.randint(5,10,3)*2 cells = np.random.randint(5,10,3)*2
size = cells.astype(np.float) size = cells.astype(float)
seeds = np.vstack((size*np.array([0.5,0.25,0.5]),size*np.array([0.5,0.75,0.5]))) seeds = np.vstack((size*np.array([0.5,0.25,0.5]),size*np.array([0.5,0.75,0.5])))
material = np.zeros(cells) material = np.zeros(cells)
material[:,cells[1]//2:,:] = 1 material[:,cells[1]//2:,:] = 1

View File

@ -7,6 +7,7 @@ from damask import Orientation
from damask import Table from damask import Table
from damask import lattice from damask import lattice
from damask import util from damask import util
from damask import grid_filters
@pytest.fixture @pytest.fixture
@ -25,13 +26,16 @@ class TestOrientation:
@pytest.mark.parametrize('shape',[None,5,(4,6)]) @pytest.mark.parametrize('shape',[None,5,(4,6)])
def test_equal(self,lattice,shape): def test_equal(self,lattice,shape):
R = Rotation.from_random(shape) R = Rotation.from_random(shape)
assert Orientation(R,lattice) == Orientation(R,lattice) assert Orientation(R,lattice) == Orientation(R,lattice) if shape is None else \
(Orientation(R,lattice) == Orientation(R,lattice)).all()
@pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('lattice',Orientation.crystal_families)
@pytest.mark.parametrize('shape',[None,5,(4,6)]) @pytest.mark.parametrize('shape',[None,5,(4,6)])
def test_unequal(self,lattice,shape): def test_unequal(self,lattice,shape):
R = Rotation.from_random(shape) R = Rotation.from_random(shape)
assert not(Orientation(R,lattice) != Orientation(R,lattice)) assert not ( Orientation(R,lattice) != Orientation(R,lattice) if shape is None else \
(Orientation(R,lattice) != Orientation(R,lattice)).any())
@pytest.mark.parametrize('a,b',[ @pytest.mark.parametrize('a,b',[
(dict(rotation=[1,0,0,0]), (dict(rotation=[1,0,0,0]),
@ -115,7 +119,7 @@ class TestOrientation:
== np.eye(3)) == np.eye(3))
def test_from_cubochoric(self): def test_from_cubochoric(self):
assert np.all(Orientation.from_cubochoric(c=np.zeros(3),lattice='triclinic').as_matrix() assert np.all(Orientation.from_cubochoric(x=np.zeros(3),lattice='triclinic').as_matrix()
== np.eye(3)) == np.eye(3))
def test_from_spherical_component(self): def test_from_spherical_component(self):
@ -138,7 +142,7 @@ class TestOrientation:
dict(lattice='hP',a=1.0 ), dict(lattice='hP',a=1.0 ),
dict(lattice='cI',a=1.0, ), dict(lattice='cI',a=1.0, ),
]) ])
def test_from_direction(self,kwargs): def test_from_directions(self,kwargs):
for a,b in np.random.random((10,2,3)): for a,b in np.random.random((10,2,3)):
c = np.cross(b,a) c = np.cross(b,a)
if np.all(np.isclose(c,0)): continue if np.all(np.isclose(c,0)): continue
@ -148,6 +152,21 @@ class TestOrientation:
assert np.isclose(np.dot(x/np.linalg.norm(x),np.array([1,0,0])),1) \ assert np.isclose(np.dot(x/np.linalg.norm(x),np.array([1,0,0])),1) \
and np.isclose(np.dot(z/np.linalg.norm(z),np.array([0,0,1])),1) and np.isclose(np.dot(z/np.linalg.norm(z),np.array([0,0,1])),1)
@pytest.mark.parametrize('function',[Orientation.from_random,
Orientation.from_quaternion,
Orientation.from_Euler_angles,
Orientation.from_axis_angle,
Orientation.from_basis,
Orientation.from_matrix,
Orientation.from_Rodrigues_vector,
Orientation.from_homochoric,
Orientation.from_cubochoric,
Orientation.from_spherical_component,
Orientation.from_fiber_component,
Orientation.from_directions])
def test_invalid_from(self,function):
with pytest.raises(TypeError):
function(c=.1,degrees=True,invalid=66)
def test_negative_angle(self): def test_negative_angle(self):
with pytest.raises(ValueError): with pytest.raises(ValueError):
@ -218,6 +237,16 @@ class TestOrientation:
for r, theO in zip(o.reduced.flatten(),o.flatten()): for r, theO in zip(o.reduced.flatten(),o.flatten()):
assert r == theO.reduced assert r == theO.reduced
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
def test_reduced_corner_cases(self,lattice):
# test whether there is always a sym-eq rotation that falls into the FZ
N = np.random.randint(10,40)
size = np.ones(3)*np.pi**(2./3.)
grid = grid_filters.coordinates0_node([N+1,N+1,N+1],size,-size*.5)
evenly_distributed = Orientation.from_cubochoric(x=grid[:-2,:-2,:-2],lattice=lattice)
assert evenly_distributed.shape == evenly_distributed.reduced.shape
@pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('lattice',Orientation.crystal_families)
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)]) @pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
@pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]])) @pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]]))
@ -403,7 +432,7 @@ class TestOrientation:
def test_relationship_vectorize(self,set_of_quaternions,lattice,model): def test_relationship_vectorize(self,set_of_quaternions,lattice,model):
r = Orientation(rotation=set_of_quaternions[:200].reshape((50,4,4)),lattice=lattice).related(model) r = Orientation(rotation=set_of_quaternions[:200].reshape((50,4,4)),lattice=lattice).related(model)
for i in range(200): for i in range(200):
assert r.reshape((-1,200))[:,i] == Orientation(set_of_quaternions[i],lattice).related(model) assert (r.reshape((-1,200))[:,i] == Orientation(set_of_quaternions[i],lattice).related(model)).all()
@pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch']) @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch'])
@pytest.mark.parametrize('lattice',['cF','cI']) @pytest.mark.parametrize('lattice',['cF','cI'])

View File

@ -21,7 +21,7 @@ def default(tmp_path,ref_path):
fname = '12grains6x7x8_tensionY.hdf5' fname = '12grains6x7x8_tensionY.hdf5'
shutil.copy(ref_path/fname,tmp_path) shutil.copy(ref_path/fname,tmp_path)
f = Result(tmp_path/fname) f = Result(tmp_path/fname)
f.pick('times',20.0) f.view('times',20.0)
return f return f
@pytest.fixture @pytest.fixture
@ -43,56 +43,56 @@ class TestResult:
print(default) print(default)
def test_pick_all(self,default): def test_view_all(self,default):
default.pick('increments',True) default.view('increments',True)
a = default.get_dataset_location('F') a = default.get_dataset_location('F')
default.pick('increments','*') default.view('increments','*')
b = default.get_dataset_location('F') b = default.get_dataset_location('F')
default.pick('increments',default.incs_in_range(0,np.iinfo(int).max)) default.view('increments',default.incs_in_range(0,np.iinfo(int).max))
c = default.get_dataset_location('F') c = default.get_dataset_location('F')
default.pick('times',True) default.view('times',True)
d = default.get_dataset_location('F') d = default.get_dataset_location('F')
default.pick('times','*') default.view('times','*')
e = default.get_dataset_location('F') e = default.get_dataset_location('F')
default.pick('times',default.times_in_range(0.0,np.inf)) default.view('times',default.times_in_range(0.0,np.inf))
f = default.get_dataset_location('F') f = default.get_dataset_location('F')
assert a == b == c == d == e ==f assert a == b == c == d == e ==f
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations @pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
def test_pick_none(self,default,what): def test_view_none(self,default,what):
default.pick(what,False) default.view(what,False)
a = default.get_dataset_location('F') a = default.get_dataset_location('F')
default.pick(what,[]) default.view(what,[])
b = default.get_dataset_location('F') b = default.get_dataset_location('F')
assert a == b == [] assert a == b == []
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations @pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
def test_pick_more(self,default,what): def test_view_more(self,default,what):
default.pick(what,False) default.view(what,False)
default.pick_more(what,'*') default.view_more(what,'*')
a = default.get_dataset_location('F') a = default.get_dataset_location('F')
default.pick(what,True) default.view(what,True)
b = default.get_dataset_location('F') b = default.get_dataset_location('F')
assert a == b assert a == b
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations @pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
def test_pick_less(self,default,what): def test_view_less(self,default,what):
default.pick(what,True) default.view(what,True)
default.pick_less(what,'*') default.view_less(what,'*')
a = default.get_dataset_location('F') a = default.get_dataset_location('F')
default.pick(what,False) default.view(what,False)
b = default.get_dataset_location('F') b = default.get_dataset_location('F')
assert a == b == [] assert a == b == []
def test_pick_invalid(self,default): def test_view_invalid(self,default):
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
default.pick('invalid',True) default.view('invalid',True)
def test_add_absolute(self,default): def test_add_absolute(self,default):
default.add_absolute('F_e') default.add_absolute('F_e')
@ -307,7 +307,7 @@ class TestResult:
@pytest.mark.parametrize('overwrite',['off','on']) @pytest.mark.parametrize('overwrite',['off','on'])
def test_add_overwrite(self,default,overwrite): def test_add_overwrite(self,default,overwrite):
default.pick('times',default.times_in_range(0,np.inf)[-1]) default.view('times',default.times_in_range(0,np.inf)[-1])
default.add_stress_Cauchy() default.add_stress_Cauchy()
loc = default.get_dataset_location('sigma') loc = default.get_dataset_location('sigma')

View File

@ -526,7 +526,7 @@ class TestRotation:
o = backward(forward(m)) o = backward(forward(m))
u = np.array([np.pi*2,np.pi,np.pi*2]) u = np.array([np.pi*2,np.pi,np.pi*2])
ok = np.allclose(m,o,atol=atol) ok = np.allclose(m,o,atol=atol)
ok = ok or np.allclose(np.where(np.isclose(m,u),m-u,m),np.where(np.isclose(o,u),o-u,o),atol=atol) ok |= np.allclose(np.where(np.isclose(m,u),m-u,m),np.where(np.isclose(o,u),o-u,o),atol=atol)
if np.isclose(m[1],0.0,atol=atol) or np.isclose(m[1],np.pi,atol=atol): if np.isclose(m[1],0.0,atol=atol) or np.isclose(m[1],np.pi,atol=atol):
sum_phi = np.unwrap([m[0]+m[2],o[0]+o[2]]) sum_phi = np.unwrap([m[0]+m[2],o[0]+o[2]])
ok |= np.isclose(sum_phi[0],sum_phi[1],atol=atol) ok |= np.isclose(sum_phi[0],sum_phi[1],atol=atol)
@ -550,19 +550,22 @@ class TestRotation:
assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) and o[3]<=np.pi+1.e-9, f'{m},{o},{rot.as_quaternion()}' assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) and o[3]<=np.pi+1.e-9, f'{m},{o},{rot.as_quaternion()}'
@pytest.mark.parametrize('forward,backward',[(Rotation._ro2qu,Rotation._qu2ro), @pytest.mark.parametrize('forward,backward',[(Rotation._ro2qu,Rotation._qu2ro),
#(Rotation._ro2om,Rotation._om2ro), (Rotation._ro2om,Rotation._om2ro),
#(Rotation._ro2eu,Rotation._eu2ro), (Rotation._ro2eu,Rotation._eu2ro),
(Rotation._ro2ax,Rotation._ax2ro), (Rotation._ro2ax,Rotation._ax2ro),
(Rotation._ro2ho,Rotation._ho2ro), (Rotation._ro2ho,Rotation._ho2ro),
(Rotation._ro2cu,Rotation._cu2ro)]) (Rotation._ro2cu,Rotation._cu2ro)])
def test_Rodrigues_internal(self,set_of_rotations,forward,backward): def test_Rodrigues_internal(self,set_of_rotations,forward,backward):
"""Ensure invariance of conversion from Rodrigues-Frank vector and back.""" """Ensure invariance of conversion from Rodrigues-Frank vector and back."""
cutoff = np.tan(np.pi*.5*(1.-1e-4)) cutoff = np.tan(np.pi*.5*(1.-1e-5))
for rot in set_of_rotations: for rot in set_of_rotations:
m = rot.as_Rodrigues_vector() m = rot.as_Rodrigues_vector()
o = backward(forward(m)) o = backward(forward(m))
ok = np.allclose(np.clip(m,None,cutoff),np.clip(o,None,cutoff),atol=atol) ok = np.allclose(np.clip(m,None,cutoff),np.clip(o,None,cutoff),atol=atol)
ok = ok or np.isclose(m[3],0.0,atol=atol) ok |= np.isclose(m[3],0.0,atol=atol)
if m[3] > cutoff:
ok |= np.allclose(m[:3],-1*o[:3])
assert ok and np.isclose(np.linalg.norm(o[:3]),1.0), f'{m},{o},{rot.as_quaternion()}' assert ok and np.isclose(np.linalg.norm(o[:3]),1.0), f'{m},{o},{rot.as_quaternion()}'
@pytest.mark.parametrize('forward,backward',[(Rotation._ho2qu,Rotation._qu2ho), @pytest.mark.parametrize('forward,backward',[(Rotation._ho2qu,Rotation._qu2ho),
@ -592,7 +595,7 @@ class TestRotation:
o = backward(forward(m)) o = backward(forward(m))
ok = np.allclose(m,o,atol=atol) ok = np.allclose(m,o,atol=atol)
if np.count_nonzero(np.isclose(np.abs(o),np.pi**(2./3.)*.5)): if np.count_nonzero(np.isclose(np.abs(o),np.pi**(2./3.)*.5)):
ok = ok or np.allclose(m*-1.,o,atol=atol) ok |= np.allclose(m*-1.,o,atol=atol)
assert ok and np.max(np.abs(o)) < np.pi**(2./3.) * 0.5 + 1.e-9, f'{m},{o},{rot.as_quaternion()}' assert ok and np.max(np.abs(o)) < np.pi**(2./3.) * 0.5 + 1.e-9, f'{m},{o},{rot.as_quaternion()}'
@pytest.mark.parametrize('vectorized, single',[(Rotation._qu2om,qu2om), @pytest.mark.parametrize('vectorized, single',[(Rotation._qu2om,qu2om),
@ -686,6 +689,10 @@ class TestRotation:
with pytest.raises(TypeError): with pytest.raises(TypeError):
Rotation(np.ones(3)) Rotation(np.ones(3))
def test_to_numpy(self):
r = Rotation.from_random(np.random.randint(0,10,4))
assert np.all(r.as_quaternion() == np.array(r))
@pytest.mark.parametrize('degrees',[True,False]) @pytest.mark.parametrize('degrees',[True,False])
def test_Eulers(self,set_of_rotations,degrees): def test_Eulers(self,set_of_rotations,degrees):
for rot in set_of_rotations: for rot in set_of_rotations:
@ -719,7 +726,7 @@ class TestRotation:
o = Rotation.from_axis_angle(rot.as_axis_angle()).as_axis_angle() o = Rotation.from_axis_angle(rot.as_axis_angle()).as_axis_angle()
ok = np.allclose(m,o,atol=atol) ok = np.allclose(m,o,atol=atol)
if np.isclose(m[3],np.pi,atol=atol): if np.isclose(m[3],np.pi,atol=atol):
ok = ok or np.allclose(m*np.array([-1.,-1.,-1.,1.]),o,atol=atol) ok |= np.allclose(m*np.array([-1.,-1.,-1.,1.]),o,atol=atol)
assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) \ assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) \
and o[3]<=np.pi+1.e-9, f'{m},{o},{rot.as_quaternion()}' and o[3]<=np.pi+1.e-9, f'{m},{o},{rot.as_quaternion()}'
@ -740,7 +747,7 @@ class TestRotation:
m = rot.as_Rodrigues_vector() m = rot.as_Rodrigues_vector()
o = Rotation.from_homochoric(rot.as_homochoric()*P*-1,P).as_Rodrigues_vector() o = Rotation.from_homochoric(rot.as_homochoric()*P*-1,P).as_Rodrigues_vector()
ok = np.allclose(np.clip(m,None,cutoff),np.clip(o,None,cutoff),atol=atol) ok = np.allclose(np.clip(m,None,cutoff),np.clip(o,None,cutoff),atol=atol)
ok = ok or np.isclose(m[3],0.0,atol=atol) ok |= np.isclose(m[3],0.0,atol=atol)
assert ok and np.isclose(np.linalg.norm(o[:3]),1.0), f'{m},{o},{rot.as_quaternion()}' assert ok and np.isclose(np.linalg.norm(o[:3]),1.0), f'{m},{o},{rot.as_quaternion()}'
@pytest.mark.parametrize('P',[1,-1]) @pytest.mark.parametrize('P',[1,-1])
@ -780,14 +787,32 @@ class TestRotation:
else: else:
assert r.shape == shape assert r.shape == shape
def test_equal(self): @pytest.mark.parametrize('shape',[None,5,(4,6)])
assert Rotation.from_random(rng_seed=1) == Rotation.from_random(rng_seed=1) def test_equal(self,shape):
R = Rotation.from_random(shape,rng_seed=1)
assert R == R if shape is None else (R == R).all()
@pytest.mark.parametrize('shape',[None,5,(4,6)])
def test_unequal(self,shape):
R = Rotation.from_random(shape,rng_seed=1)
assert not (R != R if shape is None else (R != R).any())
def test_equal_ambiguous(self):
qu = np.random.rand(10,4)
qu[:,0] = 0.
qu/=np.linalg.norm(qu,axis=1,keepdims=True)
assert (Rotation(qu) == Rotation(-qu)).all()
def test_inversion(self): def test_inversion(self):
r = Rotation.from_random() r = Rotation.from_random()
assert r == ~~r assert r == ~~r
@pytest.mark.parametrize('shape',[None,1,(1,),(4,2),(1,1,1)]) @pytest.mark.parametrize('shape',[1,(1,),(4,2),(1,1,1),tuple(np.random.randint(0,10,4))])
def test_size(self,shape):
assert Rotation.from_random(shape).size == np.prod(shape)
@pytest.mark.parametrize('shape',[None,1,(1,),(4,2),(1,1,1),tuple(np.random.randint(0,10,4))])
def test_shape(self,shape): def test_shape(self,shape):
r = Rotation.from_random(shape=shape) r = Rotation.from_random(shape=shape)
assert r.shape == (shape if isinstance(shape,tuple) else (shape,) if shape else ()) assert r.shape == (shape if isinstance(shape,tuple) else (shape,) if shape else ())
@ -798,7 +823,7 @@ class TestRotation:
p = Rotation.from_random(shape=shape) p = Rotation.from_random(shape=shape)
s = r.append(p) s = r.append(p)
print(f'append 2x {shape} --> {s.shape}') print(f'append 2x {shape} --> {s.shape}')
assert s[0,...] == r[0,...] and s[-1,...] == p[-1,...] assert np.logical_and(s[0,...] == r[0,...], s[-1,...] == p[-1,...]).all()
@pytest.mark.parametrize('shape',[None,1,(1,),(4,2),(3,3,2)]) @pytest.mark.parametrize('shape',[None,1,(1,),(4,2),(3,3,2)])
def test_append_list(self,shape): def test_append_list(self,shape):
@ -806,7 +831,7 @@ class TestRotation:
p = Rotation.from_random(shape=shape) p = Rotation.from_random(shape=shape)
s = r.append([r,p]) s = r.append([r,p])
print(f'append 3x {shape} --> {s.shape}') print(f'append 3x {shape} --> {s.shape}')
assert s[0,...] == r[0,...] and s[-1,...] == p[-1,...] assert np.logical_and(s[0,...] == r[0,...], s[-1,...] == p[-1,...]).all()
@pytest.mark.parametrize('quat,standardized',[ @pytest.mark.parametrize('quat,standardized',[
([-1,0,0,0],[1,0,0,0]), ([-1,0,0,0],[1,0,0,0]),
@ -828,7 +853,7 @@ class TestRotation:
@pytest.mark.parametrize('order',['C','F']) @pytest.mark.parametrize('order',['C','F'])
def test_flatten_reshape(self,shape,order): def test_flatten_reshape(self,shape,order):
r = Rotation.from_random(shape=shape) r = Rotation.from_random(shape=shape)
assert r == r.flatten(order).reshape(shape,order) assert (r == r.flatten(order).reshape(shape,order)).all()
@pytest.mark.parametrize('function',[Rotation.from_quaternion, @pytest.mark.parametrize('function',[Rotation.from_quaternion,
Rotation.from_Euler_angles, Rotation.from_Euler_angles,
@ -939,7 +964,7 @@ class TestRotation:
def test_rotate_inverse(self): def test_rotate_inverse(self):
R = Rotation.from_random() R = Rotation.from_random()
assert np.allclose(np.eye(3),(~R@R).as_matrix()) assert np.allclose(np.eye(3),(~R*R).as_matrix())
@pytest.mark.parametrize('data',[np.random.rand(3), @pytest.mark.parametrize('data',[np.random.rand(3),
np.random.rand(3,3), np.random.rand(3,3),
@ -973,6 +998,42 @@ class TestRotation:
R_2 = Rotation.from_Euler_angles([360,0,0],degrees=True) R_2 = Rotation.from_Euler_angles([360,0,0],degrees=True)
assert np.allclose(R_1.misorientation(R_2).as_matrix(),np.eye(3)) assert np.allclose(R_1.misorientation(R_2).as_matrix(),np.eye(3))
def test_composition(self):
a,b = (Rotation.from_random(),Rotation.from_random())
c = a * b
a *= b
assert c == a
def test_composition_invalid(self):
with pytest.raises(TypeError):
Rotation()*np.ones(3)
def test_composition_inverse(self):
a,b = (Rotation.from_random(),Rotation.from_random())
c = a / b
a /= b
assert c == a
def test_composition_inverse_invalid(self):
with pytest.raises(TypeError):
Rotation()/np.ones(3)
def test_power(self):
a = Rotation.from_random()
r = (np.random.rand()-.5)*4
b = a**r
a **= r
assert a == b
def test_invariant(self):
R = Rotation.from_random()
assert R/R == R*R**(-1) == Rotation()
@pytest.mark.parametrize('item',[np.ones(3),np.ones((3,3)), np.ones((3,3,3,3))])
def test_apply(self,item):
r = Rotation.from_random()
assert (r.apply(item) == r@item).all()
@pytest.mark.parametrize('angle',[10,20,30,40,50,60,70,80,90,100,120]) @pytest.mark.parametrize('angle',[10,20,30,40,50,60,70,80,90,100,120])
def test_average(self,angle): def test_average(self,angle):
R = Rotation.from_axis_angle([[0,0,1,10],[0,0,1,angle]],degrees=True) R = Rotation.from_axis_angle([[0,0,1,10],[0,0,1,angle]],degrees=True)

View File

@ -49,17 +49,18 @@ class TestUtil:
dist_sampled = np.histogram(centers[selected],bins)[0]/N_samples*np.sum(dist) dist_sampled = np.histogram(centers[selected],bins)[0]/N_samples*np.sum(dist)
assert np.sqrt(((dist - dist_sampled) ** 2).mean()) < .025 and selected.shape[0]==N_samples assert np.sqrt(((dist - dist_sampled) ** 2).mean()) < .025 and selected.shape[0]==N_samples
@pytest.mark.parametrize('point,normalize,answer', @pytest.mark.parametrize('point,direction,normalize,keepdims,answer',
[ [
([1,0,0],False,[1,0,0]), ([1,0,0],'z',False,True, [1,0,0]),
([1,0,0],True, [1,0,0]), ([1,0,0],'z',True, False,[1,0]),
([0,1,1],False,[0,0.5,0]), ([0,1,1],'z',False,True, [0,0.5,0]),
([0,1,1],True, [0,0.41421356,0]), ([0,1,1],'y',True, False,[0.41421356,0]),
([1,1,1],False,[0.5,0.5,0]), ([1,1,0],'x',False,False,[0.5,0]),
([1,1,1],True, [0.3660254, 0.3660254, 0]), ([1,1,1],'y',True, True, [0.3660254, 0,0.3660254]),
]) ])
def test_project_stereographic(self,point,normalize,answer): def test_project_stereographic(self,point,direction,normalize,keepdims,answer):
assert np.allclose(util.project_stereographic(np.array(point),normalize=normalize),answer) assert np.allclose(util.project_stereographic(np.array(point),direction=direction,
normalize=normalize,keepdims=keepdims),answer)
@pytest.mark.parametrize('fro,to,mode,answer', @pytest.mark.parametrize('fro,to,mode,answer',
[ [

View File

@ -19,7 +19,7 @@ module CPFEM
use HDF5_utilities use HDF5_utilities
use results use results
use lattice use lattice
use constitutive use phase
implicit none implicit none
private private
@ -72,7 +72,6 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine CPFEM_initAll subroutine CPFEM_initAll
call parallelization_init
call DAMASK_interface_init call DAMASK_interface_init
call prec_init call prec_init
call IO_init call IO_init
@ -86,7 +85,7 @@ subroutine CPFEM_initAll
call discretization_marc_init call discretization_marc_init
call lattice_init call lattice_init
call material_init(.false.) call material_init(.false.)
call constitutive_init call phase_init
call homogenization_init call homogenization_init
call crystallite_init call crystallite_init
call CPFEM_init call CPFEM_init
@ -179,11 +178,11 @@ subroutine CPFEM_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyS
if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) call CPFEM_forward if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) call CPFEM_forward
chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP))) !chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP)))
case (THERMAL_conduction_ID) chosenThermal1 ! case (THERMAL_conduction_ID) chosenThermal1
temperature(material_homogenizationAt(elCP))%p(material_homogenizationMemberAt(ip,elCP)) = & ! temperature(material_homogenizationAt(elCP))%p(material_homogenizationMemberAt(ip,elCP)) = &
temperature_inp ! temperature_inp
end select chosenThermal1 !end select chosenThermal1
homogenization_F0(1:3,1:3,ma) = ffn homogenization_F0(1:3,1:3,ma) = ffn
homogenization_F(1:3,1:3,ma) = ffn1 homogenization_F(1:3,1:3,ma) = ffn1
@ -258,7 +257,7 @@ end subroutine CPFEM_general
subroutine CPFEM_forward subroutine CPFEM_forward
call homogenization_forward call homogenization_forward
call constitutive_forward call phase_forward
end subroutine CPFEM_forward end subroutine CPFEM_forward
@ -273,7 +272,7 @@ subroutine CPFEM_results(inc,time)
call results_openJobFile call results_openJobFile
call results_addIncrement(inc,time) call results_addIncrement(inc,time)
call constitutive_results call phase_results
call homogenization_results call homogenization_results
call discretization_results call discretization_results
call results_finalizeIncrement call results_finalizeIncrement

View File

@ -19,7 +19,7 @@ module CPFEM2
use discretization use discretization
use HDF5_utilities use HDF5_utilities
use homogenization use homogenization
use constitutive use phase
#if defined(Mesh) #if defined(Mesh)
use FEM_quadrature use FEM_quadrature
use discretization_mesh use discretization_mesh
@ -60,7 +60,7 @@ subroutine CPFEM_initAll
call discretization_grid_init(restart=interface_restartInc>0) call discretization_grid_init(restart=interface_restartInc>0)
#endif #endif
call material_init(restart=interface_restartInc>0) call material_init(restart=interface_restartInc>0)
call constitutive_init call phase_init
call homogenization_init call homogenization_init
call crystallite_init call crystallite_init
call CPFEM_init call CPFEM_init
@ -74,9 +74,22 @@ end subroutine CPFEM_initAll
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine CPFEM_init subroutine CPFEM_init
integer(HID_T) :: fileHandle
print'(/,a)', ' <<<+- CPFEM init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- CPFEM init -+>>>'; flush(IO_STDOUT)
if (interface_restartInc > 0) call crystallite_restartRead
if (interface_restartInc > 0) then
print'(/,a,i0,a)', ' reading restart information of increment from file'; flush(IO_STDOUT)
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
call homogenization_restartRead(fileHandle)
call phase_restartRead(fileHandle)
call HDF5_closeFile(fileHandle)
endif
end subroutine CPFEM_init end subroutine CPFEM_init
@ -86,7 +99,17 @@ end subroutine CPFEM_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine CPFEM_restartWrite subroutine CPFEM_restartWrite
call crystallite_restartWrite integer(HID_T) :: fileHandle
print*, ' writing field and constitutive data required for restart to file';flush(IO_STDOUT)
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','a')
call homogenization_restartWrite(fileHandle)
call phase_restartWrite(fileHandle)
call HDF5_closeFile(fileHandle)
end subroutine CPFEM_restartWrite end subroutine CPFEM_restartWrite
@ -97,7 +120,7 @@ end subroutine CPFEM_restartWrite
subroutine CPFEM_forward subroutine CPFEM_forward
call homogenization_forward call homogenization_forward
call constitutive_forward call phase_forward
end subroutine CPFEM_forward end subroutine CPFEM_forward
@ -112,7 +135,7 @@ subroutine CPFEM_results(inc,time)
call results_openJobFile call results_openJobFile
call results_addIncrement(inc,time) call results_addIncrement(inc,time)
call constitutive_results call phase_results
call homogenization_results call homogenization_results
call discretization_results call discretization_results
call results_finalizeIncrement call results_finalizeIncrement

View File

@ -43,7 +43,7 @@ void gethostname_c(char hostname[], int *stat){
void getusername_c(char username[], int *stat){ void getusername_c(char username[], int *stat){
struct passwd *pw = getpwuid(geteuid()); struct passwd *pw = getpwuid(getuid());
if(pw && strlen(pw->pw_name) <= STRLEN){ if(pw && strlen(pw->pw_name) <= STRLEN){
strncpy(username,pw->pw_name,STRLEN+1); strncpy(username,pw->pw_name,STRLEN+1);
*stat = 0; *stat = 0;

View File

@ -199,7 +199,7 @@ subroutine DAMASK_interface_init
if (interface_restartInc > 0) & if (interface_restartInc > 0) &
print'(a,i6.6)', ' Restart from increment: ', interface_restartInc print'(a,i6.6)', ' Restart from increment: ', interface_restartInc
!call signalterm_c(c_funloc(catchSIGTERM)) call signalterm_c(c_funloc(catchSIGTERM))
call signalusr1_c(c_funloc(catchSIGUSR1)) call signalusr1_c(c_funloc(catchSIGUSR1))
call signalusr2_c(c_funloc(catchSIGUSR2)) call signalusr2_c(c_funloc(catchSIGUSR2))
call interface_setSIGTERM(.false.) call interface_setSIGTERM(.false.)
@ -386,24 +386,14 @@ end function makeRelativePath
subroutine catchSIGTERM(signal) bind(C) subroutine catchSIGTERM(signal) bind(C)
integer(C_INT), value :: signal integer(C_INT), value :: signal
print'(a,i0)', ' received signal ',signal
call interface_setSIGTERM(.true.) call interface_setSIGTERM(.true.)
print'(a,i0,a)', ' received signal ',signal, ', set SIGTERM=TRUE'
end subroutine catchSIGTERM end subroutine catchSIGTERM
!--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGTERM.
!--------------------------------------------------------------------------------------------------
subroutine interface_setSIGTERM(state)
logical, intent(in) :: state
interface_SIGTERM = state
end subroutine interface_setSIGTERM
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGUSR1 to .true. !> @brief Set global variable interface_SIGUSR1 to .true.
!> @details This function can be registered to catch signals send to the executable. !> @details This function can be registered to catch signals send to the executable.
@ -411,24 +401,14 @@ end subroutine interface_setSIGTERM
subroutine catchSIGUSR1(signal) bind(C) subroutine catchSIGUSR1(signal) bind(C)
integer(C_INT), value :: signal integer(C_INT), value :: signal
print'(a,i0)', ' received signal ',signal
call interface_setSIGUSR1(.true.) call interface_setSIGUSR1(.true.)
print'(a,i0,a)', ' received signal ',signal, ', set SIGUSR1=TRUE'
end subroutine catchSIGUSR1 end subroutine catchSIGUSR1
!--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGUSR.
!--------------------------------------------------------------------------------------------------
subroutine interface_setSIGUSR1(state)
logical, intent(in) :: state
interface_SIGUSR1 = state
end subroutine interface_setSIGUSR1
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGUSR2 to .true. !> @brief Set global variable interface_SIGUSR2 to .true.
!> @details This function can be registered to catch signals send to the executable. !> @details This function can be registered to catch signals send to the executable.
@ -436,20 +416,52 @@ end subroutine interface_setSIGUSR1
subroutine catchSIGUSR2(signal) bind(C) subroutine catchSIGUSR2(signal) bind(C)
integer(C_INT), value :: signal integer(C_INT), value :: signal
print'(a,i0,a)', ' received signal ',signal
call interface_setSIGUSR2(.true.) call interface_setSIGUSR2(.true.)
print'(a,i0,a)', ' received signal ',signal, ', set SIGUSR2=TRUE'
end subroutine catchSIGUSR2 end subroutine catchSIGUSR2
!--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGTERM.
!--------------------------------------------------------------------------------------------------
subroutine interface_setSIGTERM(state)
logical, intent(in) :: state
interface_SIGTERM = state
print*, 'set SIGTERM to',state
end subroutine interface_setSIGTERM
!--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGUSR.
!--------------------------------------------------------------------------------------------------
subroutine interface_setSIGUSR1(state)
logical, intent(in) :: state
interface_SIGUSR1 = state
print*, 'set SIGUSR1 to',state
end subroutine interface_setSIGUSR1
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Set global variable interface_SIGUSR2. !> @brief Set global variable interface_SIGUSR2.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine interface_setSIGUSR2(state) subroutine interface_setSIGUSR2(state)
logical, intent(in) :: state logical, intent(in) :: state
interface_SIGUSR2 = state interface_SIGUSR2 = state
print*, 'set SIGUSR2 to',state
end subroutine interface_setSIGUSR2 end subroutine interface_setSIGUSR2

View File

@ -7,20 +7,6 @@
!> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH !> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
!> @brief Interfaces DAMASK with MSC.Marc !> @brief Interfaces DAMASK with MSC.Marc
!> @details Usage:
!> @details - choose material as hypela2
!> @details - set statevariable 2 to index of homogenization
!> @details - set statevariable 3 to index of microstructure
!> @details - use nonsymmetric option for solver (e.g. direct profile or multifrontal sparse, the latter seems to be faster!)
!> @details - in case of ddm (domain decomposition) a SYMMETRIC solver has to be used, i.e uncheck "non-symmetric"
!> @details Marc subroutines used:
!> @details - hypela2
!> @details - uedinc
!> @details - flux
!> @details - quit
!> @details Marc common blocks included:
!> @details - concom: lovl, inc
!> @details - creeps: timinc
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
#define QUOTE(x) #x #define QUOTE(x) #x
#define PASTE(x,y) x ## y #define PASTE(x,y) x ## y
@ -65,14 +51,8 @@ subroutine DAMASK_interface_init
print'(/,a)', ' Version: '//DAMASKVERSION print'(/,a)', ' Version: '//DAMASKVERSION
! https://github.com/jeffhammond/HPCInfo/blob/master/docs/Preprocessor-Macros.md print'(/,a)', ' Compiled with: '//compiler_version()
#if __INTEL_COMPILER >= 1800 print'(a)', ' Compiler options: '//compiler_options()
print'(/,a)', ' Compiled with: '//compiler_version()
print'(a)', ' Compiler options: '//compiler_options()
#else
print'(/,a,i4.4,a,i8.8)', ' Compiled with Intel fortran version :', __INTEL_COMPILER,&
', build date :', __INTEL_COMPILER_BUILD_DATE
#endif
print'(/,a)', ' Compiled on: '//__DATE__//' at '//__TIME__ print'(/,a)', ' Compiled on: '//__DATE__//' at '//__TIME__
@ -239,7 +219,7 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
real(pReal), dimension(6) :: stress real(pReal), dimension(6) :: stress
real(pReal), dimension(6,6) :: ddsdde real(pReal), dimension(6,6) :: ddsdde
integer :: computationMode, i, cp_en, node, CPnodeID integer :: computationMode, i, cp_en, node, CPnodeID
integer(4) :: defaultNumThreadsInt !< default value set by Marc integer(pI32) :: defaultNumThreadsInt !< default value set by Marc
integer(pInt), save :: & integer(pInt), save :: &
theInc = -1_pInt, & !< needs description theInc = -1_pInt, & !< needs description
@ -250,13 +230,13 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
logical, save :: & logical, save :: &
lastIncConverged = .false., & !< needs description lastIncConverged = .false., & !< needs description
outdatedByNewInc = .false., & !< needs description outdatedByNewInc = .false., & !< needs description
CPFEM_init_done = .false., & !< remember whether init has been done already CPFEM_init_done = .false., & !< remember whether init has been done already
debug_basic = .true. debug_basic = .true.
class(tNode), pointer :: & class(tNode), pointer :: &
debug_Marc ! pointer to Marc debug options debug_Marc ! pointer to Marc debug options
if(debug_basic) then if(debug_basic) then
print'(a,/,i8,i8,i2)', ' MSC.MARC information on shape of element(2), IP:', m, nn print'(a,/,i8,i8,i2)', ' MSC.Marc information on shape of element(2), IP:', m, nn
print'(a,2(i1))', ' Jacobian: ', ngens,ngens print'(a,2(i1))', ' Jacobian: ', ngens,ngens
print'(a,i1)', ' Direct stress: ', ndi print'(a,i1)', ' Direct stress: ', ndi
print'(a,i1)', ' Shear stress: ', nshear print'(a,i1)', ' Shear stress: ', nshear
@ -271,7 +251,7 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, &
endif endif
defaultNumThreadsInt = omp_get_num_threads() ! remember number of threads set by Marc defaultNumThreadsInt = omp_get_num_threads() ! remember number of threads set by Marc
call omp_set_num_threads(1) ! no openMP call omp_set_num_threads(1_pI32) ! no openMP
if (.not. CPFEM_init_done) then if (.not. CPFEM_init_done) then
CPFEM_init_done = .true. CPFEM_init_done = .true.
@ -351,7 +331,7 @@ end subroutine hypela2
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine flux(f,ts,n,time) subroutine flux(f,ts,n,time)
use prec use prec
use thermal_conduction use homogenization
use discretization_marc use discretization_marc
implicit none implicit none
@ -364,7 +344,8 @@ subroutine flux(f,ts,n,time)
real(pReal), dimension(2), intent(out) :: & real(pReal), dimension(2), intent(out) :: &
f f
call thermal_conduction_getSourceAndItsTangent(f(1), f(2), ts(3), n(3),mesh_FEM2DAMASK_elem(n(1))) f(2) = 0.0_pReal
call thermal_conduction_getSource(f(1), n(3),mesh_FEM2DAMASK_elem(n(1)))
end subroutine flux end subroutine flux
@ -378,14 +359,28 @@ subroutine flux(f,ts,n,time)
subroutine uedinc(inc,incsub) subroutine uedinc(inc,incsub)
use prec use prec
use CPFEM use CPFEM
use discretization_marc
implicit none implicit none
integer, intent(in) :: inc, incsub integer, intent(in) :: inc, incsub
integer :: n, nqncomp, nqdatatype
integer, save :: inc_written integer, save :: inc_written
real(pReal), allocatable, dimension(:,:) :: d_n
#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment) #include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
if (inc > inc_written) then if (inc > inc_written) then
allocate(d_n(3,count(mesh_FEM2DAMASK_node /= -1)))
do n = lbound(mesh_FEM2DAMASK_node,1), ubound(mesh_FEM2DAMASK_node,1)
if (mesh_FEM2DAMASK_node(n) /= -1) then
call nodvar(1,n,d_n(1:3,mesh_FEM2DAMASK_node(n)),nqncomp,nqdatatype)
if(nqncomp == 2) d_n(3,mesh_FEM2DAMASK_node(n)) = 0.0_pReal
endif
enddo
call discretization_marc_UpdateNodeAndIpCoords(d_n)
call CPFEM_results(inc,cptim) call CPFEM_results(inc,cptim)
inc_written = inc inc_written = inc
endif endif

View File

@ -71,6 +71,12 @@ module HDF5_utilities
module procedure HDF5_addAttribute_real_array module procedure HDF5_addAttribute_real_array
end interface HDF5_addAttribute end interface HDF5_addAttribute
#ifdef PETSc
logical, parameter, private :: parallel_default = .true.
#else
logical, parameter, private :: parallel_default = .false.
#endif
contains contains
@ -105,16 +111,16 @@ end subroutine HDF5_utilities_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief open and initializes HDF5 output file !> @brief open and initializes HDF5 output file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
integer(HID_T) function HDF5_openFile(fileName,mode,parallel) integer(HID_T) function HDF5_openFile(fileName,mode)
character(len=*), intent(in) :: fileName character(len=*), intent(in) :: fileName
character, intent(in), optional :: mode character, intent(in), optional :: mode
logical, intent(in), optional :: parallel
character :: m character :: m
integer(HID_T) :: plist_id integer(HID_T) :: plist_id
integer :: hdferr integer :: hdferr
if (present(mode)) then if (present(mode)) then
m = mode m = mode
else else
@ -125,10 +131,8 @@ integer(HID_T) function HDF5_openFile(fileName,mode,parallel)
if(hdferr < 0) error stop 'HDF5 error' if(hdferr < 0) error stop 'HDF5 error'
#ifdef PETSc #ifdef PETSc
if (present(parallel)) then; if (parallel) then call h5pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr)
call h5pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr) if(hdferr < 0) error stop 'HDF5 error'
if(hdferr < 0) error stop 'HDF5 error'
endif; endif
#endif #endif
if (m == 'w') then if (m == 'w') then
@ -547,7 +551,7 @@ subroutine HDF5_read_real1(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -587,7 +591,7 @@ subroutine HDF5_read_real2(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -627,7 +631,7 @@ subroutine HDF5_read_real3(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -667,7 +671,7 @@ subroutine HDF5_read_real4(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -707,7 +711,7 @@ subroutine HDF5_read_real5(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -747,7 +751,7 @@ subroutine HDF5_read_real6(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -787,7 +791,7 @@ subroutine HDF5_read_real7(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,&
@ -829,7 +833,7 @@ subroutine HDF5_read_int1(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -869,7 +873,7 @@ subroutine HDF5_read_int2(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -909,7 +913,7 @@ subroutine HDF5_read_int3(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -949,7 +953,7 @@ subroutine HDF5_read_int4(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -989,7 +993,7 @@ subroutine HDF5_read_int5(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -1029,7 +1033,7 @@ subroutine HDF5_read_int6(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -1069,7 +1073,7 @@ subroutine HDF5_read_int7(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,parallel) myStart, totalShape, loc_id,myShape,datasetName,parallel)
else else
call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, &
myStart, totalShape, loc_id,myShape,datasetName,.false.) myStart, totalShape, loc_id,myShape,datasetName,parallel_default)
endif endif
call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,&
@ -1086,9 +1090,9 @@ end subroutine HDF5_read_int7
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real1(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real1(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:) :: dataset !< data written to file real(pReal), intent(in), dimension(:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1109,7 +1113,7 @@ subroutine HDF5_write_real1(loc_id,dataset,datasetName,parallel)
myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1127,9 +1131,9 @@ end subroutine HDF5_write_real1
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1150,7 +1154,7 @@ subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1168,9 +1172,9 @@ end subroutine HDF5_write_real2
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1191,7 +1195,7 @@ subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1209,9 +1213,9 @@ end subroutine HDF5_write_real3
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1232,7 +1236,7 @@ subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1251,9 +1255,9 @@ end subroutine HDF5_write_real4
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1274,7 +1278,7 @@ subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1292,9 +1296,9 @@ end subroutine HDF5_write_real5
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1315,7 +1319,7 @@ subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1333,9 +1337,9 @@ end subroutine HDF5_write_real6
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel)
real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file real(pReal), intent(in), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1356,7 +1360,7 @@ subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1375,9 +1379,9 @@ end subroutine HDF5_write_real7
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:) :: dataset !< data written to file integer, intent(in), dimension(:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1398,7 +1402,7 @@ subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1416,9 +1420,9 @@ end subroutine HDF5_write_int1
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1439,7 +1443,7 @@ subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1457,9 +1461,9 @@ end subroutine HDF5_write_int2
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1480,7 +1484,7 @@ subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1498,9 +1502,9 @@ end subroutine HDF5_write_int3
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1521,7 +1525,7 @@ subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1539,9 +1543,9 @@ end subroutine HDF5_write_int4
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1562,7 +1566,7 @@ subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1580,9 +1584,9 @@ end subroutine HDF5_write_int5
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1603,7 +1607,7 @@ subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then
@ -1621,9 +1625,9 @@ end subroutine HDF5_write_int6
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel) subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel)
integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file integer, intent(in), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
integer(HID_T), intent(in) :: loc_id !< file or group handle integer(HID_T), intent(in) :: loc_id !< file or group handle
character(len=*), intent(in) :: datasetName !< name of the dataset in the file character(len=*), intent(in) :: datasetName !< name of the dataset in the file
logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes
@ -1644,7 +1648,7 @@ subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel)
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel)
else else
call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & call initialize_write(dset_id, filespace_id, memspace_id, plist_id, &
myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,.false.) myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default)
endif endif
if (product(totalShape) /= 0) then if (product(totalShape) /= 0) then

View File

@ -65,8 +65,8 @@ end subroutine IO_init
function IO_readlines(fileName) result(fileContent) function IO_readlines(fileName) result(fileContent)
character(len=*), intent(in) :: fileName character(len=*), intent(in) :: fileName
character(len=pStringLen), dimension(:), allocatable :: fileContent !< file content, separated per lines character(len=pStringLen), dimension(:), allocatable :: fileContent !< file content, separated per lines
character(len=pStringLen) :: line character(len=pStringLen) :: line
character(len=:), allocatable :: rawData character(len=:), allocatable :: rawData
integer :: & integer :: &
@ -75,6 +75,7 @@ function IO_readlines(fileName) result(fileContent)
l l
logical :: warned logical :: warned
rawData = IO_read(fileName) rawData = IO_read(fileName)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -112,16 +113,21 @@ end function IO_readlines
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Read whole file. !> @brief Read whole file.
!> @details ensures that the string ends with a new line (expected UNIX behavior) !> @details ensures that the string ends with a new line (expected UNIX behavior) and rejects
! windows (CRLF) line endings
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function IO_read(fileName) result(fileContent) function IO_read(fileName) result(fileContent)
character(len=*), intent(in) :: fileName character(len=*), intent(in) :: fileName
character(len=:), allocatable :: fileContent character(len=:), allocatable :: fileContent
integer :: & integer :: &
fileLength, & fileLength, &
fileUnit, & fileUnit, &
myStat myStat, &
firstEOL
character, parameter :: CR = achar(13)
inquire(file = fileName, size=fileLength) inquire(file = fileName, size=fileLength)
open(newunit=fileUnit, file=fileName, access='stream',& open(newunit=fileUnit, file=fileName, access='stream',&
@ -137,8 +143,12 @@ function IO_read(fileName) result(fileContent)
if(myStat /= 0) call IO_error(102,ext_msg=trim(fileName)) if(myStat /= 0) call IO_error(102,ext_msg=trim(fileName))
close(fileUnit) close(fileUnit)
if(fileContent(fileLength:fileLength) /= IO_EOL) fileContent = fileContent//IO_EOL ! ensure EOL@EOF if(fileContent(fileLength:fileLength) /= IO_EOL) fileContent = fileContent//IO_EOL ! ensure EOL@EOF
firstEOL = index(fileContent,IO_EOL)
if(scan(fileContent(firstEOL:firstEOL),CR) /= 0) call IO_error(115)
end function IO_read end function IO_read
@ -151,6 +161,7 @@ logical pure function IO_isBlank(string)
integer :: posNonBlank integer :: posNonBlank
posNonBlank = verify(string,IO_WHITESPACE) posNonBlank = verify(string,IO_WHITESPACE)
IO_isBlank = posNonBlank == 0 .or. posNonBlank == scan(string,IO_COMMENT) IO_isBlank = posNonBlank == 0 .or. posNonBlank == scan(string,IO_COMMENT)
@ -170,6 +181,7 @@ pure function IO_stringPos(string)
integer :: left, right integer :: left, right
allocate(IO_stringPos(1), source=0) allocate(IO_stringPos(1), source=0)
right = 0 right = 0
@ -249,6 +261,7 @@ pure function IO_lc(string)
integer :: i,n integer :: i,n
do i=1,len(string) do i=1,len(string)
n = index(UPPER,string(i:i)) n = index(UPPER,string(i:i))
if(n/=0) then if(n/=0) then
@ -271,6 +284,7 @@ function IO_rmComment(line)
character(len=:), allocatable :: IO_rmComment character(len=:), allocatable :: IO_rmComment
integer :: split integer :: split
split = index(line,IO_COMMENT) split = index(line,IO_COMMENT)
if (split == 0) then if (split == 0) then
@ -292,6 +306,7 @@ integer function IO_stringAsInt(string)
integer :: readStatus integer :: readStatus
character(len=*), parameter :: VALIDCHARS = '0123456789+- ' character(len=*), parameter :: VALIDCHARS = '0123456789+- '
valid: if (verify(string,VALIDCHARS) == 0) then valid: if (verify(string,VALIDCHARS) == 0) then
read(string,*,iostat=readStatus) IO_stringAsInt read(string,*,iostat=readStatus) IO_stringAsInt
if (readStatus /= 0) call IO_error(111,ext_msg=string) if (readStatus /= 0) call IO_error(111,ext_msg=string)
@ -313,6 +328,7 @@ real(pReal) function IO_stringAsFloat(string)
integer :: readStatus integer :: readStatus
character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- ' character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- '
valid: if (verify(string,VALIDCHARS) == 0) then valid: if (verify(string,VALIDCHARS) == 0) then
read(string,*,iostat=readStatus) IO_stringAsFloat read(string,*,iostat=readStatus) IO_stringAsFloat
if (readStatus /= 0) call IO_error(112,ext_msg=string) if (readStatus /= 0) call IO_error(112,ext_msg=string)
@ -331,6 +347,7 @@ logical function IO_stringAsBool(string)
character(len=*), intent(in) :: string !< string for conversion to int value character(len=*), intent(in) :: string !< string for conversion to int value
if (trim(adjustl(string)) == 'True' .or. trim(adjustl(string)) == 'true') then if (trim(adjustl(string)) == 'True' .or. trim(adjustl(string)) == 'true') then
IO_stringAsBool = .true. IO_stringAsBool = .true.
elseif (trim(adjustl(string)) == 'False' .or. trim(adjustl(string)) == 'false') then elseif (trim(adjustl(string)) == 'False' .or. trim(adjustl(string)) == 'false') then
@ -356,6 +373,7 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg)
character(len=:), allocatable :: msg character(len=:), allocatable :: msg
character(len=pStringLen) :: formatString character(len=pStringLen) :: formatString
select case (error_ID) select case (error_ID)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -382,6 +400,9 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg)
msg = 'invalid character for logical:' msg = 'invalid character for logical:'
case (114) case (114)
msg = 'cannot decode base64 string:' msg = 'cannot decode base64 string:'
case (115)
msg = 'found CR. Windows file endings (CRLF) are not supported.'
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! lattice error messages ! lattice error messages

View File

@ -72,7 +72,7 @@ module YAML_types
getKey => tNode_getKey_byIndex getKey => tNode_getKey_byIndex
procedure :: & procedure :: &
contains => tNode_contains contains => tNode_contains
generic :: & generic :: &
get => tNode_get_byIndex, & get => tNode_get_byIndex, &
tNode_get_byKey tNode_get_byKey
@ -157,7 +157,7 @@ module YAML_types
emptyDict emptyDict
type(tList), target, public :: & type(tList), target, public :: &
emptyList emptyList
abstract interface abstract interface
recursive function asFormattedString(self,indent) recursive function asFormattedString(self,indent)
@ -179,7 +179,7 @@ module YAML_types
public :: & public :: &
YAML_types_init, & YAML_types_init, &
output_asStrings, & !ToDo: Hack for GNU. Remove later output_asStrings, & !ToDo: Hack for GNU. Remove later
assignment(=) assignment(=)
contains contains
@ -207,11 +207,11 @@ subroutine selfTest
select type(s1) select type(s1)
class is(tScalar) class is(tScalar)
s1 = '1' s1 = '1'
if(s1%asInt() /= 1) error stop 'tScalar_asInt' if (s1%asInt() /= 1) error stop 'tScalar_asInt'
if(dNeq(s1%asFloat(),1.0_pReal)) error stop 'tScalar_asFloat' if (dNeq(s1%asFloat(),1.0_pReal)) error stop 'tScalar_asFloat'
s1 = 'true' s1 = 'true'
if(.not. s1%asBool()) error stop 'tScalar_asBool' if (.not. s1%asBool()) error stop 'tScalar_asBool'
if(s1%asString() /= 'true') error stop 'tScalar_asString' if (s1%asString() /= 'true') error stop 'tScalar_asString'
end select end select
block block
@ -232,18 +232,18 @@ subroutine selfTest
call l1%append(s1) call l1%append(s1)
call l1%append(s2) call l1%append(s2)
n => l1 n => l1
if(any(l1%asInts() /= [2,3])) error stop 'tList_asInts' if (any(l1%asInts() /= [2,3])) error stop 'tList_asInts'
if(any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) error stop 'tList_asFloats' if (any(dNeq(l1%asFloats(),[2.0_pReal,3.0_pReal]))) error stop 'tList_asFloats'
if(n%get_asInt(1) /= 2) error stop 'byIndex_asInt' if (n%get_asInt(1) /= 2) error stop 'byIndex_asInt'
if(dNeq(n%get_asFloat(2),3.0_pReal)) error stop 'byIndex_asFloat' if (dNeq(n%get_asFloat(2),3.0_pReal)) error stop 'byIndex_asFloat'
endselect endselect
allocate(tList::l2) allocate(tList::l2)
select type(l2) select type(l2)
class is(tList) class is(tList)
call l2%append(l1) call l2%append(l1)
if(any(l2%get_asInts(1) /= [2,3])) error stop 'byIndex_asInts' if (any(l2%get_asInts(1) /= [2,3])) error stop 'byIndex_asInts'
if(any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) error stop 'byIndex_asFloats' if (any(dNeq(l2%get_asFloats(1),[2.0_pReal,3.0_pReal]))) error stop 'byIndex_asFloats'
n => l2 n => l2
end select end select
deallocate(n) deallocate(n)
@ -265,10 +265,10 @@ subroutine selfTest
call l1%append(s2) call l1%append(s2)
n => l1 n => l1
if(any(l1%asBools() .neqv. [.true., .false.])) error stop 'tList_asBools' if (any(l1%asBools() .neqv. [.true., .false.])) error stop 'tList_asBools'
if(any(l1%asStrings() /= ['true ','False'])) error stop 'tList_asStrings' if (any(l1%asStrings() /= ['true ','False'])) error stop 'tList_asStrings'
if(n%get_asBool(2)) error stop 'byIndex_asBool' if (n%get_asBool(2)) error stop 'byIndex_asBool'
if(n%get_asString(1) /= 'true') error stop 'byIndex_asString' if (n%get_asString(1) /= 'true') error stop 'byIndex_asString'
end block end block
end subroutine selfTest end subroutine selfTest
@ -418,7 +418,7 @@ function tNode_get_byIndex(self,i) result(node)
integer :: j integer :: j
self_ => self%asList() self_ => self%asList()
if(i < 1 .or. i > self_%length) call IO_error(150,ext_msg='tNode_get_byIndex') if (i < 1 .or. i > self_%length) call IO_error(150,ext_msg='tNode_get_byIndex')
j = 1 j = 1
item => self_%first item => self_%first
@ -599,7 +599,7 @@ function tNode_getKey_byIndex(self,i) result(key)
dict => self%asDict() dict => self%asDict()
item => dict%first item => dict%first
do j = 1, dict%length do j = 1, dict%length
if(j == i) then if (j == i) then
key = item%key key = item%key
exit exit
else else
@ -613,7 +613,7 @@ end function tNode_getKey_byIndex
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
!> @brief Checks if a given key/item is present in the dict/list !> @brief Checks if a given key/item is present in the dict/list
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
function tNode_contains(self,k) result(exists) function tNode_contains(self,k) result(exists)
class(tNode), intent(in), target :: self class(tNode), intent(in), target :: self
character(len=*), intent(in) :: k character(len=*), intent(in) :: k
@ -624,18 +624,18 @@ function tNode_contains(self,k) result(exists)
type(tDict), pointer :: dict type(tDict), pointer :: dict
exists = .false. exists = .false.
if(self%isDict()) then if (self%isDict()) then
dict => self%asDict() dict => self%asDict()
do j=1, dict%length do j=1, dict%length
if(dict%getKey(j) == k) then if (dict%getKey(j) == k) then
exists = .true. exists = .true.
return return
endif endif
enddo enddo
elseif(self%isList()) then elseif (self%isList()) then
list => self%asList() list => self%asList()
do j =1, list%length do j=1, list%length
if(list%get_asString(j) == k) then if (list%get_asString(j) == k) then
exists = .true. exists = .true.
return return
endif endif
@ -663,8 +663,8 @@ function tNode_get_byKey(self,k,defaultVal) result(node)
logical :: found logical :: found
found = present(defaultVal) found = present(defaultVal)
if(found) node => defaultVal if (found) node => defaultVal
self_ => self%asDict() self_ => self%asDict()
j = 1 j = 1
@ -677,11 +677,11 @@ function tNode_get_byKey(self,k,defaultVal) result(node)
item => item%next item => item%next
j = j + 1 j = j + 1
enddo enddo
if (.not. found) then if (.not. found) then
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
else else
if(associated(item)) node => item%node if (associated(item)) node => item%node
endif endif
end function tNode_get_byKey end function tNode_get_byKey
@ -700,11 +700,11 @@ function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsFloat = scalar%asFloat() nodeAsFloat = scalar%asFloat()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsFloat = defaultVal nodeAsFloat = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -726,11 +726,11 @@ function tNode_get_byKey_asInt(self,k,defaultVal) result(nodeAsInt)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsInt = scalar%asInt() nodeAsInt = scalar%asInt()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsInt = defaultVal nodeAsInt = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -752,11 +752,11 @@ function tNode_get_byKey_asBool(self,k,defaultVal) result(nodeAsBool)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsBool = scalar%asBool() nodeAsBool = scalar%asBool()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsBool = defaultVal nodeAsBool = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -778,11 +778,11 @@ function tNode_get_byKey_asString(self,k,defaultVal) result(nodeAsString)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tScalar), pointer :: scalar type(tScalar), pointer :: scalar
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
scalar => node%asScalar() scalar => node%asScalar()
nodeAsString = scalar%asString() nodeAsString = scalar%asString()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsString = defaultVal nodeAsString = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -806,18 +806,18 @@ function tNode_get_byKey_asFloats(self,k,defaultVal,requiredSize) result(nodeAsF
class(tNode), pointer :: node class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
list => node%asList() list => node%asList()
nodeAsFloats = list%asFloats() nodeAsFloats = list%asFloats()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsFloats = defaultVal nodeAsFloats = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
endif endif
if(present(requiredSize)) then if (present(requiredSize)) then
if(requiredSize /= size(nodeAsFloats)) call IO_error(146,ext_msg=k) if (requiredSize /= size(nodeAsFloats)) call IO_error(146,ext_msg=k)
endif endif
end function tNode_get_byKey_asFloats end function tNode_get_byKey_asFloats
@ -837,18 +837,18 @@ function tNode_get_byKey_asInts(self,k,defaultVal,requiredSize) result(nodeAsInt
class(tNode), pointer :: node class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
list => node%asList() list => node%asList()
nodeAsInts = list%asInts() nodeAsInts = list%asInts()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsInts = defaultVal nodeAsInts = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
endif endif
if(present(requiredSize)) then if (present(requiredSize)) then
if(requiredSize /= size(nodeAsInts)) call IO_error(146,ext_msg=k) if (requiredSize /= size(nodeAsInts)) call IO_error(146,ext_msg=k)
endif endif
end function tNode_get_byKey_asInts end function tNode_get_byKey_asInts
@ -867,11 +867,11 @@ function tNode_get_byKey_asBools(self,k,defaultVal) result(nodeAsBools)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
list => node%asList() list => node%asList()
nodeAsBools = list%asBools() nodeAsBools = list%asBools()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsBools = defaultVal nodeAsBools = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -893,11 +893,11 @@ function tNode_get_byKey_asStrings(self,k,defaultVal) result(nodeAsStrings)
class(tNode), pointer :: node class(tNode), pointer :: node
type(tList), pointer :: list type(tList), pointer :: list
if(self%contains(k)) then if (self%contains(k)) then
node => self%get(k) node => self%get(k)
list => node%asList() list => node%asList()
nodeAsStrings = list%asStrings() nodeAsStrings = list%asStrings()
elseif(present(defaultVal)) then elseif (present(defaultVal)) then
nodeAsStrings = defaultVal nodeAsStrings = defaultVal
else else
call IO_error(143,ext_msg=k) call IO_error(143,ext_msg=k)
@ -925,7 +925,7 @@ function output_asStrings(self) result(output) !ToDo: SR: Rem
end function output_asStrings end function output_asStrings
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Returns the index of a key in a dictionary !> @brief Returns the index of a key in a dictionary
@ -944,7 +944,7 @@ function tNode_get_byKey_asIndex(self,key) result(keyIndex)
item => dict%first item => dict%first
keyIndex = -1 keyIndex = -1
do i = 1, dict%length do i = 1, dict%length
if(key == item%key) then if (key == item%key) then
keyIndex = i keyIndex = i
exit exit
else else
@ -952,9 +952,9 @@ function tNode_get_byKey_asIndex(self,key) result(keyIndex)
endif endif
enddo enddo
if(keyIndex == -1) call IO_error(140,ext_msg=key) if (keyIndex == -1) call IO_error(140,ext_msg=key)
end function tNode_get_byKey_asIndex end function tNode_get_byKey_asIndex
@ -985,7 +985,7 @@ recursive function tList_asFormattedString(self,indent) result(str)
integer :: i, indent_ integer :: i, indent_
str = '' str = ''
if(present(indent)) then if (present(indent)) then
indent_ = indent indent_ = indent
else else
indent_ = 0 indent_ = 0
@ -993,7 +993,7 @@ recursive function tList_asFormattedString(self,indent) result(str)
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length
if(i /= 1) str = str//repeat(' ',indent_) if (i /= 1) str = str//repeat(' ',indent_)
str = str//'- '//item%node%asFormattedString(indent_+2) str = str//'- '//item%node%asFormattedString(indent_+2)
item => item%next item => item%next
end do end do
@ -1014,7 +1014,7 @@ recursive function tDict_asFormattedString(self,indent) result(str)
integer :: i, indent_ integer :: i, indent_
str = '' str = ''
if(present(indent)) then if (present(indent)) then
indent_ = indent indent_ = indent
else else
indent_ = 0 indent_ = 0
@ -1022,7 +1022,7 @@ recursive function tDict_asFormattedString(self,indent) result(str)
item => self%first item => self%first
do i = 1, self%length do i = 1, self%length
if(i /= 1) str = str//repeat(' ',indent_) if (i /= 1) str = str//repeat(' ',indent_)
select type(node_1 =>item%node) select type(node_1 =>item%node)
class is(tScalar) class is(tScalar)
str = str//trim(item%key)//': '//item%node%asFormattedString(indent_+len_trim(item%key)+2) str = str//trim(item%key)//': '//item%node%asFormattedString(indent_+len_trim(item%key)+2)
@ -1270,7 +1270,7 @@ recursive subroutine tItem_finalize(self)
type(tItem),intent(inout) :: self type(tItem),intent(inout) :: self
deallocate(self%node) deallocate(self%node)
if(associated(self%next)) deallocate(self%next) if (associated(self%next)) deallocate(self%next)
end subroutine tItem_finalize end subroutine tItem_finalize

View File

@ -7,7 +7,6 @@
#include "IO.f90" #include "IO.f90"
#include "YAML_types.f90" #include "YAML_types.f90"
#include "YAML_parse.f90" #include "YAML_parse.f90"
#include "future.f90"
#include "config.f90" #include "config.f90"
#include "LAPACK_interface.f90" #include "LAPACK_interface.f90"
#include "math.f90" #include "math.f90"
@ -17,38 +16,36 @@
#include "results.f90" #include "results.f90"
#include "geometry_plastic_nonlocal.f90" #include "geometry_plastic_nonlocal.f90"
#include "discretization.f90" #include "discretization.f90"
#ifdef Marc4DAMASK
#include "marc/discretization_marc.f90" #include "marc/discretization_marc.f90"
#endif
#include "material.f90" #include "material.f90"
#include "lattice.f90" #include "lattice.f90"
#include "constitutive.f90" #include "phase.f90"
#include "constitutive_mech.f90" #include "phase_mechanical.f90"
#include "constitutive_plastic_none.f90" #include "phase_mechanical_plastic.f90"
#include "constitutive_plastic_isotropic.f90" #include "phase_mechanical_plastic_none.f90"
#include "constitutive_plastic_phenopowerlaw.f90" #include "phase_mechanical_plastic_isotropic.f90"
#include "constitutive_plastic_kinehardening.f90" #include "phase_mechanical_plastic_phenopowerlaw.f90"
#include "constitutive_plastic_dislotwin.f90" #include "phase_mechanical_plastic_kinehardening.f90"
#include "constitutive_plastic_disloTungsten.f90" #include "phase_mechanical_plastic_dislotwin.f90"
#include "constitutive_plastic_nonlocal.f90" #include "phase_mechanical_plastic_dislotungsten.f90"
#include "constitutive_thermal.f90" #include "phase_mechanical_plastic_nonlocal.f90"
#include "source_thermal_dissipation.f90" #include "phase_mechanical_eigen.f90"
#include "source_thermal_externalheat.f90" #include "phase_mechanical_eigen_cleavageopening.f90"
#include "kinematics_thermal_expansion.f90" #include "phase_mechanical_eigen_slipplaneopening.f90"
#include "constitutive_damage.f90" #include "phase_mechanical_eigen_thermalexpansion.f90"
#include "source_damage_isoBrittle.f90" #include "phase_thermal.f90"
#include "source_damage_isoDuctile.f90" #include "phase_thermal_dissipation.f90"
#include "source_damage_anisoBrittle.f90" #include "phase_thermal_externalheat.f90"
#include "source_damage_anisoDuctile.f90" #include "phase_damage.f90"
#include "kinematics_cleavage_opening.f90" #include "phase_damage_isobrittle.f90"
#include "kinematics_slipplane_opening.f90" #include "phase_damage_isoductile.f90"
#include "thermal_isothermal.f90" #include "phase_damage_anisobrittle.f90"
#include "thermal_conduction.f90" #include "phase_damage_anisoductile.f90"
#include "damage_none.f90"
#include "damage_nonlocal.f90"
#include "homogenization.f90" #include "homogenization.f90"
#include "homogenization_mech.f90" #include "homogenization_mechanical.f90"
#include "homogenization_mech_none.f90" #include "homogenization_mechanical_pass.f90"
#include "homogenization_mech_isostrain.f90" #include "homogenization_mechanical_isostrain.f90"
#include "homogenization_mech_RGC.f90" #include "homogenization_mechanical_RGC.f90"
#include "homogenization_thermal.f90"
#include "homogenization_damage.f90"
#include "CPFEM.f90" #include "CPFEM.f90"

View File

@ -5,16 +5,10 @@
!! precedence over material.yaml. !! precedence over material.yaml.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module config module config
use prec
use DAMASK_interface
use IO use IO
use YAML_parse use YAML_parse
use YAML_types use YAML_types
#ifdef PETSc
#include <petsc/finclude/petscsys.h>
use petscsys
#endif
implicit none implicit none
private private
@ -50,17 +44,12 @@ end subroutine config_init
subroutine parse_material subroutine parse_material
logical :: fileExists logical :: fileExists
character(len=:), allocatable :: fname
fname = getSolverJobName()//'.yaml'
inquire(file=fname,exist=fileExists) inquire(file='material.yaml',exist=fileExists)
if(.not. fileExists) then if(.not. fileExists) call IO_error(100,ext_msg='material.yaml')
fname = 'material.yaml' print*, 'reading material.yaml'; flush(IO_STDOUT)
inquire(file=fname,exist=fileExists) config_material => YAML_parse_file('material.yaml')
if(.not. fileExists) call IO_error(100,ext_msg=fname)
endif
print*, 'reading '//fname; flush(IO_STDOUT)
config_material => YAML_parse_file(fname)
end subroutine parse_material end subroutine parse_material
@ -72,6 +61,7 @@ subroutine parse_numerics
logical :: fexist logical :: fexist
config_numerics => emptyDict config_numerics => emptyDict
inquire(file='numerics.yaml', exist=fexist) inquire(file='numerics.yaml', exist=fexist)
if (fexist) then if (fexist) then
@ -89,6 +79,7 @@ subroutine parse_debug
logical :: fexist logical :: fexist
config_debug => emptyDict config_debug => emptyDict
inquire(file='debug.yaml', exist=fexist) inquire(file='debug.yaml', exist=fexist)
fileExists: if (fexist) then fileExists: if (fexist) then

File diff suppressed because it is too large Load Diff

View File

@ -1,253 +0,0 @@
!----------------------------------------------------------------------------------------------------
!> @brief internal microstructure state for all damage sources and kinematics constitutive models
!----------------------------------------------------------------------------------------------------
submodule(constitutive) constitutive_damage
interface
module function source_damage_anisoBrittle_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_damage_anisoBrittle_init
module function source_damage_anisoDuctile_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_damage_anisoDuctile_init
module function source_damage_isoBrittle_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_damage_isoBrittle_init
module function source_damage_isoDuctile_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_damage_isoDuctile_init
module function kinematics_cleavage_opening_init(kinematics_length) result(myKinematics)
integer, intent(in) :: kinematics_length
logical, dimension(:,:), allocatable :: myKinematics
end function kinematics_cleavage_opening_init
module function kinematics_slipplane_opening_init(kinematics_length) result(myKinematics)
integer, intent(in) :: kinematics_length
logical, dimension(:,:), allocatable :: myKinematics
end function kinematics_slipplane_opening_init
module subroutine source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
integer, intent(in) :: &
phase, & !< phase ID of element
constituent !< position of element within its phase instance
real(pReal), intent(in) :: &
phi !< damage parameter
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
end subroutine source_damage_anisoBrittle_getRateAndItsTangent
module subroutine source_damage_anisoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
integer, intent(in) :: &
phase, & !< phase ID of element
constituent !< position of element within its phase instance
real(pReal), intent(in) :: &
phi !< damage parameter
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
end subroutine source_damage_anisoDuctile_getRateAndItsTangent
module subroutine source_damage_isoBrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
integer, intent(in) :: &
phase, & !< phase ID of element
constituent !< position of element within its phase instance
real(pReal), intent(in) :: &
phi !< damage parameter
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
end subroutine source_damage_isoBrittle_getRateAndItsTangent
module subroutine source_damage_isoDuctile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
integer, intent(in) :: &
phase, & !< phase ID of element
constituent !< position of element within its phase instance
real(pReal), intent(in) :: &
phi !< damage parameter
real(pReal), intent(out) :: &
localphiDot, &
dLocalphiDot_dPhi
end subroutine source_damage_isoDuctile_getRateAndItsTangent
module subroutine source_damage_anisoBrittle_results(phase,group)
integer, intent(in) :: phase
character(len=*), intent(in) :: group
end subroutine source_damage_anisoBrittle_results
module subroutine source_damage_anisoDuctile_results(phase,group)
integer, intent(in) :: phase
character(len=*), intent(in) :: group
end subroutine source_damage_anisoDuctile_results
module subroutine source_damage_isoBrittle_results(phase,group)
integer, intent(in) :: phase
character(len=*), intent(in) :: group
end subroutine source_damage_isoBrittle_results
module subroutine source_damage_isoDuctile_results(phase,group)
integer, intent(in) :: phase
character(len=*), intent(in) :: group
end subroutine source_damage_isoDuctile_results
end interface
contains
!----------------------------------------------------------------------------------------------
!< @brief initialize damage sources and kinematics mechanism
!----------------------------------------------------------------------------------------------
module subroutine damage_init
integer :: &
ph !< counter in phase loop
class(tNode), pointer :: &
phases, &
phase, &
sources, &
kinematics
phases => config_material%get('phase')
allocate(sourceState (phases%length))
allocate(phase_Nsources(phases%length),source = 0) ! same for kinematics
do ph = 1,phases%length
phase => phases%get(ph)
sources => phase%get('source',defaultVal=emptyList)
phase_Nsources(ph) = sources%length
allocate(sourceState(ph)%p(phase_Nsources(ph)))
enddo
allocate(phase_source(maxval(phase_Nsources),phases%length), source = SOURCE_undefined_ID)
! initialize source mechanisms
if(maxval(phase_Nsources) /= 0) then
where(source_damage_isoBrittle_init (maxval(phase_Nsources))) phase_source = SOURCE_damage_isoBrittle_ID
where(source_damage_isoDuctile_init (maxval(phase_Nsources))) phase_source = SOURCE_damage_isoDuctile_ID
where(source_damage_anisoBrittle_init (maxval(phase_Nsources))) phase_source = SOURCE_damage_anisoBrittle_ID
where(source_damage_anisoDuctile_init (maxval(phase_Nsources))) phase_source = SOURCE_damage_anisoDuctile_ID
endif
!--------------------------------------------------------------------------------------------------
! initialize kinematic mechanisms
allocate(phase_Nkinematics(phases%length),source = 0)
do ph = 1,phases%length
phase => phases%get(ph)
kinematics => phase%get('kinematics',defaultVal=emptyList)
phase_Nkinematics(ph) = kinematics%length
enddo
allocate(phase_kinematics(maxval(phase_Nkinematics),phases%length), source = KINEMATICS_undefined_ID)
if(maxval(phase_Nkinematics) /= 0) then
where(kinematics_cleavage_opening_init(maxval(phase_Nkinematics))) phase_kinematics = KINEMATICS_cleavage_opening_ID
where(kinematics_slipplane_opening_init(maxval(phase_Nkinematics))) phase_kinematics = KINEMATICS_slipplane_opening_ID
endif
end subroutine damage_init
!----------------------------------------------------------------------------------------------
!< @brief returns local part of nonlocal damage driving force
!----------------------------------------------------------------------------------------------
module subroutine constitutive_damage_getRateAndItsTangents(phiDot, dPhiDot_dPhi, phi, ip, el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi !< damage parameter
real(pReal), intent(inout) :: &
phiDot, &
dPhiDot_dPhi
real(pReal) :: &
localphiDot, &
dLocalphiDot_dPhi
integer :: &
phase, &
grain, &
source, &
constituent
phiDot = 0.0_pReal
dPhiDot_dPhi = 0.0_pReal
do grain = 1, homogenization_Nconstituents(material_homogenizationAt(el))
phase = material_phaseAt(grain,el)
constituent = material_phasememberAt(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, phase, constituent)
case (SOURCE_damage_isoDuctile_ID)
call source_damage_isoductile_getRateAndItsTangent (localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
case (SOURCE_damage_anisoBrittle_ID)
call source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
case (SOURCE_damage_anisoDuctile_ID)
call source_damage_anisoductile_getRateAndItsTangent(localphiDot, dLocalphiDot_dPhi, phi, phase, constituent)
case default
localphiDot = 0.0_pReal
dLocalphiDot_dPhi = 0.0_pReal
end select
phiDot = phiDot + localphiDot
dPhiDot_dPhi = dPhiDot_dPhi + dLocalphiDot_dPhi
enddo
enddo
end subroutine constitutive_damage_getRateAndItsTangents
!----------------------------------------------------------------------------------------------
!< @brief writes damage sources results to HDF5 output file
!----------------------------------------------------------------------------------------------
module subroutine damage_results(group,ph)
character(len=*), intent(in) :: group
integer, intent(in) :: ph
integer :: so
sourceLoop: do so = 1, phase_Nsources(ph)
if (phase_source(so,ph) /= SOURCE_UNDEFINED_ID) &
call results_closeGroup(results_addGroup(group//'sources/')) ! should be 'damage'
sourceType: select case (phase_source(so,ph))
case (SOURCE_damage_anisoBrittle_ID) sourceType
call source_damage_anisoBrittle_results(ph,group//'sources/')
case (SOURCE_damage_anisoDuctile_ID) sourceType
call source_damage_anisoDuctile_results(ph,group//'sources/')
case (SOURCE_damage_isoBrittle_ID) sourceType
call source_damage_isoBrittle_results(ph,group//'sources/')
case (SOURCE_damage_isoDuctile_ID) sourceType
call source_damage_isoDuctile_results(ph,group//'sources/')
end select sourceType
enddo SourceLoop
end subroutine damage_results
end submodule constitutive_damage

View File

@ -1,125 +0,0 @@
!----------------------------------------------------------------------------------------------------
!> @brief internal microstructure state for all thermal sources and kinematics constitutive models
!----------------------------------------------------------------------------------------------------
submodule(constitutive) constitutive_thermal
interface
module function source_thermal_dissipation_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_thermal_dissipation_init
module function source_thermal_externalheat_init(source_length) result(mySources)
integer, intent(in) :: source_length
logical, dimension(:,:), allocatable :: mySources
end function source_thermal_externalheat_init
module function kinematics_thermal_expansion_init(kinematics_length) result(myKinematics)
integer, intent(in) :: kinematics_length
logical, dimension(:,:), allocatable :: myKinematics
end function kinematics_thermal_expansion_init
module subroutine source_thermal_dissipation_getRateAndItsTangent(TDot, dTDot_dT, Tstar, Lp, phase)
integer, intent(in) :: &
phase !< phase ID of element
real(pReal), intent(in), dimension(3,3) :: &
Tstar !< 2nd Piola Kirchhoff stress tensor for a given element
real(pReal), intent(in), dimension(3,3) :: &
Lp !< plastic velocuty gradient for a given element
real(pReal), intent(out) :: &
TDot, &
dTDot_dT
end subroutine source_thermal_dissipation_getRateAndItsTangent
module subroutine source_thermal_externalheat_getRateAndItsTangent(TDot, dTDot_dT, phase, of)
integer, intent(in) :: &
phase, &
of
real(pReal), intent(out) :: &
TDot, &
dTDot_dT
end subroutine source_thermal_externalheat_getRateAndItsTangent
end interface
contains
!----------------------------------------------------------------------------------------------
!< @brief initializes thermal sources and kinematics mechanism
!----------------------------------------------------------------------------------------------
module subroutine thermal_init
! initialize source mechanisms
if(maxval(phase_Nsources) /= 0) then
where(source_thermal_dissipation_init (maxval(phase_Nsources))) phase_source = SOURCE_thermal_dissipation_ID
where(source_thermal_externalheat_init(maxval(phase_Nsources))) phase_source = SOURCE_thermal_externalheat_ID
endif
!--------------------------------------------------------------------------------------------------
!initialize kinematic mechanisms
if(maxval(phase_Nkinematics) /= 0) where(kinematics_thermal_expansion_init(maxval(phase_Nkinematics))) &
phase_kinematics = KINEMATICS_thermal_expansion_ID
end subroutine thermal_init
!----------------------------------------------------------------------------------------------
!< @brief calculates thermal dissipation rate
!----------------------------------------------------------------------------------------------
module subroutine constitutive_thermal_getRateAndItsTangents(TDot, dTDot_dT, T, S, Lp, ip, el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
T
real(pReal), intent(in), dimension(:,:,:,:,:) :: &
S, & !< current 2nd Piola Kirchhoff stress
Lp !< plastic velocity gradient
real(pReal), intent(inout) :: &
TDot, &
dTDot_dT
real(pReal) :: &
my_Tdot, &
my_dTdot_dT
integer :: &
phase, &
homog, &
instance, &
grain, &
source, &
constituent
homog = material_homogenizationAt(el)
instance = thermal_typeInstance(homog)
do grain = 1, homogenization_Nconstituents(homog)
phase = material_phaseAt(grain,el)
constituent = material_phasememberAt(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, &
S(1:3,1:3,grain,ip,el), &
Lp(1:3,1:3,grain,ip,el), &
phase)
case (SOURCE_thermal_externalheat_ID)
call source_thermal_externalheat_getRateAndItsTangent(my_Tdot, my_dTdot_dT, &
phase, constituent)
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 subroutine constitutive_thermal_getRateAndItsTangents
end submodule constitutive_thermal

View File

@ -1,39 +0,0 @@
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for constant damage field
!--------------------------------------------------------------------------------------------------
module damage_none
use prec
use config
use material
implicit none
public
contains
!--------------------------------------------------------------------------------------------------
!> @brief allocates all neccessary fields, reads information from material configuration file
!--------------------------------------------------------------------------------------------------
subroutine damage_none_init
integer :: h,Nmaterialpoints
print'(/,a)', ' <<<+- damage_none init -+>>>'; flush(6)
do h = 1, size(material_name_homogenization)
if (damage_type(h) /= DAMAGE_NONE_ID) cycle
Nmaterialpoints = count(material_homogenizationAt == h)
damageState(h)%sizeState = 0
allocate(damageState(h)%state0 (0,Nmaterialpoints))
allocate(damageState(h)%subState0(0,Nmaterialpoints))
allocate(damageState(h)%state (0,Nmaterialpoints))
allocate (damage(h)%p(Nmaterialpoints), source=1.0_pReal)
enddo
end subroutine damage_none_init
end module damage_none

View File

@ -1,208 +0,0 @@
!--------------------------------------------------------------------------------------------------
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief material subroutine for non-locally evolving damage field
!--------------------------------------------------------------------------------------------------
module damage_nonlocal
use prec
use material
use config
use YAML_types
use lattice
use constitutive
use results
implicit none
private
type :: tParameters
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type, private :: tNumerics
real(pReal) :: &
charLength !< characteristic length scale for gradient problems
end type tNumerics
type(tparameters), dimension(:), allocatable :: &
param
type(tNumerics), private :: &
num
public :: &
damage_nonlocal_init, &
damage_nonlocal_getSourceAndItsTangent, &
damage_nonlocal_getDiffusion, &
damage_nonlocal_getMobility, &
damage_nonlocal_putNonLocalDamage, &
damage_nonlocal_results
contains
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_init
integer :: Ninstances,Nmaterialpoints,h
class(tNode), pointer :: &
num_generic, &
material_homogenization, &
homog, &
homogDamage
print'(/,a)', ' <<<+- damage_nonlocal init -+>>>'; flush(6)
!------------------------------------------------------------------------------------
! read numerics parameter
num_generic => config_numerics%get('generic',defaultVal= emptyDict)
num%charLength = num_generic%get_asFloat('charLength',defaultVal=1.0_pReal)
Ninstances = count(damage_type == DAMAGE_nonlocal_ID)
allocate(param(Ninstances))
material_homogenization => config_material%get('homogenization')
do h = 1, material_homogenization%length
if (damage_type(h) /= DAMAGE_NONLOCAL_ID) cycle
homog => material_homogenization%get(h)
homogDamage => homog%get('damage')
associate(prm => param(damage_typeInstance(h)))
#if defined (__GFORTRAN__)
prm%output = output_asStrings(homogDamage)
#else
prm%output = homogDamage%get_asStrings('output',defaultVal=emptyStringArray)
#endif
Nmaterialpoints = count(material_homogenizationAt == h)
damageState(h)%sizeState = 1
allocate(damageState(h)%state0 (1,Nmaterialpoints), source=1.0_pReal)
allocate(damageState(h)%subState0(1,Nmaterialpoints), source=1.0_pReal)
allocate(damageState(h)%state (1,Nmaterialpoints), source=1.0_pReal)
damage(h)%p => damageState(h)%state(1,:)
end associate
enddo
end subroutine damage_nonlocal_init
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized damage driving forces
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ip, el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
real(pReal) :: &
phiDot, dPhiDot_dPhi
phiDot = 0.0_pReal
dPhiDot_dPhi = 0.0_pReal
call constitutive_damage_getRateAndItsTangents(phiDot, dPhiDot_dPhi, phi, ip, el)
phiDot = phiDot/real(homogenization_Nconstituents(material_homogenizationAt(el)),pReal)
dPhiDot_dPhi = dPhiDot_dPhi/real(homogenization_Nconstituents(material_homogenizationAt(el)),pReal)
end subroutine damage_nonlocal_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized non local damage diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function damage_nonlocal_getDiffusion(ip,el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), dimension(3,3) :: &
damage_nonlocal_getDiffusion
integer :: &
homog, &
grain
homog = material_homogenizationAt(el)
damage_nonlocal_getDiffusion = 0.0_pReal
do grain = 1, homogenization_Nconstituents(homog)
damage_nonlocal_getDiffusion = damage_nonlocal_getDiffusion + &
crystallite_push33ToRef(grain,ip,el,lattice_D(1:3,1:3,material_phaseAt(grain,el)))
enddo
damage_nonlocal_getDiffusion = &
num%charLength**2*damage_nonlocal_getDiffusion/real(homogenization_Nconstituents(homog),pReal)
end function damage_nonlocal_getDiffusion
!--------------------------------------------------------------------------------------------------
!> @brief Returns homogenized nonlocal damage mobility
!--------------------------------------------------------------------------------------------------
real(pReal) function damage_nonlocal_getMobility(ip,el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
integer :: &
co
damage_nonlocal_getMobility = 0.0_pReal
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el))
damage_nonlocal_getMobility = damage_nonlocal_getMobility + lattice_M(material_phaseAt(co,el))
enddo
damage_nonlocal_getMobility = damage_nonlocal_getMobility/&
real(homogenization_Nconstituents(material_homogenizationAt(el)),pReal)
end function damage_nonlocal_getMobility
!--------------------------------------------------------------------------------------------------
!> @brief updated nonlocal damage field with solution from damage phase field PDE
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_putNonLocalDamage(phi,ip,el)
integer, intent(in) :: &
ip, & !< integration point number
el !< element number
real(pReal), intent(in) :: &
phi
integer :: &
homog, &
offset
homog = material_homogenizationAt(el)
offset = material_homogenizationMemberAt(ip,el)
damage(homog)%p(offset) = phi
end subroutine damage_nonlocal_putNonLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_results(homog,group)
integer, intent(in) :: homog
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(damage_typeInstance(homog)))
outputsLoop: do o = 1,size(prm%output)
select case(prm%output(o))
case ('phi')
call results_writeDataset(group,damage(homog)%p,prm%output(o),&
'damage indicator','-')
end select
enddo outputsLoop
end associate
end subroutine damage_nonlocal_results
end module damage_nonlocal

View File

@ -686,7 +686,7 @@ module element
1, 5,11, 7, 8,12,15,14, & 1, 5,11, 7, 8,12,15,14, &
5, 2, 6,11,12, 9,13,15, & 5, 2, 6,11,12, 9,13,15, &
7,11, 6, 3,14,15,13,10, & 7,11, 6, 3,14,15,13,10, &
8,12,15, 4, 4, 9,13,10 & 8,12,15,14, 4, 9,13,10 &
#if !defined(__GFORTRAN__) #if !defined(__GFORTRAN__)
],shape(CELL6)) ],shape(CELL6))
#else #else

View File

@ -1,35 +0,0 @@
!--------------------------------------------------------------------------------------------------
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
!> @brief New fortran functions for compiler versions that do not support them
!--------------------------------------------------------------------------------------------------
module future
use prec
implicit none
public
contains
#if defined(__GFORTRAN__) && __GNUC__<9 || defined(__INTEL_COMPILER) && INTEL_COMPILER<1800
!--------------------------------------------------------------------------------------------------
!> @brief substitute for the findloc intrinsic (only for integer, dimension(:) at the moment)
!--------------------------------------------------------------------------------------------------
function findloc(a,v)
integer, intent(in), dimension(:) :: a
integer, intent(in) :: v
integer :: i,j
integer, allocatable, dimension(:) :: findloc
allocate(findloc(count(a==v)))
j = 1
do i = 1, size(a)
if (a(i)==v) then
findloc(j) = i
j = j + 1
endif
enddo
end function findloc
#endif
end module future

View File

@ -18,9 +18,9 @@ program DAMASK_grid
use CPFEM2 use CPFEM2
use material use material
use spectral_utilities use spectral_utilities
use grid_mech_spectral_basic use grid_mechanical_spectral_basic
use grid_mech_spectral_polarisation use grid_mechanical_spectral_polarisation
use grid_mech_FEM use grid_mechanical_FEM
use grid_damage_spectral use grid_damage_spectral
use grid_thermal_spectral use grid_thermal_spectral
use results use results
@ -36,10 +36,11 @@ program DAMASK_grid
integer :: N, & !< number of increments integer :: N, & !< number of increments
f_out, & !< frequency of result writes f_out, & !< frequency of result writes
f_restart !< frequency of restart writes f_restart !< frequency of restart writes
logical :: drop_guessing !< do not follow trajectory of former loadcase logical :: estimate_rate !< follow trajectory of former loadcase
integer(kind(FIELD_UNDEFINED_ID)), allocatable :: ID(:)
end type tLoadCase end type tLoadCase
integer(kind(FIELD_UNDEFINED_ID)), allocatable :: ID(:)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! variables related to information from load case and geom file ! variables related to information from load case and geom file
real(pReal), dimension(9) :: temp_valueVector !< temporarily from loadcase file when reading in tensors (initialize to 0.0) real(pReal), dimension(9) :: temp_valueVector !< temporarily from loadcase file when reading in tensors (initialize to 0.0)
@ -53,6 +54,7 @@ program DAMASK_grid
integer, parameter :: & integer, parameter :: &
subStepFactor = 2 !< for each substep, divide the last time increment by 2.0 subStepFactor = 2 !< for each substep, divide the last time increment by 2.0
real(pReal) :: & real(pReal) :: &
T_0 = 300.0_pReal, &
time = 0.0_pReal, & !< elapsed time time = 0.0_pReal, & !< elapsed time
time0 = 0.0_pReal, & !< begin of interval time0 = 0.0_pReal, & !< begin of interval
timeinc = 1.0_pReal, & !< current time interval timeinc = 1.0_pReal, & !< current time interval
@ -61,10 +63,12 @@ program DAMASK_grid
logical :: & logical :: &
guess, & !< guess along former trajectory guess, & !< guess along former trajectory
stagIterate, & stagIterate, &
cutBack = .false. cutBack = .false.,&
signal
integer :: & integer :: &
i, j, m, field, & i, j, m, field, &
errorID = 0, & errorID = 0, &
ierr,&
cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$ cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$
stepFraction = 0, & !< fraction of current time interval stepFraction = 0, & !< fraction of current time interval
l = 0, & !< current load case l = 0, & !< current load case
@ -76,30 +80,33 @@ program DAMASK_grid
maxCutBack, & !< max number of cut backs maxCutBack, & !< max number of cut backs
stagItMax !< max number of field level staggered iterations stagItMax !< max number of field level staggered iterations
character(len=pStringLen) :: & character(len=pStringLen) :: &
incInfo, & incInfo
loadcase_string
type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases
type(tSolutionState), allocatable, dimension(:) :: solres type(tSolutionState), allocatable, dimension(:) :: solres
procedure(grid_mech_spectral_basic_init), pointer :: & procedure(grid_mechanical_spectral_basic_init), pointer :: &
mech_init mechanical_init
procedure(grid_mech_spectral_basic_forward), pointer :: & procedure(grid_mechanical_spectral_basic_forward), pointer :: &
mech_forward mechanical_forward
procedure(grid_mech_spectral_basic_solution), pointer :: & procedure(grid_mechanical_spectral_basic_solution), pointer :: &
mech_solution mechanical_solution
procedure(grid_mech_spectral_basic_updateCoords), pointer :: & procedure(grid_mechanical_spectral_basic_updateCoords), pointer :: &
mech_updateCoords mechanical_updateCoords
procedure(grid_mech_spectral_basic_restartWrite), pointer :: & procedure(grid_mechanical_spectral_basic_restartWrite), pointer :: &
mech_restartWrite mechanical_restartWrite
external :: & external :: &
quit quit
class (tNode), pointer :: & class (tNode), pointer :: &
num_grid, & num_grid, &
debug_grid, & ! pointer to grid debug options
config_load, & config_load, &
load_steps, & load_steps, &
load_step, & load_step, &
solver, &
initial_conditions, &
ic_thermal, &
thermal, &
step_bc, &
step_mech, & step_mech, &
step_discretization, & step_discretization, &
step_deformation, & step_deformation, &
@ -109,17 +116,11 @@ program DAMASK_grid
! init DAMASK (all modules) ! init DAMASK (all modules)
call CPFEM_initAll call CPFEM_initAll
print'(/,a)', ' <<<+- DAMASK_spectral init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- DAMASK_grid init -+>>>'; flush(IO_STDOUT)
print*, 'Shanthraj et al., Handbook of Mechanics of Materials, 2019' print*, 'Shanthraj et al., Handbook of Mechanics of Materials, 2019'
print*, 'https://doi.org/10.1007/978-981-10-6855-3_80' print*, 'https://doi.org/10.1007/978-981-10-6855-3_80'
!--------------------------------------------------------------------------------------------------
! initialize field solver information
nActiveFields = 1
if (any(thermal_type == THERMAL_conduction_ID )) nActiveFields = nActiveFields + 1
if (any(damage_type == DAMAGE_nonlocal_ID )) nActiveFields = nActiveFields + 1
allocate(solres(nActiveFields))
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
! reading field paramters from numerics file and do sanity checks ! reading field paramters from numerics file and do sanity checks
@ -130,62 +131,69 @@ program DAMASK_grid
if (stagItMax < 0) call IO_error(301,ext_msg='maxStaggeredIter') if (stagItMax < 0) call IO_error(301,ext_msg='maxStaggeredIter')
if (maxCutBack < 0) call IO_error(301,ext_msg='maxCutBack') if (maxCutBack < 0) call IO_error(301,ext_msg='maxCutBack')
config_load => YAML_parse_file(trim(interface_loadFile))
solver => config_load%get('solver')
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! assign mechanics solver depending on selected type ! assign mechanics solver depending on selected type
debug_grid => config_debug%get('grid',defaultVal=emptyList) nActiveFields = 1
select case (trim(num_grid%get_asString('solver', defaultVal = 'Basic'))) select case (solver%get_asString('mechanical'))
case ('Basic') case ('spectral_basic')
mech_init => grid_mech_spectral_basic_init mechanical_init => grid_mechanical_spectral_basic_init
mech_forward => grid_mech_spectral_basic_forward mechanical_forward => grid_mechanical_spectral_basic_forward
mech_solution => grid_mech_spectral_basic_solution mechanical_solution => grid_mechanical_spectral_basic_solution
mech_updateCoords => grid_mech_spectral_basic_updateCoords mechanical_updateCoords => grid_mechanical_spectral_basic_updateCoords
mech_restartWrite => grid_mech_spectral_basic_restartWrite mechanical_restartWrite => grid_mechanical_spectral_basic_restartWrite
case ('Polarisation') case ('spectral_polarization')
mech_init => grid_mech_spectral_polarisation_init mechanical_init => grid_mechanical_spectral_polarisation_init
mech_forward => grid_mech_spectral_polarisation_forward mechanical_forward => grid_mechanical_spectral_polarisation_forward
mech_solution => grid_mech_spectral_polarisation_solution mechanical_solution => grid_mechanical_spectral_polarisation_solution
mech_updateCoords => grid_mech_spectral_polarisation_updateCoords mechanical_updateCoords => grid_mechanical_spectral_polarisation_updateCoords
mech_restartWrite => grid_mech_spectral_polarisation_restartWrite mechanical_restartWrite => grid_mechanical_spectral_polarisation_restartWrite
case ('FEM') case ('FEM')
mech_init => grid_mech_FEM_init mechanical_init => grid_mechanical_FEM_init
mech_forward => grid_mech_FEM_forward mechanical_forward => grid_mechanical_FEM_forward
mech_solution => grid_mech_FEM_solution mechanical_solution => grid_mechanical_FEM_solution
mech_updateCoords => grid_mech_FEM_updateCoords mechanical_updateCoords => grid_mechanical_FEM_updateCoords
mech_restartWrite => grid_mech_FEM_restartWrite mechanical_restartWrite => grid_mechanical_FEM_restartWrite
case default case default
call IO_error(error_ID = 891, ext_msg = trim(num_grid%get_asString('solver'))) call IO_error(error_ID = 891, ext_msg = trim(solver%get_asString('mechanical')))
end select end select
!--------------------------------------------------------------------------------------------------
! initialize field solver information
if (solver%get_asString('thermal',defaultVal = 'n/a') == 'spectral') nActiveFields = nActiveFields + 1
if (solver%get_asString('damage', defaultVal = 'n/a') == 'spectral') nActiveFields = nActiveFields + 1
allocate(solres(nActiveFields))
allocate( ID(nActiveFields))
field = 1
ID(field) = FIELD_MECH_ID ! mechanical active by default
thermalActive: if (solver%get_asString('thermal',defaultVal = 'n/a') == 'spectral') then
field = field + 1
ID(field) = FIELD_THERMAL_ID
endif thermalActive
damageActive: if (solver%get_asString('damage',defaultVal = 'n/a') == 'spectral') then
field = field + 1
ID(field) = FIELD_DAMAGE_ID
endif damageActive
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! reading information from load case file and to sanity checks load_steps => config_load%get('loadstep')
config_load => YAML_parse_file(trim(interface_loadFile))
load_steps => config_load%get('step')
allocate(loadCases(load_steps%length)) ! array of load cases allocate(loadCases(load_steps%length)) ! array of load cases
do l = 1, load_steps%length do l = 1, load_steps%length
allocate(loadCases(l)%ID(nActiveFields))
field = 1
loadCases(l)%ID(field) = FIELD_MECH_ID ! mechanical active by default
thermalActive: if (any(thermal_type == THERMAL_conduction_ID)) then
field = field + 1
loadCases(l)%ID(field) = FIELD_THERMAL_ID
endif thermalActive
damageActive: if (any(damage_type == DAMAGE_nonlocal_ID)) then
field = field + 1
loadCases(l)%ID(field) = FIELD_DAMAGE_ID
endif damageActive
load_step => load_steps%get(l) load_step => load_steps%get(l)
step_bc => load_step%get('boundary_conditions')
step_mech => load_step%get('mechanics') step_mech => step_bc%get('mechanical')
loadCases(l)%stress%myType='' loadCases(l)%stress%myType=''
readMech: do m = 1, step_mech%length readMech: do m = 1, step_mech%length
select case (step_mech%getKey(m)) select case (step_mech%getKey(m))
@ -217,21 +225,19 @@ program DAMASK_grid
if (.not. allocated(loadCases(l)%deformation%myType)) call IO_error(error_ID=837,ext_msg = 'L/dot_F/F missing') if (.not. allocated(loadCases(l)%deformation%myType)) call IO_error(error_ID=837,ext_msg = 'L/dot_F/F missing')
step_discretization => load_step%get('discretization') step_discretization => load_step%get('discretization')
if(.not. step_discretization%contains('t')) call IO_error(error_ID=837,ext_msg = 't missing') if (.not. step_discretization%contains('t')) call IO_error(error_ID=837,ext_msg = 't missing')
if(.not. step_discretization%contains('N')) call IO_error(error_ID=837,ext_msg = 'N missing') if (.not. step_discretization%contains('N')) call IO_error(error_ID=837,ext_msg = 'N missing')
loadCases(l)%t = step_discretization%get_asFloat('t') loadCases(l)%t = step_discretization%get_asFloat('t')
loadCases(l)%N = step_discretization%get_asInt ('N') loadCases(l)%N = step_discretization%get_asInt ('N')
loadCases(l)%r = step_discretization%get_asFloat('r', defaultVal= 1.0_pReal) loadCases(l)%r = step_discretization%get_asFloat('r', defaultVal= 1.0_pReal)
loadCases(l)%f_out = step_discretization%get_asInt ('f_out', defaultVal=1)
loadCases(l)%f_restart = step_discretization%get_asInt ('f_restart', defaultVal=huge(0))
loadCases(l)%drop_guessing = (load_step%get_asBool('drop_guessing',defaultVal=.false.) .or. & loadCases(l)%f_restart = load_step%get_asInt('f_restart', defaultVal=huge(0))
merge(.false.,.true.,l > 1)) loadCases(l)%f_out = load_step%get_asInt('f_out', defaultVal=1)
loadCases(l)%estimate_rate = (load_step%get_asBool('estimate_rate',defaultVal=.true.) .and. l>1)
reportAndCheck: if (worldrank == 0) then reportAndCheck: if (worldrank == 0) then
write (loadcase_string, '(i0)' ) l
print'(/,a,i0)', ' load case: ', l print'(/,a,i0)', ' load case: ', l
print*, ' drop_guessing:', loadCases(l)%drop_guessing print*, ' estimate_rate:', loadCases(l)%estimate_rate
if (loadCases(l)%deformation%myType == 'L') then if (loadCases(l)%deformation%myType == 'L') then
do j = 1, 3 do j = 1, 3
if (any(loadCases(l)%deformation%mask(j,1:3) .eqv. .true.) .and. & if (any(loadCases(l)%deformation%mask(j,1:3) .eqv. .true.) .and. &
@ -283,13 +289,13 @@ program DAMASK_grid
else else
print'(a,f0.3)', ' r: ', loadCases(l)%r print'(a,f0.3)', ' r: ', loadCases(l)%r
endif endif
print'(a,f0.3)', ' t: ', loadCases(l)%t print'(a,f0.3)', ' t: ', loadCases(l)%t
print'(a,i0)', ' N: ', loadCases(l)%N print'(a,i0)', ' N: ', loadCases(l)%N
print'(a,i0)', ' f_out: ', loadCases(l)%f_out print'(a,i0)', ' f_out: ', loadCases(l)%f_out
if (loadCases(l)%f_restart < huge(0)) & if (loadCases(l)%f_restart < huge(0)) &
print'(a,i0)', ' f_restart: ', loadCases(l)%f_restart print'(a,i0)', ' f_restart: ', loadCases(l)%f_restart
if (errorID > 0) call IO_error(error_ID = errorID, ext_msg = loadcase_string) ! exit with error message if (errorID > 0) call IO_error(error_ID = errorID, el = l)
endif reportAndCheck endif reportAndCheck
enddo enddo
@ -298,12 +304,14 @@ program DAMASK_grid
! doing initialization depending on active solvers ! doing initialization depending on active solvers
call spectral_Utilities_init call spectral_Utilities_init
do field = 1, nActiveFields do field = 1, nActiveFields
select case (loadCases(1)%ID(field)) select case (ID(field))
case(FIELD_MECH_ID) case(FIELD_MECH_ID)
call mech_init call mechanical_init
case(FIELD_THERMAL_ID) case(FIELD_THERMAL_ID)
call grid_thermal_spectral_init initial_conditions => config_load%get('initial_conditions',defaultVal=emptyDict)
thermal => initial_conditions%get('thermal',defaultVal=emptyDict)
call grid_thermal_spectral_init(thermal%get_asFloat('T',defaultVal = T_0))
case(FIELD_DAMAGE_ID) case(FIELD_DAMAGE_ID)
call grid_damage_spectral_init call grid_damage_spectral_init
@ -331,7 +339,7 @@ program DAMASK_grid
loadCaseLooping: do l = 1, size(loadCases) loadCaseLooping: do l = 1, size(loadCases)
time0 = time ! load case start time time0 = time ! load case start time
guess = .not. loadCases(l)%drop_guessing ! change of load case? homogeneous guess for the first inc guess = loadCases(l)%estimate_rate ! change of load case? homogeneous guess for the first inc
incLooping: do inc = 1, loadCases(l)%N incLooping: do inc = 1, loadCases(l)%N
totalIncsCounter = totalIncsCounter + 1 totalIncsCounter = totalIncsCounter + 1
@ -374,9 +382,9 @@ program DAMASK_grid
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! forward fields ! forward fields
do field = 1, nActiveFields do field = 1, nActiveFields
select case(loadCases(l)%ID(field)) select case(ID(field))
case(FIELD_MECH_ID) case(FIELD_MECH_ID)
call mech_forward (& call mechanical_forward (&
cutBack,guess,timeinc,timeIncOld,remainingLoadCaseTime, & cutBack,guess,timeinc,timeIncOld,remainingLoadCaseTime, &
deformation_BC = loadCases(l)%deformation, & deformation_BC = loadCases(l)%deformation, &
stress_BC = loadCases(l)%stress, & stress_BC = loadCases(l)%stress, &
@ -394,9 +402,9 @@ program DAMASK_grid
stagIterate = .true. stagIterate = .true.
do while (stagIterate) do while (stagIterate)
do field = 1, nActiveFields do field = 1, nActiveFields
select case(loadCases(l)%ID(field)) select case(ID(field))
case(FIELD_MECH_ID) case(FIELD_MECH_ID)
solres(field) = mech_solution(incInfo) solres(field) = mechanical_solution(incInfo)
case(FIELD_THERMAL_ID) case(FIELD_THERMAL_ID)
solres(field) = grid_thermal_spectral_solution(timeinc) solres(field) = grid_thermal_spectral_solution(timeinc)
case(FIELD_DAMAGE_ID) case(FIELD_DAMAGE_ID)
@ -417,13 +425,13 @@ program DAMASK_grid
if ( (all(solres(:)%converged .and. solres(:)%stagConverged)) & ! converged if ( (all(solres(:)%converged .and. solres(:)%stagConverged)) & ! converged
.and. .not. solres(1)%termIll) then ! and acceptable solution found .and. .not. solres(1)%termIll) then ! and acceptable solution found
call mech_updateCoords call mechanical_updateCoords
timeIncOld = timeinc timeIncOld = timeinc
cutBack = .false. cutBack = .false.
guess = .true. ! start guessing after first converged (sub)inc guess = .true. ! start guessing after first converged (sub)inc
if (worldrank == 0) then if (worldrank == 0) then
write(statUnit,*) totalIncsCounter, time, cutBackLevel, & write(statUnit,*) totalIncsCounter, time, cutBackLevel, &
solres%converged, solres%iterationsNeeded solres(1)%converged, solres(1)%iterationsNeeded
flush(statUnit) flush(statUnit)
endif endif
elseif (cutBackLevel < maxCutBack) then ! further cutbacking tolerated? elseif (cutBackLevel < maxCutBack) then ! further cutbacking tolerated?
@ -449,18 +457,27 @@ program DAMASK_grid
print'(/,a,i0,a)', ' increment ', totalIncsCounter, ' NOT converged' print'(/,a,i0,a)', ' increment ', totalIncsCounter, ' NOT converged'
endif; flush(IO_STDOUT) endif; flush(IO_STDOUT)
if (mod(inc,loadCases(l)%f_out) == 0) then call MPI_Allreduce(interface_SIGUSR1,signal,1,MPI_LOGICAL,MPI_LOR,PETSC_COMM_WORLD,ierr)
if (ierr /= 0) error stop 'MPI error'
if (mod(inc,loadCases(l)%f_out) == 0 .or. signal) then
print'(1/,a)', ' ... writing results to file ......................................' print'(1/,a)', ' ... writing results to file ......................................'
flush(IO_STDOUT) flush(IO_STDOUT)
call CPFEM_results(totalIncsCounter,time) call CPFEM_results(totalIncsCounter,time)
endif endif
if (mod(inc,loadCases(l)%f_restart) == 0) then if(signal) call interface_setSIGUSR1(.false.)
call mech_restartWrite call MPI_Allreduce(interface_SIGUSR2,signal,1,MPI_LOGICAL,MPI_LOR,PETSC_COMM_WORLD,ierr)
if (ierr /= 0) error stop 'MPI error'
if (mod(inc,loadCases(l)%f_restart) == 0 .or. signal) then
call mechanical_restartWrite
call CPFEM_restartWrite call CPFEM_restartWrite
endif endif
if(signal) call interface_setSIGUSR2(.false.)
call MPI_Allreduce(interface_SIGTERM,signal,1,MPI_LOGICAL,MPI_LOR,PETSC_COMM_WORLD,ierr)
if (ierr /= 0) error stop 'MPI error'
if (signal) exit loadCaseLooping
endif skipping endif skipping
enddo incLooping enddo incLooping
enddo loadCaseLooping enddo loadCaseLooping

View File

@ -68,8 +68,11 @@ subroutine discretization_grid_init(restart)
print'(/,a)', ' <<<+- discretization_grid init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- discretization_grid init -+>>>'; flush(IO_STDOUT)
if(worldrank == 0) call readVTR(grid,geomSize,origin,materialAt_global) if(worldrank == 0) then
call readVTR(grid,geomSize,origin,materialAt_global)
else
allocate(materialAt_global(0)) ! needed for IntelMPI
endif
call MPI_Bcast(grid,3,MPI_INTEGER,0,PETSC_COMM_WORLD, ierr) call MPI_Bcast(grid,3,MPI_INTEGER,0,PETSC_COMM_WORLD, ierr)
if (ierr /= 0) error stop 'MPI error' if (ierr /= 0) error stop 'MPI error'

View File

@ -15,10 +15,10 @@ module grid_damage_spectral
use IO use IO
use spectral_utilities use spectral_utilities
use discretization_grid use discretization_grid
use damage_nonlocal
use YAML_types use YAML_types
use homogenization
use config use config
implicit none implicit none
private private
@ -43,13 +43,13 @@ module grid_damage_spectral
phi_current, & !< field of current damage phi_current, & !< field of current damage
phi_lastInc, & !< field of previous damage phi_lastInc, & !< field of previous damage
phi_stagInc !< field of staggered damage phi_stagInc !< field of staggered damage
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! reference diffusion tensor, mobility etc. ! reference diffusion tensor, mobility etc.
integer :: totalIter = 0 !< total iteration in current increment integer :: totalIter = 0 !< total iteration in current increment
real(pReal), dimension(3,3) :: K_ref real(pReal), dimension(3,3) :: K_ref
real(pReal) :: mu_ref real(pReal) :: mu_ref
public :: & public :: &
grid_damage_spectral_init, & grid_damage_spectral_init, &
grid_damage_spectral_solution, & grid_damage_spectral_solution, &
@ -62,8 +62,8 @@ contains
! ToDo: Restart not implemented ! ToDo: Restart not implemented
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_damage_spectral_init subroutine grid_damage_spectral_init
PetscInt, dimension(0:worldsize-1) :: localK PetscInt, dimension(0:worldsize-1) :: localK
DM :: damage_grid DM :: damage_grid
Vec :: uBound, lBound Vec :: uBound, lBound
PetscErrorCode :: ierr PetscErrorCode :: ierr
@ -72,22 +72,22 @@ subroutine grid_damage_spectral_init
num_generic num_generic
character(len=pStringLen) :: & character(len=pStringLen) :: &
snes_type snes_type
print'(/,a)', ' <<<+- grid_spectral_damage init -+>>>' print'(/,a)', ' <<<+- grid_spectral_damage init -+>>>'
print*, 'Shanthraj et al., Handbook of Mechanics of Materials, 2019' print*, 'Shanthraj et al., Handbook of Mechanics of Materials, 2019'
print*, 'https://doi.org/10.1007/978-981-10-6855-3_80' print*, 'https://doi.org/10.1007/978-981-10-6855-3_80'
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
! read numerical parameters and do sanity checks ! read numerical parameters and do sanity checks
num_grid => config_numerics%get('grid',defaultVal=emptyDict) num_grid => config_numerics%get('grid',defaultVal=emptyDict)
num%itmax = num_grid%get_asInt ('itmax',defaultVal=250) num%itmax = num_grid%get_asInt ('itmax',defaultVal=250)
num%eps_damage_atol = num_grid%get_asFloat ('eps_damage_atol',defaultVal=1.0e-2_pReal) num%eps_damage_atol = num_grid%get_asFloat ('eps_damage_atol',defaultVal=1.0e-2_pReal)
num%eps_damage_rtol = num_grid%get_asFloat ('eps_damage_rtol',defaultVal=1.0e-6_pReal) num%eps_damage_rtol = num_grid%get_asFloat ('eps_damage_rtol',defaultVal=1.0e-6_pReal)
num_generic => config_numerics%get('generic',defaultVal=emptyDict) num_generic => config_numerics%get('generic',defaultVal=emptyDict)
num%residualStiffness = num_generic%get_asFloat('residualStiffness', defaultVal=1.0e-6_pReal) num%residualStiffness = num_generic%get_asFloat('residualStiffness', defaultVal=1.0e-6_pReal)
if (num%residualStiffness < 0.0_pReal) call IO_error(301,ext_msg='residualStiffness') if (num%residualStiffness < 0.0_pReal) call IO_error(301,ext_msg='residualStiffness')
if (num%itmax <= 1) call IO_error(301,ext_msg='itmax') if (num%itmax <= 1) call IO_error(301,ext_msg='itmax')
if (num%eps_damage_atol <= 0.0_pReal) call IO_error(301,ext_msg='eps_damage_atol') if (num%eps_damage_atol <= 0.0_pReal) call IO_error(301,ext_msg='eps_damage_atol')
@ -104,7 +104,7 @@ subroutine grid_damage_spectral_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! initialize solver specific parts of PETSc ! initialize solver specific parts of PETSc
call SNESCreate(PETSC_COMM_WORLD,damage_snes,ierr); CHKERRQ(ierr) call SNESCreate(PETSC_COMM_WORLD,damage_snes,ierr); CHKERRQ(ierr)
call SNESSetOptionsPrefix(damage_snes,'damage_',ierr);CHKERRQ(ierr) call SNESSetOptionsPrefix(damage_snes,'damage_',ierr);CHKERRQ(ierr)
localK = 0 localK = 0
localK(worldrank) = grid3 localK(worldrank) = grid3
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr)
@ -122,7 +122,7 @@ subroutine grid_damage_spectral_init
call DMsetUp(damage_grid,ierr); CHKERRQ(ierr) call DMsetUp(damage_grid,ierr); CHKERRQ(ierr)
call DMCreateGlobalVector(damage_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor) call DMCreateGlobalVector(damage_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor)
call DMDASNESSetFunctionLocal(damage_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector call DMDASNESSetFunctionLocal(damage_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetFromOptions(damage_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments call SNESSetFromOptions(damage_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
call SNESGetType(damage_snes,snes_type,ierr); CHKERRQ(ierr) call SNESGetType(damage_snes,snes_type,ierr); CHKERRQ(ierr)
if (trim(snes_type) == 'vinewtonrsls' .or. & if (trim(snes_type) == 'vinewtonrsls' .or. &
@ -137,12 +137,12 @@ subroutine grid_damage_spectral_init
endif endif
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! init fields ! init fields
call DMDAGetCorners(damage_grid,xstart,ystart,zstart,xend,yend,zend,ierr) call DMDAGetCorners(damage_grid,xstart,ystart,zstart,xend,yend,zend,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
xend = xstart + xend - 1 xend = xstart + xend - 1
yend = ystart + yend - 1 yend = ystart + yend - 1
zend = zstart + zend - 1 zend = zstart + zend - 1
allocate(phi_current(grid(1),grid(2),grid3), source=1.0_pReal) allocate(phi_current(grid(1),grid(2),grid3), source=1.0_pReal)
allocate(phi_lastInc(grid(1),grid(2),grid3), source=1.0_pReal) allocate(phi_lastInc(grid(1),grid(2),grid3), source=1.0_pReal)
allocate(phi_stagInc(grid(1),grid(2),grid3), source=1.0_pReal) allocate(phi_stagInc(grid(1),grid(2),grid3), source=1.0_pReal)
@ -157,26 +157,26 @@ end subroutine grid_damage_spectral_init
!> @brief solution for the spectral damage scheme with internal iterations !> @brief solution for the spectral damage scheme with internal iterations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function grid_damage_spectral_solution(timeinc) result(solution) function grid_damage_spectral_solution(timeinc) result(solution)
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
timeinc !< increment in time for current solution timeinc !< increment in time for current solution
integer :: i, j, k, cell integer :: i, j, k, ce
type(tSolutionState) :: solution type(tSolutionState) :: solution
PetscInt :: devNull PetscInt :: devNull
PetscReal :: phi_min, phi_max, stagNorm, solnNorm PetscReal :: phi_min, phi_max, stagNorm, solnNorm
PetscErrorCode :: ierr PetscErrorCode :: ierr
SNESConvergedReason :: reason SNESConvergedReason :: reason
solution%converged =.false. solution%converged =.false.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set module wide availabe data ! set module wide availabe data
params%timeinc = timeinc params%timeinc = timeinc
call SNESSolve(damage_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr) call SNESSolve(damage_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
call SNESGetConvergedReason(damage_snes,reason,ierr); CHKERRQ(ierr) call SNESGetConvergedReason(damage_snes,reason,ierr); CHKERRQ(ierr)
if (reason < 1) then if (reason < 1) then
solution%converged = .false. solution%converged = .false.
solution%iterationsNeeded = num%itmax solution%iterationsNeeded = num%itmax
@ -192,20 +192,20 @@ function grid_damage_spectral_solution(timeinc) result(solution)
solution%stagConverged = stagNorm < max(num%eps_damage_atol, num%eps_damage_rtol*solnNorm) solution%stagConverged = stagNorm < max(num%eps_damage_atol, num%eps_damage_rtol*solnNorm)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! updating damage state ! updating damage state
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),1,cell) call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),ce)
enddo; enddo; enddo enddo; enddo; enddo
call VecMin(solution_vec,devNull,phi_min,ierr); CHKERRQ(ierr) call VecMin(solution_vec,devNull,phi_min,ierr); CHKERRQ(ierr)
call VecMax(solution_vec,devNull,phi_max,ierr); CHKERRQ(ierr) call VecMax(solution_vec,devNull,phi_max,ierr); CHKERRQ(ierr)
if (solution%converged) & if (solution%converged) &
print'(/,a)', ' ... nonlocal damage converged .....................................' print'(/,a)', ' ... nonlocal damage converged .....................................'
print'(/,a,f8.6,2x,f8.6,2x,e11.4)', ' Minimum|Maximum|Delta Damage = ', phi_min, phi_max, stagNorm print'(/,a,f8.6,2x,f8.6,2x,e11.4)', ' Minimum|Maximum|Delta Damage = ', phi_min, phi_max, stagNorm
print'(/,a)', ' ===========================================================================' print'(/,a)', ' ==========================================================================='
flush(IO_STDOUT) flush(IO_STDOUT)
end function grid_damage_spectral_solution end function grid_damage_spectral_solution
@ -214,31 +214,31 @@ end function grid_damage_spectral_solution
!> @brief spectral damage forwarding routine !> @brief spectral damage forwarding routine
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_damage_spectral_forward(cutBack) subroutine grid_damage_spectral_forward(cutBack)
logical, intent(in) :: cutBack logical, intent(in) :: cutBack
integer :: i, j, k, cell integer :: i, j, k, ce
DM :: dm_local DM :: dm_local
PetscScalar, dimension(:,:,:), pointer :: x_scal PetscScalar, dimension(:,:,:), pointer :: x_scal
PetscErrorCode :: ierr PetscErrorCode :: ierr
if (cutBack) then if (cutBack) then
phi_current = phi_lastInc phi_current = phi_lastInc
phi_stagInc = phi_lastInc phi_stagInc = phi_lastInc
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! reverting damage field state ! reverting damage field state
cell = 0 ce = 0
call SNESGetDM(damage_snes,dm_local,ierr); CHKERRQ(ierr) call SNESGetDM(damage_snes,dm_local,ierr); CHKERRQ(ierr)
call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with
x_scal(xstart:xend,ystart:yend,zstart:zend) = phi_current x_scal(xstart:xend,ystart:yend,zstart:zend) = phi_current
call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr)
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),1,cell) call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),ce)
enddo; enddo; enddo enddo; enddo; enddo
else else
phi_lastInc = phi_current phi_lastInc = phi_current
call updateReference call updateReference
endif endif
end subroutine grid_damage_spectral_forward end subroutine grid_damage_spectral_forward
@ -247,7 +247,7 @@ end subroutine grid_damage_spectral_forward
!> @brief forms the spectral damage residual vector !> @brief forms the spectral damage residual vector
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine formResidual(in,x_scal,f_scal,dummy,ierr) subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: & DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
in in
PetscScalar, dimension( & PetscScalar, dimension( &
@ -258,31 +258,31 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
f_scal f_scal
PetscObject :: dummy PetscObject :: dummy
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer :: i, j, k, cell integer :: i, j, k, ce
real(pReal) :: phiDot, dPhiDot_dPhi, mobility real(pReal) :: phiDot, dPhiDot_dPhi, mobility
phi_current = x_scal phi_current = x_scal
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate polarization field ! evaluate polarization field
scalarField_real = 0.0_pReal scalarField_real = 0.0_pReal
scalarField_real(1:grid(1),1:grid(2),1:grid3) = phi_current scalarField_real(1:grid(1),1:grid(2),1:grid3) = phi_current
call utilities_FFTscalarForward call utilities_FFTscalarForward
call utilities_fourierScalarGradient !< calculate gradient of damage field call utilities_fourierScalarGradient !< calculate gradient of damage field
call utilities_FFTvectorBackward call utilities_FFTvectorBackward
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
vectorField_real(1:3,i,j,k) = matmul(damage_nonlocal_getDiffusion(1,cell) - K_ref, & vectorField_real(1:3,i,j,k) = matmul(damage_nonlocal_getDiffusion(ce) - K_ref, &
vectorField_real(1:3,i,j,k)) vectorField_real(1:3,i,j,k))
enddo; enddo; enddo enddo; enddo; enddo
call utilities_FFTvectorForward call utilities_FFTvectorForward
call utilities_fourierVectorDivergence !< calculate damage divergence in fourier field call utilities_fourierVectorDivergence !< calculate damage divergence in fourier field
call utilities_FFTscalarBackward call utilities_FFTscalarBackward
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi_current(i,j,k), 1, cell) call damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi_current(i,j,k),ce)
mobility = damage_nonlocal_getMobility(1,cell) mobility = damage_nonlocal_getMobility(ce)
scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + phiDot) & scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + phiDot) &
+ mobility*(phi_lastInc(i,j,k) - phi_current(i,j,k)) & + mobility*(phi_lastInc(i,j,k) - phi_current(i,j,k)) &
+ mu_ref*phi_current(i,j,k) + mu_ref*phi_current(i,j,k)
@ -297,7 +297,7 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
scalarField_real(1:grid(1),1:grid(2),1:grid3) = phi_lastInc scalarField_real(1:grid(1),1:grid(2),1:grid3) = phi_lastInc
where(scalarField_real(1:grid(1),1:grid(2),1:grid3) < num%residualStiffness) & where(scalarField_real(1:grid(1),1:grid(2),1:grid3) < num%residualStiffness) &
scalarField_real(1:grid(1),1:grid(2),1:grid3) = num%residualStiffness scalarField_real(1:grid(1),1:grid(2),1:grid3) = num%residualStiffness
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! constructing residual ! constructing residual
f_scal = scalarField_real(1:grid(1),1:grid(2),1:grid3) - phi_current f_scal = scalarField_real(1:grid(1),1:grid(2),1:grid3) - phi_current
@ -310,15 +310,15 @@ end subroutine formResidual
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine updateReference subroutine updateReference
integer :: i,j,k,cell,ierr integer :: i,j,k,ce,ierr
cell = 0 ce = 0
K_ref = 0.0_pReal K_ref = 0.0_pReal
mu_ref = 0.0_pReal mu_ref = 0.0_pReal
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
K_ref = K_ref + damage_nonlocal_getDiffusion(1,cell) K_ref = K_ref + damage_nonlocal_getDiffusion(ce)
mu_ref = mu_ref + damage_nonlocal_getMobility(1,cell) mu_ref = mu_ref + damage_nonlocal_getMobility(ce)
enddo; enddo; enddo enddo; enddo; enddo
K_ref = K_ref*wgt K_ref = K_ref*wgt
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr)

View File

@ -4,7 +4,7 @@
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
!> @brief Grid solver for mechanics: FEM !> @brief Grid solver for mechanics: FEM
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module grid_mech_FEM module grid_mechanical_FEM
#include <petsc/finclude/petscsnes.h> #include <petsc/finclude/petscsnes.h>
#include <petsc/finclude/petscdmda.h> #include <petsc/finclude/petscdmda.h>
use PETScdmda use PETScdmda
@ -45,8 +45,8 @@ module grid_mech_FEM
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! PETSc data ! PETSc data
DM :: mech_grid DM :: mechanical_grid
SNES :: mech_snes SNES :: mechanical_snes
Vec :: solution_current, solution_lastInc, solution_rate Vec :: solution_current, solution_lastInc, solution_rate
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -79,18 +79,18 @@ module grid_mech_FEM
totalIter = 0 !< total iteration in current increment totalIter = 0 !< total iteration in current increment
public :: & public :: &
grid_mech_FEM_init, & grid_mechanical_FEM_init, &
grid_mech_FEM_solution, & grid_mechanical_FEM_solution, &
grid_mech_FEM_forward, & grid_mechanical_FEM_forward, &
grid_mech_FEM_updateCoords, & grid_mechanical_FEM_updateCoords, &
grid_mech_FEM_restartWrite grid_mechanical_FEM_restartWrite
contains contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief allocates all necessary fields and fills them with data, potentially from restart info !> @brief allocates all necessary fields and fills them with data, potentially from restart info
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_FEM_init subroutine grid_mechanical_FEM_init
real(pReal), parameter :: HGCoeff = 0.0e-2_pReal real(pReal), parameter :: HGCoeff = 0.0e-2_pReal
real(pReal), parameter, dimension(4,8) :: & real(pReal), parameter, dimension(4,8) :: &
@ -108,13 +108,11 @@ subroutine grid_mech_FEM_init
u_current,u_lastInc u_current,u_lastInc
PetscInt, dimension(0:worldsize-1) :: localK PetscInt, dimension(0:worldsize-1) :: localK
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
character(len=pStringLen) :: &
fileName
class(tNode), pointer :: & class(tNode), pointer :: &
num_grid, & num_grid, &
debug_grid debug_grid
print'(/,a)', ' <<<+- grid_mech_FEM init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- grid_mechanical_FEM init -+>>>'; flush(IO_STDOUT)
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
! debugging options ! debugging options
@ -141,8 +139,11 @@ subroutine grid_mech_FEM_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set default and user defined options for PETSc ! set default and user defined options for PETSc
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type newtonls -mech_ksp_type fgmres & call PetscOptionsInsertString(PETSC_NULL_OPTIONS, &
&-mech_ksp_max_it 25 -mech_pc_type ml -mech_mg_levels_ksp_type chebyshev',ierr) '-mechanical_snes_type newtonls -mechanical_ksp_type fgmres &
&-mechanical_ksp_max_it 25 -mechanical_pc_type ml &
&-mechanical_mg_levels_ksp_type chebyshev', &
ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
@ -155,8 +156,10 @@ subroutine grid_mech_FEM_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! initialize solver specific parts of PETSc ! initialize solver specific parts of PETSc
call SNESCreate(PETSC_COMM_WORLD,mech_snes,ierr); CHKERRQ(ierr) call SNESCreate(PETSC_COMM_WORLD,mechanical_snes,ierr)
call SNESSetOptionsPrefix(mech_snes,'mech_',ierr);CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetOptionsPrefix(mechanical_snes,'mechanical_',ierr)
CHKERRQ(ierr)
localK = 0 localK = 0
localK(worldrank) = grid3 localK(worldrank) = grid3
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr)
@ -167,34 +170,44 @@ subroutine grid_mech_FEM_init
1, 1, worldsize, & 1, 1, worldsize, &
3, 1, & 3, 1, &
[grid(1)],[grid(2)],localK, & [grid(1)],[grid(2)],localK, &
mech_grid,ierr) mechanical_grid,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetDM(mech_snes,mech_grid,ierr); CHKERRQ(ierr) call SNESSetDM(mechanical_snes,mechanical_grid,ierr)
call DMsetFromOptions(mech_grid,ierr); CHKERRQ(ierr)
call DMsetUp(mech_grid,ierr); CHKERRQ(ierr)
call DMDASetUniformCoordinates(mech_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call DMCreateGlobalVector(mech_grid,solution_current,ierr); CHKERRQ(ierr) call DMsetFromOptions(mechanical_grid,ierr)
call DMCreateGlobalVector(mech_grid,solution_lastInc,ierr); CHKERRQ(ierr)
call DMCreateGlobalVector(mech_grid,solution_rate ,ierr); CHKERRQ(ierr)
call DMSNESSetFunctionLocal(mech_grid,formResidual,PETSC_NULL_SNES,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call DMSNESSetJacobianLocal(mech_grid,formJacobian,PETSC_NULL_SNES,ierr) call DMsetUp(mechanical_grid,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetConvergenceTest(mech_snes,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,ierr) ! specify custom convergence check function "_converged" call DMDASetUniformCoordinates(mechanical_grid,0.0_pReal,geomSize(1),0.0_pReal,geomSize(2),0.0_pReal,geomSize(3),ierr)
CHKERRQ(ierr)
call DMCreateGlobalVector(mechanical_grid,solution_current,ierr)
CHKERRQ(ierr)
call DMCreateGlobalVector(mechanical_grid,solution_lastInc,ierr)
CHKERRQ(ierr)
call DMCreateGlobalVector(mechanical_grid,solution_rate ,ierr)
CHKERRQ(ierr)
call DMSNESSetFunctionLocal(mechanical_grid,formResidual,PETSC_NULL_SNES,ierr)
CHKERRQ(ierr)
call DMSNESSetJacobianLocal(mechanical_grid,formJacobian,PETSC_NULL_SNES,ierr)
CHKERRQ(ierr)
call SNESSetConvergenceTest(mechanical_snes,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,ierr) ! specify custom convergence check function "_converged"
CHKERRQ(ierr)
call SNESSetMaxLinearSolveFailures(mechanical_snes, huge(1), ierr) ! ignore linear solve failures
CHKERRQ(ierr)
call SNESSetFromOptions(mechanical_snes,ierr) ! pull it all together with additional cli arguments
CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetMaxLinearSolveFailures(mech_snes, huge(1), ierr); CHKERRQ(ierr) ! ignore linear solve failures
call SNESSetFromOptions(mech_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional cli arguments
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! init fields ! init fields
call VecSet(solution_current,0.0_pReal,ierr);CHKERRQ(ierr) call VecSet(solution_current,0.0_pReal,ierr);CHKERRQ(ierr)
call VecSet(solution_lastInc,0.0_pReal,ierr);CHKERRQ(ierr) call VecSet(solution_lastInc,0.0_pReal,ierr);CHKERRQ(ierr)
call VecSet(solution_rate ,0.0_pReal,ierr);CHKERRQ(ierr) call VecSet(solution_rate ,0.0_pReal,ierr);CHKERRQ(ierr)
call DMDAVecGetArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
call DMDAVecGetArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr) CHKERRQ(ierr)
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr)
call DMDAGetCorners(mech_grid,xstart,ystart,zstart,xend,yend,zend,ierr) ! local grid extent call DMDAGetCorners(mechanical_grid,xstart,ystart,zstart,xend,yend,zend,ierr) ! local grid extent
CHKERRQ(ierr) CHKERRQ(ierr)
xend = xstart+xend-1 xend = xstart+xend-1
yend = ystart+yend-1 yend = ystart+yend-1
@ -219,8 +232,7 @@ subroutine grid_mech_FEM_init
restartRead: if (interface_restartInc > 0) then restartRead: if (interface_restartInc > 0) then
print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file' print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file'
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
fileHandle = HDF5_openFile(fileName)
groupHandle = HDF5_openGroup(fileHandle,'solver') groupHandle = HDF5_openGroup(fileHandle,'solver')
call HDF5_read(groupHandle,P_aim, 'P_aim') call HDF5_read(groupHandle,P_aim, 'P_aim')
@ -242,9 +254,9 @@ subroutine grid_mech_FEM_init
call utilities_constitutiveResponse(P_current,P_av,C_volAvg,devNull, & ! stress field, stress avg, global average of stiffness and (min+max)/2 call utilities_constitutiveResponse(P_current,P_av,C_volAvg,devNull, & ! stress field, stress avg, global average of stiffness and (min+max)/2
F, & ! target F F, & ! target F
0.0_pReal) ! time increment 0.0_pReal) ! time increment
call DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr) call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr) call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
restartRead2: if (interface_restartInc > 0) then restartRead2: if (interface_restartInc > 0) then
@ -257,13 +269,13 @@ subroutine grid_mech_FEM_init
endif restartRead2 endif restartRead2
end subroutine grid_mech_FEM_init end subroutine grid_mechanical_FEM_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief solution for the FEM scheme with internal iterations !> @brief solution for the FEM scheme with internal iterations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function grid_mech_FEM_solution(incInfoIn) result(solution) function grid_mechanical_FEM_solution(incInfoIn) result(solution)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! input data for solution ! input data for solution
@ -284,11 +296,13 @@ function grid_mech_FEM_solution(incInfoIn) result(solution)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! solve BVP ! solve BVP
call SNESsolve(mech_snes,PETSC_NULL_VEC,solution_current,ierr); CHKERRQ(ierr) call SNESsolve(mechanical_snes,PETSC_NULL_VEC,solution_current,ierr)
CHKERRQ(ierr)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! check convergence ! check convergence
call SNESGetConvergedReason(mech_snes,reason,ierr); CHKERRQ(ierr) call SNESGetConvergedReason(mechanical_snes,reason,ierr)
CHKERRQ(ierr)
solution%converged = reason > 0 solution%converged = reason > 0
solution%iterationsNeeded = totalIter solution%iterationsNeeded = totalIter
@ -296,14 +310,14 @@ function grid_mech_FEM_solution(incInfoIn) result(solution)
terminallyIll = .false. terminallyIll = .false.
P_aim = merge(P_aim,P_av,params%stress_mask) P_aim = merge(P_aim,P_av,params%stress_mask)
end function grid_mech_FEM_solution end function grid_mechanical_FEM_solution
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief forwarding routine !> @brief forwarding routine
!> @details find new boundary conditions and best F estimate for end of current timestep !> @details find new boundary conditions and best F estimate for end of current timestep
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,& subroutine grid_mechanical_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
deformation_BC,stress_BC,rotation_BC) deformation_BC,stress_BC,rotation_BC)
logical, intent(in) :: & logical, intent(in) :: &
@ -323,8 +337,10 @@ subroutine grid_mech_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
u_current,u_lastInc u_current,u_lastInc
call DMDAVecGetArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
call DMDAVecGetArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr) CHKERRQ(ierr)
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr)
if (cutBack) then if (cutBack) then
C_volAvg = C_volAvgLastInc C_volAvg = C_volAvgLastInc
@ -371,8 +387,10 @@ subroutine grid_mech_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
call VecAXPY(solution_current,Delta_t,solution_rate,ierr); CHKERRQ(ierr) call VecAXPY(solution_current,Delta_t,solution_rate,ierr); CHKERRQ(ierr)
call DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr) CHKERRQ(ierr)
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set module wide available data ! set module wide available data
@ -380,36 +398,37 @@ subroutine grid_mech_FEM_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
params%rotation_BC = rotation_BC params%rotation_BC = rotation_BC
params%timeinc = Delta_t params%timeinc = Delta_t
end subroutine grid_mech_FEM_forward end subroutine grid_mechanical_FEM_forward
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Update coordinates !> @brief Update coordinates
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_FEM_updateCoords subroutine grid_mechanical_FEM_updateCoords
call utilities_updateCoords(F) call utilities_updateCoords(F)
end subroutine grid_mech_FEM_updateCoords end subroutine grid_mechanical_FEM_updateCoords
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Write current solver and constitutive data for restart to file !> @brief Write current solver and constitutive data for restart to file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_FEM_restartWrite subroutine grid_mechanical_FEM_restartWrite
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
PetscScalar, dimension(:,:,:,:), pointer :: u_current,u_lastInc PetscScalar, dimension(:,:,:,:), pointer :: u_current,u_lastInc
character(len=pStringLen) :: fileName
call DMDAVecGetArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr)
call DMDAVecGetArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(mechanical_grid,solution_current,u_current,ierr)
CHKERRQ(ierr)
call DMDAVecGetArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr)
print*, 'writing solver data required for restart to file'; flush(IO_STDOUT) print*, 'writing solver data required for restart to file'; flush(IO_STDOUT)
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
fileHandle = HDF5_openFile(fileName,'w')
groupHandle = HDF5_addGroup(fileHandle,'solver') groupHandle = HDF5_addGroup(fileHandle,'solver')
call HDF5_write(groupHandle,P_aim, 'P_aim') call HDF5_write(groupHandle,P_aim, 'P_aim')
@ -427,10 +446,12 @@ subroutine grid_mech_FEM_restartWrite
call HDF5_closeGroup(groupHandle) call HDF5_closeGroup(groupHandle)
call HDF5_closeFile(fileHandle) call HDF5_closeFile(fileHandle)
call DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr);CHKERRQ(ierr) call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr);CHKERRQ(ierr) CHKERRQ(ierr)
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
CHKERRQ(ierr)
end subroutine grid_mech_FEM_restartWrite end subroutine grid_mechanical_FEM_restartWrite
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -498,8 +519,10 @@ subroutine formResidual(da_local,x_local, &
PetscErrorCode :: ierr PetscErrorCode :: ierr
real(pReal), dimension(3,3,3,3) :: devNull real(pReal), dimension(3,3,3,3) :: devNull
call SNESGetNumberFunctionEvals(mech_snes,nfuncs,ierr); CHKERRQ(ierr) call SNESGetNumberFunctionEvals(mechanical_snes,nfuncs,ierr)
call SNESGetIterationNumber(mech_snes,PETScIter,ierr); CHKERRQ(ierr) CHKERRQ(ierr)
call SNESGetIterationNumber(mechanical_snes,PETScIter,ierr)
CHKERRQ(ierr)
if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment if (nfuncs == 0 .and. PETScIter == 0) totalIter = -1 ! new increment
@ -679,4 +702,4 @@ subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr)
end subroutine formJacobian end subroutine formJacobian
end module grid_mech_FEM end module grid_mechanical_FEM

View File

@ -4,7 +4,7 @@
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
!> @brief Grid solver for mechanics: Spectral basic !> @brief Grid solver for mechanics: Spectral basic
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module grid_mech_spectral_basic module grid_mechanical_spectral_basic
#include <petsc/finclude/petscsnes.h> #include <petsc/finclude/petscsnes.h>
#include <petsc/finclude/petscdmda.h> #include <petsc/finclude/petscdmda.h>
use PETScdmda use PETScdmda
@ -79,18 +79,18 @@ module grid_mech_spectral_basic
totalIter = 0 !< total iteration in current increment totalIter = 0 !< total iteration in current increment
public :: & public :: &
grid_mech_spectral_basic_init, & grid_mechanical_spectral_basic_init, &
grid_mech_spectral_basic_solution, & grid_mechanical_spectral_basic_solution, &
grid_mech_spectral_basic_forward, & grid_mechanical_spectral_basic_forward, &
grid_mech_spectral_basic_updateCoords, & grid_mechanical_spectral_basic_updateCoords, &
grid_mech_spectral_basic_restartWrite grid_mechanical_spectral_basic_restartWrite
contains contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief allocates all necessary fields and fills them with data, potentially from restart info !> @brief allocates all necessary fields and fills them with data, potentially from restart info
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_basic_init subroutine grid_mechanical_spectral_basic_init
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
PetscErrorCode :: ierr PetscErrorCode :: ierr
@ -99,13 +99,11 @@ subroutine grid_mech_spectral_basic_init
PetscInt, dimension(0:worldsize-1) :: localK PetscInt, dimension(0:worldsize-1) :: localK
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
integer :: fileUnit integer :: fileUnit
character(len=pStringLen) :: &
fileName
class (tNode), pointer :: & class (tNode), pointer :: &
num_grid, & num_grid, &
debug_grid debug_grid
print'(/,a)', ' <<<+- grid_mech_spectral_basic init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- grid_mechanical_spectral_basic init -+>>>'; flush(IO_STDOUT)
print*, 'Eisenlohr et al., International Journal of Plasticity 46:3753, 2013' print*, 'Eisenlohr et al., International Journal of Plasticity 46:3753, 2013'
print*, 'https://doi.org/10.1016/j.ijplas.2012.09.012'//IO_EOL print*, 'https://doi.org/10.1016/j.ijplas.2012.09.012'//IO_EOL
@ -139,7 +137,7 @@ subroutine grid_mech_spectral_basic_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set default and user defined options for PETSc ! set default and user defined options for PETSc
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type ngmres',ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
@ -152,7 +150,7 @@ subroutine grid_mech_spectral_basic_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! initialize solver specific parts of PETSc ! initialize solver specific parts of PETSc
call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr) call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr)
call SNESSetOptionsPrefix(snes,'mech_',ierr);CHKERRQ(ierr) call SNESSetOptionsPrefix(snes,'mechanical_',ierr);CHKERRQ(ierr)
localK = 0 localK = 0
localK(worldrank) = grid3 localK(worldrank) = grid3
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr)
@ -182,8 +180,7 @@ subroutine grid_mech_spectral_basic_init
restartRead: if (interface_restartInc > 0) then restartRead: if (interface_restartInc > 0) then
print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file' print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file'
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
fileHandle = HDF5_openFile(fileName)
groupHandle = HDF5_openGroup(fileHandle,'solver') groupHandle = HDF5_openGroup(fileHandle,'solver')
call HDF5_read(groupHandle,P_aim, 'P_aim') call HDF5_read(groupHandle,P_aim, 'P_aim')
@ -222,13 +219,13 @@ subroutine grid_mech_spectral_basic_init
call utilities_updateGamma(C_minMaxAvg) call utilities_updateGamma(C_minMaxAvg)
call utilities_saveReferenceStiffness call utilities_saveReferenceStiffness
end subroutine grid_mech_spectral_basic_init end subroutine grid_mechanical_spectral_basic_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief solution for the basic scheme with internal iterations !> @brief solution for the basic scheme with internal iterations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function grid_mech_spectral_basic_solution(incInfoIn) result(solution) function grid_mechanical_spectral_basic_solution(incInfoIn) result(solution)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! input data for solution ! input data for solution
@ -262,14 +259,14 @@ function grid_mech_spectral_basic_solution(incInfoIn) result(solution)
terminallyIll = .false. terminallyIll = .false.
P_aim = merge(P_aim,P_av,params%stress_mask) P_aim = merge(P_aim,P_av,params%stress_mask)
end function grid_mech_spectral_basic_solution end function grid_mechanical_spectral_basic_solution
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief forwarding routine !> @brief forwarding routine
!> @details find new boundary conditions and best F estimate for end of current timestep !> @details find new boundary conditions and best F estimate for end of current timestep
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_basic_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,& subroutine grid_mechanical_spectral_basic_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
deformation_BC,stress_BC,rotation_BC) deformation_BC,stress_BC,rotation_BC)
logical, intent(in) :: & logical, intent(in) :: &
@ -339,13 +336,13 @@ subroutine grid_mech_spectral_basic_forward(cutBack,guess,Delta_t,Delta_t_old,t_
params%rotation_BC = rotation_BC params%rotation_BC = rotation_BC
params%timeinc = Delta_t params%timeinc = Delta_t
end subroutine grid_mech_spectral_basic_forward end subroutine grid_mechanical_spectral_basic_forward
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Update coordinates !> @brief Update coordinates
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_basic_updateCoords subroutine grid_mechanical_spectral_basic_updateCoords
PetscErrorCode :: ierr PetscErrorCode :: ierr
PetscScalar, dimension(:,:,:,:), pointer :: F PetscScalar, dimension(:,:,:,:), pointer :: F
@ -354,25 +351,23 @@ subroutine grid_mech_spectral_basic_updateCoords
call utilities_updateCoords(F) call utilities_updateCoords(F)
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
end subroutine grid_mech_spectral_basic_updateCoords end subroutine grid_mechanical_spectral_basic_updateCoords
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Write current solver and constitutive data for restart to file !> @brief Write current solver and constitutive data for restart to file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_basic_restartWrite subroutine grid_mechanical_spectral_basic_restartWrite
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
PetscScalar, dimension(:,:,:,:), pointer :: F PetscScalar, dimension(:,:,:,:), pointer :: F
character(len=pStringLen) :: fileName
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
print*, 'writing solver data required for restart to file'; flush(IO_STDOUT) print*, 'writing solver data required for restart to file'; flush(IO_STDOUT)
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
fileHandle = HDF5_openFile(fileName,'w')
groupHandle = HDF5_addGroup(fileHandle,'solver') groupHandle = HDF5_addGroup(fileHandle,'solver')
call HDF5_write(groupHandle,P_aim, 'P_aim') call HDF5_write(groupHandle,P_aim, 'P_aim')
@ -393,7 +388,7 @@ subroutine grid_mech_spectral_basic_restartWrite
call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
end subroutine grid_mech_spectral_basic_restartWrite end subroutine grid_mechanical_spectral_basic_restartWrite
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -506,4 +501,4 @@ subroutine formResidual(in, F, &
end subroutine formResidual end subroutine formResidual
end module grid_mech_spectral_basic end module grid_mechanical_spectral_basic

View File

@ -4,7 +4,7 @@
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
!> @brief Grid solver for mechanics: Spectral Polarisation !> @brief Grid solver for mechanics: Spectral Polarisation
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module grid_mech_spectral_polarisation module grid_mechanical_spectral_polarisation
#include <petsc/finclude/petscsnes.h> #include <petsc/finclude/petscsnes.h>
#include <petsc/finclude/petscdmda.h> #include <petsc/finclude/petscdmda.h>
use PETScdmda use PETScdmda
@ -90,18 +90,18 @@ module grid_mech_spectral_polarisation
totalIter = 0 !< total iteration in current increment totalIter = 0 !< total iteration in current increment
public :: & public :: &
grid_mech_spectral_polarisation_init, & grid_mechanical_spectral_polarisation_init, &
grid_mech_spectral_polarisation_solution, & grid_mechanical_spectral_polarisation_solution, &
grid_mech_spectral_polarisation_forward, & grid_mechanical_spectral_polarisation_forward, &
grid_mech_spectral_polarisation_updateCoords, & grid_mechanical_spectral_polarisation_updateCoords, &
grid_mech_spectral_polarisation_restartWrite grid_mechanical_spectral_polarisation_restartWrite
contains contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief allocates all necessary fields and fills them with data, potentially from restart info !> @brief allocates all necessary fields and fills them with data, potentially from restart info
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_polarisation_init subroutine grid_mechanical_spectral_polarisation_init
real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P real(pReal), dimension(3,3,grid(1),grid(2),grid3) :: P
PetscErrorCode :: ierr PetscErrorCode :: ierr
@ -112,13 +112,11 @@ subroutine grid_mech_spectral_polarisation_init
PetscInt, dimension(0:worldsize-1) :: localK PetscInt, dimension(0:worldsize-1) :: localK
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
integer :: fileUnit integer :: fileUnit
character(len=pStringLen) :: &
fileName
class (tNode), pointer :: & class (tNode), pointer :: &
num_grid, & num_grid, &
debug_grid debug_grid
print'(/,a)', ' <<<+- grid_mech_spectral_polarisation init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- grid_mechanical_spectral_polarization init -+>>>'; flush(IO_STDOUT)
print*, 'Shanthraj et al., International Journal of Plasticity 66:3145, 2015' print*, 'Shanthraj et al., International Journal of Plasticity 66:3145, 2015'
print*, 'https://doi.org/10.1016/j.ijplas.2014.02.006' print*, 'https://doi.org/10.1016/j.ijplas.2014.02.006'
@ -157,7 +155,7 @@ subroutine grid_mech_spectral_polarisation_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set default and user defined options for PETSc ! set default and user defined options for PETSc
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type ngmres',ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
@ -172,7 +170,7 @@ subroutine grid_mech_spectral_polarisation_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! initialize solver specific parts of PETSc ! initialize solver specific parts of PETSc
call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr) call SNESCreate(PETSC_COMM_WORLD,snes,ierr); CHKERRQ(ierr)
call SNESSetOptionsPrefix(snes,'mech_',ierr);CHKERRQ(ierr) call SNESSetOptionsPrefix(snes,'mechanical_',ierr);CHKERRQ(ierr)
localK = 0 localK = 0
localK(worldrank) = grid3 localK(worldrank) = grid3
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr)
@ -204,8 +202,7 @@ subroutine grid_mech_spectral_polarisation_init
restartRead: if (interface_restartInc > 0) then restartRead: if (interface_restartInc > 0) then
print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file' print'(/,a,i0,a)', ' reading restart data of increment ', interface_restartInc, ' from file'
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
fileHandle = HDF5_openFile(fileName)
groupHandle = HDF5_openGroup(fileHandle,'solver') groupHandle = HDF5_openGroup(fileHandle,'solver')
call HDF5_read(groupHandle,P_aim, 'P_aim') call HDF5_read(groupHandle,P_aim, 'P_aim')
@ -250,13 +247,13 @@ subroutine grid_mech_spectral_polarisation_init
C_scale = C_minMaxAvg C_scale = C_minMaxAvg
S_scale = math_invSym3333(C_minMaxAvg) S_scale = math_invSym3333(C_minMaxAvg)
end subroutine grid_mech_spectral_polarisation_init end subroutine grid_mechanical_spectral_polarisation_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief solution for the Polarisation scheme with internal iterations !> @brief solution for the Polarisation scheme with internal iterations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function grid_mech_spectral_polarisation_solution(incInfoIn) result(solution) function grid_mechanical_spectral_polarisation_solution(incInfoIn) result(solution)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! input data for solution ! input data for solution
@ -294,14 +291,14 @@ function grid_mech_spectral_polarisation_solution(incInfoIn) result(solution)
terminallyIll = .false. terminallyIll = .false.
P_aim = merge(P_aim,P_av,params%stress_mask) P_aim = merge(P_aim,P_av,params%stress_mask)
end function grid_mech_spectral_polarisation_solution end function grid_mechanical_spectral_polarisation_solution
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief forwarding routine !> @brief forwarding routine
!> @details find new boundary conditions and best F estimate for end of current timestep !> @details find new boundary conditions and best F estimate for end of current timestep
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_polarisation_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,& subroutine grid_mechanical_spectral_polarisation_forward(cutBack,guess,Delta_t,Delta_t_old,t_remaining,&
deformation_BC,stress_BC,rotation_BC) deformation_BC,stress_BC,rotation_BC)
logical, intent(in) :: & logical, intent(in) :: &
@ -393,13 +390,13 @@ subroutine grid_mech_spectral_polarisation_forward(cutBack,guess,Delta_t,Delta_t
params%rotation_BC = rotation_BC params%rotation_BC = rotation_BC
params%timeinc = Delta_t params%timeinc = Delta_t
end subroutine grid_mech_spectral_polarisation_forward end subroutine grid_mechanical_spectral_polarisation_forward
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Update coordinates !> @brief Update coordinates
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_polarisation_updateCoords subroutine grid_mechanical_spectral_polarisation_updateCoords
PetscErrorCode :: ierr PetscErrorCode :: ierr
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau
@ -408,18 +405,17 @@ subroutine grid_mech_spectral_polarisation_updateCoords
call utilities_updateCoords(FandF_tau(0:8,:,:,:)) call utilities_updateCoords(FandF_tau(0:8,:,:,:))
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
end subroutine grid_mech_spectral_polarisation_updateCoords end subroutine grid_mechanical_spectral_polarisation_updateCoords
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Write current solver and constitutive data for restart to file !> @brief Write current solver and constitutive data for restart to file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_mech_spectral_polarisation_restartWrite subroutine grid_mechanical_spectral_polarisation_restartWrite
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer(HID_T) :: fileHandle, groupHandle integer(HID_T) :: fileHandle, groupHandle
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau
character(len=pStringLen) :: fileName
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
F => FandF_tau(0: 8,:,:,:) F => FandF_tau(0: 8,:,:,:)
@ -427,8 +423,7 @@ subroutine grid_mech_spectral_polarisation_restartWrite
print*, 'writing solver data required for restart to file'; flush(IO_STDOUT) print*, 'writing solver data required for restart to file'; flush(IO_STDOUT)
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5' fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
fileHandle = HDF5_openFile(fileName,'w')
groupHandle = HDF5_addGroup(fileHandle,'solver') groupHandle = HDF5_addGroup(fileHandle,'solver')
call HDF5_write(groupHandle,F_aim, 'P_aim') call HDF5_write(groupHandle,F_aim, 'P_aim')
@ -450,7 +445,7 @@ subroutine grid_mech_spectral_polarisation_restartWrite
call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
end subroutine grid_mech_spectral_polarisation_restartWrite end subroutine grid_mechanical_spectral_polarisation_restartWrite
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
@ -618,4 +613,4 @@ subroutine formResidual(in, FandF_tau, &
end subroutine formResidual end subroutine formResidual
end module grid_mech_spectral_polarisation end module grid_mechanical_spectral_polarisation

View File

@ -15,11 +15,11 @@ module grid_thermal_spectral
use IO use IO
use spectral_utilities use spectral_utilities
use discretization_grid use discretization_grid
use thermal_conduction use homogenization
use YAML_types use YAML_types
use config use config
use material use material
implicit none implicit none
private private
@ -45,11 +45,11 @@ module grid_thermal_spectral
T_stagInc !< field of staggered temperature T_stagInc !< field of staggered temperature
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! reference diffusion tensor, mobility etc. ! reference diffusion tensor, mobility etc.
integer :: totalIter = 0 !< total iteration in current increment integer :: totalIter = 0 !< total iteration in current increment
real(pReal), dimension(3,3) :: K_ref real(pReal), dimension(3,3) :: K_ref
real(pReal) :: mu_ref real(pReal) :: mu_ref
public :: & public :: &
grid_thermal_spectral_init, & grid_thermal_spectral_init, &
grid_thermal_spectral_solution, & grid_thermal_spectral_solution, &
@ -61,10 +61,12 @@ contains
!> @brief allocates all neccessary fields and fills them with data !> @brief allocates all neccessary fields and fills them with data
! ToDo: Restart not implemented ! ToDo: Restart not implemented
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_thermal_spectral_init subroutine grid_thermal_spectral_init(T_0)
PetscInt, dimension(0:worldsize-1) :: localK real(pReal), intent(in) :: T_0
integer :: i, j, k, cell
PetscInt, dimension(0:worldsize-1) :: localK
integer :: i, j, k, ce
DM :: thermal_grid DM :: thermal_grid
PetscScalar, dimension(:,:,:), pointer :: x_scal PetscScalar, dimension(:,:,:), pointer :: x_scal
PetscErrorCode :: ierr PetscErrorCode :: ierr
@ -93,11 +95,11 @@ subroutine grid_thermal_spectral_init
CHKERRQ(ierr) CHKERRQ(ierr)
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! initialize solver specific parts of PETSc ! initialize solver specific parts of PETSc
call SNESCreate(PETSC_COMM_WORLD,thermal_snes,ierr); CHKERRQ(ierr) call SNESCreate(PETSC_COMM_WORLD,thermal_snes,ierr); CHKERRQ(ierr)
call SNESSetOptionsPrefix(thermal_snes,'thermal_',ierr);CHKERRQ(ierr) call SNESSetOptionsPrefix(thermal_snes,'thermal_',ierr);CHKERRQ(ierr)
localK = 0 localK = 0
localK(worldrank) = grid3 localK(worldrank) = grid3
call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,localK,worldsize,MPI_INTEGER,MPI_SUM,PETSC_COMM_WORLD,ierr)
@ -115,25 +117,26 @@ subroutine grid_thermal_spectral_init
call DMsetUp(thermal_grid,ierr); CHKERRQ(ierr) call DMsetUp(thermal_grid,ierr); CHKERRQ(ierr)
call DMCreateGlobalVector(thermal_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor) call DMCreateGlobalVector(thermal_grid,solution_vec,ierr); CHKERRQ(ierr) ! global solution vector (grid x 1, i.e. every def grad tensor)
call DMDASNESSetFunctionLocal(thermal_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector call DMDASNESSetFunctionLocal(thermal_grid,INSERT_VALUES,formResidual,PETSC_NULL_SNES,ierr) ! residual vector of same shape as solution vector
CHKERRQ(ierr) CHKERRQ(ierr)
call SNESSetFromOptions(thermal_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments call SNESSetFromOptions(thermal_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! init fields ! init fields
call DMDAGetCorners(thermal_grid,xstart,ystart,zstart,xend,yend,zend,ierr) call DMDAGetCorners(thermal_grid,xstart,ystart,zstart,xend,yend,zend,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
xend = xstart + xend - 1 xend = xstart + xend - 1
yend = ystart + yend - 1 yend = ystart + yend - 1
zend = zstart + zend - 1 zend = zstart + zend - 1
allocate(T_current(grid(1),grid(2),grid3), source=0.0_pReal) allocate(T_current(grid(1),grid(2),grid3), source=0.0_pReal)
allocate(T_lastInc(grid(1),grid(2),grid3), source=0.0_pReal) allocate(T_lastInc(grid(1),grid(2),grid3), source=0.0_pReal)
allocate(T_stagInc(grid(1),grid(2),grid3), source=0.0_pReal) allocate(T_stagInc(grid(1),grid(2),grid3), source=0.0_pReal)
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
T_current(i,j,k) = temperature(material_homogenizationAt(cell))%p(material_homogenizationMemberAt(1,cell)) T_current(i,j,k) = T_0
T_lastInc(i,j,k) = T_current(i,j,k) T_lastInc(i,j,k) = T_current(i,j,k)
T_stagInc(i,j,k) = T_current(i,j,k) T_stagInc(i,j,k) = T_current(i,j,k)
call homogenization_thermal_setField(T_0,0.0_pReal,ce)
enddo; enddo; enddo enddo; enddo; enddo
call DMDAVecGetArrayF90(thermal_grid,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with call DMDAVecGetArrayF90(thermal_grid,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with
x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current
@ -143,26 +146,26 @@ subroutine grid_thermal_spectral_init
end subroutine grid_thermal_spectral_init end subroutine grid_thermal_spectral_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief solution for the spectral thermal scheme with internal iterations !> @brief solution for the spectral thermal scheme with internal iterations
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function grid_thermal_spectral_solution(timeinc) result(solution) function grid_thermal_spectral_solution(timeinc) result(solution)
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
timeinc !< increment in time for current solution timeinc !< increment in time for current solution
integer :: i, j, k, cell integer :: i, j, k, ce
type(tSolutionState) :: solution type(tSolutionState) :: solution
PetscInt :: devNull PetscInt :: devNull
PetscReal :: T_min, T_max, stagNorm, solnNorm PetscReal :: T_min, T_max, stagNorm, solnNorm
PetscErrorCode :: ierr PetscErrorCode :: ierr
SNESConvergedReason :: reason SNESConvergedReason :: reason
solution%converged =.false. solution%converged =.false.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! set module wide availabe data ! set module wide availabe data
params%timeinc = timeinc params%timeinc = timeinc
call SNESSolve(thermal_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr) call SNESSolve(thermal_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
@ -183,13 +186,13 @@ function grid_thermal_spectral_solution(timeinc) result(solution)
solution%stagConverged = stagNorm < max(num%eps_thermal_atol, num%eps_thermal_rtol*solnNorm) solution%stagConverged = stagNorm < max(num%eps_thermal_atol, num%eps_thermal_rtol*solnNorm)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! updating thermal state ! updating thermal state
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call thermal_conduction_putTemperatureAndItsRate(T_current(i,j,k), & call homogenization_thermal_setField(T_current(i,j,k), &
(T_current(i,j,k)-T_lastInc(i,j,k))/params%timeinc, & (T_current(i,j,k)-T_lastInc(i,j,k))/params%timeinc, &
1,cell) ce)
enddo; enddo; enddo enddo; enddo; enddo
call VecMin(solution_vec,devNull,T_min,ierr); CHKERRQ(ierr) call VecMin(solution_vec,devNull,T_min,ierr); CHKERRQ(ierr)
@ -198,7 +201,7 @@ function grid_thermal_spectral_solution(timeinc) result(solution)
print'(/,a)', ' ... thermal conduction converged ..................................' print'(/,a)', ' ... thermal conduction converged ..................................'
print'(/,a,f8.4,2x,f8.4,2x,f8.4)', ' Minimum|Maximum|Delta Temperature / K = ', T_min, T_max, stagNorm print'(/,a,f8.4,2x,f8.4,2x,f8.4)', ' Minimum|Maximum|Delta Temperature / K = ', T_min, T_max, stagNorm
print'(/,a)', ' ===========================================================================' print'(/,a)', ' ==========================================================================='
flush(IO_STDOUT) flush(IO_STDOUT)
end function grid_thermal_spectral_solution end function grid_thermal_spectral_solution
@ -207,36 +210,35 @@ end function grid_thermal_spectral_solution
!> @brief forwarding routine !> @brief forwarding routine
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine grid_thermal_spectral_forward(cutBack) subroutine grid_thermal_spectral_forward(cutBack)
logical, intent(in) :: cutBack logical, intent(in) :: cutBack
integer :: i, j, k, cell integer :: i, j, k, ce
DM :: dm_local DM :: dm_local
PetscScalar, dimension(:,:,:), pointer :: x_scal PetscScalar, dimension(:,:,:), pointer :: x_scal
PetscErrorCode :: ierr PetscErrorCode :: ierr
if (cutBack) then if (cutBack) then
T_current = T_lastInc T_current = T_lastInc
T_stagInc = T_lastInc T_stagInc = T_lastInc
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! reverting thermal field state ! reverting thermal field state
cell = 0 ce = 0
call SNESGetDM(thermal_snes,dm_local,ierr); CHKERRQ(ierr) call SNESGetDM(thermal_snes,dm_local,ierr); CHKERRQ(ierr)
call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with call DMDAVecGetArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) !< get the data out of PETSc to work with
x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current
call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr) call DMDAVecRestoreArrayF90(dm_local,solution_vec,x_scal,ierr); CHKERRQ(ierr)
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call thermal_conduction_putTemperatureAndItsRate(T_current(i,j,k), & call homogenization_thermal_setField(T_current(i,j,k), &
(T_current(i,j,k) - & (T_current(i,j,k)-T_lastInc(i,j,k))/params%timeinc, &
T_lastInc(i,j,k))/params%timeinc, & ce)
1,cell)
enddo; enddo; enddo enddo; enddo; enddo
else else
T_lastInc = T_current T_lastInc = T_current
call updateReference call updateReference
endif endif
end subroutine grid_thermal_spectral_forward end subroutine grid_thermal_spectral_forward
@ -244,7 +246,7 @@ end subroutine grid_thermal_spectral_forward
!> @brief forms the spectral thermal residual vector !> @brief forms the spectral thermal residual vector
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine formResidual(in,x_scal,f_scal,dummy,ierr) subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: & DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
in in
PetscScalar, dimension( & PetscScalar, dimension( &
@ -255,33 +257,33 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
f_scal f_scal
PetscObject :: dummy PetscObject :: dummy
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer :: i, j, k, cell integer :: i, j, k, ce
real(pReal) :: Tdot, dTdot_dT real(pReal) :: Tdot
T_current = x_scal T_current = x_scal
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate polarization field ! evaluate polarization field
scalarField_real = 0.0_pReal scalarField_real = 0.0_pReal
scalarField_real(1:grid(1),1:grid(2),1:grid3) = T_current scalarField_real(1:grid(1),1:grid(2),1:grid3) = T_current
call utilities_FFTscalarForward call utilities_FFTscalarForward
call utilities_fourierScalarGradient !< calculate gradient of temperature field call utilities_fourierScalarGradient !< calculate gradient of temperature field
call utilities_FFTvectorBackward call utilities_FFTvectorBackward
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
vectorField_real(1:3,i,j,k) = matmul(thermal_conduction_getConductivity(1,cell) - K_ref, & vectorField_real(1:3,i,j,k) = matmul(thermal_conduction_getConductivity(ce) - K_ref, &
vectorField_real(1:3,i,j,k)) vectorField_real(1:3,i,j,k))
enddo; enddo; enddo enddo; enddo; enddo
call utilities_FFTvectorForward call utilities_FFTvectorForward
call utilities_fourierVectorDivergence !< calculate temperature divergence in fourier field call utilities_fourierVectorDivergence !< calculate temperature divergence in fourier field
call utilities_FFTscalarBackward call utilities_FFTscalarBackward
cell = 0 ce = 0
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
call thermal_conduction_getSourceAndItsTangent(Tdot, dTdot_dT, T_current(i,j,k), 1, cell) call thermal_conduction_getSource(Tdot,1,ce)
scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + Tdot) & scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + Tdot) &
+ thermal_conduction_getMassDensity (1,cell)* & + thermal_conduction_getMassDensity (ce)* &
thermal_conduction_getSpecificHeat(1,cell)*(T_lastInc(i,j,k) - & thermal_conduction_getSpecificHeat(ce)*(T_lastInc(i,j,k) - &
T_current(i,j,k))& T_current(i,j,k))&
+ mu_ref*T_current(i,j,k) + mu_ref*T_current(i,j,k)
enddo; enddo; enddo enddo; enddo; enddo
@ -291,7 +293,7 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
call utilities_FFTscalarForward call utilities_FFTscalarForward
call utilities_fourierGreenConvolution(K_ref, mu_ref, params%timeinc) call utilities_fourierGreenConvolution(K_ref, mu_ref, params%timeinc)
call utilities_FFTscalarBackward call utilities_FFTscalarBackward
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! constructing residual ! constructing residual
f_scal = T_current - scalarField_real(1:grid(1),1:grid(2),1:grid3) f_scal = T_current - scalarField_real(1:grid(1),1:grid(2),1:grid3)
@ -304,15 +306,15 @@ end subroutine formResidual
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine updateReference subroutine updateReference
integer :: i,j,k,cell,ierr integer :: i,j,k,ce,ierr
cell = 0 ce = 0
K_ref = 0.0_pReal K_ref = 0.0_pReal
mu_ref = 0.0_pReal mu_ref = 0.0_pReal
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
cell = cell + 1 ce = ce + 1
K_ref = K_ref + thermal_conduction_getConductivity(1,cell) K_ref = K_ref + thermal_conduction_getConductivity(ce)
mu_ref = mu_ref + thermal_conduction_getMassDensity(1,cell)* thermal_conduction_getSpecificHeat(1,cell) mu_ref = mu_ref + thermal_conduction_getMassDensity(ce)* thermal_conduction_getSpecificHeat(ce)
enddo; enddo; enddo enddo; enddo; enddo
K_ref = K_ref*wgt K_ref = K_ref*wgt
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr) call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr)

View File

@ -10,17 +10,47 @@ module homogenization
use config use config
use math use math
use material use material
use constitutive use phase
use discretization use discretization
use thermal_isothermal use HDF5_utilities
use thermal_conduction
use damage_none
use damage_nonlocal
use results use results
use lattice
implicit none implicit none
private private
enum, bind(c); enumerator :: &
THERMAL_ISOTHERMAL_ID, &
THERMAL_CONDUCTION_ID, &
DAMAGE_NONE_ID, &
DAMAGE_NONLOCAL_ID, &
HOMOGENIZATION_UNDEFINED_ID, &
HOMOGENIZATION_NONE_ID, &
HOMOGENIZATION_ISOSTRAIN_ID, &
HOMOGENIZATION_RGC_ID
end enum
type(tState), allocatable, dimension(:), public :: &
homogState, &
damageState_h
integer(kind(THERMAL_isothermal_ID)), dimension(:), allocatable :: &
thermal_type !< thermal transport model
integer(kind(DAMAGE_none_ID)), dimension(:), allocatable :: &
damage_type !< nonlocal damage model
integer(kind(HOMOGENIZATION_undefined_ID)), dimension(:), allocatable :: &
homogenization_type !< type of each homogenization
type, private :: tNumerics_damage
real(pReal) :: &
charLength !< characteristic length scale for gradient problems
end type tNumerics_damage
type(tNumerics_damage), private :: &
num_damage
logical, public :: & logical, public :: &
terminallyIll = .false. !< at least one material point is terminally ill terminallyIll = .false. !< at least one material point is terminally ill
@ -39,10 +69,6 @@ module homogenization
type :: tNumerics type :: tNumerics
integer :: & integer :: &
nMPstate !< materialpoint state loop limit nMPstate !< materialpoint state loop limit
real(pReal) :: &
subStepMinHomog, & !< minimum (relative) size of sub-step allowed during cutback in homogenization
subStepSizeHomog, & !< size of first substep when cutback in homogenization
stepIncreaseHomog !< increase of next substep size when previous substep converged in homogenization
end type tNumerics end type tNumerics
type(tNumerics) :: num type(tNumerics) :: num
@ -50,48 +76,143 @@ module homogenization
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
interface interface
module subroutine mech_init(num_homog) module subroutine mechanical_init(num_homog)
class(tNode), pointer, intent(in) :: & class(tNode), pointer, intent(in) :: &
num_homog !< pointer to mechanical homogenization numerics data num_homog !< pointer to mechanical homogenization numerics data
end subroutine mech_init end subroutine mechanical_init
module subroutine mech_partition(subF,ip,el) module subroutine thermal_init
end subroutine thermal_init
module subroutine damage_init
end subroutine damage_init
module subroutine mechanical_partition(subF,ce)
real(pReal), intent(in), dimension(3,3) :: & real(pReal), intent(in), dimension(3,3) :: &
subF subF
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point ce
el !< element number end subroutine mechanical_partition
end subroutine mech_partition
module subroutine mech_homogenize(ip,el) module subroutine thermal_partition(ce)
integer, intent(in) :: ce
end subroutine thermal_partition
module subroutine damage_partition(ce)
integer, intent(in) :: ce
end subroutine damage_partition
module subroutine thermal_homogenize(ip,el)
integer, intent(in) :: ip,el
end subroutine thermal_homogenize
module subroutine mechanical_homogenize(dt,ce)
real(pReal), intent(in) :: dt
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point ce !< cell
el !< element number end subroutine mechanical_homogenize
end subroutine mech_homogenize
module subroutine mech_results(group_base,h) module subroutine mechanical_results(group_base,ho)
character(len=*), intent(in) :: group_base character(len=*), intent(in) :: group_base
integer, intent(in) :: h integer, intent(in) :: ho
end subroutine mech_results end subroutine mechanical_results
module function mech_updateState(subdt,subF,ip,el) result(doneAndHappy) module function mechanical_updateState(subdt,subF,ce) result(doneAndHappy)
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
subdt !< current time step subdt !< current time step
real(pReal), intent(in), dimension(3,3) :: & real(pReal), intent(in), dimension(3,3) :: &
subF subF
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point ce !< cell
el !< element number
logical, dimension(2) :: doneAndHappy logical, dimension(2) :: doneAndHappy
end function mech_updateState end function mechanical_updateState
module function thermal_conduction_getConductivity(ce) result(K)
integer, intent(in) :: ce
real(pReal), dimension(3,3) :: K
end function thermal_conduction_getConductivity
module function thermal_conduction_getSpecificHeat(ce) result(c_P)
integer, intent(in) :: ce
real(pReal) :: c_P
end function thermal_conduction_getSpecificHeat
module function thermal_conduction_getMassDensity(ce) result(rho)
integer, intent(in) :: ce
real(pReal) :: rho
end function thermal_conduction_getMassDensity
module subroutine homogenization_thermal_setField(T,dot_T, ce)
integer, intent(in) :: ce
real(pReal), intent(in) :: T, dot_T
end subroutine homogenization_thermal_setField
module subroutine thermal_conduction_results(ho,group)
integer, intent(in) :: ho
character(len=*), intent(in) :: group
end subroutine thermal_conduction_results
module function homogenization_thermal_T(ce) result(T)
integer, intent(in) :: ce
real(pReal) :: T
end function homogenization_thermal_T
module subroutine thermal_conduction_getSource(Tdot, ip, el)
integer, intent(in) :: &
ip, &
el
real(pReal), intent(out) :: Tdot
end subroutine thermal_conduction_getSource
module function damage_nonlocal_getMobility(ce) result(M)
integer, intent(in) :: ce
real(pReal) :: M
end function damage_nonlocal_getMobility
module subroutine damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ce)
integer, intent(in) :: ce
real(pReal), intent(in) :: &
phi
real(pReal) :: &
phiDot, dPhiDot_dPhi
end subroutine damage_nonlocal_getSourceAndItsTangent
module subroutine damage_nonlocal_putNonLocalDamage(phi,ce)
integer, intent(in) :: ce
real(pReal), intent(in) :: &
phi
end subroutine damage_nonlocal_putNonLocalDamage
module subroutine damage_nonlocal_results(ho,group)
integer, intent(in) :: ho
character(len=*), intent(in) :: group
end subroutine damage_nonlocal_results
end interface end interface
public :: & public :: &
homogenization_init, & homogenization_init, &
materialpoint_stressAndItsTangent, & materialpoint_stressAndItsTangent, &
thermal_conduction_getSpecificHeat, &
thermal_conduction_getConductivity, &
thermal_conduction_getMassDensity, &
thermal_conduction_getSource, &
damage_nonlocal_getMobility, &
damage_nonlocal_getSourceAndItsTangent, &
damage_nonlocal_putNonLocalDamage, &
homogenization_thermal_setfield, &
homogenization_thermal_T, &
homogenization_forward, & homogenization_forward, &
homogenization_results homogenization_results, &
homogenization_restartRead, &
homogenization_restartWrite, &
THERMAL_CONDUCTION_ID, &
DAMAGE_NONLOCAL_ID
public :: &
damage_nonlocal_init, &
damage_nonlocal_getDiffusion
contains contains
@ -99,7 +220,7 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief module initialization !> @brief module initialization
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine homogenization_init subroutine homogenization_init()
class (tNode) , pointer :: & class (tNode) , pointer :: &
num_homog, & num_homog, &
@ -107,27 +228,21 @@ subroutine homogenization_init
print'(/,a)', ' <<<+- homogenization init -+>>>'; flush(IO_STDOUT) print'(/,a)', ' <<<+- homogenization init -+>>>'; flush(IO_STDOUT)
allocate(homogState (size(material_name_homogenization)))
allocate(damageState_h (size(material_name_homogenization)))
call material_parseHomogenization()
num_homog => config_numerics%get('homogenization',defaultVal=emptyDict) num_homog => config_numerics%get('homogenization',defaultVal=emptyDict)
num_homogGeneric => num_homog%get('generic',defaultVal=emptyDict) num_homogGeneric => num_homog%get('generic',defaultVal=emptyDict)
num%nMPstate = num_homogGeneric%get_asInt ('nMPstate', defaultVal=10) num%nMPstate = num_homogGeneric%get_asInt('nMPstate',defaultVal=10)
num%subStepMinHomog = num_homogGeneric%get_asFloat('subStepMin', defaultVal=1.0e-3_pReal) if (num%nMPstate < 1) call IO_error(301,ext_msg='nMPstate')
num%subStepSizeHomog = num_homogGeneric%get_asFloat('subStepSize', defaultVal=0.25_pReal)
num%stepIncreaseHomog = num_homogGeneric%get_asFloat('stepIncrease', defaultVal=1.5_pReal)
if (num%nMPstate < 1) call IO_error(301,ext_msg='nMPstate') call mechanical_init(num_homog)
if (num%subStepMinHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepMinHomog') call thermal_init()
if (num%subStepSizeHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeHomog') call damage_init()
if (num%stepIncreaseHomog <= 0.0_pReal) call IO_error(301,ext_msg='stepIncreaseHomog') call damage_nonlocal_init()
call mech_init(num_homog)
if (any(thermal_type == THERMAL_isothermal_ID)) call thermal_isothermal_init
if (any(thermal_type == THERMAL_conduction_ID)) call thermal_conduction_init
if (any(damage_type == DAMAGE_none_ID)) call damage_none_init
if (any(damage_type == DAMAGE_nonlocal_ID)) call damage_nonlocal_init
end subroutine homogenization_init end subroutine homogenization_init
@ -144,126 +259,96 @@ subroutine materialpoint_stressAndItsTangent(dt,FEsolving_execIP,FEsolving_execE
NiterationMPstate, & NiterationMPstate, &
ip, & !< integration point number ip, & !< integration point number
el, & !< element number el, & !< element number
myNgrains, co, ce, ho, me myNgrains, co, ce, ho, me, ph
real(pReal) :: &
subFrac, &
subStep
logical :: & logical :: &
converged converged
logical, dimension(2) :: & logical, dimension(2) :: &
doneAndHappy doneAndHappy
!$OMP PARALLEL
!$OMP PARALLEL DO PRIVATE(ce,me,ho,myNgrains,NiterationMPstate,subFrac,converged,subStep,doneAndHappy) !$OMP DO PRIVATE(ce,me,ho,myNgrains,NiterationMPstate,converged,doneAndHappy)
do el = FEsolving_execElem(1),FEsolving_execElem(2) do el = FEsolving_execElem(1),FEsolving_execElem(2)
ho = material_homogenizationAt(el) ho = material_homogenizationAt(el)
myNgrains = homogenization_Nconstituents(ho) myNgrains = homogenization_Nconstituents(ho)
do ip = FEsolving_execIP(1),FEsolving_execIP(2) do ip = FEsolving_execIP(1),FEsolving_execIP(2)
me = material_homogenizationMemberAt(ip,el) ce = (el-1)*discretization_nIPs + ip
!-------------------------------------------------------------------------------------------------- me = material_homogenizationMemberAt2(ce)
! initialize restoration points
call constitutive_initializeRestorationPoints(ip,el)
subFrac = 0.0_pReal call phase_restore(ce,.false.) ! wrong name (is more a forward function)
converged = .false. ! pretend failed step ...
subStep = 1.0_pReal/num%subStepSizeHomog ! ... larger then the requested calculation
if (homogState(ho)%sizeState > 0) & if(homogState(ho)%sizeState > 0) homogState(ho)%State(:,me) = homogState(ho)%State0(:,me)
homogState(ho)%subState0(:,me) = homogState(ho)%State0(:,me) if(damageState_h(ho)%sizeState > 0) damageState_h(ho)%State(:,me) = damageState_h(ho)%State0(:,me)
if (damageState(ho)%sizeState > 0) & call damage_partition(ce)
damageState(ho)%subState0(:,me) = damageState(ho)%State0(:,me)
cutBackLooping: do while (.not. terminallyIll .and. subStep > num%subStepMinHomog) doneAndHappy = [.false.,.true.]
if (converged) then NiterationMPstate = 0
subFrac = subFrac + subStep convergenceLooping: do while (.not. (terminallyIll .or. doneAndHappy(1)) &
subStep = min(1.0_pReal-subFrac,num%stepIncreaseHomog*subStep) ! introduce flexibility for step increase/acceleration .and. NiterationMPstate < num%nMPstate)
NiterationMPstate = NiterationMPstate + 1
steppingNeeded: if (subStep > num%subStepMinHomog) then
! wind forward grain starting point if (.not. doneAndHappy(1)) then
call constitutive_windForward(ip,el) call mechanical_partition(homogenization_F(1:3,1:3,ce),ce)
converged = .true.
do co = 1, myNgrains
converged = converged .and. crystallite_stress(dt,co,ip,el)
enddo
if(homogState(ho)%sizeState > 0) & if (.not. converged) then
homogState(ho)%subState0(:,me) = homogState(ho)%State(:,me) doneAndHappy = [.true.,.false.]
if(damageState(ho)%sizeState > 0) & else
damageState(ho)%subState0(:,me) = damageState(ho)%State(:,me) doneAndHappy = mechanical_updateState(dt,homogenization_F(1:3,1:3,ce),ce)
converged = all(doneAndHappy)
endif steppingNeeded endif
elseif ( (myNgrains == 1 .and. subStep <= 1.0 ) .or. & ! single grain already tried internal subStepping in crystallite
num%subStepSizeHomog * subStep <= num%subStepMinHomog ) then ! would require too small subStep
! cutback makes no sense
if (.not. terminallyIll) & ! so first signals terminally ill...
print*, ' Integration point ', ip,' at element ', el, ' terminally ill'
terminallyIll = .true. ! ...and kills all others
else ! cutback makes sense
subStep = num%subStepSizeHomog * subStep ! crystallite had severe trouble, so do a significant cutback
call constitutive_restore(ip,el,subStep < 1.0_pReal)
if(homogState(ho)%sizeState > 0) &
homogState(ho)%State(:,me) = homogState(ho)%subState0(:,me)
if(damageState(ho)%sizeState > 0) &
damageState(ho)%State(:,me) = damageState(ho)%subState0(:,me)
endif endif
if (subStep > num%subStepMinHomog) doneAndHappy = [.false.,.true.] enddo convergenceLooping
if (.not. converged) then
NiterationMPstate = 0 if (.not. terminallyIll) print*, ' Integration point ', ip,' at element ', el, ' terminally ill'
convergenceLooping: do while (.not. terminallyIll & terminallyIll = .true.
.and. .not. doneAndHappy(1) & endif
.and. NiterationMPstate < num%nMPstate)
NiterationMPstate = NiterationMPstate + 1
!--------------------------------------------------------------------------------------------------
! deformation partitioning
if (.not. doneAndHappy(1)) then
ce = (el-1)*discretization_nIPs + ip
call mech_partition(homogenization_F0(1:3,1:3,ce) &
+ (homogenization_F(1:3,1:3,ce)-homogenization_F0(1:3,1:3,ce))&
*(subStep+subFrac), &
ip,el)
converged = .true.
do co = 1, myNgrains
converged = converged .and. crystallite_stress(dt*subStep,co,ip,el)
enddo
if (.not. converged) then
doneAndHappy = [.true.,.false.]
else
ce = (el-1)*discretization_nIPs + ip
doneAndHappy = mech_updateState(dt*subStep, &
homogenization_F0(1:3,1:3,ce) &
+ (homogenization_F(1:3,1:3,ce)-homogenization_F0(1:3,1:3,ce)) &
*(subStep+subFrac), &
ip,el)
converged = all(doneAndHappy)
endif
endif
enddo convergenceLooping
enddo cutBackLooping
enddo enddo
enddo enddo
!$OMP END PARALLEL DO !$OMP END DO
if (.not. terminallyIll ) then if (.not. terminallyIll) then
!$OMP PARALLEL DO PRIVATE(ho,myNgrains) !$OMP DO PRIVATE(ho,ph,ce)
do el = FEsolving_execElem(1),FEsolving_execElem(2)
if (terminallyIll) continue
ho = material_homogenizationAt(el)
do ip = FEsolving_execIP(1),FEsolving_execIP(2)
ce = (el-1)*discretization_nIPs + ip
call thermal_partition(ce)
do co = 1, homogenization_Nconstituents(ho)
ph = material_phaseAt(co,el)
if (.not. thermal_stress(dt,ph,material_phaseMemberAt(co,ip,el))) then
if (.not. terminallyIll) & ! so first signals terminally ill...
print*, ' Integration point ', ip,' at element ', el, ' terminally ill'
terminallyIll = .true. ! ...and kills all others
endif
enddo
call thermal_homogenize(ip,el)
enddo
enddo
!$OMP END DO
!$OMP DO PRIVATE(ho,ce)
elementLooping3: do el = FEsolving_execElem(1),FEsolving_execElem(2) elementLooping3: do el = FEsolving_execElem(1),FEsolving_execElem(2)
ho = material_homogenizationAt(el) ho = material_homogenizationAt(el)
myNgrains = homogenization_Nconstituents(ho)
IpLooping3: do ip = FEsolving_execIP(1),FEsolving_execIP(2) IpLooping3: do ip = FEsolving_execIP(1),FEsolving_execIP(2)
do co = 1, myNgrains ce = (el-1)*discretization_nIPs + ip
do co = 1, homogenization_Nconstituents(ho)
call crystallite_orientations(co,ip,el) call crystallite_orientations(co,ip,el)
enddo enddo
call mech_homogenize(ip,el) call mechanical_homogenize(dt,ce)
enddo IpLooping3 enddo IpLooping3
enddo elementLooping3 enddo elementLooping3
!$OMP END PARALLEL DO !$OMP END DO
else else
print'(/,a,/)', ' << HOMOG >> Material Point terminally ill' print'(/,a,/)', ' << HOMOG >> Material Point terminally ill'
endif endif
!$OMP END PARALLEL
end subroutine materialpoint_stressAndItsTangent end subroutine materialpoint_stressAndItsTangent
@ -283,7 +368,7 @@ subroutine homogenization_results
group_base = 'current/homogenization/'//trim(material_name_homogenization(ho)) group_base = 'current/homogenization/'//trim(material_name_homogenization(ho))
call results_closeGroup(results_addGroup(group_base)) call results_closeGroup(results_addGroup(group_base))
call mech_results(group_base,ho) call mechanical_results(group_base,ho)
group = trim(group_base)//'/damage' group = trim(group_base)//'/damage'
call results_closeGroup(results_addGroup(group)) call results_closeGroup(results_addGroup(group))
@ -315,9 +400,185 @@ subroutine homogenization_forward
do ho = 1, size(material_name_homogenization) do ho = 1, size(material_name_homogenization)
homogState (ho)%state0 = homogState (ho)%state homogState (ho)%state0 = homogState (ho)%state
damageState(ho)%state0 = damageState(ho)%state if(damageState_h(ho)%sizeState > 0) &
damageState_h(ho)%state0 = damageState_h(ho)%state
enddo enddo
end subroutine homogenization_forward end subroutine homogenization_forward
!--------------------------------------------------------------------------------------------------
!--------------------------------------------------------------------------------------------------
subroutine homogenization_restartWrite(fileHandle)
integer(HID_T), intent(in) :: fileHandle
integer(HID_T), dimension(2) :: groupHandle
integer :: ho
groupHandle(1) = HDF5_addGroup(fileHandle,'homogenization')
do ho = 1, size(material_name_homogenization)
groupHandle(2) = HDF5_addGroup(groupHandle(1),material_name_homogenization(ho))
call HDF5_write(groupHandle(2),homogState(ho)%state,'omega') ! ToDo: should be done by mech
call HDF5_closeGroup(groupHandle(2))
enddo
call HDF5_closeGroup(groupHandle(1))
end subroutine homogenization_restartWrite
!--------------------------------------------------------------------------------------------------
!--------------------------------------------------------------------------------------------------
subroutine homogenization_restartRead(fileHandle)
integer(HID_T), intent(in) :: fileHandle
integer(HID_T), dimension(2) :: groupHandle
integer :: ho
groupHandle(1) = HDF5_openGroup(fileHandle,'homogenization')
do ho = 1, size(material_name_homogenization)
groupHandle(2) = HDF5_openGroup(groupHandle(1),material_name_homogenization(ho))
call HDF5_read(groupHandle(2),homogState(ho)%state,'omega') ! ToDo: should be done by mech
call HDF5_closeGroup(groupHandle(2))
enddo
call HDF5_closeGroup(groupHandle(1))
end subroutine homogenization_restartRead
!--------------------------------------------------------------------------------------------------
!> @brief module initialization
!> @details reads in material parameters, allocates arrays, and does sanity checks
!--------------------------------------------------------------------------------------------------
subroutine damage_nonlocal_init
integer :: Ninstances,Nmaterialpoints,h
class(tNode), pointer :: &
num_generic, &
material_homogenization
print'(/,a)', ' <<<+- damage_nonlocal init -+>>>'; flush(6)
!------------------------------------------------------------------------------------
! read numerics parameter
num_generic => config_numerics%get('generic',defaultVal= emptyDict)
num_damage%charLength = num_generic%get_asFloat('charLength',defaultVal=1.0_pReal)
Ninstances = count(damage_type == DAMAGE_nonlocal_ID)
material_homogenization => config_material%get('homogenization')
do h = 1, material_homogenization%length
if (damage_type(h) /= DAMAGE_NONLOCAL_ID) cycle
Nmaterialpoints = count(material_homogenizationAt == h)
damageState_h(h)%sizeState = 1
allocate(damageState_h(h)%state0 (1,Nmaterialpoints), source=1.0_pReal)
allocate(damageState_h(h)%state (1,Nmaterialpoints), source=1.0_pReal)
enddo
end subroutine damage_nonlocal_init
!--------------------------------------------------------------------------------------------------
!> @brief returns homogenized non local damage diffusion tensor in reference configuration
!--------------------------------------------------------------------------------------------------
function damage_nonlocal_getDiffusion(ce)
integer, intent(in) :: ce
real(pReal), dimension(3,3) :: &
damage_nonlocal_getDiffusion
integer :: &
ho, &
co
ho = material_homogenizationAt2(ce)
damage_nonlocal_getDiffusion = 0.0_pReal
do co = 1, homogenization_Nconstituents(ho)
damage_nonlocal_getDiffusion = damage_nonlocal_getDiffusion + &
crystallite_push33ToRef(co,ce,lattice_D(1:3,1:3,material_phaseAt2(co,ce)))
enddo
damage_nonlocal_getDiffusion = &
num_damage%charLength**2*damage_nonlocal_getDiffusion/real(homogenization_Nconstituents(ho),pReal)
end function damage_nonlocal_getDiffusion
!--------------------------------------------------------------------------------------------------
!> @brief parses the homogenization part from the material configuration
! ToDo: This should be done in homogenization
!--------------------------------------------------------------------------------------------------
subroutine material_parseHomogenization
class(tNode), pointer :: &
material_homogenization, &
homog, &
homogMech, &
homogThermal, &
homogDamage
integer :: h
material_homogenization => config_material%get('homogenization')
allocate(homogenization_type(size(material_name_homogenization)), source=HOMOGENIZATION_undefined_ID)
allocate(thermal_type(size(material_name_homogenization)), source=THERMAL_isothermal_ID)
allocate(damage_type (size(material_name_homogenization)), source=DAMAGE_none_ID)
do h=1, size(material_name_homogenization)
homog => material_homogenization%get(h)
homogMech => homog%get('mechanics')
select case (homogMech%get_asString('type'))
case('pass')
homogenization_type(h) = HOMOGENIZATION_NONE_ID
case('isostrain')
homogenization_type(h) = HOMOGENIZATION_ISOSTRAIN_ID
case('RGC')
homogenization_type(h) = HOMOGENIZATION_RGC_ID
case default
call IO_error(500,ext_msg=homogMech%get_asString('type'))
end select
if (homog%contains('thermal')) then
homogThermal => homog%get('thermal')
select case (homogThermal%get_asString('type'))
case('pass')
thermal_type(h) = THERMAL_conduction_ID
case default
call IO_error(500,ext_msg=homogThermal%get_asString('type'))
end select
endif
if (homog%contains('damage')) then
homogDamage => homog%get('damage')
select case (homogDamage%get_asString('type'))
case('pass')
damage_type(h) = DAMAGE_nonlocal_ID
case default
call IO_error(500,ext_msg=homogDamage%get_asString('type'))
end select
endif
enddo
end subroutine material_parseHomogenization
end module homogenization end module homogenization

View File

@ -0,0 +1,168 @@
!--------------------------------------------------------------------------------------------------
!> @author Martin Diehl, KU Leuven
!--------------------------------------------------------------------------------------------------
submodule(homogenization) homogenization_damage
use lattice
type :: tDataContainer
real(pReal), dimension(:), allocatable :: phi
end type tDataContainer
type(tDataContainer), dimension(:), allocatable :: current
type :: tParameters
character(len=pStringLen), allocatable, dimension(:) :: &
output
end type tParameters
type(tparameters), dimension(:), allocatable :: &
param
contains
!--------------------------------------------------------------------------------------------------
!> @brief Allocate variables and set parameters.
!--------------------------------------------------------------------------------------------------
module subroutine damage_init()
class(tNode), pointer :: &
configHomogenizations, &
configHomogenization, &
configHomogenizationDamage
integer :: ho
print'(/,a)', ' <<<+- homogenization:damage init -+>>>'
print'(/,a)', ' <<<+- homogenization:damage:isodamage init -+>>>'
configHomogenizations => config_material%get('homogenization')
allocate(param(configHomogenizations%length))
allocate(current(configHomogenizations%length))
do ho = 1, configHomogenizations%length
allocate(current(ho)%phi(count(material_homogenizationAt2==ho)), source=1.0_pReal)
configHomogenization => configHomogenizations%get(ho)
associate(prm => param(ho))
if (configHomogenization%contains('damage')) then
configHomogenizationDamage => configHomogenization%get('damage')
#if defined (__GFORTRAN__)
prm%output = output_asStrings(configHomogenizationDamage)
#else
prm%output = configHomogenizationDamage%get_asStrings('output',defaultVal=emptyStringArray)
#endif
else
prm%output = emptyStringArray
endif
end associate
enddo
end subroutine damage_init
!--------------------------------------------------------------------------------------------------
!> @brief Partition temperature onto the individual constituents.
!--------------------------------------------------------------------------------------------------
module subroutine damage_partition(ce)
real(pReal) :: phi
integer, intent(in) :: ce
integer :: co
if(damageState_h(material_homogenizationAt2(ce))%sizeState < 1) return
phi = damagestate_h(material_homogenizationAt2(ce))%state(1,material_homogenizationMemberAt2(ce))
do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
call phase_damage_set_phi(phi,co,ce)
enddo
end subroutine damage_partition
!--------------------------------------------------------------------------------------------------
!> @brief Returns homogenized nonlocal damage mobility
!--------------------------------------------------------------------------------------------------
module function damage_nonlocal_getMobility(ce) result(M)
integer, intent(in) :: ce
integer :: &
co
real(pReal) :: M
M = 0.0_pReal
do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
M = M + lattice_M(material_phaseAt2(co,ce))
enddo
M = M/real(homogenization_Nconstituents(material_homogenizationAt2(ce)),pReal)
end function damage_nonlocal_getMobility
!--------------------------------------------------------------------------------------------------
!> @brief calculates homogenized damage driving forces
!--------------------------------------------------------------------------------------------------
module subroutine damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi, ce)
integer, intent(in) :: ce
real(pReal), intent(in) :: &
phi
real(pReal) :: &
phiDot, dPhiDot_dPhi
phiDot = 0.0_pReal
dPhiDot_dPhi = 0.0_pReal
call phase_damage_getRateAndItsTangents(phiDot, dPhiDot_dPhi, phi, ce)
phiDot = phiDot/real(homogenization_Nconstituents(material_homogenizationAt2(ce)),pReal)
dPhiDot_dPhi = dPhiDot_dPhi/real(homogenization_Nconstituents(material_homogenizationAt2(ce)),pReal)
end subroutine damage_nonlocal_getSourceAndItsTangent
!--------------------------------------------------------------------------------------------------
!> @brief updated nonlocal damage field with solution from damage phase field PDE
!--------------------------------------------------------------------------------------------------
module subroutine damage_nonlocal_putNonLocalDamage(phi,ce)
integer, intent(in) :: ce
real(pReal), intent(in) :: &
phi
integer :: &
ho, &
me
ho = material_homogenizationAt2(ce)
me = material_homogenizationMemberAt2(ce)
damagestate_h(ho)%state(1,me) = phi
end subroutine damage_nonlocal_putNonLocalDamage
!--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file
!--------------------------------------------------------------------------------------------------
module subroutine damage_nonlocal_results(ho,group)
integer, intent(in) :: ho
character(len=*), intent(in) :: group
integer :: o
associate(prm => param(ho))
outputsLoop: do o = 1,size(prm%output)
select case(prm%output(o))
case ('phi')
call results_writeDataset(group,damagestate_h(ho)%state(1,:),prm%output(o),&
'damage indicator','-')
end select
enddo outputsLoop
end associate
end subroutine damage_nonlocal_results
end submodule homogenization_damage

View File

@ -2,75 +2,72 @@
!> @author Martin Diehl, KU Leuven !> @author Martin Diehl, KU Leuven
!> @brief Partition F and homogenize P/dPdF !> @brief Partition F and homogenize P/dPdF
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
submodule(homogenization) homogenization_mech submodule(homogenization) mechanical
interface interface
module subroutine mech_none_init module subroutine mechanical_pass_init
end subroutine mech_none_init end subroutine mechanical_pass_init
module subroutine mech_isostrain_init module subroutine mechanical_isostrain_init
end subroutine mech_isostrain_init end subroutine mechanical_isostrain_init
module subroutine mech_RGC_init(num_homogMech) module subroutine mechanical_RGC_init(num_homogMech)
class(tNode), pointer, intent(in) :: & class(tNode), pointer, intent(in) :: &
num_homogMech !< pointer to mechanical homogenization numerics data num_homogMech !< pointer to mechanical homogenization numerics data
end subroutine mech_RGC_init end subroutine mechanical_RGC_init
module subroutine mech_isostrain_partitionDeformation(F,avgF) module subroutine mechanical_isostrain_partitionDeformation(F,avgF)
real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient
real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point
end subroutine mech_isostrain_partitionDeformation end subroutine mechanical_isostrain_partitionDeformation
module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) module subroutine mechanical_RGC_partitionDeformation(F,avgF,ce)
real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient
real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point
integer, intent(in) :: & integer, intent(in) :: &
instance, & ce
of end subroutine mechanical_RGC_partitionDeformation
end subroutine mech_RGC_partitionDeformation
module subroutine mech_isostrain_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) module subroutine mechanical_isostrain_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,ho)
real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point
real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
integer, intent(in) :: instance integer, intent(in) :: ho
end subroutine mech_isostrain_averageStressAndItsTangent end subroutine mechanical_isostrain_averageStressAndItsTangent
module subroutine mech_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) module subroutine mechanical_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,ho)
real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point
real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
integer, intent(in) :: instance integer, intent(in) :: ho
end subroutine mech_RGC_averageStressAndItsTangent end subroutine mechanical_RGC_averageStressAndItsTangent
module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHappy) module function mechanical_RGC_updateState(P,F,avgF,dt,dPdF,ce) result(doneAndHappy)
logical, dimension(2) :: doneAndHappy logical, dimension(2) :: doneAndHappy
real(pReal), dimension(:,:,:), intent(in) :: & real(pReal), dimension(:,:,:), intent(in) :: &
P,& !< partitioned stresses P,& !< partitioned stresses
F,& !< partitioned deformation gradients F !< partitioned deformation gradients
F0 !< partitioned initial deformation gradients
real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
real(pReal), dimension(3,3), intent(in) :: avgF !< average F real(pReal), dimension(3,3), intent(in) :: avgF !< average F
real(pReal), intent(in) :: dt !< time increment real(pReal), intent(in) :: dt !< time increment
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point number ce !< cell
el !< element number end function mechanical_RGC_updateState
end function mech_RGC_updateState
module subroutine mech_RGC_results(instance,group) module subroutine mechanical_RGC_results(ho,group)
integer, intent(in) :: instance !< homogenization instance integer, intent(in) :: ho !< homogenization type
character(len=*), intent(in) :: group !< group name in HDF5 file character(len=*), intent(in) :: group !< group name in HDF5 file
end subroutine mech_RGC_results end subroutine mechanical_RGC_results
end interface end interface
@ -79,7 +76,7 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Allocate variables and set parameters. !> @brief Allocate variables and set parameters.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_init(num_homog) module subroutine mechanical_init(num_homog)
class(tNode), pointer, intent(in) :: & class(tNode), pointer, intent(in) :: &
num_homog num_homog
@ -87,7 +84,7 @@ module subroutine mech_init(num_homog)
class(tNode), pointer :: & class(tNode), pointer :: &
num_homogMech num_homogMech
print'(/,a)', ' <<<+- homogenization_mech init -+>>>' print'(/,a)', ' <<<+- homogenization:mechanical init -+>>>'
allocate(homogenization_dPdF(3,3,3,3,discretization_nIPs*discretization_Nelems), source=0.0_pReal) allocate(homogenization_dPdF(3,3,3,3,discretization_nIPs*discretization_Nelems), source=0.0_pReal)
homogenization_F0 = spread(math_I3,3,discretization_nIPs*discretization_Nelems) ! initialize to identity homogenization_F0 = spread(math_I3,3,discretization_nIPs*discretization_Nelems) ! initialize to identity
@ -95,150 +92,145 @@ module subroutine mech_init(num_homog)
allocate(homogenization_P(3,3,discretization_nIPs*discretization_Nelems), source=0.0_pReal) allocate(homogenization_P(3,3,discretization_nIPs*discretization_Nelems), source=0.0_pReal)
num_homogMech => num_homog%get('mech',defaultVal=emptyDict) num_homogMech => num_homog%get('mech',defaultVal=emptyDict)
if (any(homogenization_type == HOMOGENIZATION_NONE_ID)) call mech_none_init if (any(homogenization_type == HOMOGENIZATION_NONE_ID)) call mechanical_pass_init
if (any(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)) call mech_isostrain_init if (any(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)) call mechanical_isostrain_init
if (any(homogenization_type == HOMOGENIZATION_RGC_ID)) call mech_RGC_init(num_homogMech) if (any(homogenization_type == HOMOGENIZATION_RGC_ID)) call mechanical_RGC_init(num_homogMech)
end subroutine mech_init end subroutine mechanical_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Partition F onto the individual constituents. !> @brief Partition F onto the individual constituents.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_partition(subF,ip,el) module subroutine mechanical_partition(subF,ce)
real(pReal), intent(in), dimension(3,3) :: & real(pReal), intent(in), dimension(3,3) :: &
subF subF
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point ce
el !< element number
chosenHomogenization: select case(homogenization_type(material_homogenizationAt(el))) integer :: co
real(pReal), dimension (3,3,homogenization_Nconstituents(material_homogenizationAt2(ce))) :: Fs
chosenHomogenization: select case(homogenization_type(material_homogenizationAt2(ce)))
case (HOMOGENIZATION_NONE_ID) chosenHomogenization case (HOMOGENIZATION_NONE_ID) chosenHomogenization
crystallite_F(1:3,1:3,1,ip,el) = subF Fs(1:3,1:3,1) = subF
case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization
call mech_isostrain_partitionDeformation(& call mechanical_isostrain_partitionDeformation(Fs,subF)
crystallite_F(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
subF)
case (HOMOGENIZATION_RGC_ID) chosenHomogenization case (HOMOGENIZATION_RGC_ID) chosenHomogenization
call mech_RGC_partitionDeformation(& call mechanical_RGC_partitionDeformation(Fs,subF,ce)
crystallite_F(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
subF,&
ip, &
el)
end select chosenHomogenization end select chosenHomogenization
end subroutine mech_partition do co = 1,homogenization_Nconstituents(material_homogenizationAt2(ce))
call phase_mechanical_setF(Fs(1:3,1:3,co),co,ce)
enddo
end subroutine mechanical_partition
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Average P and dPdF from the individual constituents. !> @brief Average P and dPdF from the individual constituents.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_homogenize(ip,el) module subroutine mechanical_homogenize(dt,ce)
integer, intent(in) :: & real(pReal), intent(in) :: dt
ip, & !< integration point integer, intent(in) :: ce
el !< element number
integer :: co,ce integer :: co
real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationAt(el))) real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationAt2(ce)))
real(pReal) :: Ps(3,3,homogenization_Nconstituents(material_homogenizationAt2(ce)))
ce = (el-1)* discretization_nIPs + ip chosenHomogenization: select case(homogenization_type(material_homogenizationAt2(ce)))
chosenHomogenization: select case(homogenization_type(material_homogenizationAt(el)))
case (HOMOGENIZATION_NONE_ID) chosenHomogenization case (HOMOGENIZATION_NONE_ID) chosenHomogenization
homogenization_P(1:3,1:3,ce) = crystallite_P(1:3,1:3,1,ip,el) homogenization_P(1:3,1:3,ce) = phase_mechanical_getP(1,ce)
homogenization_dPdF(1:3,1:3,1:3,1:3,ce) = crystallite_stressTangent(1,ip,el) homogenization_dPdF(1:3,1:3,1:3,1:3,ce) = phase_mechanical_dPdF(dt,1,ce)
case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el)) do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el) dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(dt,co,ce)
Ps(:,:,co) = phase_mechanical_getP(co,ce)
enddo enddo
call mech_isostrain_averageStressAndItsTangent(& call mechanical_isostrain_averageStressAndItsTangent(&
homogenization_P(1:3,1:3,ce), & homogenization_P(1:3,1:3,ce), &
homogenization_dPdF(1:3,1:3,1:3,1:3,ce),& homogenization_dPdF(1:3,1:3,1:3,1:3,ce),&
crystallite_P(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), & Ps,dPdFs, &
dPdFs, & material_homogenizationAt2(ce))
homogenization_typeInstance(material_homogenizationAt(el)))
case (HOMOGENIZATION_RGC_ID) chosenHomogenization case (HOMOGENIZATION_RGC_ID) chosenHomogenization
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el)) do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el) dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(dt,co,ce)
Ps(:,:,co) = phase_mechanical_getP(co,ce)
enddo enddo
call mech_RGC_averageStressAndItsTangent(& call mechanical_RGC_averageStressAndItsTangent(&
homogenization_P(1:3,1:3,ce), & homogenization_P(1:3,1:3,ce), &
homogenization_dPdF(1:3,1:3,1:3,1:3,ce),& homogenization_dPdF(1:3,1:3,1:3,1:3,ce),&
crystallite_P(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), & Ps,dPdFs, &
dPdFs, & material_homogenizationAt2(ce))
homogenization_typeInstance(material_homogenizationAt(el)))
end select chosenHomogenization end select chosenHomogenization
end subroutine mech_homogenize end subroutine mechanical_homogenize
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief update the internal state of the homogenization scheme and tell whether "done" and !> @brief update the internal state of the homogenization scheme and tell whether "done" and
!> "happy" with result !> "happy" with result
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module function mech_updateState(subdt,subF,ip,el) result(doneAndHappy) module function mechanical_updateState(subdt,subF,ce) result(doneAndHappy)
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
subdt !< current time step subdt !< current time step
real(pReal), intent(in), dimension(3,3) :: & real(pReal), intent(in), dimension(3,3) :: &
subF subF
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point ce
el !< element number
logical, dimension(2) :: doneAndHappy logical, dimension(2) :: doneAndHappy
integer :: co integer :: co
real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationAt(el))) real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationAt2(ce)))
real(pReal) :: Fs(3,3,homogenization_Nconstituents(material_homogenizationAt2(ce)))
real(pReal) :: Ps(3,3,homogenization_Nconstituents(material_homogenizationAt2(ce)))
if (homogenization_type(material_homogenizationAt(el)) == HOMOGENIZATION_RGC_ID) then if (homogenization_type(material_homogenizationAt2(ce)) == HOMOGENIZATION_RGC_ID) then
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el)) do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el) dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(subdt,co,ce)
Fs(:,:,co) = phase_mechanical_getF(co,ce)
Ps(:,:,co) = phase_mechanical_getP(co,ce)
enddo enddo
doneAndHappy = & doneAndHappy = mechanical_RGC_updateState(Ps,Fs,subF,subdt,dPdFs,ce)
mech_RGC_updateState(crystallite_P(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
crystallite_F(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
crystallite_partitionedF0(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el),&
subF,&
subdt, &
dPdFs, &
ip, &
el)
else else
doneAndHappy = .true. doneAndHappy = .true.
endif endif
end function mech_updateState end function mechanical_updateState
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief Write results to file. !> @brief Write results to file.
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_results(group_base,h) module subroutine mechanical_results(group_base,ho)
use material, only: &
material_homogenization_type => homogenization_type
character(len=*), intent(in) :: group_base character(len=*), intent(in) :: group_base
integer, intent(in) :: h integer, intent(in) :: ho
character(len=:), allocatable :: group character(len=:), allocatable :: group
group = trim(group_base)//'/mech' group = trim(group_base)//'/mech'
call results_closeGroup(results_addGroup(group)) call results_closeGroup(results_addGroup(group))
select case(material_homogenization_type(h)) select case(homogenization_type(ho))
case(HOMOGENIZATION_rgc_ID) case(HOMOGENIZATION_rgc_ID)
call mech_RGC_results(homogenization_typeInstance(h),group) call mechanical_RGC_results(ho,group)
end select end select
@ -249,7 +241,7 @@ module subroutine mech_results(group_base,h)
!call results_writeDataset(group,temp,'P',& !call results_writeDataset(group,temp,'P',&
! '1st Piola-Kirchhoff stress','Pa') ! '1st Piola-Kirchhoff stress','Pa')
end subroutine mech_results end subroutine mechanical_results
end submodule homogenization_mech end submodule mechanical

View File

@ -6,7 +6,7 @@
!> @brief Relaxed grain cluster (RGC) homogenization scheme !> @brief Relaxed grain cluster (RGC) homogenization scheme
!> N_constituents is defined as p x q x r (cluster) !> N_constituents is defined as p x q x r (cluster)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
submodule(homogenization:homogenization_mech) homogenization_mech_RGC submodule(homogenization:mechanical) RGC
use rotations use rotations
use lattice use lattice
@ -24,9 +24,6 @@ submodule(homogenization:homogenization_mech) homogenization_mech_RGC
end type tParameters end type tParameters
type :: tRGCstate type :: tRGCstate
real(pReal), pointer, dimension(:) :: &
work, &
penaltyEnergy
real(pReal), pointer, dimension(:,:) :: & real(pReal), pointer, dimension(:,:) :: &
relaxationVector relaxationVector
end type tRGCstate end type tRGCstate
@ -74,14 +71,13 @@ contains
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief allocates all necessary fields, reads information from material configuration file !> @brief allocates all necessary fields, reads information from material configuration file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_RGC_init(num_homogMech) module subroutine mechanical_RGC_init(num_homogMech)
class(tNode), pointer, intent(in) :: & class(tNode), pointer, intent(in) :: &
num_homogMech !< pointer to mechanical homogenization numerics data num_homogMech !< pointer to mechanical homogenization numerics data
integer :: & integer :: &
Ninstances, & ho, &
h, &
Nmaterialpoints, & Nmaterialpoints, &
sizeState, nIntFaceTot sizeState, nIntFaceTot
@ -91,10 +87,9 @@ module subroutine mech_RGC_init(num_homogMech)
homog, & homog, &
homogMech homogMech
print'(/,a)', ' <<<+- homogenization_mech_rgc init -+>>>' print'(/,a)', ' <<<+- homogenization:mechanical:RGC init -+>>>'
Ninstances = count(homogenization_type == HOMOGENIZATION_RGC_ID) print'(a,i2)', ' # instances: ',count(homogenization_type == HOMOGENIZATION_RGC_ID); flush(IO_STDOUT)
print'(a,i2)', ' # instances: ',Ninstances; flush(IO_STDOUT)
print*, 'Tjahjanto et al., International Journal of Material Forming 2(1):939942, 2009' print*, 'Tjahjanto et al., International Journal of Material Forming 2(1):939942, 2009'
print*, 'https://doi.org/10.1007/s12289-009-0619-1'//IO_EOL print*, 'https://doi.org/10.1007/s12289-009-0619-1'//IO_EOL
@ -104,10 +99,11 @@ module subroutine mech_RGC_init(num_homogMech)
allocate(param(Ninstances)) material_homogenization => config_material%get('homogenization')
allocate(state(Ninstances)) allocate(param(material_homogenization%length))
allocate(state0(Ninstances)) allocate(state(material_homogenization%length))
allocate(dependentState(Ninstances)) allocate(state0(material_homogenization%length))
allocate(dependentState(material_homogenization%length))
num_RGC => num_homogMech%get('RGC',defaultVal=emptyDict) num_RGC => num_homogMech%get('RGC',defaultVal=emptyDict)
@ -140,15 +136,14 @@ module subroutine mech_RGC_init(num_homogMech)
if (num%volDiscrPow <= 0.0_pReal) call IO_error(301,ext_msg='volDiscrPw_RGC') if (num%volDiscrPow <= 0.0_pReal) call IO_error(301,ext_msg='volDiscrPw_RGC')
material_homogenization => config_material%get('homogenization') do ho = 1, size(homogenization_type)
do h = 1, size(homogenization_type) if (homogenization_type(ho) /= HOMOGENIZATION_RGC_ID) cycle
if (homogenization_type(h) /= HOMOGENIZATION_RGC_ID) cycle homog => material_homogenization%get(ho)
homog => material_homogenization%get(h)
homogMech => homog%get('mechanics') homogMech => homog%get('mechanics')
associate(prm => param(homogenization_typeInstance(h)), & associate(prm => param(ho), &
stt => state(homogenization_typeInstance(h)), & stt => state(ho), &
st0 => state0(homogenization_typeInstance(h)), & st0 => state0(ho), &
dst => dependentState(homogenization_typeInstance(h))) dst => dependentState(ho))
#if defined (__GFORTRAN__) #if defined (__GFORTRAN__)
prm%output = output_asStrings(homogMech) prm%output = output_asStrings(homogMech)
@ -157,8 +152,8 @@ module subroutine mech_RGC_init(num_homogMech)
#endif #endif
prm%N_constituents = homogMech%get_asInts('cluster_size',requiredSize=3) prm%N_constituents = homogMech%get_asInts('cluster_size',requiredSize=3)
if (homogenization_Nconstituents(h) /= product(prm%N_constituents)) & if (homogenization_Nconstituents(ho) /= product(prm%N_constituents)) &
call IO_error(211,ext_msg='N_constituents (mech_RGC)') call IO_error(211,ext_msg='N_constituents (mechanical_RGC)')
prm%xi_alpha = homogMech%get_asFloat('xi_alpha') prm%xi_alpha = homogMech%get_asFloat('xi_alpha')
prm%c_alpha = homogMech%get_asFloat('c_alpha') prm%c_alpha = homogMech%get_asFloat('c_alpha')
@ -166,22 +161,18 @@ module subroutine mech_RGC_init(num_homogMech)
prm%D_alpha = homogMech%get_asFloats('D_alpha', requiredSize=3) prm%D_alpha = homogMech%get_asFloats('D_alpha', requiredSize=3)
prm%a_g = homogMech%get_asFloats('a_g', requiredSize=3) prm%a_g = homogMech%get_asFloats('a_g', requiredSize=3)
Nmaterialpoints = count(material_homogenizationAt == h) Nmaterialpoints = count(material_homogenizationAt == ho)
nIntFaceTot = 3*( (prm%N_constituents(1)-1)*prm%N_constituents(2)*prm%N_constituents(3) & nIntFaceTot = 3*( (prm%N_constituents(1)-1)*prm%N_constituents(2)*prm%N_constituents(3) &
+ prm%N_constituents(1)*(prm%N_constituents(2)-1)*prm%N_constituents(3) & + prm%N_constituents(1)*(prm%N_constituents(2)-1)*prm%N_constituents(3) &
+ prm%N_constituents(1)*prm%N_constituents(2)*(prm%N_constituents(3)-1)) + prm%N_constituents(1)*prm%N_constituents(2)*(prm%N_constituents(3)-1))
sizeState = nIntFaceTot & sizeState = nIntFaceTot
+ size(['avg constitutive work ','average penalty energy'])
homogState(h)%sizeState = sizeState homogState(ho)%sizeState = sizeState
allocate(homogState(h)%state0 (sizeState,Nmaterialpoints), source=0.0_pReal) allocate(homogState(ho)%state0 (sizeState,Nmaterialpoints), source=0.0_pReal)
allocate(homogState(h)%subState0(sizeState,Nmaterialpoints), source=0.0_pReal) allocate(homogState(ho)%state (sizeState,Nmaterialpoints), source=0.0_pReal)
allocate(homogState(h)%state (sizeState,Nmaterialpoints), source=0.0_pReal)
stt%relaxationVector => homogState(h)%state(1:nIntFaceTot,:) stt%relaxationVector => homogState(ho)%state(1:nIntFaceTot,:)
st0%relaxationVector => homogState(h)%state0(1:nIntFaceTot,:) st0%relaxationVector => homogState(ho)%state0(1:nIntFaceTot,:)
stt%work => homogState(h)%state(nIntFaceTot+1,:)
stt%penaltyEnergy => homogState(h)%state(nIntFaceTot+2,:)
allocate(dst%volumeDiscrepancy( Nmaterialpoints), source=0.0_pReal) allocate(dst%volumeDiscrepancy( Nmaterialpoints), source=0.0_pReal)
allocate(dst%relaxationRate_avg( Nmaterialpoints), source=0.0_pReal) allocate(dst%relaxationRate_avg( Nmaterialpoints), source=0.0_pReal)
@ -190,35 +181,36 @@ module subroutine mech_RGC_init(num_homogMech)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! assigning cluster orientations ! assigning cluster orientations
dependentState(homogenization_typeInstance(h))%orientation = spread(eu2om(prm%a_g*inRad),3,Nmaterialpoints) dependentState(ho)%orientation = spread(eu2om(prm%a_g*inRad),3,Nmaterialpoints)
!dst%orientation = spread(eu2om(prm%a_g*inRad),3,Nmaterialpoints) ifort version 18.0.1 crashes (for whatever reason) !dst%orientation = spread(eu2om(prm%a_g*inRad),3,Nmaterialpoints) ifort version 18.0.1 crashes (for whatever reason)
end associate end associate
enddo enddo
end subroutine mech_RGC_init end subroutine mechanical_RGC_init
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief partitions the deformation gradient onto the constituents !> @brief partitions the deformation gradient onto the constituents
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) module subroutine mechanical_RGC_partitionDeformation(F,avgF,ce)
real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned F per grain real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned F per grain
real(pReal), dimension (3,3), intent(in) :: avgF !< averaged F real(pReal), dimension (3,3), intent(in) :: avgF !< averaged F
integer, intent(in) :: & integer, intent(in) :: &
instance, & ce
of
real(pReal), dimension(3) :: aVect,nVect real(pReal), dimension(3) :: aVect,nVect
integer, dimension(4) :: intFace integer, dimension(4) :: intFace
integer, dimension(3) :: iGrain3 integer, dimension(3) :: iGrain3
integer :: iGrain,iFace,i,j integer :: iGrain,iFace,i,j,ho,me
associate(prm => param(instance))
associate(prm => param(material_homogenizationAt2(ce)))
ho = material_homogenizationAt2(ce)
me = material_homogenizationMemberAt2(ce)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! compute the deformation gradient of individual grains due to relaxations ! compute the deformation gradient of individual grains due to relaxations
F = 0.0_pReal F = 0.0_pReal
@ -226,8 +218,8 @@ module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of)
iGrain3 = grain1to3(iGrain,prm%N_constituents) iGrain3 = grain1to3(iGrain,prm%N_constituents)
do iFace = 1,6 do iFace = 1,6
intFace = getInterface(iFace,iGrain3) ! identifying 6 interfaces of each grain intFace = getInterface(iFace,iGrain3) ! identifying 6 interfaces of each grain
aVect = relaxationVector(intFace,instance,of) ! get the relaxation vectors for each interface from global relaxation vector array aVect = relaxationVector(intFace,ho,me) ! get the relaxation vectors for each interface from global relaxation vector array
nVect = interfaceNormal(intFace,instance,of) nVect = interfaceNormal(intFace,ho,me)
forall (i=1:3,j=1:3) & forall (i=1:3,j=1:3) &
F(i,j,iGrain) = F(i,j,iGrain) + aVect(i)*nVect(j) ! calculating deformation relaxations due to interface relaxation F(i,j,iGrain) = F(i,j,iGrain) + aVect(i)*nVect(j) ! calculating deformation relaxations due to interface relaxation
enddo enddo
@ -236,29 +228,27 @@ module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of)
end associate end associate
end subroutine mech_RGC_partitionDeformation end subroutine mechanical_RGC_partitionDeformation
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief update the internal state of the homogenization scheme and tell whether "done" and !> @brief update the internal state of the homogenization scheme and tell whether "done" and
! "happy" with result ! "happy" with result
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHappy) module function mechanical_RGC_updateState(P,F,avgF,dt,dPdF,ce) result(doneAndHappy)
logical, dimension(2) :: doneAndHappy logical, dimension(2) :: doneAndHappy
real(pReal), dimension(:,:,:), intent(in) :: & real(pReal), dimension(:,:,:), intent(in) :: &
P,& !< partitioned stresses P,& !< partitioned stresses
F,& !< partitioned deformation gradients F !< partitioned deformation gradients
F0 !< partitioned initial deformation gradients
real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
real(pReal), dimension(3,3), intent(in) :: avgF !< average F real(pReal), dimension(3,3), intent(in) :: avgF !< average F
real(pReal), intent(in) :: dt !< time increment real(pReal), intent(in) :: dt !< time increment
integer, intent(in) :: & integer, intent(in) :: &
ip, & !< integration point number ce !< cell
el !< element number
integer, dimension(4) :: intFaceN,intFaceP,faceID integer, dimension(4) :: intFaceN,intFaceP,faceID
integer, dimension(3) :: nGDim,iGr3N,iGr3P integer, dimension(3) :: nGDim,iGr3N,iGr3P
integer :: instance,iNum,i,j,nIntFaceTot,iGrN,iGrP,iMun,iFace,k,l,ipert,iGrain,nGrain, of integer :: ho,iNum,i,j,nIntFaceTot,iGrN,iGrP,iMun,iFace,k,l,ipert,iGrain,nGrain, me
real(pReal), dimension(3,3,size(P,3)) :: R,pF,pR,D,pD real(pReal), dimension(3,3,size(P,3)) :: R,pF,pR,D,pD
real(pReal), dimension(3,size(P,3)) :: NN,devNull real(pReal), dimension(3,size(P,3)) :: NN,devNull
real(pReal), dimension(3) :: normP,normN,mornP,mornN real(pReal), dimension(3) :: normP,normN,mornP,mornN
@ -272,10 +262,10 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
return return
endif zeroTimeStep endif zeroTimeStep
instance = homogenization_typeInstance(material_homogenizationAt(el)) ho = material_homogenizationAt2(ce)
of = material_homogenizationMemberAt(ip,el)
associate(stt => state(instance), st0 => state0(instance), dst => dependentState(instance), prm => param(instance)) me = material_homogenizationMemberAt2(ce)
associate(stt => state(ho), st0 => state0(ho), dst => dependentState(ho), prm => param(ho))
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! get the dimension of the cluster (grains and interfaces) ! get the dimension of the cluster (grains and interfaces)
@ -287,38 +277,38 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! allocate the size of the global relaxation arrays/jacobian matrices depending on the size of the cluster ! allocate the size of the global relaxation arrays/jacobian matrices depending on the size of the cluster
allocate(resid(3*nIntFaceTot), source=0.0_pReal) allocate(resid(3*nIntFaceTot), source=0.0_pReal)
allocate(tract(nIntFaceTot,3), source=0.0_pReal) allocate(tract(nIntFaceTot,3), source=0.0_pReal)
relax = stt%relaxationVector(:,of) relax = stt%relaxationVector(:,me)
drelax = stt%relaxationVector(:,of) - st0%relaxationVector(:,of) drelax = stt%relaxationVector(:,me) - st0%relaxationVector(:,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! computing interface mismatch and stress penalty tensor for all interfaces of all grains ! computing interface mismatch and stress penalty tensor for all interfaces of all grains
call stressPenalty(R,NN,avgF,F,ip,el,instance,of) call stressPenalty(R,NN,avgF,F,ho,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! calculating volume discrepancy and stress penalty related to overall volume discrepancy ! calculating volume discrepancy and stress penalty related to overall volume discrepancy
call volumePenalty(D,dst%volumeDiscrepancy(of),avgF,F,nGrain,instance,of) call volumePenalty(D,dst%volumeDiscrepancy(me),avgF,F,nGrain)
!------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------
! computing the residual stress from the balance of traction at all (interior) interfaces ! computing the residual stress from the balance of traction at all (interior) interfaces
do iNum = 1,nIntFaceTot do iNum = 1,nIntFaceTot
faceID = interface1to4(iNum,param(instance)%N_constituents) ! identifying the interface ID in local coordinate system (4-dimensional index) faceID = interface1to4(iNum,param(ho)%N_constituents) ! identifying the interface ID in local coordinate system (4-dimensional index)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! identify the left/bottom/back grain (-|N) ! identify the left/bottom/back grain (-|N)
iGr3N = faceID(2:4) ! identifying the grain ID in local coordinate system (3-dimensional index) iGr3N = faceID(2:4) ! identifying the grain ID in local coordinate system (3-dimensional index)
iGrN = grain3to1(iGr3N,param(instance)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index) iGrN = grain3to1(iGr3N,param(ho)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index)
intFaceN = getInterface(2*faceID(1),iGr3N) intFaceN = getInterface(2*faceID(1),iGr3N)
normN = interfaceNormal(intFaceN,instance,of) normN = interfaceNormal(intFaceN,ho,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! identify the right/up/front grain (+|P) ! identify the right/up/front grain (+|P)
iGr3P = iGr3N iGr3P = iGr3N
iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identifying the grain ID in local coordinate system (3-dimensional index) iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identifying the grain ID in local coordinate system (3-dimensional index)
iGrP = grain3to1(iGr3P,param(instance)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index) iGrP = grain3to1(iGr3P,param(ho)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index)
intFaceP = getInterface(2*faceID(1)-1,iGr3P) intFaceP = getInterface(2*faceID(1)-1,iGr3P)
normP = interfaceNormal(intFaceP,instance,of) normP = interfaceNormal(intFaceP,ho,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! compute the residual of traction at the interface (in local system, 4-dimensional index) ! compute the residual of traction at the interface (in local system, 4-dimensional index)
@ -346,20 +336,9 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
if (residMax < num%rtol*stresMax .or. residMax < num%atol) then if (residMax < num%rtol*stresMax .or. residMax < num%atol) then
doneAndHappy = .true. doneAndHappy = .true.
!-------------------------------------------------------------------------------------------------- dst%mismatch(1:3,me) = sum(NN,2)/real(nGrain,pReal)
! compute/update the state for postResult, i.e., all energy densities computed by time-integration dst%relaxationRate_avg(me) = sum(abs(drelax))/dt/real(3*nIntFaceTot,pReal)
do iGrain = 1,product(prm%N_constituents) dst%relaxationRate_max(me) = maxval(abs(drelax))/dt
do i = 1,3;do j = 1,3
stt%work(of) = stt%work(of) &
+ P(i,j,iGrain)*(F(i,j,iGrain) - F0(i,j,iGrain))/real(nGrain,pReal)
stt%penaltyEnergy(of) = stt%penaltyEnergy(of) &
+ R(i,j,iGrain)*(F(i,j,iGrain) - F0(i,j,iGrain))/real(nGrain,pReal)
enddo; enddo
enddo
dst%mismatch(1:3,of) = sum(NN,2)/real(nGrain,pReal)
dst%relaxationRate_avg(of) = sum(abs(drelax))/dt/real(3*nIntFaceTot,pReal)
dst%relaxationRate_max(of) = maxval(abs(drelax))/dt
return return
@ -378,18 +357,18 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
! ... of the constitutive stress tangent, assembled from dPdF or material constitutive model "smatrix" ! ... of the constitutive stress tangent, assembled from dPdF or material constitutive model "smatrix"
allocate(smatrix(3*nIntFaceTot,3*nIntFaceTot), source=0.0_pReal) allocate(smatrix(3*nIntFaceTot,3*nIntFaceTot), source=0.0_pReal)
do iNum = 1,nIntFaceTot do iNum = 1,nIntFaceTot
faceID = interface1to4(iNum,param(instance)%N_constituents) ! assembling of local dPdF into global Jacobian matrix faceID = interface1to4(iNum,param(ho)%N_constituents) ! assembling of local dPdF into global Jacobian matrix
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! identify the left/bottom/back grain (-|N) ! identify the left/bottom/back grain (-|N)
iGr3N = faceID(2:4) ! identifying the grain ID in local coordinate sytem iGr3N = faceID(2:4) ! identifying the grain ID in local coordinate sytem
iGrN = grain3to1(iGr3N,param(instance)%N_constituents) ! translate into global grain ID iGrN = grain3to1(iGr3N,param(ho)%N_constituents) ! translate into global grain ID
intFaceN = getInterface(2*faceID(1),iGr3N) ! identifying the connecting interface in local coordinate system intFaceN = getInterface(2*faceID(1),iGr3N) ! identifying the connecting interface in local coordinate system
normN = interfaceNormal(intFaceN,instance,of) normN = interfaceNormal(intFaceN,ho,me)
do iFace = 1,6 do iFace = 1,6
intFaceN = getInterface(iFace,iGr3N) ! identifying all interfaces that influence relaxation of the above interface intFaceN = getInterface(iFace,iGr3N) ! identifying all interfaces that influence relaxation of the above interface
mornN = interfaceNormal(intFaceN,instance,of) mornN = interfaceNormal(intFaceN,ho,me)
iMun = interface4to1(intFaceN,param(instance)%N_constituents) ! translate the interfaces ID into local 4-dimensional index iMun = interface4to1(intFaceN,param(ho)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
if (iMun > 0) then ! get the corresponding tangent if (iMun > 0) then ! get the corresponding tangent
do i=1,3; do j=1,3; do k=1,3; do l=1,3 do i=1,3; do j=1,3; do k=1,3; do l=1,3
smatrix(3*(iNum-1)+i,3*(iMun-1)+j) = smatrix(3*(iNum-1)+i,3*(iMun-1)+j) & smatrix(3*(iNum-1)+i,3*(iMun-1)+j) = smatrix(3*(iNum-1)+i,3*(iMun-1)+j) &
@ -404,13 +383,13 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
! identify the right/up/front grain (+|P) ! identify the right/up/front grain (+|P)
iGr3P = iGr3N iGr3P = iGr3N
iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identifying the grain ID in local coordinate sytem iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identifying the grain ID in local coordinate sytem
iGrP = grain3to1(iGr3P,param(instance)%N_constituents) ! translate into global grain ID iGrP = grain3to1(iGr3P,param(ho)%N_constituents) ! translate into global grain ID
intFaceP = getInterface(2*faceID(1)-1,iGr3P) ! identifying the connecting interface in local coordinate system intFaceP = getInterface(2*faceID(1)-1,iGr3P) ! identifying the connecting interface in local coordinate system
normP = interfaceNormal(intFaceP,instance,of) normP = interfaceNormal(intFaceP,ho,me)
do iFace = 1,6 do iFace = 1,6
intFaceP = getInterface(iFace,iGr3P) ! identifying all interfaces that influence relaxation of the above interface intFaceP = getInterface(iFace,iGr3P) ! identifying all interfaces that influence relaxation of the above interface
mornP = interfaceNormal(intFaceP,instance,of) mornP = interfaceNormal(intFaceP,ho,me)
iMun = interface4to1(intFaceP,param(instance)%N_constituents) ! translate the interfaces ID into local 4-dimensional index iMun = interface4to1(intFaceP,param(ho)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
if (iMun > 0) then ! get the corresponding tangent if (iMun > 0) then ! get the corresponding tangent
do i=1,3; do j=1,3; do k=1,3; do l=1,3 do i=1,3; do j=1,3; do k=1,3; do l=1,3
smatrix(3*(iNum-1)+i,3*(iMun-1)+j) = smatrix(3*(iNum-1)+i,3*(iMun-1)+j) & smatrix(3*(iNum-1)+i,3*(iMun-1)+j) = smatrix(3*(iNum-1)+i,3*(iMun-1)+j) &
@ -430,31 +409,31 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
do ipert = 1,3*nIntFaceTot do ipert = 1,3*nIntFaceTot
p_relax = relax p_relax = relax
p_relax(ipert) = relax(ipert) + num%pPert ! perturb the relaxation vector p_relax(ipert) = relax(ipert) + num%pPert ! perturb the relaxation vector
stt%relaxationVector(:,of) = p_relax stt%relaxationVector(:,me) = p_relax
call grainDeformation(pF,avgF,instance,of) ! rain deformation from perturbed state call grainDeformation(pF,avgF,ho,me) ! rain deformation from perturbed state
call stressPenalty(pR,DevNull, avgF,pF,ip,el,instance,of) ! stress penalty due to interface mismatch from perturbed state call stressPenalty(pR,DevNull, avgF,pF,ho,me) ! stress penalty due to interface mismatch from perturbed state
call volumePenalty(pD,devNull(1,1), avgF,pF,nGrain,instance,of) ! stress penalty due to volume discrepancy from perturbed state call volumePenalty(pD,devNull(1,1), avgF,pF,nGrain) ! stress penalty due to volume discrepancy from perturbed state
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! computing the global stress residual array from the perturbed state ! computing the global stress residual array from the perturbed state
p_resid = 0.0_pReal p_resid = 0.0_pReal
do iNum = 1,nIntFaceTot do iNum = 1,nIntFaceTot
faceID = interface1to4(iNum,param(instance)%N_constituents) ! identifying the interface ID in local coordinate system (4-dimensional index) faceID = interface1to4(iNum,param(ho)%N_constituents) ! identifying the interface ID in local coordinate system (4-dimensional index)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! identify the left/bottom/back grain (-|N) ! identify the left/bottom/back grain (-|N)
iGr3N = faceID(2:4) ! identify the grain ID in local coordinate system (3-dimensional index) iGr3N = faceID(2:4) ! identify the grain ID in local coordinate system (3-dimensional index)
iGrN = grain3to1(iGr3N,param(instance)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index) iGrN = grain3to1(iGr3N,param(ho)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index)
intFaceN = getInterface(2*faceID(1),iGr3N) ! identify the interface ID of the grain intFaceN = getInterface(2*faceID(1),iGr3N) ! identify the interface ID of the grain
normN = interfaceNormal(intFaceN,instance,of) normN = interfaceNormal(intFaceN,ho,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! identify the right/up/front grain (+|P) ! identify the right/up/front grain (+|P)
iGr3P = iGr3N iGr3P = iGr3N
iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identify the grain ID in local coordinate system (3-dimensional index) iGr3P(faceID(1)) = iGr3N(faceID(1))+1 ! identify the grain ID in local coordinate system (3-dimensional index)
iGrP = grain3to1(iGr3P,param(instance)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index) iGrP = grain3to1(iGr3P,param(ho)%N_constituents) ! translate the local grain ID into global coordinate system (1-dimensional index)
intFaceP = getInterface(2*faceID(1)-1,iGr3P) ! identify the interface ID of the grain intFaceP = getInterface(2*faceID(1)-1,iGr3P) ! identify the interface ID of the grain
normP = interfaceNormal(intFaceP,instance,of) normP = interfaceNormal(intFaceP,ho,me)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! compute the residual stress (contribution of mismatch and volume penalties) from perturbed state ! compute the residual stress (contribution of mismatch and volume penalties) from perturbed state
@ -494,11 +473,11 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
do i = 1,3*nIntFaceTot;do j = 1,3*nIntFaceTot do i = 1,3*nIntFaceTot;do j = 1,3*nIntFaceTot
drelax(i) = drelax(i) - jnverse(i,j)*resid(j) ! Calculate the correction for the state variable drelax(i) = drelax(i) - jnverse(i,j)*resid(j) ! Calculate the correction for the state variable
enddo; enddo enddo; enddo
stt%relaxationVector(:,of) = relax + drelax ! Updateing the state variable for the next iteration stt%relaxationVector(:,me) = relax + drelax ! Updateing the state variable for the next iteration
if (any(abs(drelax) > num%maxdRelax)) then ! Forcing cutback when the incremental change of relaxation vector becomes too large if (any(abs(drelax) > num%maxdRelax)) then ! Forcing cutback when the incremental change of relaxation vector becomes too large
doneAndHappy = [.true.,.false.] doneAndHappy = [.true.,.false.]
!$OMP CRITICAL (write2out) !$OMP CRITICAL (write2out)
print'(a,i3,a,i3,a)',' RGC_updateState: ip ',ip,' | el ',el,' enforces cutback' print'(a,i3,a,i3,a)',' RGC_updateState: enforces cutback'
print'(a,e15.8)',' due to large relaxation change = ',maxval(abs(drelax)) print'(a,e15.8)',' due to large relaxation change = ',maxval(abs(drelax))
flush(IO_STDOUT) flush(IO_STDOUT)
!$OMP END CRITICAL (write2out) !$OMP END CRITICAL (write2out)
@ -510,27 +489,26 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------
!> @brief calculate stress-like penalty due to deformation mismatch !> @brief calculate stress-like penalty due to deformation mismatch
!------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------
subroutine stressPenalty(rPen,nMis,avgF,fDef,ip,el,instance,of) subroutine stressPenalty(rPen,nMis,avgF,fDef,ho,me)
real(pReal), dimension (:,:,:), intent(out) :: rPen !< stress-like penalty real(pReal), dimension (:,:,:), intent(out) :: rPen !< stress-like penalty
real(pReal), dimension (:,:), intent(out) :: nMis !< total amount of mismatch real(pReal), dimension (:,:), intent(out) :: nMis !< total amount of mismatch
real(pReal), dimension (:,:,:), intent(in) :: fDef !< deformation gradients real(pReal), dimension (:,:,:), intent(in) :: fDef !< deformation gradients
real(pReal), dimension (3,3), intent(in) :: avgF !< initial effective stretch tensor real(pReal), dimension (3,3), intent(in) :: avgF !< initial effective stretch tensor
integer, intent(in) :: ip,el,instance,of integer, intent(in) :: ho, me
integer, dimension (4) :: intFace integer, dimension (4) :: intFace
integer, dimension (3) :: iGrain3,iGNghb3,nGDim integer, dimension (3) :: iGrain3,iGNghb3,nGDim
real(pReal), dimension (3,3) :: gDef,nDef real(pReal), dimension (3,3) :: gDef,nDef
real(pReal), dimension (3) :: nVect,surfCorr real(pReal), dimension (3) :: nVect,surfCorr
real(pReal), dimension (2) :: Gmoduli
integer :: iGrain,iGNghb,iFace,i,j,k,l integer :: iGrain,iGNghb,iFace,i,j,k,l
real(pReal) :: muGrain,muGNghb,nDefNorm real(pReal) :: muGrain,muGNghb,nDefNorm
real(pReal), parameter :: & real(pReal), parameter :: &
nDefToler = 1.0e-10_pReal, & nDefToler = 1.0e-10_pReal, &
b = 2.5e-10_pReal ! Length of Burgers vector b = 2.5e-10_pReal ! Length of Burgers vector
nGDim = param(instance)%N_constituents nGDim = param(ho)%N_constituents
rPen = 0.0_pReal rPen = 0.0_pReal
nMis = 0.0_pReal nMis = 0.0_pReal
@ -538,27 +516,26 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
! get the correction factor the modulus of penalty stress representing the evolution of area of ! get the correction factor the modulus of penalty stress representing the evolution of area of
! the interfaces due to deformations ! the interfaces due to deformations
surfCorr = surfaceCorrection(avgF,instance,of) surfCorr = surfaceCorrection(avgF,ho,me)
associate(prm => param(instance))
associate(prm => param(ho))
!----------------------------------------------------------------------------------------------- !-----------------------------------------------------------------------------------------------
! computing the mismatch and penalty stress tensor of all grains ! computing the mismatch and penalty stress tensor of all grains
grainLoop: do iGrain = 1,product(prm%N_constituents) grainLoop: do iGrain = 1,product(prm%N_constituents)
muGrain = equivalentMu(iGrain,ip,el) muGrain = equivalentMu(iGrain,ce)
iGrain3 = grain1to3(iGrain,prm%N_constituents) ! get the grain ID in local 3-dimensional index (x,y,z)-position iGrain3 = grain1to3(iGrain,prm%N_constituents) ! get the grain ID in local 3-dimensional index (x,y,z)-position
interfaceLoop: do iFace = 1,6 interfaceLoop: do iFace = 1,6
intFace = getInterface(iFace,iGrain3) ! get the 4-dimensional index of the interface in local numbering system of the grain intFace = getInterface(iFace,iGrain3) ! get the 4-dimensional index of the interface in local numbering system of the grain
nVect = interfaceNormal(intFace,instance,of) nVect = interfaceNormal(intFace,ho,me)
iGNghb3 = iGrain3 ! identify the neighboring grain across the interface iGNghb3 = iGrain3 ! identify the neighboring grain across the interface
iGNghb3(abs(intFace(1))) = iGNghb3(abs(intFace(1))) & iGNghb3(abs(intFace(1))) = iGNghb3(abs(intFace(1))) &
+ int(real(intFace(1),pReal)/real(abs(intFace(1)),pReal)) + int(real(intFace(1),pReal)/real(abs(intFace(1)),pReal))
where(iGNghb3 < 1) iGNghb3 = nGDim where(iGNghb3 < 1) iGNghb3 = nGDim
where(iGNghb3 >nGDim) iGNghb3 = 1 where(iGNghb3 >nGDim) iGNghb3 = 1
iGNghb = grain3to1(iGNghb3,prm%N_constituents) ! get the ID of the neighboring grain iGNghb = grain3to1(iGNghb3,prm%N_constituents) ! get the ID of the neighboring grain
muGNghb = equivalentMu(iGNghb,ip,el) muGNghb = equivalentMu(iGNghb,ce)
gDef = 0.5_pReal*(fDef(1:3,1:3,iGNghb) - fDef(1:3,1:3,iGrain)) ! difference/jump in deformation gradeint across the neighbor gDef = 0.5_pReal*(fDef(1:3,1:3,iGNghb) - fDef(1:3,1:3,iGrain)) ! difference/jump in deformation gradeint across the neighbor
!------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------
@ -597,7 +574,7 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------
!> @brief calculate stress-like penalty due to volume discrepancy !> @brief calculate stress-like penalty due to volume discrepancy
!------------------------------------------------------------------------------------------------ !------------------------------------------------------------------------------------------------
subroutine volumePenalty(vPen,vDiscrep,fAvg,fDef,nGrain,instance,of) subroutine volumePenalty(vPen,vDiscrep,fAvg,fDef,nGrain)
real(pReal), dimension (:,:,:), intent(out) :: vPen ! stress-like penalty due to volume real(pReal), dimension (:,:,:), intent(out) :: vPen ! stress-like penalty due to volume
real(pReal), intent(out) :: vDiscrep ! total volume discrepancy real(pReal), intent(out) :: vDiscrep ! total volume discrepancy
@ -605,9 +582,7 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
real(pReal), dimension (:,:,:), intent(in) :: fDef ! deformation gradients real(pReal), dimension (:,:,:), intent(in) :: fDef ! deformation gradients
real(pReal), dimension (3,3), intent(in) :: fAvg ! overall deformation gradient real(pReal), dimension (3,3), intent(in) :: fAvg ! overall deformation gradient
integer, intent(in) :: & integer, intent(in) :: &
Ngrain, & Ngrain
instance, &
of
real(pReal), dimension(size(vPen,3)) :: gVol real(pReal), dimension(size(vPen,3)) :: gVol
integer :: i integer :: i
@ -637,14 +612,14 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!> @brief compute the correction factor accouted for surface evolution (area change) due to !> @brief compute the correction factor accouted for surface evolution (area change) due to
! deformation ! deformation
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
function surfaceCorrection(avgF,instance,of) function surfaceCorrection(avgF,ho,me)
real(pReal), dimension(3) :: surfaceCorrection real(pReal), dimension(3) :: surfaceCorrection
real(pReal), dimension(3,3), intent(in) :: avgF !< average F real(pReal), dimension(3,3), intent(in) :: avgF !< average F
integer, intent(in) :: & integer, intent(in) :: &
instance, & ho, &
of me
real(pReal), dimension(3,3) :: invC real(pReal), dimension(3,3) :: invC
real(pReal), dimension(3) :: nVect real(pReal), dimension(3) :: nVect
real(pReal) :: detF real(pReal) :: detF
@ -655,7 +630,7 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
surfaceCorrection = 0.0_pReal surfaceCorrection = 0.0_pReal
do iBase = 1,3 do iBase = 1,3
nVect = interfaceNormal([iBase,1,1,1],instance,of) nVect = interfaceNormal([iBase,1,1,1],ho,me)
do i = 1,3; do j = 1,3 do i = 1,3; do j = 1,3
surfaceCorrection(iBase) = surfaceCorrection(iBase) + invC(i,j)*nVect(i)*nVect(j) ! compute the component of (the inverse of) the stretch in the direction of the normal surfaceCorrection(iBase) = surfaceCorrection(iBase) + invC(i,j)*nVect(i)*nVect(j) ! compute the component of (the inverse of) the stretch in the direction of the normal
enddo; enddo enddo; enddo
@ -668,15 +643,17 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
!> @brief compute the equivalent shear and bulk moduli from the elasticity tensor !> @brief compute the equivalent shear and bulk moduli from the elasticity tensor
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
real(pReal) function equivalentMu(grainID,ip,el) real(pReal) function equivalentMu(grainID,ce)
integer, intent(in) :: & integer, intent(in) :: &
grainID,& grainID,&
ip, & !< integration point number ce
el !< element number
real(pReal), dimension(6,6) :: C
equivalentMu = lattice_equivalent_mu(constitutive_homogenizedC(grainID,ip,el),'voigt') C = phase_homogenizedC(material_phaseAt2(grainID,ce),material_phaseMemberAt2(grainID,ce))
equivalentMu = lattice_equivalent_mu(C,'voigt')
end function equivalentMu end function equivalentMu
@ -685,14 +662,14 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!> @brief calculating the grain deformation gradient (the same with !> @brief calculating the grain deformation gradient (the same with
! homogenization_RGC_partitionDeformation, but used only for perturbation scheme) ! homogenization_RGC_partitionDeformation, but used only for perturbation scheme)
!------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------
subroutine grainDeformation(F, avgF, instance, of) subroutine grainDeformation(F, avgF, ho, me)
real(pReal), dimension(:,:,:), intent(out) :: F !< partitioned F per grain real(pReal), dimension(:,:,:), intent(out) :: F !< partitioned F per grain
real(pReal), dimension(:,:), intent(in) :: avgF !< averaged F real(pReal), dimension(:,:), intent(in) :: avgF !< averaged F
integer, intent(in) :: & integer, intent(in) :: &
instance, & ho, &
of me
real(pReal), dimension(3) :: aVect,nVect real(pReal), dimension(3) :: aVect,nVect
integer, dimension(4) :: intFace integer, dimension(4) :: intFace
@ -702,15 +679,15 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
!----------------------------------------------------------------------------------------------- !-----------------------------------------------------------------------------------------------
! compute the deformation gradient of individual grains due to relaxations ! compute the deformation gradient of individual grains due to relaxations
associate(prm => param(instance)) associate (prm => param(ho))
F = 0.0_pReal F = 0.0_pReal
do iGrain = 1,product(prm%N_constituents) do iGrain = 1,product(prm%N_constituents)
iGrain3 = grain1to3(iGrain,prm%N_constituents) iGrain3 = grain1to3(iGrain,prm%N_constituents)
do iFace = 1,6 do iFace = 1,6
intFace = getInterface(iFace,iGrain3) intFace = getInterface(iFace,iGrain3)
aVect = relaxationVector(intFace,instance,of) aVect = relaxationVector(intFace,ho,me)
nVect = interfaceNormal(intFace,instance,of) nVect = interfaceNormal(intFace,ho,me)
forall (i=1:3,j=1:3) & forall (i=1:3,j=1:3) &
F(i,j,iGrain) = F(i,j,iGrain) + aVect(i)*nVect(j) ! effective relaxations F(i,j,iGrain) = F(i,j,iGrain) + aVect(i)*nVect(j) ! effective relaxations
enddo enddo
@ -721,49 +698,43 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
end subroutine grainDeformation end subroutine grainDeformation
end function mech_RGC_updateState end function mechanical_RGC_updateState
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief derive average stress and stiffness from constituent quantities !> @brief derive average stress and stiffness from constituent quantities
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) module subroutine mechanical_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,ho)
real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point
real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
integer, intent(in) :: instance integer, intent(in) :: ho
avgP = sum(P,3) /real(product(param(instance)%N_constituents),pReal) avgP = sum(P,3) /real(product(param(ho)%N_constituents),pReal)
dAvgPdAvgF = sum(dPdF,5)/real(product(param(instance)%N_constituents),pReal) dAvgPdAvgF = sum(dPdF,5)/real(product(param(ho)%N_constituents),pReal)
end subroutine mech_RGC_averageStressAndItsTangent end subroutine mechanical_RGC_averageStressAndItsTangent
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief writes results to HDF5 output file !> @brief writes results to HDF5 output file
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
module subroutine mech_RGC_results(instance,group) module subroutine mechanical_RGC_results(ho,group)
integer, intent(in) :: instance integer, intent(in) :: ho
character(len=*), intent(in) :: group character(len=*), intent(in) :: group
integer :: o integer :: o
associate(stt => state(instance), dst => dependentState(instance), prm => param(instance)) associate(stt => state(ho), dst => dependentState(ho), prm => param(ho))
outputsLoop: do o = 1,size(prm%output) outputsLoop: do o = 1,size(prm%output)
select case(trim(prm%output(o))) select case(trim(prm%output(o)))
case('W')
call results_writeDataset(group,stt%work,trim(prm%output(o)), &
'work density','J/m³')
case('M') case('M')
call results_writeDataset(group,dst%mismatch,trim(prm%output(o)), & call results_writeDataset(group,dst%mismatch,trim(prm%output(o)), &
'average mismatch tensor','1') 'average mismatch tensor','1')
case('R')
call results_writeDataset(group,stt%penaltyEnergy,trim(prm%output(o)), &
'mismatch penalty density','J/m³')
case('Delta_V') case('Delta_V')
call results_writeDataset(group,dst%volumeDiscrepancy,trim(prm%output(o)), & call results_writeDataset(group,dst%volumeDiscrepancy,trim(prm%output(o)), &
'volume discrepancy','m³') 'volume discrepancy','m³')
@ -777,17 +748,17 @@ module subroutine mech_RGC_results(instance,group)
enddo outputsLoop enddo outputsLoop
end associate end associate
end subroutine mech_RGC_results end subroutine mechanical_RGC_results
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief collect relaxation vectors of an interface !> @brief collect relaxation vectors of an interface
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
pure function relaxationVector(intFace,instance,of) pure function relaxationVector(intFace,ho,me)
real(pReal), dimension (3) :: relaxationVector real(pReal), dimension (3) :: relaxationVector
integer, intent(in) :: instance,of integer, intent(in) :: ho,me
integer, dimension(4), intent(in) :: intFace !< set of interface ID in 4D array (normal and position) integer, dimension(4), intent(in) :: intFace !< set of interface ID in 4D array (normal and position)
integer :: iNum integer :: iNum
@ -795,29 +766,35 @@ pure function relaxationVector(intFace,instance,of)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! collect the interface relaxation vector from the global state array ! collect the interface relaxation vector from the global state array
iNum = interface4to1(intFace,param(instance)%N_constituents) ! identify the position of the interface in global state array associate (prm => param(ho), &
stt => state(ho))
iNum = interface4to1(intFace,prm%N_constituents) ! identify the position of the interface in global state array
if (iNum > 0) then if (iNum > 0) then
relaxationVector = state(instance)%relaxationVector((3*iNum-2):(3*iNum),of) relaxationVector = stt%relaxationVector((3*iNum-2):(3*iNum),me)
else else
relaxationVector = 0.0_pReal relaxationVector = 0.0_pReal
endif endif
end associate
end function relaxationVector end function relaxationVector
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
!> @brief identify the normal of an interface !> @brief identify the normal of an interface
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
pure function interfaceNormal(intFace,instance,of) pure function interfaceNormal(intFace,ho,me)
real(pReal), dimension(3) :: interfaceNormal real(pReal), dimension(3) :: interfaceNormal
integer, dimension(4), intent(in) :: intFace !< interface ID in 4D array (normal and position) integer, dimension(4), intent(in) :: intFace !< interface ID in 4D array (normal and position)
integer, intent(in) :: & integer, intent(in) :: &
instance, & ho, &
of me
integer :: nPos integer :: nPos
associate (dst => dependentState(ho))
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! get the normal of the interface, identified from the value of intFace(1) ! get the normal of the interface, identified from the value of intFace(1)
@ -825,7 +802,9 @@ pure function interfaceNormal(intFace,instance,of)
nPos = abs(intFace(1)) ! identify the position of the interface in global state array nPos = abs(intFace(1)) ! identify the position of the interface in global state array
interfaceNormal(nPos) = real(intFace(1)/abs(intFace(1)),pReal) ! get the normal vector w.r.t. cluster axis interfaceNormal(nPos) = real(intFace(1)/abs(intFace(1)),pReal) ! get the normal vector w.r.t. cluster axis
interfaceNormal = matmul(dependentState(instance)%orientation(1:3,1:3,of),interfaceNormal) ! map the normal vector into sample coordinate system (basis) interfaceNormal = matmul(dst%orientation(1:3,1:3,me),interfaceNormal) ! map the normal vector into sample coordinate system (basis)
end associate
end function interfaceNormal end function interfaceNormal
@ -970,4 +949,4 @@ pure function interface1to4(iFace1D, nGDim)
end function interface1to4 end function interface1to4
end submodule homogenization_mech_RGC end submodule RGC

Some files were not shown because too many files have changed in this diff Show More