Merge remote-tracking branch 'origin/development' into config_from_dream3D
This commit is contained in:
commit
3b27c64709
|
@ -95,7 +95,7 @@ checkout:
|
|||
- release
|
||||
|
||||
###################################################################################################
|
||||
Pytest_python:
|
||||
pytest_python:
|
||||
stage: python
|
||||
script:
|
||||
- cd $DAMASKROOT/python
|
||||
|
@ -252,7 +252,7 @@ setup_mesh:
|
|||
- release
|
||||
|
||||
###################################################################################################
|
||||
Pytest_grid:
|
||||
pytest_fortran:
|
||||
stage: grid
|
||||
script:
|
||||
- module load $IntelCompiler $MPI_Intel $PETSc_Intel
|
||||
|
@ -287,14 +287,6 @@ J2_plasticBehavior:
|
|||
- master
|
||||
- release
|
||||
|
||||
Marc_elementLib:
|
||||
stage: marc
|
||||
script:
|
||||
- module load $IntelMarc $HDF5Marc $MSC
|
||||
- Marc_elementLib/test.py
|
||||
except:
|
||||
- master
|
||||
- release
|
||||
|
||||
###################################################################################################
|
||||
SpectralRuntime:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[submodule "PRIVATE"]
|
||||
path = PRIVATE
|
||||
path = PRIVATE
|
||||
url = ../PRIVATE.git
|
||||
branch = master
|
||||
shallow = true
|
||||
shallow = true
|
||||
|
|
|
@ -84,7 +84,7 @@ for executable in python python3; do
|
|||
done
|
||||
secondLevel "Details on $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
|
||||
$DEFAULT_PYTHON -c "import $module; \
|
||||
print('Version: {}'.format($module.__version__)); \
|
||||
|
@ -94,10 +94,6 @@ thirdLevel vtk
|
|||
$DEFAULT_PYTHON -c "import vtk; \
|
||||
print('Version: {}'.format(vtk.vtkVersion.GetVTKVersion())); \
|
||||
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"
|
||||
for executable in gcc g++ gfortran ;do
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
2
PRIVATE
2
PRIVATE
|
@ -1 +1 @@
|
|||
Subproject commit 45ef93dbfa3e0e6fa830914b3632e188c308a099
|
||||
Subproject commit 13dfa0ee9d702782f0b7999f3f7fb2384f58d768
|
|
@ -1,5 +1,5 @@
|
|||
# "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_VERSION = 2020
|
||||
set MSC_ROOT = /opt/msc
|
||||
set MSC_VERSION = 2020
|
||||
|
|
|
@ -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
|
|
@ -38,7 +38,7 @@ PATH=${DAMASK_ROOT}/bin:$PATH
|
|||
SOLVER=$(type -p DAMASK_grid || true 2>/dev/null)
|
||||
[ "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
|
||||
# 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 "
|
||||
[ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT
|
||||
echo
|
||||
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS"
|
||||
echo "Multithreading OMP_NUM_THREADS=$OMP_NUM_THREADS"
|
||||
echo -n "heap size "
|
||||
[[ "$(ulimit -d)" == "unlimited" ]] \
|
||||
&& echo "unlimited" \
|
||||
|
@ -86,11 +86,13 @@ if [ ! -z "$PS1" ]; then
|
|||
echo
|
||||
fi
|
||||
|
||||
export DAMASK_NUM_THREADS
|
||||
export OMP_NUM_THREADS
|
||||
export MSC_ROOT
|
||||
export MSC_VERSION
|
||||
export DAMASK_ROOT
|
||||
export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH
|
||||
|
||||
for var in BASE STAT SOLVER BRANCH; do
|
||||
unset "${var}"
|
||||
done
|
||||
unset "ENV_ROOT"
|
||||
unset "DAMASK_ROOT"
|
||||
|
|
|
@ -30,7 +30,7 @@ PATH=${DAMASK_ROOT}/bin:$PATH
|
|||
SOLVER=$(which DAMASK_grid || true 2>/dev/null)
|
||||
[[ "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
|
||||
# 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 "
|
||||
[ -d $MSC_ROOT ] && echo $MSC_ROOT || blink $MSC_ROOT
|
||||
echo
|
||||
echo "Multithreading DAMASK_NUM_THREADS=$DAMASK_NUM_THREADS"
|
||||
echo "Multithreading OMP_NUM_THREADS=$OMP_NUM_THREADS"
|
||||
echo -n "heap size "
|
||||
[[ "$(ulimit -d)" == "unlimited" ]] \
|
||||
&& echo "unlimited" \
|
||||
|
@ -80,11 +80,13 @@ if [ ! -z "$PS1" ]; then
|
|||
echo
|
||||
fi
|
||||
|
||||
export DAMASK_NUM_THREADS
|
||||
export OMP_NUM_THREADS
|
||||
export MSC_ROOT
|
||||
export MSC_VERSION
|
||||
export DAMASK_ROOT
|
||||
export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH
|
||||
|
||||
for var in SOLVER BRANCH; do
|
||||
unset "${var}"
|
||||
done
|
||||
unset "ENV_ROOT"
|
||||
unset "DAMASK_ROOT"
|
||||
|
|
|
@ -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}
|
|
@ -1,4 +0,0 @@
|
|||
[DP_Steel]
|
||||
crystallite 1
|
||||
(constituent) phase 1 texture 1 fraction 0.82
|
||||
(constituent) phase 2 texture 2 fraction 0.18
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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]
|
|
@ -1,3 +0,0 @@
|
|||
hydrogenflux_diffusion11 1.0
|
||||
hydrogenflux_mobility11 1.0
|
||||
hydrogenVolume 1e-28
|
|
@ -1,9 +1,9 @@
|
|||
# Kuo, J. C., Mikrostrukturmechanik von Bikristallen mit Kippkorngrenzen. Shaker-Verlag 2004. http://edoc.mpg.de/204079
|
||||
Aluminum:
|
||||
lattice: aP
|
||||
mechanics:
|
||||
lattice: aP
|
||||
elasticity: {C_11: 110.9e9, C_12: 58.34e9, type: hooke}
|
||||
output: [F, P, Fe, Fp, Lp]
|
||||
output: [F, P, F_e, F_p, L_p]
|
||||
elasticity: {type: hooke, C_11: 110.9e9, C_12: 58.34e9}
|
||||
plasticity:
|
||||
type: isotropic
|
||||
output: [xi]
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
# Maiti and Eisenlohr 2018 Scripta Materialia
|
||||
Air:
|
||||
lattice: aP
|
||||
mechanics:
|
||||
lattice: aP
|
||||
elasticity: {C_11: 10e9, C_12: 0.0, type: hooke}
|
||||
output: [F, P, Fe, Fp, Lp]
|
||||
output: [F, P, F_e, F_p, L_p]
|
||||
elasticity: {type: hooke, C_11: 1e8, C_12: 1e6}
|
||||
plasticity:
|
||||
type: isotropic
|
||||
output: [xi]
|
||||
|
@ -14,4 +13,4 @@ Air:
|
|||
M: 3
|
||||
h_0: 1e6
|
||||
a: 2
|
||||
dilatation: true
|
||||
dilatation: True
|
||||
|
|
|
@ -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
|
|
@ -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]
|
|
@ -2,8 +2,8 @@
|
|||
# Tasan et.al. 2015 International Journal of Plasticity
|
||||
# Diehl et.al. 2015 Meccanica
|
||||
Ferrite:
|
||||
lattice: cI
|
||||
mechanics:
|
||||
lattice: cI
|
||||
elasticity: {C_11: 233.3e9, C_12: 135.5e9, C_44: 118.0e9, type: hooke}
|
||||
plasticity:
|
||||
N_sl: [12, 12]
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# Tasan et.al. 2015 International Journal of Plasticity
|
||||
# Diehl et.al. 2015 Meccanica
|
||||
Martensite:
|
||||
lattice: cI
|
||||
mechanics:
|
||||
lattice: cI
|
||||
elasticity: {C_11: 417.4e9, C_12: 242.4e9, C_44: 211.1e9, type: hooke}
|
||||
plasticity:
|
||||
N_sl: [12, 12]
|
||||
|
|
|
@ -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 35–43
|
||||
# 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
|
||||
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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]
|
|
@ -1,2 +0,0 @@
|
|||
[001]
|
||||
(gauss) phi1 0.000 Phi 0.000 phi2 0.000
|
|
@ -1,2 +0,0 @@
|
|||
[101]
|
||||
(gauss) phi1 0.000 Phi 45.000 phi2 90.000
|
|
@ -1,2 +0,0 @@
|
|||
[111]
|
||||
(gauss) phi1 0.000 Phi 54.7356 phi2 45.000
|
|
@ -1,2 +0,0 @@
|
|||
[123]
|
||||
(gauss) phi1 209.805 Phi 29.206 phi2 63.435
|
|
@ -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}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -2,108 +2,108 @@
|
|||
homogenization:
|
||||
SX:
|
||||
N_constituents: 1
|
||||
mechanics: {type: none}
|
||||
mechanics: {type: pass}
|
||||
|
||||
material:
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [1.0, 0.0, 0.0, 0.0]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.33012772942625784, -0.6781865350268957, 0.6494525351030648, 0.09638521992649676]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.43596817439583935, -0.5982537129781701, 0.046599032277502436, 0.6707106499919265]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.169734823419553, -0.699615227367322, -0.6059581215838098, -0.33844257746495854]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.9698864809294915, 0.1729052643205874, -0.15948307917616958, 0.06315956884687175]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.46205660912967883, 0.3105054068891252, -0.617849551030653, 0.555294529545738]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.4512443497461787, -0.7636045534540555, -0.04739348426715133, -0.45939142396805815]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.2161856212656443, -0.6581450184826598, -0.5498086209601588, 0.4667112513346289]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.8753220715350803, -0.4561599367657419, -0.13298279533852678, -0.08969369719975541]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.11908260752431069, 0.18266024809834172, -0.7144822594012615, -0.664807992845101]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.751104669484278, 0.5585633382623958, -0.34579336397009175, 0.06538900566860861]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.08740438971703973, 0.8991264096610437, -0.4156704205935976, 0.10559485570696363]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.5584325870096193, 0.6016408353068798, -0.14280340445801173, 0.5529814994483859]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.4052725440888093, 0.25253073423599154, 0.5693263597910454, -0.669215876471182]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.7570164606888676, 0.15265448024694664, -0.5998021466848317, 0.20942796551297105]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.6987659297138081, -0.132172211261028, -0.19693254724422338, 0.6748883269678543]
|
||||
- homogenization: SX
|
||||
constituents:
|
||||
- phase: Aluminum
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
O: [0.7729330445886478, 0.21682179052722322, -0.5207379472917645, 0.2905078484066341]
|
||||
|
||||
phase:
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -5,13 +5,9 @@ import glob
|
|||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
import damask
|
||||
|
||||
msc_version = float(damask.environment.options['MSC_VERSION'])
|
||||
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
|
||||
msc_version = os.environ['MSC_VERSION']
|
||||
msc_root = Path(os.environ['MSC_ROOT'])
|
||||
damask_root = Path(os.environ['DAMASK_ROOT'])
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
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:
|
||||
content = f.read()
|
||||
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)
|
||||
with open(dst/Path(in_file).name,'w') as f:
|
||||
f.write(content)
|
||||
|
@ -53,8 +49,8 @@ for in_file in glob.glob(str(src/'job_run.ms')):
|
|||
|
||||
print('compiling Mentat menu binaries...')
|
||||
|
||||
executable = str(msc_root/f'mentat{msc_version}/bin/mentat')
|
||||
menu_file = str(msc_root/f'mentat{msc_version}/menus/linux64/main.msb')
|
||||
executable = msc_root/f'mentat{msc_version}/bin/mentat'
|
||||
menu_file = msc_root/f'mentat{msc_version}/menus/linux64/main.msb'
|
||||
os.system(f'xvfb-run {executable} -compile {menu_file}')
|
||||
|
||||
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
# Makes postprocessing routines accessible from everywhere.
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
import damask
|
||||
|
||||
env = damask.Environment()
|
||||
bin_dir = env.root_dir/Path('bin')
|
||||
bin_dir = Path(os.environ['DAMASK_ROOT'])/'bin'
|
||||
|
||||
if not bin_dir.exists():
|
||||
bin_dir.mkdir()
|
||||
|
@ -15,7 +13,7 @@ if not bin_dir.exists():
|
|||
|
||||
sys.stdout.write('\nsymbolic linking...\n')
|
||||
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'):
|
||||
src = the_dir/the_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,)})\
|
||||
.add('pos',coords.reshape(-1,3))
|
||||
|
||||
results.pick('homogenizations',False)
|
||||
results.pick('phases',True)
|
||||
results.view('homogenizations',False)
|
||||
results.view('phases',True)
|
||||
for label in options.con:
|
||||
x = results.get_dataset_location(label)
|
||||
if len(x) != 0:
|
||||
table = table.add(label,results.read_dataset(x,0,plain=True).reshape(results.cells.prod(),-1))
|
||||
|
||||
results.pick('phases',False)
|
||||
results.pick('homogenizations',True)
|
||||
results.view('phases',False)
|
||||
results.view('homogenizations',True)
|
||||
for label in options.mat:
|
||||
x = results.get_dataset_location(label)
|
||||
if len(x) != 0:
|
||||
|
|
|
@ -16,8 +16,6 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
|
|||
__version__ = version
|
||||
|
||||
# make classes directly accessible as damask.Class
|
||||
from ._environment import Environment as _ # noqa
|
||||
environment = _()
|
||||
from . import util # noqa
|
||||
from . import seeds # noqa
|
||||
from . import tensor # noqa
|
||||
|
@ -38,7 +36,6 @@ from ._result import Result # noqa
|
|||
|
||||
|
||||
# deprecated
|
||||
Environment = _
|
||||
from ._asciitable import ASCIItable # noqa
|
||||
from ._test import Test # noqa
|
||||
from .util import extendableOption # noqa
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
Save as JSON file for use in Paraview.
|
||||
|
||||
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
|
||||
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 = []
|
||||
for i,c in enumerate(np.round(self.colors,6).tolist()):
|
||||
colors+=[i]+c
|
||||
|
@ -254,8 +275,7 @@ class Colormap(mpl.colors.ListedColormap):
|
|||
'RGBPoints':colors
|
||||
}]
|
||||
|
||||
with open(self.name.replace(' ','_')+'.json', 'w') if fhandle is None else fhandle as f:
|
||||
json.dump(out, f,indent=4)
|
||||
json.dump(out,self._get_file_handle(fname,'json'),indent=4)
|
||||
|
||||
|
||||
def save_ASCII(self,fname=None):
|
||||
|
@ -264,24 +284,14 @@ class Colormap(mpl.colors.ListedColormap):
|
|||
|
||||
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
|
||||
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}
|
||||
t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}')
|
||||
|
||||
with open(self.name.replace(' ','_')+'.txt', 'w') if fhandle is None else fhandle as f:
|
||||
t.save(f)
|
||||
t.save(self._get_file_handle(fname,'txt'))
|
||||
|
||||
|
||||
def save_GOM(self,fname=None):
|
||||
|
@ -290,26 +300,19 @@ class Colormap(mpl.colors.ListedColormap):
|
|||
|
||||
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
|
||||
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
|
||||
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 ' \
|
||||
+ 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))]) \
|
||||
+ '\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):
|
||||
|
@ -318,24 +321,16 @@ class Colormap(mpl.colors.ListedColormap):
|
|||
|
||||
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
|
||||
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
|
||||
gmsh_str = 'View.ColorTable = {\n' \
|
||||
+'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \
|
||||
+'\n}\n'
|
||||
with open(self.name.replace(' ','_')+'.msh', 'w') if fhandle is None else fhandle as f:
|
||||
f.write(gmsh_str)
|
||||
self._get_file_handle(fname,'msh').write(gmsh_str)
|
||||
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import copy
|
||||
from io import StringIO
|
||||
from collections.abc import Iterable
|
||||
import abc
|
||||
|
||||
import numpy as np
|
||||
|
@ -35,6 +37,50 @@ class Config(dict):
|
|||
output.seek(0)
|
||||
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
|
||||
def load(cls,fname):
|
||||
"""
|
||||
|
@ -52,6 +98,7 @@ class Config(dict):
|
|||
fhandle = fname
|
||||
return cls(yaml.safe_load(fhandle))
|
||||
|
||||
|
||||
def save(self,fname,**kwargs):
|
||||
"""
|
||||
Save to yaml file.
|
||||
|
@ -65,7 +112,7 @@ class Config(dict):
|
|||
|
||||
"""
|
||||
try:
|
||||
fhandle = open(fname,'w')
|
||||
fhandle = open(fname,'w',newline='\n')
|
||||
except TypeError:
|
||||
fhandle = fname
|
||||
|
||||
|
@ -95,6 +142,7 @@ class Config(dict):
|
|||
"""Check for completeness."""
|
||||
pass
|
||||
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def is_valid(self):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import copy
|
||||
from os import path
|
||||
|
||||
import numpy as np
|
||||
|
@ -7,6 +6,7 @@ import h5py
|
|||
from . import Config
|
||||
from . import Rotation
|
||||
from . import Orientation
|
||||
from . import util
|
||||
|
||||
class ConfigMaterial(Config):
|
||||
"""Material configuration."""
|
||||
|
@ -15,11 +15,10 @@ class ConfigMaterial(Config):
|
|||
'homogenization': {},
|
||||
'phase': {}}
|
||||
|
||||
def __init__(self,d={}):
|
||||
def __init__(self,d=_defaults):
|
||||
"""Initialize object with default dictionary keys."""
|
||||
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):
|
||||
"""
|
||||
|
@ -51,7 +50,7 @@ class ConfigMaterial(Config):
|
|||
|
||||
|
||||
@staticmethod
|
||||
def from_table(table,constituents={},**kwargs):
|
||||
def from_table(table,**kwargs):
|
||||
"""
|
||||
Load from an ASCII table.
|
||||
|
||||
|
@ -59,12 +58,9 @@ class ConfigMaterial(Config):
|
|||
----------
|
||||
table : damask.Table
|
||||
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
|
||||
Keyword arguments where the key is the name and the value specifies
|
||||
the label of the data column in the table
|
||||
Keyword arguments where the key is the name and the value specifies
|
||||
the label of the data column in the table.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
@ -75,32 +71,30 @@ class ConfigMaterial(Config):
|
|||
pos pos pos qu qu qu qu phase homog
|
||||
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
|
||||
>>> 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:
|
||||
- constituents:
|
||||
- O: [0.19, 0.8, 0.24, -0.51]
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- O: [0.8, 0.19, 0.24, -0.51]
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
phase: Steel
|
||||
homogenization: SX
|
||||
homogenization: {}
|
||||
phase: {}
|
||||
|
||||
"""
|
||||
constituents_ = {k:table.get(v) for k,v in constituents.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)
|
||||
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
|
||||
|
@ -108,11 +102,11 @@ class ConfigMaterial(Config):
|
|||
r"""
|
||||
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
|
||||
----------
|
||||
fname : str
|
||||
fname : str
|
||||
path to the DREAM3D file.
|
||||
base_group : str
|
||||
Name of the group (folder) below 'DataContainers',
|
||||
|
@ -126,7 +120,7 @@ class ConfigMaterial(Config):
|
|||
phase_id : str
|
||||
Name of the dataset containing phase IDs for each grain,
|
||||
for example 'Phases'.
|
||||
phase_name : list
|
||||
phase_name : list
|
||||
List with name of the phases.
|
||||
|
||||
Examples
|
||||
|
@ -135,25 +129,25 @@ class ConfigMaterial(Config):
|
|||
>>> import damask
|
||||
>>> import damask.ConfigMaterial as cm
|
||||
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\
|
||||
'EulerAngles','Phases',['Ferrite'])
|
||||
'EulerAngles','Phases',['Ferrite'])
|
||||
|
||||
for point based data with single phase
|
||||
>>> import damask
|
||||
>>> import damask.ConfigMaterial as cm
|
||||
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\
|
||||
'EulerAngles','Phases',['Ferrite'])
|
||||
'EulerAngles','Phases',['Ferrite'])
|
||||
|
||||
for grain based data with dual phase
|
||||
>>> import damask
|
||||
>>> import damask.ConfigMaterial as cm
|
||||
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'Grain Data'\
|
||||
'EulerAngles','Phases',['Ferrite','Martensite'])
|
||||
'EulerAngles','Phases',['Ferrite','Martensite'])
|
||||
|
||||
for point based data with dual phase
|
||||
>>> import damask
|
||||
>>> import damask.ConfigMaterial as cm
|
||||
>>> cm.load_from_Dream3D('20grains16x16x16.dream3D','SyntheticVolumeDataContainer', 'CellData'\
|
||||
'EulerAngles','Phases',['Ferrite','Martensite'])
|
||||
'EulerAngles','Phases',['Ferrite','Martensite'])
|
||||
|
||||
"""
|
||||
root_dir = 'DataContainers'
|
||||
|
@ -162,13 +156,13 @@ class ConfigMaterial(Config):
|
|||
|
||||
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,):
|
||||
grain_orientations = np.array(hdf[orientation_path]).reshape(cells.prod(),3,order='F')
|
||||
else:
|
||||
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)
|
||||
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.save()
|
||||
|
||||
|
||||
@property
|
||||
def is_complete(self):
|
||||
"""Check for completeness."""
|
||||
ok = True
|
||||
for top_level in ['homogenization','phase','material']:
|
||||
# ToDo: With python 3.8 as prerequisite we can shorten with :=
|
||||
ok &= top_level in self
|
||||
if top_level not in self: print(f'{top_level} entry missing')
|
||||
|
||||
|
@ -238,7 +231,7 @@ class ConfigMaterial(Config):
|
|||
|
||||
@property
|
||||
def is_valid(self):
|
||||
"""Check for valid file layout."""
|
||||
"""Check for valid content."""
|
||||
ok = True
|
||||
|
||||
if 'phase' in self:
|
||||
|
@ -247,25 +240,23 @@ class ConfigMaterial(Config):
|
|||
try:
|
||||
Orientation(lattice=v['lattice'])
|
||||
except KeyError:
|
||||
s = v['lattice']
|
||||
print(f"Invalid lattice: '{s}' in phase '{k}'")
|
||||
print(f"Invalid lattice '{v['lattice']}' in phase '{k}'")
|
||||
ok = False
|
||||
|
||||
if 'material' in self:
|
||||
for i,v in enumerate(self['material']):
|
||||
if 'constituents' in v:
|
||||
f = 0.0
|
||||
for c in v['constituents']:
|
||||
f+= float(c['fraction'])
|
||||
for i,m in enumerate(self['material']):
|
||||
if 'constituents' in m:
|
||||
v = 0.0
|
||||
for c in m['constituents']:
|
||||
v += float(c['v'])
|
||||
if 'O' in c:
|
||||
try:
|
||||
Rotation.from_quaternion(c['O'])
|
||||
except ValueError:
|
||||
o = c['O']
|
||||
print(f"Invalid orientation: '{o}' in material '{i}'")
|
||||
print(f"Invalid orientation '{c['O']}' in material '{i}'")
|
||||
ok = False
|
||||
if not np.isclose(f,1.0):
|
||||
print(f"Invalid total fraction '{f}' in material '{i}'")
|
||||
if not np.isclose(v,1.0):
|
||||
print(f"Total fraction v = {v} ≠ 1 in material '{i}'")
|
||||
ok = False
|
||||
|
||||
return ok
|
||||
|
@ -284,10 +275,15 @@ class ConfigMaterial(Config):
|
|||
constituent: list of ints, optional
|
||||
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']):
|
||||
if ID and i not in ID: continue
|
||||
if ID is not None and i not in ID: continue
|
||||
for c in m['constituents']:
|
||||
if constituent is not None and c not in constituent: continue
|
||||
try:
|
||||
|
@ -308,10 +304,15 @@ class ConfigMaterial(Config):
|
|||
ID: list of ints, optional
|
||||
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']):
|
||||
if ID and i not in ID: continue
|
||||
if ID is not None and i not in ID: continue
|
||||
try:
|
||||
m['homogenization'] = mapping[m['homogenization']]
|
||||
except KeyError:
|
||||
|
@ -319,93 +320,92 @@ class ConfigMaterial(Config):
|
|||
return dup
|
||||
|
||||
|
||||
def material_add(self,constituents=None,**kwargs):
|
||||
def material_add(self,**kwargs):
|
||||
"""
|
||||
Add material entries.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
constituents : dict, optional
|
||||
Entries for 'constituents' as key-value pair.
|
||||
**kwargs
|
||||
Key-value pairs.
|
||||
|
||||
Returns
|
||||
-------
|
||||
cfg : damask.ConfigMaterial
|
||||
Updated material configuration.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> import damask
|
||||
>>> O = damask.Rotation.from_random(3).as_quaternion()
|
||||
>>> phase = ['Aluminum','Steel','Aluminum']
|
||||
>>> m = damask.ConfigMaterial().material_add(constituents={'phase':phase,'O':O},
|
||||
... homogenization='SX')
|
||||
>>> m = damask.ConfigMaterial().material_add(phase = ['Aluminum','Steel'],
|
||||
... O = damask.Rotation.from_random(2),
|
||||
... homogenization = 'SX')
|
||||
>>> m
|
||||
material:
|
||||
- constituents:
|
||||
- O: [0.577764, -0.146299, -0.617669, 0.513010]
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- O: [0.184176, 0.340305, 0.737247, 0.553840]
|
||||
fraction: 1.0
|
||||
v: 1.0
|
||||
phase: Steel
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- O: [0.0886257, -0.144848, 0.615674, -0.769487]
|
||||
fraction: 1.0
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
homogenization: {}
|
||||
phase: {}
|
||||
|
||||
>>> m = damask.ConfigMaterial().material_add(phase = np.array(['Austenite','Martensite']).reshape(1,2),
|
||||
... 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: {}
|
||||
phase: {}
|
||||
|
||||
"""
|
||||
length = -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')
|
||||
N,n,shaped = 1,1,{}
|
||||
|
||||
for k,v in kwargs.items():
|
||||
if hasattr(v,'__len__') and not isinstance(v,str):
|
||||
for i,vv in enumerate(v):
|
||||
c[i][k] = vv.item() if isinstance(vv,np.generic) else vv
|
||||
else:
|
||||
for i in range(len(c)):
|
||||
c[i][k] = v
|
||||
dup = copy.deepcopy(self)
|
||||
dup['material'] = dup['material'] + c if 'material' in dup else c
|
||||
shaped[k] = np.array(v)
|
||||
s = shaped[k].shape[:-1] if k=='O' else shaped[k].shape
|
||||
N = max(N,s[0]) if len(s)>0 else N
|
||||
n = max(n,s[1]) if len(s)>1 else n
|
||||
|
||||
mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
|
||||
|
||||
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
|
||||
|
||||
|
||||
@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
|
||||
|
|
|
@ -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]
|
|
@ -1,7 +1,7 @@
|
|||
import copy
|
||||
import multiprocessing as mp
|
||||
from functools import partial
|
||||
from os import path
|
||||
import os
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
@ -10,7 +10,6 @@ import h5py
|
|||
from scipy import ndimage, spatial
|
||||
from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np
|
||||
|
||||
from . import environment
|
||||
from . import VTK
|
||||
from . import util
|
||||
from . import grid_filters
|
||||
|
@ -57,13 +56,10 @@ class Grid:
|
|||
|
||||
|
||||
def __copy__(self):
|
||||
"""Copy grid."""
|
||||
"""Create deep copy."""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
|
||||
def copy(self):
|
||||
"""Copy grid."""
|
||||
return self.__copy__()
|
||||
copy = __copy__
|
||||
|
||||
|
||||
def diff(self,other):
|
||||
|
@ -126,7 +122,7 @@ class Grid:
|
|||
|
||||
@size.setter
|
||||
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}')
|
||||
else:
|
||||
self._size = np.array(size)
|
||||
|
@ -206,7 +202,7 @@ class Grid:
|
|||
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:
|
||||
f = open(fname)
|
||||
except TypeError:
|
||||
|
@ -281,14 +277,14 @@ class Grid:
|
|||
"""
|
||||
root_dir ='DataContainers'
|
||||
f = h5py.File(fname, 'r')
|
||||
g = path.join(root_dir,base_group,'_SIMPL_GEOMETRY')
|
||||
cells = f[path.join(g,'DIMENSIONS')][()]
|
||||
size = f[path.join(g,'SPACING')][()] * cells
|
||||
origin = f[path.join(g,'ORIGIN')][()]
|
||||
g = os.path.join(root_dir,base_group,'_SIMPL_GEOMETRY')
|
||||
cells = f[os.path.join(g,'DIMENSIONS')][()]
|
||||
size = f[os.path.join(g,'SPACING')][()] * cells
|
||||
origin = f[os.path.join(g,'ORIGIN')][()]
|
||||
|
||||
ma = np.arange(cells.prod(),dtype=int) \
|
||||
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'))
|
||||
|
||||
|
@ -307,7 +303,7 @@ class Grid:
|
|||
Need to be ordered (1./x fast, 3./z slow).
|
||||
labels : str or list of str
|
||||
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))
|
||||
|
@ -358,7 +354,7 @@ class Grid:
|
|||
seeds_p = seeds
|
||||
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])
|
||||
pool.close()
|
||||
pool.join()
|
||||
|
@ -545,7 +541,7 @@ class Grid:
|
|||
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 \
|
||||
+ ['grid a {} b {} c {}'.format(*self.cells),
|
||||
'size x {} y {} z {}'.format(*self.size),
|
||||
|
@ -764,26 +760,21 @@ class Grid:
|
|||
|
||||
"""
|
||||
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
|
||||
|
||||
Eulers = R.as_Euler_angles(degrees=True)
|
||||
material_in = self.material.copy()
|
||||
dtype = float if isinstance(fill,float) or self.material.dtype in np.sctypes['float'] else int
|
||||
|
||||
material = self.material
|
||||
# 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
|
||||
for angle,axes in zip(Eulers[::-1], [(0,1),(1,2),(0,1)]):
|
||||
material_out = ndimage.rotate(material_in,angle,axes,order=0,
|
||||
prefilter=False,output=dtype,cval=fill)
|
||||
if np.prod(material_in.shape) == np.prod(material_out.shape):
|
||||
# avoid scipy interpolation errors for rotations close to multiples of 90°
|
||||
material_in = np.rot90(material_in,k=np.rint(angle/90.).astype(int),axes=axes)
|
||||
else:
|
||||
material_in = material_out
|
||||
for angle,axes in zip(R.as_Euler_angles(degrees=True)[::-1], [(0,1),(1,2),(0,1)]):
|
||||
material_temp = ndimage.rotate(material,angle,axes,order=0,prefilter=False,output=dtype,cval=fill)
|
||||
# avoid scipy interpolation errors for rotations close to multiples of 90°
|
||||
material = material_temp if np.prod(material_temp.shape) != np.prod(material.shape) else \
|
||||
np.rot90(material,k=np.rint(angle/90.).astype(int),axes=axes)
|
||||
|
||||
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,
|
||||
size = self.size/self.cells*np.asarray(material_in.shape),
|
||||
return Grid(material = material,
|
||||
size = self.size/self.cells*np.asarray(material.shape),
|
||||
origin = origin,
|
||||
comments = self.comments+[util.execution_stamp('Grid','rotate')],
|
||||
)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import inspect
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import Rotation
|
||||
|
@ -7,7 +9,7 @@ from . import tensor
|
|||
_parameter_doc = \
|
||||
"""lattice : str
|
||||
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:
|
||||
a : float, optional
|
||||
Length of lattice parameter "a".
|
||||
|
@ -107,8 +109,7 @@ class Orientation(Rotation):
|
|||
lattice = None,
|
||||
a = None,b = None,c = None,
|
||||
alpha = None,beta = None,gamma = None,
|
||||
degrees = False,
|
||||
**kwargs):
|
||||
degrees = False):
|
||||
"""
|
||||
Initialize orientation object.
|
||||
|
||||
|
@ -199,7 +200,7 @@ class Orientation(Rotation):
|
|||
|
||||
|
||||
def __copy__(self,**kwargs):
|
||||
"""Copy."""
|
||||
"""Create deep copy."""
|
||||
return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion,
|
||||
lattice =kwargs['lattice'] if 'lattice' in kwargs else self.lattice
|
||||
if self.lattice is not None else self.family,
|
||||
|
@ -225,96 +226,150 @@ class Orientation(Rotation):
|
|||
Orientation to check for equality.
|
||||
|
||||
"""
|
||||
return super().__eq__(other) \
|
||||
and hasattr(other, 'family') and self.family == other.family \
|
||||
and hasattr(other, 'lattice') and self.lattice == other.lattice \
|
||||
and hasattr(other, 'parameters') and self.parameters == other.parameters
|
||||
matching_type = all([hasattr(other,attr) and getattr(self,attr) == getattr(other,attr)
|
||||
for attr in ['family','lattice','parameters']])
|
||||
return np.logical_and(super().__eq__(other),matching_type)
|
||||
|
||||
|
||||
def __matmul__(self,other):
|
||||
def __ne__(self,other):
|
||||
"""
|
||||
Rotation of vector, second or fourth order tensor, or rotation object.
|
||||
Not equal to other.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other : numpy.ndarray, Rotation, or Orientation
|
||||
Vector, second or fourth order tensor, or rotation object that is rotated.
|
||||
other : Orientation
|
||||
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
|
||||
-------
|
||||
other_rot : numpy.ndarray or Rotation
|
||||
Rotated vector, second or fourth order tensor, or rotation object.
|
||||
composition : Orientation
|
||||
Compound rotation self*other, i.e. first other then self rotation.
|
||||
|
||||
"""
|
||||
return self.copy(rotation=Rotation.__matmul__(self,Rotation(other.quaternion))) \
|
||||
if isinstance(other,self.__class__) else \
|
||||
Rotation.__matmul__(self,other)
|
||||
if isinstance(other,Orientation) or isinstance(other,Rotation):
|
||||
return self.copy(rotation=Rotation.__mul__(self,Rotation(other.quaternion)))
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_random,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_quaternion,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_axis_angle,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_basis,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_matrix,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_homochoric,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_cubochoric,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_spherical_component,_parameter_doc)
|
||||
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
|
||||
@util.extended_docstring(Rotation.from_fiber_component,_parameter_doc)
|
||||
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
|
||||
|
@ -429,7 +484,7 @@ class Orientation(Rotation):
|
|||
raise ValueError('Missing crystal symmetry')
|
||||
|
||||
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
|
||||
|
@ -469,26 +524,26 @@ class Orientation(Rotation):
|
|||
if self.family is None:
|
||||
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'):
|
||||
# using '*'/prod for 'and'
|
||||
if self.family == 'cubic':
|
||||
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':
|
||||
return (np.prod(1. >= rho_abs,axis=-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[...,2])).astype(np.bool)
|
||||
(2. >= np.sqrt(3) + rho_abs[...,2])).astype(bool)
|
||||
elif self.family == 'tetragonal':
|
||||
return (np.prod(1. >= rho_abs[...,:2],axis=-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':
|
||||
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':
|
||||
return (1. >= rho_abs[...,1]).astype(np.bool)
|
||||
return (1. >= rho_abs[...,1]).astype(bool)
|
||||
else:
|
||||
return np.all(np.isfinite(rho_abs),axis=-1)
|
||||
|
||||
|
@ -512,28 +567,28 @@ class Orientation(Rotation):
|
|||
if self.family is None:
|
||||
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'):
|
||||
if self.family == 'cubic':
|
||||
return ((rho[...,0] >= rho[...,1]) &
|
||||
(rho[...,1] >= rho[...,2]) &
|
||||
(rho[...,2] >= 0)).astype(np.bool)
|
||||
(rho[...,2] >= 0)).astype(bool)
|
||||
elif self.family == 'hexagonal':
|
||||
return ((rho[...,0] >= rho[...,1]*np.sqrt(3)) &
|
||||
(rho[...,1] >= 0) &
|
||||
(rho[...,2] >= 0)).astype(np.bool)
|
||||
(rho[...,2] >= 0)).astype(bool)
|
||||
elif self.family == 'tetragonal':
|
||||
return ((rho[...,0] >= rho[...,1]) &
|
||||
(rho[...,1] >= 0) &
|
||||
(rho[...,2] >= 0)).astype(np.bool)
|
||||
(rho[...,2] >= 0)).astype(bool)
|
||||
elif self.family == 'orthorhombic':
|
||||
return ((rho[...,0] >= 0) &
|
||||
(rho[...,1] >= 0) &
|
||||
(rho[...,2] >= 0)).astype(np.bool)
|
||||
(rho[...,2] >= 0)).astype(bool)
|
||||
elif self.family == 'monoclinic':
|
||||
return ((rho[...,1] >= 0) &
|
||||
(rho[...,2] >= 0)).astype(np.bool)
|
||||
(rho[...,2] >= 0)).astype(bool)
|
||||
else:
|
||||
return np.ones_like(rho[...,0],dtype=bool)
|
||||
|
||||
|
@ -608,7 +663,7 @@ class Orientation(Rotation):
|
|||
o,lattice = self.relation_operations(model,return_lattice=True)
|
||||
target = Orientation(lattice=lattice)
|
||||
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,
|
||||
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'],
|
||||
|
|
|
@ -80,12 +80,12 @@ class Result:
|
|||
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.selection = {'increments': self.increments,
|
||||
'phases': self.phases,
|
||||
'homogenizations': self.homogenizations,
|
||||
'out_type_ph': self.out_type_ph,
|
||||
'out_type_ho': self.out_type_ho
|
||||
}
|
||||
self.visible = {'increments': self.increments,
|
||||
'phases': self.phases,
|
||||
'homogenizations': self.homogenizations,
|
||||
'out_type_ph': self.out_type_ph,
|
||||
'out_type_ho': self.out_type_ho
|
||||
}
|
||||
|
||||
self.fname = Path(fname).absolute()
|
||||
|
||||
|
@ -94,23 +94,23 @@ class Result:
|
|||
|
||||
def __repr__(self):
|
||||
"""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()
|
||||
|
||||
self.pick('increments',all_selected_increments[-1:])
|
||||
last = '' if len(all_selected_increments) < 2 else self.list_data()
|
||||
self.view('increments',visible_increments[-1:])
|
||||
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 \
|
||||
''.join([f'\n{inc}\n ...\n' for inc in all_selected_increments[1:-2]])
|
||||
in_between = '' if len(visible_increments) < 3 else \
|
||||
''.join([f'\n{inc}\n ...\n' for inc in visible_increments[1:-1]])
|
||||
|
||||
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.
|
||||
|
||||
|
@ -119,10 +119,10 @@ class Result:
|
|||
action : str
|
||||
Select from 'set', 'add', and 'del'.
|
||||
what : str
|
||||
Attribute to change (must be from self.selection).
|
||||
Attribute to change (must be from self.visible).
|
||||
datasets : list of str or bool
|
||||
Name of datasets as list, supports ? and * wildcards.
|
||||
True is equivalent to [*], False is equivalent to []
|
||||
Name of datasets as list; supports ? and * wildcards.
|
||||
True is equivalent to [*], False is equivalent to [].
|
||||
|
||||
"""
|
||||
def natural_sort(key):
|
||||
|
@ -156,18 +156,18 @@ class Result:
|
|||
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_]
|
||||
existing = set(self.selection[what])
|
||||
existing = set(self.visible[what])
|
||||
|
||||
if action == 'set':
|
||||
self.selection[what] = valid
|
||||
self.visible[what] = valid
|
||||
elif action == 'add':
|
||||
add = existing.union(valid)
|
||||
add_sorted = sorted(add, key=natural_sort)
|
||||
self.selection[what] = add_sorted
|
||||
self.visible[what] = add_sorted
|
||||
elif action == 'del':
|
||||
diff = existing.difference(valid)
|
||||
diff_sorted = sorted(diff, key=natural_sort)
|
||||
self.selection[what] = diff_sorted
|
||||
self.visible[what] = diff_sorted
|
||||
|
||||
|
||||
def _get_attribute(self,path,attr):
|
||||
|
@ -200,7 +200,7 @@ class Result:
|
|||
self._allow_modification = True
|
||||
|
||||
def disallow_modification(self):
|
||||
"""Disllow to overwrite existing data (default case)."""
|
||||
"""Disallow to overwrite existing data (default case)."""
|
||||
self._allow_modification = False
|
||||
|
||||
|
||||
|
@ -245,84 +245,84 @@ class Result:
|
|||
|
||||
def iterate(self,what):
|
||||
"""
|
||||
Iterate over selection items by setting each one selected.
|
||||
Iterate over visible items and view them independently.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
what : str
|
||||
Attribute to change (must be from self.selection).
|
||||
Attribute to change (must be from self.visible).
|
||||
|
||||
"""
|
||||
datasets = self.selection[what]
|
||||
last_selection = datasets.copy()
|
||||
datasets = self.visible[what]
|
||||
last_view = datasets.copy()
|
||||
for dataset in datasets:
|
||||
if last_selection != self.selection[what]:
|
||||
self._manage_selection('set',what,datasets)
|
||||
if last_view != self.visible[what]:
|
||||
self._manage_view('set',what,datasets)
|
||||
raise Exception
|
||||
self._manage_selection('set',what,dataset)
|
||||
last_selection = self.selection[what]
|
||||
self._manage_view('set',what,dataset)
|
||||
last_view = self.visible[what]
|
||||
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
|
||||
----------
|
||||
what : str
|
||||
attribute to change (must be from self.selection)
|
||||
Attribute to change (must be from self.visible).
|
||||
datasets : list of str or bool
|
||||
name of datasets as list, supports ? and * wildcards.
|
||||
True is equivalent to [*], False is equivalent to []
|
||||
Name of datasets as list; supports ? and * wildcards.
|
||||
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
|
||||
----------
|
||||
what : str
|
||||
attribute to change (must be from self.selection)
|
||||
Attribute to change (must be from self.visible).
|
||||
datasets : list of str or bool
|
||||
name of datasets as list, supports ? and * wildcards.
|
||||
True is equivalent to [*], False is equivalent to []
|
||||
Name of datasets as list; supports ? and * wildcards.
|
||||
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
|
||||
----------
|
||||
what : str
|
||||
attribute to change (must be from self.selection)
|
||||
Attribute to change (must be from self.visible).
|
||||
datasets : list of str or bool
|
||||
name of datasets as list, supports ? and * wildcards.
|
||||
True is equivalent to [*], False is equivalent to []
|
||||
Name of datasets as list; supports ? and * wildcards.
|
||||
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):
|
||||
"""
|
||||
Rename datasets.
|
||||
Rename dataset.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name_old : str
|
||||
name of the datasets to be renamed
|
||||
Name of the dataset to be renamed.
|
||||
name_new : str
|
||||
new name of the datasets
|
||||
New name of the dataset.
|
||||
|
||||
"""
|
||||
if self._allow_modification:
|
||||
|
@ -353,13 +353,13 @@ class Result:
|
|||
----------
|
||||
datasets : iterable or str
|
||||
constituent : int
|
||||
Constituent to consider for phase data
|
||||
Constituent to consider for phase data.
|
||||
tagged : bool
|
||||
tag Table.column name with '#constituent'
|
||||
defaults to False
|
||||
Tag Table.column name with '#constituent'.
|
||||
Defaults to False.
|
||||
split : bool
|
||||
split Table by increment and return dictionary of Tables
|
||||
defaults to True
|
||||
Split Table by increment and return dictionary of Tables.
|
||||
Defaults to True.
|
||||
|
||||
"""
|
||||
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:
|
||||
for dataset in sets:
|
||||
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]
|
||||
key = '/'.join([prop,name+tag])
|
||||
if key not in inGeom:
|
||||
|
@ -388,15 +388,15 @@ class Result:
|
|||
np.nan,
|
||||
dtype=np.dtype(f[path]))
|
||||
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:
|
||||
try:
|
||||
tbl[inc].add(path,data)
|
||||
tbl[inc] = tbl[inc].add(path,data)
|
||||
except KeyError:
|
||||
tbl[inc] = Table(data.reshape(self.N_materialpoints,-1),{path:data.shape[1:]})
|
||||
else:
|
||||
try:
|
||||
tbl.add(path,data)
|
||||
tbl = tbl.add(path,data)
|
||||
except AttributeError:
|
||||
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.
|
||||
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
|
||||
----------
|
||||
|
@ -1134,8 +1134,7 @@ class Result:
|
|||
|
||||
"""
|
||||
chunk_size = 1024**2//8
|
||||
num_threads = damask.environment.options['DAMASK_NUM_THREADS']
|
||||
pool = mp.Pool(int(num_threads) if num_threads is not None else None)
|
||||
pool = mp.Pool(int(os.environ.get('OMP_NUM_THREADS',1)))
|
||||
lock = mp.Manager().Lock()
|
||||
|
||||
groups = self.groups_with_datasets(datasets.values())
|
||||
|
@ -1190,8 +1189,8 @@ class Result:
|
|||
"""
|
||||
Write XDMF file to directly visualize data in DADF5 file.
|
||||
|
||||
This works only for scalar, 3-vector and 3x3-tensor data.
|
||||
Selection is not taken into account.
|
||||
The view is not taken into account, i.e. the content of the
|
||||
whole file will be included.
|
||||
"""
|
||||
if self.N_constituents != 1 or len(self.phases) != 1 or not self.structured:
|
||||
raise TypeError('XDMF output requires homogeneous grid')
|
||||
|
@ -1288,7 +1287,7 @@ class Result:
|
|||
np.prod(shape))}
|
||||
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())
|
||||
|
||||
|
||||
|
@ -1320,10 +1319,10 @@ class Result:
|
|||
|
||||
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()
|
||||
self.pick('homogenizations',False)
|
||||
viewed_backup_ho = self.visible['homogenizations'].copy()
|
||||
self.view('homogenizations',False)
|
||||
for label in (labels if isinstance(labels,list) else [labels]):
|
||||
for o in self.iterate('out_type_ph'):
|
||||
for c in range(self.N_constituents):
|
||||
|
@ -1343,10 +1342,10 @@ class Result:
|
|||
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
|
||||
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()
|
||||
self.pick('phases',False)
|
||||
viewed_backup_ph = self.visible['phases'].copy()
|
||||
self.view('phases',False)
|
||||
for label in (labels if isinstance(labels,list) else [labels]):
|
||||
for _ in self.iterate('out_type_ho'):
|
||||
paths = self.get_dataset_location(label)
|
||||
|
@ -1354,7 +1353,7 @@ class Result:
|
|||
continue
|
||||
array = self.read_dataset(paths)
|
||||
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'))
|
||||
v.add(u,'u')
|
||||
|
|
|
@ -35,6 +35,11 @@ class Rotation:
|
|||
- b = Q @ 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
|
||||
----------
|
||||
D. Rowenhorst et al., Modelling and Simulation in Materials Science and Engineering 23:083501, 2015
|
||||
|
@ -65,22 +70,13 @@ class Rotation:
|
|||
|
||||
|
||||
def __repr__(self):
|
||||
"""Represent rotation as unit quaternion, rotation matrix, and Bunge-Euler angles."""
|
||||
if self == Rotation():
|
||||
return 'Rotation()'
|
||||
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)),
|
||||
])
|
||||
"""Represent rotation as unit quaternion(s)."""
|
||||
return f'Quaternion{" " if self.quaternion.shape == (4,) else "s of shape "+str(self.quaternion.shape)+chr(10)}'\
|
||||
+ str(self.quaternion)
|
||||
|
||||
|
||||
# ToDo: Check difference __copy__ vs __deepcopy__
|
||||
def __copy__(self,**kwargs):
|
||||
"""Copy."""
|
||||
"""Create deep copy."""
|
||||
return self.__class__(rotation=kwargs['rotation'] if 'rotation' in kwargs else self.quaternion)
|
||||
|
||||
copy = __copy__
|
||||
|
@ -97,6 +93,26 @@ class Rotation:
|
|||
"""
|
||||
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
|
||||
account. See numpy.allclose for details.
|
||||
|
||||
|
@ -106,13 +122,21 @@ class Rotation:
|
|||
Rotation to check for equality.
|
||||
|
||||
"""
|
||||
return np.prod(self.shape,dtype=int) == np.prod(other.shape,dtype=int) \
|
||||
and np.allclose(self.quaternion,other.quaternion)
|
||||
return np.logical_not(self==other)
|
||||
|
||||
|
||||
def __array__(self):
|
||||
"""Initializer for numpy."""
|
||||
return self.quaternion
|
||||
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self.quaternion[...,0].size
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self.quaternion.shape[:-1]
|
||||
return self.quaternion[...,0].shape
|
||||
|
||||
|
||||
def __len__(self):
|
||||
|
@ -127,41 +151,46 @@ class Rotation:
|
|||
return dup
|
||||
|
||||
|
||||
def __pow__(self,pwr):
|
||||
def __pow__(self,exp):
|
||||
"""
|
||||
Raise quaternion to power.
|
||||
|
||||
Equivalent to performing the rotation 'pwr' times.
|
||||
Perform the rotation 'exp' times.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pwr : float
|
||||
Power to raise quaternion to.
|
||||
exp : float
|
||||
Exponent.
|
||||
|
||||
"""
|
||||
phi = np.arccos(self.quaternion[...,0:1])
|
||||
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 __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):
|
||||
def __ipow__(self,exp):
|
||||
"""
|
||||
Rotation of vector, second or fourth order tensor, or rotation object.
|
||||
Perform the rotation 'exp' times (in-place).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other : numpy.ndarray or Rotation
|
||||
Vector, second or fourth order tensor, or rotation object that is rotated.
|
||||
exp : float
|
||||
Exponent.
|
||||
|
||||
"""
|
||||
return self**exp
|
||||
|
||||
|
||||
def __mul__(self,other):
|
||||
"""
|
||||
Compose this rotation with other.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other : Rotation of shape(self.shape)
|
||||
Rotation for composition.
|
||||
|
||||
Returns
|
||||
-------
|
||||
other_rot : numpy.ndarray or Rotation
|
||||
Rotated vector, second or fourth order tensor, or rotation object.
|
||||
composition : Rotation
|
||||
Compound rotation self*other, i.e. first other then self 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,)))
|
||||
p = q_m*p_o + q_o*p_m + _P * np.cross(p_m,p_o)
|
||||
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:
|
||||
q_m = self.quaternion[...,0]
|
||||
p_m = self.quaternion[...,1:]
|
||||
|
@ -193,9 +285,13 @@ class Rotation:
|
|||
return np.einsum('...im,...jn,...ko,...lp,...mnop',R,R,R,R,other)
|
||||
else:
|
||||
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:
|
||||
raise TypeError(f'Cannot rotate {type(other)}')
|
||||
|
||||
apply = __matmul__
|
||||
|
||||
|
||||
def _standardize(self):
|
||||
"""Standardize quaternion (ensure positive real hemisphere)."""
|
||||
|
@ -296,7 +392,7 @@ class Rotation:
|
|||
Rotation to which the misorientation is computed.
|
||||
|
||||
"""
|
||||
return other@~self
|
||||
return other*~self
|
||||
|
||||
|
||||
################################################################################################
|
||||
|
@ -379,15 +475,17 @@ class Rotation:
|
|||
|
||||
Parameters
|
||||
----------
|
||||
vector : bool, optional
|
||||
Return as actual Rodrigues-Frank vector, i.e. axis
|
||||
and angle argument are not separated.
|
||||
compact : bool, optional
|
||||
Return as actual Rodrigues-Frank vector,
|
||||
i.e. axis and angle argument are not separated.
|
||||
|
||||
Returns
|
||||
-------
|
||||
rho : numpy.ndarray of shape (...,4) unless vector == True:
|
||||
numpy.ndarray of shape (...,3)
|
||||
Rodrigues-Frank vector: [n_1, n_2, n_3, tan(ω/2)], ǀnǀ = 1 and ω ∈ [0,π].
|
||||
rho : numpy.ndarray of shape (...,4) containing
|
||||
[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)
|
||||
|
@ -415,8 +513,8 @@ class Rotation:
|
|||
|
||||
Returns
|
||||
-------
|
||||
c : numpy.ndarray of shape (...,3)
|
||||
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3).
|
||||
x : numpy.ndarray of shape (...,3)
|
||||
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
|
||||
|
||||
"""
|
||||
return Rotation._qu2cu(self.quaternion)
|
||||
|
@ -427,8 +525,7 @@ class Rotation:
|
|||
@staticmethod
|
||||
def from_quaternion(q,
|
||||
accept_homomorph = False,
|
||||
P = -1,
|
||||
**kwargs):
|
||||
P = -1):
|
||||
"""
|
||||
Initialize from quaternion.
|
||||
|
||||
|
@ -463,8 +560,7 @@ class Rotation:
|
|||
|
||||
@staticmethod
|
||||
def from_Euler_angles(phi,
|
||||
degrees = False,
|
||||
**kwargs):
|
||||
degrees = False):
|
||||
"""
|
||||
Initialize from Bunge-Euler angles.
|
||||
|
||||
|
@ -491,8 +587,7 @@ class Rotation:
|
|||
def from_axis_angle(axis_angle,
|
||||
degrees = False,
|
||||
normalize = False,
|
||||
P = -1,
|
||||
**kwargs):
|
||||
P = -1):
|
||||
"""
|
||||
Initialize from Axis angle pair.
|
||||
|
||||
|
@ -529,8 +624,7 @@ class Rotation:
|
|||
@staticmethod
|
||||
def from_basis(basis,
|
||||
orthonormal = True,
|
||||
reciprocal = False,
|
||||
**kwargs):
|
||||
reciprocal = False):
|
||||
"""
|
||||
Initialize from lattice basis vectors.
|
||||
|
||||
|
@ -564,7 +658,7 @@ class Rotation:
|
|||
return Rotation(Rotation._om2qu(om))
|
||||
|
||||
@staticmethod
|
||||
def from_matrix(R,**kwargs):
|
||||
def from_matrix(R):
|
||||
"""
|
||||
Initialize from rotation matrix.
|
||||
|
||||
|
@ -608,8 +702,7 @@ class Rotation:
|
|||
@staticmethod
|
||||
def from_Rodrigues_vector(rho,
|
||||
normalize = False,
|
||||
P = -1,
|
||||
**kwargs):
|
||||
P = -1):
|
||||
"""
|
||||
Initialize from Rodrigues-Frank vector (angle separated from axis).
|
||||
|
||||
|
@ -640,8 +733,7 @@ class Rotation:
|
|||
|
||||
@staticmethod
|
||||
def from_homochoric(h,
|
||||
P = -1,
|
||||
**kwargs):
|
||||
P = -1):
|
||||
"""
|
||||
Initialize from homochoric vector.
|
||||
|
||||
|
@ -667,21 +759,20 @@ class Rotation:
|
|||
return Rotation(Rotation._ho2qu(ho))
|
||||
|
||||
@staticmethod
|
||||
def from_cubochoric(c,
|
||||
P = -1,
|
||||
**kwargs):
|
||||
def from_cubochoric(x,
|
||||
P = -1):
|
||||
"""
|
||||
Initialize from cubochoric vector.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
c : numpy.ndarray of shape (...,3)
|
||||
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3).
|
||||
x : numpy.ndarray of shape (...,3)
|
||||
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
|
||||
P : int ∈ {-1,1}, optional
|
||||
Convention used. Defaults to -1.
|
||||
|
||||
"""
|
||||
cu = np.array(c,dtype=float)
|
||||
cu = np.array(x,dtype=float)
|
||||
if cu.shape[:-2:-1] != (3,):
|
||||
raise ValueError('Invalid shape.')
|
||||
if abs(P) != 1:
|
||||
|
@ -697,8 +788,7 @@ class Rotation:
|
|||
|
||||
@staticmethod
|
||||
def from_random(shape = None,
|
||||
rng_seed = None,
|
||||
**kwargs):
|
||||
rng_seed = None):
|
||||
"""
|
||||
Draw random rotation.
|
||||
|
||||
|
@ -791,8 +881,7 @@ class Rotation:
|
|||
sigma,
|
||||
N = 500,
|
||||
degrees = True,
|
||||
rng_seed = None,
|
||||
**kwargs):
|
||||
rng_seed = None):
|
||||
"""
|
||||
Calculate set of rotations with Gaussian distribution around center.
|
||||
|
||||
|
@ -819,7 +908,7 @@ class Rotation:
|
|||
np.sqrt(1-u**2)*np.sin(Theta),
|
||||
u, omega])
|
||||
|
||||
return Rotation.from_axis_angle(p) @ center
|
||||
return Rotation.from_axis_angle(p) * center
|
||||
|
||||
|
||||
@staticmethod
|
||||
|
@ -828,8 +917,7 @@ class Rotation:
|
|||
sigma = 0.0,
|
||||
N = 500,
|
||||
degrees = True,
|
||||
rng_seed = None,
|
||||
**kwargs):
|
||||
rng_seed = None):
|
||||
"""
|
||||
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
|
||||
|
||||
return R_align.broadcast_to(N) \
|
||||
@ Rotation.from_axis_angle(p,normalize=True) \
|
||||
@ Rotation.from_axis_angle(f)
|
||||
* Rotation.from_axis_angle(p,normalize=True) \
|
||||
* Rotation.from_axis_angle(f)
|
||||
|
||||
|
||||
####################################################################################################
|
||||
|
@ -1060,7 +1148,6 @@ class Rotation:
|
|||
@staticmethod
|
||||
def _om2ax(om):
|
||||
"""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],
|
||||
om[...,2,0:1]-om[...,0,2:3],
|
||||
om[...,0,1:2]-om[...,1,0:1]
|
||||
|
|
|
@ -26,7 +26,7 @@ class Table:
|
|||
comments_ = [comments] if isinstance(comments,str) else comments
|
||||
self.comments = [] if comments_ is None else [c for c in comments_]
|
||||
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()
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -42,12 +42,10 @@ class Table:
|
|||
return len(self.data)
|
||||
|
||||
def __copy__(self):
|
||||
"""Copy Table."""
|
||||
"""Create deep copy."""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def copy(self):
|
||||
"""Copy Table."""
|
||||
return self.__copy__()
|
||||
copy = __copy__
|
||||
|
||||
|
||||
def _label_discrete(self):
|
||||
|
@ -191,6 +189,11 @@ class Table:
|
|||
label : str
|
||||
Column label.
|
||||
|
||||
Returns
|
||||
-------
|
||||
data : numpy.ndarray
|
||||
Array of column data.
|
||||
|
||||
"""
|
||||
if re.match(r'[0-9]*?_',label):
|
||||
idx,key = label.split('_',1)
|
||||
|
@ -214,6 +217,11 @@ class Table:
|
|||
info : str, optional
|
||||
Human-readable information about the new data.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Updated table.
|
||||
|
||||
"""
|
||||
dup = self.copy()
|
||||
dup._add_comment(label,data.shape[1:],info)
|
||||
|
@ -240,6 +248,11 @@ class Table:
|
|||
info : str, optional
|
||||
Human-readable information about the modified data.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Updated table.
|
||||
|
||||
"""
|
||||
dup = self.copy()
|
||||
dup._add_comment(label,data.shape[1:],info)
|
||||
|
@ -263,6 +276,11 @@ class Table:
|
|||
label : str
|
||||
Column label.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Updated table.
|
||||
|
||||
"""
|
||||
dup = self.copy()
|
||||
dup.data.drop(columns=label,inplace=True)
|
||||
|
@ -281,6 +299,11 @@ class Table:
|
|||
label_new : str or iterable of str
|
||||
New column label(s).
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Updated table.
|
||||
|
||||
"""
|
||||
dup = self.copy()
|
||||
columns = dict(zip([old] if isinstance(old,str) else old,
|
||||
|
@ -302,6 +325,11 @@ class Table:
|
|||
ascending : bool or list, optional
|
||||
Set sort order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Updated table.
|
||||
|
||||
"""
|
||||
dup = self.copy()
|
||||
dup._label_discrete()
|
||||
|
@ -322,6 +350,11 @@ class Table:
|
|||
other : Table
|
||||
Table to append.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Concatenated table.
|
||||
|
||||
"""
|
||||
if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns):
|
||||
raise KeyError('Labels or shapes or order do not match')
|
||||
|
@ -342,6 +375,11 @@ class Table:
|
|||
other : Table
|
||||
Table to join.
|
||||
|
||||
Returns
|
||||
-------
|
||||
table : Table
|
||||
Joined table.
|
||||
|
||||
"""
|
||||
if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]:
|
||||
raise KeyError('Dublicated keys or row count mismatch')
|
||||
|
@ -382,7 +420,7 @@ class Table:
|
|||
[f'# {comment}' for comment in self.comments]
|
||||
|
||||
try:
|
||||
fhandle = open(fname,'w')
|
||||
fhandle = open(fname,'w',newline='\n')
|
||||
except TypeError:
|
||||
fhandle = fname
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import logging
|
|||
import logging.config
|
||||
from collections.abc import Iterable
|
||||
from optparse import OptionParser
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
@ -180,7 +181,7 @@ class Test:
|
|||
|
||||
def fileInRoot(self,dir,file):
|
||||
"""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):
|
||||
|
@ -282,40 +283,6 @@ class Test:
|
|||
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,
|
||||
headings1,file1,
|
||||
normHeadings='',normType=None,
|
||||
|
@ -468,101 +435,6 @@ class Test:
|
|||
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):
|
||||
|
||||
ret = culprit
|
||||
|
|
|
@ -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 . import util
|
||||
from . import environment
|
||||
from . import Table
|
||||
|
||||
|
||||
|
@ -247,8 +246,8 @@ class VTK:
|
|||
raise ValueError('No label defined for numpy.ndarray')
|
||||
|
||||
N_data = data.shape[0]
|
||||
d = np_to_vtk((data.astype(np.float32) if data.dtype in [np.float64, np.float128]
|
||||
else data).reshape(N_data,-1),deep=True) # avoid large files
|
||||
d = np_to_vtk((data.astype(np.single) if data.dtype in [np.double, np.longdouble] else
|
||||
data).reshape(N_data,-1),deep=True) # avoid large files
|
||||
d.SetName(label)
|
||||
|
||||
if N_data == N_points:
|
||||
|
@ -348,6 +347,21 @@ class VTK:
|
|||
|
||||
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.SetInputData(self.vtk_data)
|
||||
actor = vtk.vtkActor()
|
||||
|
@ -361,7 +375,7 @@ class VTK:
|
|||
ren.AddActor(actor)
|
||||
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.SetRenderWindow(window)
|
||||
|
|
|
@ -2,14 +2,13 @@ import subprocess
|
|||
import shlex
|
||||
import re
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from .. import environment
|
||||
|
||||
class Marc:
|
||||
"""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.
|
||||
|
||||
|
@ -25,9 +24,7 @@ class Marc:
|
|||
@property
|
||||
def library_path(self):
|
||||
|
||||
path_MSC = environment.options['MSC_ROOT']
|
||||
path_lib = Path(f'{path_MSC}/mentat{self.version}/shlib/linux64')
|
||||
|
||||
path_lib = Path(f'{os.environ["MSC_ROOT"]}/mentat{self.version}/shlib/linux64')
|
||||
if not path_lib.is_dir():
|
||||
raise FileNotFoundError(f'library path "{path_lib}" not found')
|
||||
|
||||
|
@ -37,9 +34,7 @@ class Marc:
|
|||
@property
|
||||
def tools_path(self):
|
||||
|
||||
path_MSC = environment.options['MSC_ROOT']
|
||||
path_tools = Path(f'{path_MSC}/marc{self.version}/tools')
|
||||
|
||||
path_tools = Path(f'{os.environ["MSC_ROOT"]}/marc{self.version}/tools')
|
||||
if not path_tools.is_dir():
|
||||
raise FileNotFoundError(f'tools path "{path_tools}" not found')
|
||||
|
||||
|
@ -54,7 +49,7 @@ class Marc:
|
|||
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'))
|
||||
if not usersub.is_file():
|
||||
raise FileNotFoundError(f'subroutine ({"source" if compile else "binary"}) "{usersub}" not found')
|
||||
|
@ -71,7 +66,7 @@ class Marc:
|
|||
|
||||
if logfile is not None:
|
||||
try:
|
||||
f = open(logfile,'w+')
|
||||
f = open(logfile,'w+',newline='\n')
|
||||
except TypeError:
|
||||
f = logfile
|
||||
else:
|
||||
|
|
|
@ -133,6 +133,8 @@ def execute(cmd,
|
|||
stdout = stdout.decode('utf-8').replace('\x08','')
|
||||
stderr = stderr.decode('utf-8').replace('\x08','')
|
||||
if process.returncode != 0:
|
||||
print(stdout)
|
||||
print(stderr)
|
||||
raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}")
|
||||
return stdout, stderr
|
||||
|
||||
|
@ -183,7 +185,7 @@ def scale_to_coprime(v):
|
|||
# Python 3.9 provides math.lcm, see https://stackoverflow.com/questions/51716916.
|
||||
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)
|
||||
|
||||
with np.errstate(invalid='ignore'):
|
||||
|
@ -193,7 +195,7 @@ def scale_to_coprime(v):
|
|||
return m
|
||||
|
||||
|
||||
def project_stereographic(vector,normalize=False):
|
||||
def project_stereographic(vector,direction='z',normalize=True,keepdims=False):
|
||||
"""
|
||||
Apply stereographic projection to vector.
|
||||
|
||||
|
@ -201,18 +203,37 @@ def project_stereographic(vector,normalize=False):
|
|||
----------
|
||||
vector : numpy.ndarray of shape (...,3)
|
||||
Vector coordinates to be projected.
|
||||
direction : str
|
||||
Projection direction 'x', 'y', or 'z'.
|
||||
Defaults to 'z'.
|
||||
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
|
||||
-------
|
||||
coordinates : numpy.ndarray of shape (...,2)
|
||||
coordinates : numpy.ndarray of shape (...,2 | 3)
|
||||
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
|
||||
return np.block([v_[...,:2]/(1+np.abs(v_[...,2:3])),
|
||||
np.zeros_like(v_[...,2:3])])
|
||||
shift = 'zyx'.index(direction)
|
||||
v_ = np.roll(vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector,
|
||||
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):
|
||||
|
@ -418,7 +439,7 @@ class _ProgressBar:
|
|||
bar = '█' * filled_length + '░' * (self.bar_length - filled_length)
|
||||
delta_time = datetime.datetime.now() - self.start_time
|
||||
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.flush()
|
||||
|
||||
|
|
|
@ -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()))
|
||||
|
||||
setuptools.setup(
|
||||
name="damask",
|
||||
name='damask',
|
||||
version=version,
|
||||
author="The DAMASK team",
|
||||
author_email="damask@mpie.de",
|
||||
description="DAMASK library",
|
||||
long_description="Python library for pre and post processing of DAMASK simulations",
|
||||
url="https://damask.mpie.de",
|
||||
author='The DAMASK team',
|
||||
author_email='damask@mpie.de',
|
||||
description='DAMASK library',
|
||||
long_description='Python library for pre and post processing of DAMASK simulations',
|
||||
url='https://damask.mpie.de',
|
||||
packages=setuptools.find_packages(),
|
||||
include_package_data=True,
|
||||
python_requires = '>=3.6',
|
||||
install_requires = [
|
||||
"pandas", # requires numpy
|
||||
"scipy",
|
||||
"h5py", # requires numpy
|
||||
"vtk",
|
||||
"matplotlib", # requires numpy, pillow
|
||||
"pyaml"
|
||||
'pandas>=0.24', # requires numpy
|
||||
'scipy>=1.2',
|
||||
'h5py>=2.9', # requires numpy
|
||||
'vtk>=8.1',
|
||||
'matplotlib>=3.0', # requires numpy, pillow
|
||||
'pyaml>=3.12'
|
||||
],
|
||||
classifiers = [
|
||||
"Intended Audience :: Science/Research",
|
||||
"Topic :: Scientific/Engineering",
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
||||
"Operating System :: OS Independent",
|
||||
'Intended Audience :: Science/Research',
|
||||
'Topic :: Scientific/Engineering',
|
||||
'Programming Language :: Python :: 3',
|
||||
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
|
||||
'Operating System :: OS Independent',
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
homogenization:
|
||||
SX:
|
||||
N_constituents: 1
|
||||
mechanics: {type: none}
|
||||
mechanics: {type: pass}
|
||||
Taylor:
|
||||
N_constituents: 2
|
||||
mechanics: {type: isostrain}
|
||||
|
||||
material:
|
||||
- constituents:
|
||||
- fraction: 1.0
|
||||
- v: 1.0
|
||||
O: [1.0, 0.0, 0.0, 0.0]
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- fraction: 1.0
|
||||
- v: 1.0
|
||||
O: [0.7936696712125002, -0.28765777461664166, -0.3436487135089419, 0.4113964260949434]
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- fraction: 1.0
|
||||
- v: 1.0
|
||||
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
|
||||
phase: Aluminum
|
||||
homogenization: SX
|
||||
- constituents:
|
||||
- fraction: 0.5
|
||||
- v: 0.5
|
||||
O: [0.28645844315788244, -0.022571491243423537, -0.467933059311115, -0.8357456192708106]
|
||||
phase: Aluminum
|
||||
- fraction: 0.5
|
||||
- v: 0.5
|
||||
O: [0.3986143167493579, -0.7014883552495493, 0.2154871765709027, 0.5500781677772945]
|
||||
phase: Steel
|
||||
homogenization: Taylor
|
||||
|
|
|
@ -22,6 +22,19 @@ class TestConfig:
|
|||
with open(tmp_path/'config.yaml') as f:
|
||||
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):
|
||||
config = Config()
|
||||
config['A'] = 1
|
||||
|
|
|
@ -5,6 +5,7 @@ import numpy as np
|
|||
|
||||
from damask import ConfigMaterial
|
||||
from damask import Table
|
||||
from damask import Rotation
|
||||
|
||||
@pytest.fixture
|
||||
def ref_path(ref_path_base):
|
||||
|
@ -42,7 +43,7 @@ class TestConfigMaterial:
|
|||
|
||||
def test_invalid_fraction(self,ref_path):
|
||||
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
|
||||
|
||||
@pytest.mark.parametrize('item',['homogenization','phase','material'])
|
||||
|
@ -85,42 +86,25 @@ class TestConfigMaterial:
|
|||
|
||||
def test_from_table(self):
|
||||
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
|
||||
t = Table(a,{'varying':2,'constant':2})
|
||||
c = ConfigMaterial.from_table(t,constituents={'a':'varying','b':'1_constant'},c='2_constant')
|
||||
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':1,'constant':4})
|
||||
c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':'4_constant'})
|
||||
assert len(c['material']) == N
|
||||
for i,m in enumerate(c['material']):
|
||||
c = m['constituents'][0]
|
||||
assert m['c'] == 1 and c['b'] == 0 and (c['a'] == [i,1]).all()
|
||||
assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all()
|
||||
|
||||
def test_constituents(self):
|
||||
c = ConfigMaterial._constituents(c=1,v=[2,3])
|
||||
assert c[0][0]['c'] == c[1][0]['c'] == 1
|
||||
assert c[0][0]['v'] == c[1][0]['v'] -1 ==2
|
||||
|
||||
@pytest.mark.parametrize('constituents',[{'W':1,'X':[2,3]},{'Y':4},{'Z':[5,6]}])
|
||||
@pytest.mark.parametrize('a',[[7.,8.],9.])
|
||||
@pytest.mark.parametrize('b',['bd',['efg','hi']])
|
||||
def test_material_add(self,tmp_path,constituents,a,b):
|
||||
len_c = len(ConfigMaterial()._constituents(1,**constituents))
|
||||
len_a = len(a) if isinstance(a,list) else 1
|
||||
len_b = len(b) if isinstance(b,list) else 1
|
||||
m = ConfigMaterial().material_add(constituents,a=a,b=b)
|
||||
m.save()
|
||||
assert len(m['material']) == np.max([len_a,len_b,len_c])
|
||||
|
||||
@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)
|
||||
@pytest.mark.parametrize('N,n,kw',[
|
||||
(1,1,{'phase':'Gold',
|
||||
'O':[1,0,0,0],
|
||||
'homogenization':'SX'}),
|
||||
(3,1,{'phase':'Gold',
|
||||
'O':Rotation.from_random(3),
|
||||
'homogenization':'SX'}),
|
||||
(2,3,{'phase':np.broadcast_to(['a','b','c'],(2,3)),
|
||||
'O':Rotation.from_random((2,3)),
|
||||
'homogenization':['SX','PX']}),
|
||||
])
|
||||
def test_material_add(self,kw,N,n):
|
||||
m = ConfigMaterial().material_add(**kw)
|
||||
assert len(m['material']) == N
|
||||
assert len(m['material'][0]['constituents']) == n
|
||||
|
|
|
@ -347,7 +347,7 @@ class TestGrid:
|
|||
@pytest.mark.parametrize('approach',['Laguerre','Voronoi'])
|
||||
def test_tessellate_bicrystal(self,approach):
|
||||
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])))
|
||||
material = np.zeros(cells)
|
||||
material[:,cells[1]//2:,:] = 1
|
||||
|
|
|
@ -7,6 +7,7 @@ from damask import Orientation
|
|||
from damask import Table
|
||||
from damask import lattice
|
||||
from damask import util
|
||||
from damask import grid_filters
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -25,13 +26,16 @@ class TestOrientation:
|
|||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||
def test_equal(self,lattice,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('shape',[None,5,(4,6)])
|
||||
def test_unequal(self,lattice,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',[
|
||||
(dict(rotation=[1,0,0,0]),
|
||||
|
@ -115,7 +119,7 @@ class TestOrientation:
|
|||
== np.eye(3))
|
||||
|
||||
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))
|
||||
|
||||
def test_from_spherical_component(self):
|
||||
|
@ -138,7 +142,7 @@ class TestOrientation:
|
|||
dict(lattice='hP',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)):
|
||||
c = np.cross(b,a)
|
||||
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) \
|
||||
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):
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -218,6 +237,16 @@ class TestOrientation:
|
|||
for r, theO in zip(o.reduced.flatten(),o.flatten()):
|
||||
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('shape',[(1),(2,3),(4,3,2)])
|
||||
@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):
|
||||
r = Orientation(rotation=set_of_quaternions[:200].reshape((50,4,4)),lattice=lattice).related(model)
|
||||
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('lattice',['cF','cI'])
|
||||
|
|
|
@ -21,7 +21,7 @@ def default(tmp_path,ref_path):
|
|||
fname = '12grains6x7x8_tensionY.hdf5'
|
||||
shutil.copy(ref_path/fname,tmp_path)
|
||||
f = Result(tmp_path/fname)
|
||||
f.pick('times',20.0)
|
||||
f.view('times',20.0)
|
||||
return f
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -43,56 +43,56 @@ class TestResult:
|
|||
print(default)
|
||||
|
||||
|
||||
def test_pick_all(self,default):
|
||||
default.pick('increments',True)
|
||||
def test_view_all(self,default):
|
||||
default.view('increments',True)
|
||||
a = default.get_dataset_location('F')
|
||||
default.pick('increments','*')
|
||||
default.view('increments','*')
|
||||
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')
|
||||
|
||||
default.pick('times',True)
|
||||
default.view('times',True)
|
||||
d = default.get_dataset_location('F')
|
||||
default.pick('times','*')
|
||||
default.view('times','*')
|
||||
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')
|
||||
assert a == b == c == d == e ==f
|
||||
|
||||
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
|
||||
def test_pick_none(self,default,what):
|
||||
default.pick(what,False)
|
||||
def test_view_none(self,default,what):
|
||||
default.view(what,False)
|
||||
a = default.get_dataset_location('F')
|
||||
default.pick(what,[])
|
||||
default.view(what,[])
|
||||
b = default.get_dataset_location('F')
|
||||
|
||||
assert a == b == []
|
||||
|
||||
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
|
||||
def test_pick_more(self,default,what):
|
||||
default.pick(what,False)
|
||||
default.pick_more(what,'*')
|
||||
def test_view_more(self,default,what):
|
||||
default.view(what,False)
|
||||
default.view_more(what,'*')
|
||||
a = default.get_dataset_location('F')
|
||||
|
||||
default.pick(what,True)
|
||||
default.view(what,True)
|
||||
b = default.get_dataset_location('F')
|
||||
|
||||
assert a == b
|
||||
|
||||
@pytest.mark.parametrize('what',['increments','times','phases']) # ToDo: discuss homogenizations
|
||||
def test_pick_less(self,default,what):
|
||||
default.pick(what,True)
|
||||
default.pick_less(what,'*')
|
||||
def test_view_less(self,default,what):
|
||||
default.view(what,True)
|
||||
default.view_less(what,'*')
|
||||
a = default.get_dataset_location('F')
|
||||
|
||||
default.pick(what,False)
|
||||
default.view(what,False)
|
||||
b = default.get_dataset_location('F')
|
||||
|
||||
assert a == b == []
|
||||
|
||||
def test_pick_invalid(self,default):
|
||||
def test_view_invalid(self,default):
|
||||
with pytest.raises(AttributeError):
|
||||
default.pick('invalid',True)
|
||||
default.view('invalid',True)
|
||||
|
||||
def test_add_absolute(self,default):
|
||||
default.add_absolute('F_e')
|
||||
|
@ -307,7 +307,7 @@ class TestResult:
|
|||
|
||||
@pytest.mark.parametrize('overwrite',['off','on'])
|
||||
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()
|
||||
loc = default.get_dataset_location('sigma')
|
||||
|
|
|
@ -526,7 +526,7 @@ class TestRotation:
|
|||
o = backward(forward(m))
|
||||
u = np.array([np.pi*2,np.pi,np.pi*2])
|
||||
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):
|
||||
sum_phi = np.unwrap([m[0]+m[2],o[0]+o[2]])
|
||||
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()}'
|
||||
|
||||
@pytest.mark.parametrize('forward,backward',[(Rotation._ro2qu,Rotation._qu2ro),
|
||||
#(Rotation._ro2om,Rotation._om2ro),
|
||||
#(Rotation._ro2eu,Rotation._eu2ro),
|
||||
(Rotation._ro2om,Rotation._om2ro),
|
||||
(Rotation._ro2eu,Rotation._eu2ro),
|
||||
(Rotation._ro2ax,Rotation._ax2ro),
|
||||
(Rotation._ro2ho,Rotation._ho2ro),
|
||||
(Rotation._ro2cu,Rotation._cu2ro)])
|
||||
def test_Rodrigues_internal(self,set_of_rotations,forward,backward):
|
||||
"""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:
|
||||
m = rot.as_Rodrigues_vector()
|
||||
o = backward(forward(m))
|
||||
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()}'
|
||||
|
||||
@pytest.mark.parametrize('forward,backward',[(Rotation._ho2qu,Rotation._qu2ho),
|
||||
|
@ -592,7 +595,7 @@ class TestRotation:
|
|||
o = backward(forward(m))
|
||||
ok = np.allclose(m,o,atol=atol)
|
||||
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()}'
|
||||
|
||||
@pytest.mark.parametrize('vectorized, single',[(Rotation._qu2om,qu2om),
|
||||
|
@ -686,6 +689,10 @@ class TestRotation:
|
|||
with pytest.raises(TypeError):
|
||||
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])
|
||||
def test_Eulers(self,set_of_rotations,degrees):
|
||||
for rot in set_of_rotations:
|
||||
|
@ -719,7 +726,7 @@ class TestRotation:
|
|||
o = Rotation.from_axis_angle(rot.as_axis_angle()).as_axis_angle()
|
||||
ok = np.allclose(m,o,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) \
|
||||
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()
|
||||
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 = 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()}'
|
||||
|
||||
@pytest.mark.parametrize('P',[1,-1])
|
||||
|
@ -780,14 +787,32 @@ class TestRotation:
|
|||
else:
|
||||
assert r.shape == shape
|
||||
|
||||
def test_equal(self):
|
||||
assert Rotation.from_random(rng_seed=1) == Rotation.from_random(rng_seed=1)
|
||||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||
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):
|
||||
r = Rotation.from_random()
|
||||
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):
|
||||
r = Rotation.from_random(shape=shape)
|
||||
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)
|
||||
s = r.append(p)
|
||||
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)])
|
||||
def test_append_list(self,shape):
|
||||
|
@ -806,7 +831,7 @@ class TestRotation:
|
|||
p = Rotation.from_random(shape=shape)
|
||||
s = r.append([r,p])
|
||||
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',[
|
||||
([-1,0,0,0],[1,0,0,0]),
|
||||
|
@ -828,7 +853,7 @@ class TestRotation:
|
|||
@pytest.mark.parametrize('order',['C','F'])
|
||||
def test_flatten_reshape(self,shape,order):
|
||||
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,
|
||||
Rotation.from_Euler_angles,
|
||||
|
@ -939,7 +964,7 @@ class TestRotation:
|
|||
|
||||
def test_rotate_inverse(self):
|
||||
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),
|
||||
np.random.rand(3,3),
|
||||
|
@ -973,6 +998,42 @@ class TestRotation:
|
|||
R_2 = Rotation.from_Euler_angles([360,0,0],degrees=True)
|
||||
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])
|
||||
def test_average(self,angle):
|
||||
R = Rotation.from_axis_angle([[0,0,1,10],[0,0,1,angle]],degrees=True)
|
||||
|
|
|
@ -49,17 +49,18 @@ class TestUtil:
|
|||
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
|
||||
|
||||
@pytest.mark.parametrize('point,normalize,answer',
|
||||
@pytest.mark.parametrize('point,direction,normalize,keepdims,answer',
|
||||
[
|
||||
([1,0,0],False,[1,0,0]),
|
||||
([1,0,0],True, [1,0,0]),
|
||||
([0,1,1],False,[0,0.5,0]),
|
||||
([0,1,1],True, [0,0.41421356,0]),
|
||||
([1,1,1],False,[0.5,0.5,0]),
|
||||
([1,1,1],True, [0.3660254, 0.3660254, 0]),
|
||||
([1,0,0],'z',False,True, [1,0,0]),
|
||||
([1,0,0],'z',True, False,[1,0]),
|
||||
([0,1,1],'z',False,True, [0,0.5,0]),
|
||||
([0,1,1],'y',True, False,[0.41421356,0]),
|
||||
([1,1,0],'x',False,False,[0.5,0]),
|
||||
([1,1,1],'y',True, True, [0.3660254, 0,0.3660254]),
|
||||
])
|
||||
def test_project_stereographic(self,point,normalize,answer):
|
||||
assert np.allclose(util.project_stereographic(np.array(point),normalize=normalize),answer)
|
||||
def test_project_stereographic(self,point,direction,normalize,keepdims,answer):
|
||||
assert np.allclose(util.project_stereographic(np.array(point),direction=direction,
|
||||
normalize=normalize,keepdims=keepdims),answer)
|
||||
|
||||
@pytest.mark.parametrize('fro,to,mode,answer',
|
||||
[
|
||||
|
|
|
@ -19,7 +19,7 @@ module CPFEM
|
|||
use HDF5_utilities
|
||||
use results
|
||||
use lattice
|
||||
use constitutive
|
||||
use phase
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
@ -72,7 +72,6 @@ contains
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine CPFEM_initAll
|
||||
|
||||
call parallelization_init
|
||||
call DAMASK_interface_init
|
||||
call prec_init
|
||||
call IO_init
|
||||
|
@ -86,7 +85,7 @@ subroutine CPFEM_initAll
|
|||
call discretization_marc_init
|
||||
call lattice_init
|
||||
call material_init(.false.)
|
||||
call constitutive_init
|
||||
call phase_init
|
||||
call homogenization_init
|
||||
call crystallite_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
|
||||
|
||||
chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP)))
|
||||
case (THERMAL_conduction_ID) chosenThermal1
|
||||
temperature(material_homogenizationAt(elCP))%p(material_homogenizationMemberAt(ip,elCP)) = &
|
||||
temperature_inp
|
||||
end select chosenThermal1
|
||||
!chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP)))
|
||||
! case (THERMAL_conduction_ID) chosenThermal1
|
||||
! temperature(material_homogenizationAt(elCP))%p(material_homogenizationMemberAt(ip,elCP)) = &
|
||||
! temperature_inp
|
||||
!end select chosenThermal1
|
||||
homogenization_F0(1:3,1:3,ma) = ffn
|
||||
homogenization_F(1:3,1:3,ma) = ffn1
|
||||
|
||||
|
@ -258,7 +257,7 @@ end subroutine CPFEM_general
|
|||
subroutine CPFEM_forward
|
||||
|
||||
call homogenization_forward
|
||||
call constitutive_forward
|
||||
call phase_forward
|
||||
|
||||
end subroutine CPFEM_forward
|
||||
|
||||
|
@ -273,7 +272,7 @@ subroutine CPFEM_results(inc,time)
|
|||
|
||||
call results_openJobFile
|
||||
call results_addIncrement(inc,time)
|
||||
call constitutive_results
|
||||
call phase_results
|
||||
call homogenization_results
|
||||
call discretization_results
|
||||
call results_finalizeIncrement
|
||||
|
|
|
@ -19,7 +19,7 @@ module CPFEM2
|
|||
use discretization
|
||||
use HDF5_utilities
|
||||
use homogenization
|
||||
use constitutive
|
||||
use phase
|
||||
#if defined(Mesh)
|
||||
use FEM_quadrature
|
||||
use discretization_mesh
|
||||
|
@ -60,7 +60,7 @@ subroutine CPFEM_initAll
|
|||
call discretization_grid_init(restart=interface_restartInc>0)
|
||||
#endif
|
||||
call material_init(restart=interface_restartInc>0)
|
||||
call constitutive_init
|
||||
call phase_init
|
||||
call homogenization_init
|
||||
call crystallite_init
|
||||
call CPFEM_init
|
||||
|
@ -74,9 +74,22 @@ end subroutine CPFEM_initAll
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine CPFEM_init
|
||||
|
||||
integer(HID_T) :: fileHandle
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
@ -86,7 +99,17 @@ end subroutine CPFEM_init
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
|
@ -97,7 +120,7 @@ end subroutine CPFEM_restartWrite
|
|||
subroutine CPFEM_forward
|
||||
|
||||
call homogenization_forward
|
||||
call constitutive_forward
|
||||
call phase_forward
|
||||
|
||||
end subroutine CPFEM_forward
|
||||
|
||||
|
@ -112,7 +135,7 @@ subroutine CPFEM_results(inc,time)
|
|||
|
||||
call results_openJobFile
|
||||
call results_addIncrement(inc,time)
|
||||
call constitutive_results
|
||||
call phase_results
|
||||
call homogenization_results
|
||||
call discretization_results
|
||||
call results_finalizeIncrement
|
||||
|
|
|
@ -43,7 +43,7 @@ void gethostname_c(char hostname[], 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){
|
||||
strncpy(username,pw->pw_name,STRLEN+1);
|
||||
*stat = 0;
|
||||
|
|
|
@ -199,7 +199,7 @@ subroutine DAMASK_interface_init
|
|||
if (interface_restartInc > 0) &
|
||||
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 signalusr2_c(c_funloc(catchSIGUSR2))
|
||||
call interface_setSIGTERM(.false.)
|
||||
|
@ -386,24 +386,14 @@ end function makeRelativePath
|
|||
subroutine catchSIGTERM(signal) bind(C)
|
||||
|
||||
integer(C_INT), value :: signal
|
||||
|
||||
|
||||
print'(a,i0)', ' received signal ',signal
|
||||
call interface_setSIGTERM(.true.)
|
||||
|
||||
print'(a,i0,a)', ' received signal ',signal, ', set SIGTERM=TRUE'
|
||||
|
||||
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.
|
||||
!> @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)
|
||||
|
||||
integer(C_INT), value :: signal
|
||||
|
||||
|
||||
print'(a,i0)', ' received signal ',signal
|
||||
call interface_setSIGUSR1(.true.)
|
||||
|
||||
print'(a,i0,a)', ' received signal ',signal, ', set SIGUSR1=TRUE'
|
||||
|
||||
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.
|
||||
!> @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)
|
||||
|
||||
integer(C_INT), value :: signal
|
||||
|
||||
|
||||
print'(a,i0,a)', ' received signal ',signal
|
||||
call interface_setSIGUSR2(.true.)
|
||||
|
||||
print'(a,i0,a)', ' received signal ',signal, ', set SIGUSR2=TRUE'
|
||||
|
||||
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.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine interface_setSIGUSR2(state)
|
||||
|
||||
logical, intent(in) :: state
|
||||
|
||||
|
||||
interface_SIGUSR2 = state
|
||||
print*, 'set SIGUSR2 to',state
|
||||
|
||||
end subroutine interface_setSIGUSR2
|
||||
|
||||
|
|
|
@ -7,20 +7,6 @@
|
|||
!> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH
|
||||
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
|
||||
!> @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 PASTE(x,y) x ## y
|
||||
|
@ -65,14 +51,8 @@ subroutine DAMASK_interface_init
|
|||
|
||||
print'(/,a)', ' Version: '//DAMASKVERSION
|
||||
|
||||
! https://github.com/jeffhammond/HPCInfo/blob/master/docs/Preprocessor-Macros.md
|
||||
#if __INTEL_COMPILER >= 1800
|
||||
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 with: '//compiler_version()
|
||||
print'(a)', ' Compiler options: '//compiler_options()
|
||||
|
||||
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,6) :: ddsdde
|
||||
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 :: &
|
||||
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 :: &
|
||||
lastIncConverged = .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.
|
||||
class(tNode), pointer :: &
|
||||
debug_Marc ! pointer to Marc debug options
|
||||
|
||||
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,i1)', ' Direct stress: ', ndi
|
||||
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
|
||||
|
||||
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
|
||||
CPFEM_init_done = .true.
|
||||
|
@ -351,7 +331,7 @@ end subroutine hypela2
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine flux(f,ts,n,time)
|
||||
use prec
|
||||
use thermal_conduction
|
||||
use homogenization
|
||||
use discretization_marc
|
||||
|
||||
implicit none
|
||||
|
@ -364,7 +344,8 @@ subroutine flux(f,ts,n,time)
|
|||
real(pReal), dimension(2), intent(out) :: &
|
||||
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
|
||||
|
||||
|
@ -378,14 +359,28 @@ subroutine flux(f,ts,n,time)
|
|||
subroutine uedinc(inc,incsub)
|
||||
use prec
|
||||
use CPFEM
|
||||
use discretization_marc
|
||||
|
||||
implicit none
|
||||
integer, intent(in) :: inc, incsub
|
||||
integer :: n, nqncomp, nqdatatype
|
||||
integer, save :: inc_written
|
||||
real(pReal), allocatable, dimension(:,:) :: d_n
|
||||
#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
inc_written = inc
|
||||
endif
|
||||
|
||||
|
|
|
@ -71,6 +71,12 @@ module HDF5_utilities
|
|||
module procedure HDF5_addAttribute_real_array
|
||||
end interface HDF5_addAttribute
|
||||
|
||||
#ifdef PETSc
|
||||
logical, parameter, private :: parallel_default = .true.
|
||||
#else
|
||||
logical, parameter, private :: parallel_default = .false.
|
||||
#endif
|
||||
|
||||
contains
|
||||
|
||||
|
||||
|
@ -105,16 +111,16 @@ end subroutine HDF5_utilities_init
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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, intent(in), optional :: mode
|
||||
logical, intent(in), optional :: parallel
|
||||
|
||||
character :: m
|
||||
integer(HID_T) :: plist_id
|
||||
integer :: hdferr
|
||||
|
||||
|
||||
if (present(mode)) then
|
||||
m = mode
|
||||
else
|
||||
|
@ -125,10 +131,8 @@ integer(HID_T) function HDF5_openFile(fileName,mode,parallel)
|
|||
if(hdferr < 0) error stop 'HDF5 error'
|
||||
|
||||
#ifdef PETSc
|
||||
if (present(parallel)) then; if (parallel) then
|
||||
call h5pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr)
|
||||
if(hdferr < 0) error stop 'HDF5 error'
|
||||
endif; endif
|
||||
call h5pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr)
|
||||
if(hdferr < 0) error stop 'HDF5 error'
|
||||
#endif
|
||||
|
||||
if (m == 'w') then
|
||||
|
@ -547,7 +551,7 @@ subroutine HDF5_read_real1(loc_id,dataset,datasetName,parallel)
|
|||
myStart, totalShape, loc_id,myShape,datasetName,parallel)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
real(pReal), intent(inout), dimension(:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1127,9 +1131,9 @@ end subroutine HDF5_write_real1
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1168,9 +1172,9 @@ end subroutine HDF5_write_real2
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1209,9 +1213,9 @@ end subroutine HDF5_write_real3
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1251,9 +1255,9 @@ end subroutine HDF5_write_real4
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1292,9 +1296,9 @@ end subroutine HDF5_write_real5
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1333,9 +1337,9 @@ end subroutine HDF5_write_real6
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
real(pReal), intent(in), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1375,9 +1379,9 @@ end subroutine HDF5_write_real7
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1416,9 +1420,9 @@ end subroutine HDF5_write_int1
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1457,9 +1461,9 @@ end subroutine HDF5_write_int2
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1498,9 +1502,9 @@ end subroutine HDF5_write_int3
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1539,9 +1543,9 @@ end subroutine HDF5_write_int4
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1580,9 +1584,9 @@ end subroutine HDF5_write_int5
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
@ -1621,9 +1625,9 @@ end subroutine HDF5_write_int6
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel)
|
||||
|
||||
integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
integer, intent(in), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file
|
||||
integer(HID_T), intent(in) :: loc_id !< file or group handle
|
||||
character(len=*), intent(in) :: datasetName !< name of the dataset in the file
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
||||
if (product(totalShape) /= 0) then
|
||||
|
|
27
src/IO.f90
27
src/IO.f90
|
@ -65,8 +65,8 @@ end subroutine IO_init
|
|||
function IO_readlines(fileName) result(fileContent)
|
||||
|
||||
character(len=*), intent(in) :: fileName
|
||||
|
||||
character(len=pStringLen), dimension(:), allocatable :: fileContent !< file content, separated per lines
|
||||
|
||||
character(len=pStringLen) :: line
|
||||
character(len=:), allocatable :: rawData
|
||||
integer :: &
|
||||
|
@ -75,6 +75,7 @@ function IO_readlines(fileName) result(fileContent)
|
|||
l
|
||||
logical :: warned
|
||||
|
||||
|
||||
rawData = IO_read(fileName)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
|
@ -112,16 +113,21 @@ end function IO_readlines
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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)
|
||||
|
||||
character(len=*), intent(in) :: fileName
|
||||
character(len=:), allocatable :: fileContent
|
||||
|
||||
integer :: &
|
||||
fileLength, &
|
||||
fileUnit, &
|
||||
myStat
|
||||
myStat, &
|
||||
firstEOL
|
||||
character, parameter :: CR = achar(13)
|
||||
|
||||
|
||||
inquire(file = fileName, size=fileLength)
|
||||
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))
|
||||
close(fileUnit)
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -151,6 +161,7 @@ logical pure function IO_isBlank(string)
|
|||
|
||||
integer :: posNonBlank
|
||||
|
||||
|
||||
posNonBlank = verify(string,IO_WHITESPACE)
|
||||
IO_isBlank = posNonBlank == 0 .or. posNonBlank == scan(string,IO_COMMENT)
|
||||
|
||||
|
@ -170,6 +181,7 @@ pure function IO_stringPos(string)
|
|||
|
||||
integer :: left, right
|
||||
|
||||
|
||||
allocate(IO_stringPos(1), source=0)
|
||||
right = 0
|
||||
|
||||
|
@ -249,6 +261,7 @@ pure function IO_lc(string)
|
|||
|
||||
integer :: i,n
|
||||
|
||||
|
||||
do i=1,len(string)
|
||||
n = index(UPPER,string(i:i))
|
||||
if(n/=0) then
|
||||
|
@ -271,6 +284,7 @@ function IO_rmComment(line)
|
|||
character(len=:), allocatable :: IO_rmComment
|
||||
integer :: split
|
||||
|
||||
|
||||
split = index(line,IO_COMMENT)
|
||||
|
||||
if (split == 0) then
|
||||
|
@ -292,6 +306,7 @@ integer function IO_stringAsInt(string)
|
|||
integer :: readStatus
|
||||
character(len=*), parameter :: VALIDCHARS = '0123456789+- '
|
||||
|
||||
|
||||
valid: if (verify(string,VALIDCHARS) == 0) then
|
||||
read(string,*,iostat=readStatus) IO_stringAsInt
|
||||
if (readStatus /= 0) call IO_error(111,ext_msg=string)
|
||||
|
@ -313,6 +328,7 @@ real(pReal) function IO_stringAsFloat(string)
|
|||
integer :: readStatus
|
||||
character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- '
|
||||
|
||||
|
||||
valid: if (verify(string,VALIDCHARS) == 0) then
|
||||
read(string,*,iostat=readStatus) IO_stringAsFloat
|
||||
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
|
||||
|
||||
|
||||
if (trim(adjustl(string)) == 'True' .or. trim(adjustl(string)) == 'true') then
|
||||
IO_stringAsBool = .true.
|
||||
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=pStringLen) :: formatString
|
||||
|
||||
|
||||
select case (error_ID)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
|
@ -382,6 +400,9 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg)
|
|||
msg = 'invalid character for logical:'
|
||||
case (114)
|
||||
msg = 'cannot decode base64 string:'
|
||||
case (115)
|
||||
msg = 'found CR. Windows file endings (CRLF) are not supported.'
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! lattice error messages
|
||||
|
|
|
@ -72,7 +72,7 @@ module YAML_types
|
|||
getKey => tNode_getKey_byIndex
|
||||
procedure :: &
|
||||
contains => tNode_contains
|
||||
|
||||
|
||||
generic :: &
|
||||
get => tNode_get_byIndex, &
|
||||
tNode_get_byKey
|
||||
|
@ -157,7 +157,7 @@ module YAML_types
|
|||
emptyDict
|
||||
type(tList), target, public :: &
|
||||
emptyList
|
||||
|
||||
|
||||
abstract interface
|
||||
|
||||
recursive function asFormattedString(self,indent)
|
||||
|
@ -179,7 +179,7 @@ module YAML_types
|
|||
|
||||
public :: &
|
||||
YAML_types_init, &
|
||||
output_asStrings, & !ToDo: Hack for GNU. Remove later
|
||||
output_asStrings, & !ToDo: Hack for GNU. Remove later
|
||||
assignment(=)
|
||||
|
||||
contains
|
||||
|
@ -207,11 +207,11 @@ subroutine selfTest
|
|||
select type(s1)
|
||||
class is(tScalar)
|
||||
s1 = '1'
|
||||
if(s1%asInt() /= 1) error stop 'tScalar_asInt'
|
||||
if(dNeq(s1%asFloat(),1.0_pReal)) error stop 'tScalar_asFloat'
|
||||
if (s1%asInt() /= 1) error stop 'tScalar_asInt'
|
||||
if (dNeq(s1%asFloat(),1.0_pReal)) error stop 'tScalar_asFloat'
|
||||
s1 = 'true'
|
||||
if(.not. s1%asBool()) error stop 'tScalar_asBool'
|
||||
if(s1%asString() /= 'true') error stop 'tScalar_asString'
|
||||
if (.not. s1%asBool()) error stop 'tScalar_asBool'
|
||||
if (s1%asString() /= 'true') error stop 'tScalar_asString'
|
||||
end select
|
||||
|
||||
block
|
||||
|
@ -232,18 +232,18 @@ subroutine selfTest
|
|||
call l1%append(s1)
|
||||
call l1%append(s2)
|
||||
n => l1
|
||||
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(n%get_asInt(1) /= 2) error stop 'byIndex_asInt'
|
||||
if(dNeq(n%get_asFloat(2),3.0_pReal)) error stop 'byIndex_asFloat'
|
||||
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 (n%get_asInt(1) /= 2) error stop 'byIndex_asInt'
|
||||
if (dNeq(n%get_asFloat(2),3.0_pReal)) error stop 'byIndex_asFloat'
|
||||
endselect
|
||||
|
||||
allocate(tList::l2)
|
||||
select type(l2)
|
||||
class is(tList)
|
||||
call l2%append(l1)
|
||||
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(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'
|
||||
n => l2
|
||||
end select
|
||||
deallocate(n)
|
||||
|
@ -265,10 +265,10 @@ subroutine selfTest
|
|||
call l1%append(s2)
|
||||
n => l1
|
||||
|
||||
if(any(l1%asBools() .neqv. [.true., .false.])) error stop 'tList_asBools'
|
||||
if(any(l1%asStrings() /= ['true ','False'])) error stop 'tList_asStrings'
|
||||
if(n%get_asBool(2)) error stop 'byIndex_asBool'
|
||||
if(n%get_asString(1) /= 'true') error stop 'byIndex_asString'
|
||||
if (any(l1%asBools() .neqv. [.true., .false.])) error stop 'tList_asBools'
|
||||
if (any(l1%asStrings() /= ['true ','False'])) error stop 'tList_asStrings'
|
||||
if (n%get_asBool(2)) error stop 'byIndex_asBool'
|
||||
if (n%get_asString(1) /= 'true') error stop 'byIndex_asString'
|
||||
end block
|
||||
|
||||
end subroutine selfTest
|
||||
|
@ -418,7 +418,7 @@ function tNode_get_byIndex(self,i) result(node)
|
|||
integer :: j
|
||||
|
||||
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
|
||||
item => self_%first
|
||||
|
@ -599,7 +599,7 @@ function tNode_getKey_byIndex(self,i) result(key)
|
|||
dict => self%asDict()
|
||||
item => dict%first
|
||||
do j = 1, dict%length
|
||||
if(j == i) then
|
||||
if (j == i) then
|
||||
key = item%key
|
||||
exit
|
||||
else
|
||||
|
@ -613,7 +613,7 @@ end function tNode_getKey_byIndex
|
|||
!-------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
character(len=*), intent(in) :: k
|
||||
|
@ -624,18 +624,18 @@ function tNode_contains(self,k) result(exists)
|
|||
type(tDict), pointer :: dict
|
||||
|
||||
exists = .false.
|
||||
if(self%isDict()) then
|
||||
if (self%isDict()) then
|
||||
dict => self%asDict()
|
||||
do j=1, dict%length
|
||||
if(dict%getKey(j) == k) then
|
||||
if (dict%getKey(j) == k) then
|
||||
exists = .true.
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
elseif(self%isList()) then
|
||||
elseif (self%isList()) then
|
||||
list => self%asList()
|
||||
do j =1, list%length
|
||||
if(list%get_asString(j) == k) then
|
||||
do j=1, list%length
|
||||
if (list%get_asString(j) == k) then
|
||||
exists = .true.
|
||||
return
|
||||
endif
|
||||
|
@ -663,8 +663,8 @@ function tNode_get_byKey(self,k,defaultVal) result(node)
|
|||
logical :: found
|
||||
|
||||
found = present(defaultVal)
|
||||
if(found) node => defaultVal
|
||||
|
||||
if (found) node => defaultVal
|
||||
|
||||
self_ => self%asDict()
|
||||
|
||||
j = 1
|
||||
|
@ -677,11 +677,11 @@ function tNode_get_byKey(self,k,defaultVal) result(node)
|
|||
item => item%next
|
||||
j = j + 1
|
||||
enddo
|
||||
|
||||
|
||||
if (.not. found) then
|
||||
call IO_error(143,ext_msg=k)
|
||||
else
|
||||
if(associated(item)) node => item%node
|
||||
if (associated(item)) node => item%node
|
||||
endif
|
||||
|
||||
end function tNode_get_byKey
|
||||
|
@ -700,11 +700,11 @@ function tNode_get_byKey_asFloat(self,k,defaultVal) result(nodeAsFloat)
|
|||
class(tNode), pointer :: node
|
||||
type(tScalar), pointer :: scalar
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
scalar => node%asScalar()
|
||||
nodeAsFloat = scalar%asFloat()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsFloat = defaultVal
|
||||
else
|
||||
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
|
||||
type(tScalar), pointer :: scalar
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
scalar => node%asScalar()
|
||||
nodeAsInt = scalar%asInt()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsInt = defaultVal
|
||||
else
|
||||
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
|
||||
type(tScalar), pointer :: scalar
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
scalar => node%asScalar()
|
||||
nodeAsBool = scalar%asBool()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsBool = defaultVal
|
||||
else
|
||||
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
|
||||
type(tScalar), pointer :: scalar
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
scalar => node%asScalar()
|
||||
nodeAsString = scalar%asString()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsString = defaultVal
|
||||
else
|
||||
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
|
||||
type(tList), pointer :: list
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
list => node%asList()
|
||||
nodeAsFloats = list%asFloats()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsFloats = defaultVal
|
||||
else
|
||||
call IO_error(143,ext_msg=k)
|
||||
endif
|
||||
|
||||
if(present(requiredSize)) then
|
||||
if(requiredSize /= size(nodeAsFloats)) call IO_error(146,ext_msg=k)
|
||||
if (present(requiredSize)) then
|
||||
if (requiredSize /= size(nodeAsFloats)) call IO_error(146,ext_msg=k)
|
||||
endif
|
||||
|
||||
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
|
||||
type(tList), pointer :: list
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
list => node%asList()
|
||||
nodeAsInts = list%asInts()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsInts = defaultVal
|
||||
else
|
||||
call IO_error(143,ext_msg=k)
|
||||
endif
|
||||
|
||||
if(present(requiredSize)) then
|
||||
if(requiredSize /= size(nodeAsInts)) call IO_error(146,ext_msg=k)
|
||||
if (present(requiredSize)) then
|
||||
if (requiredSize /= size(nodeAsInts)) call IO_error(146,ext_msg=k)
|
||||
endif
|
||||
|
||||
end function tNode_get_byKey_asInts
|
||||
|
@ -867,11 +867,11 @@ function tNode_get_byKey_asBools(self,k,defaultVal) result(nodeAsBools)
|
|||
class(tNode), pointer :: node
|
||||
type(tList), pointer :: list
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
list => node%asList()
|
||||
nodeAsBools = list%asBools()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsBools = defaultVal
|
||||
else
|
||||
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
|
||||
type(tList), pointer :: list
|
||||
|
||||
if(self%contains(k)) then
|
||||
if (self%contains(k)) then
|
||||
node => self%get(k)
|
||||
list => node%asList()
|
||||
nodeAsStrings = list%asStrings()
|
||||
elseif(present(defaultVal)) then
|
||||
elseif (present(defaultVal)) then
|
||||
nodeAsStrings = defaultVal
|
||||
else
|
||||
call IO_error(143,ext_msg=k)
|
||||
|
@ -925,7 +925,7 @@ function output_asStrings(self) result(output) !ToDo: SR: Rem
|
|||
|
||||
|
||||
end function output_asStrings
|
||||
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
keyIndex = -1
|
||||
do i = 1, dict%length
|
||||
if(key == item%key) then
|
||||
if (key == item%key) then
|
||||
keyIndex = i
|
||||
exit
|
||||
else
|
||||
|
@ -952,9 +952,9 @@ function tNode_get_byKey_asIndex(self,key) result(keyIndex)
|
|||
endif
|
||||
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
|
||||
|
||||
|
||||
|
@ -985,7 +985,7 @@ recursive function tList_asFormattedString(self,indent) result(str)
|
|||
integer :: i, indent_
|
||||
|
||||
str = ''
|
||||
if(present(indent)) then
|
||||
if (present(indent)) then
|
||||
indent_ = indent
|
||||
else
|
||||
indent_ = 0
|
||||
|
@ -993,7 +993,7 @@ recursive function tList_asFormattedString(self,indent) result(str)
|
|||
|
||||
item => self%first
|
||||
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)
|
||||
item => item%next
|
||||
end do
|
||||
|
@ -1014,7 +1014,7 @@ recursive function tDict_asFormattedString(self,indent) result(str)
|
|||
integer :: i, indent_
|
||||
|
||||
str = ''
|
||||
if(present(indent)) then
|
||||
if (present(indent)) then
|
||||
indent_ = indent
|
||||
else
|
||||
indent_ = 0
|
||||
|
@ -1022,7 +1022,7 @@ recursive function tDict_asFormattedString(self,indent) result(str)
|
|||
|
||||
item => self%first
|
||||
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)
|
||||
class is(tScalar)
|
||||
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
|
||||
|
||||
deallocate(self%node)
|
||||
if(associated(self%next)) deallocate(self%next)
|
||||
if (associated(self%next)) deallocate(self%next)
|
||||
|
||||
end subroutine tItem_finalize
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "IO.f90"
|
||||
#include "YAML_types.f90"
|
||||
#include "YAML_parse.f90"
|
||||
#include "future.f90"
|
||||
#include "config.f90"
|
||||
#include "LAPACK_interface.f90"
|
||||
#include "math.f90"
|
||||
|
@ -17,38 +16,36 @@
|
|||
#include "results.f90"
|
||||
#include "geometry_plastic_nonlocal.f90"
|
||||
#include "discretization.f90"
|
||||
#ifdef Marc4DAMASK
|
||||
#include "marc/discretization_marc.f90"
|
||||
#endif
|
||||
#include "material.f90"
|
||||
#include "lattice.f90"
|
||||
#include "constitutive.f90"
|
||||
#include "constitutive_mech.f90"
|
||||
#include "constitutive_plastic_none.f90"
|
||||
#include "constitutive_plastic_isotropic.f90"
|
||||
#include "constitutive_plastic_phenopowerlaw.f90"
|
||||
#include "constitutive_plastic_kinehardening.f90"
|
||||
#include "constitutive_plastic_dislotwin.f90"
|
||||
#include "constitutive_plastic_disloTungsten.f90"
|
||||
#include "constitutive_plastic_nonlocal.f90"
|
||||
#include "constitutive_thermal.f90"
|
||||
#include "source_thermal_dissipation.f90"
|
||||
#include "source_thermal_externalheat.f90"
|
||||
#include "kinematics_thermal_expansion.f90"
|
||||
#include "constitutive_damage.f90"
|
||||
#include "source_damage_isoBrittle.f90"
|
||||
#include "source_damage_isoDuctile.f90"
|
||||
#include "source_damage_anisoBrittle.f90"
|
||||
#include "source_damage_anisoDuctile.f90"
|
||||
#include "kinematics_cleavage_opening.f90"
|
||||
#include "kinematics_slipplane_opening.f90"
|
||||
#include "thermal_isothermal.f90"
|
||||
#include "thermal_conduction.f90"
|
||||
#include "damage_none.f90"
|
||||
#include "damage_nonlocal.f90"
|
||||
#include "phase.f90"
|
||||
#include "phase_mechanical.f90"
|
||||
#include "phase_mechanical_plastic.f90"
|
||||
#include "phase_mechanical_plastic_none.f90"
|
||||
#include "phase_mechanical_plastic_isotropic.f90"
|
||||
#include "phase_mechanical_plastic_phenopowerlaw.f90"
|
||||
#include "phase_mechanical_plastic_kinehardening.f90"
|
||||
#include "phase_mechanical_plastic_dislotwin.f90"
|
||||
#include "phase_mechanical_plastic_dislotungsten.f90"
|
||||
#include "phase_mechanical_plastic_nonlocal.f90"
|
||||
#include "phase_mechanical_eigen.f90"
|
||||
#include "phase_mechanical_eigen_cleavageopening.f90"
|
||||
#include "phase_mechanical_eigen_slipplaneopening.f90"
|
||||
#include "phase_mechanical_eigen_thermalexpansion.f90"
|
||||
#include "phase_thermal.f90"
|
||||
#include "phase_thermal_dissipation.f90"
|
||||
#include "phase_thermal_externalheat.f90"
|
||||
#include "phase_damage.f90"
|
||||
#include "phase_damage_isobrittle.f90"
|
||||
#include "phase_damage_isoductile.f90"
|
||||
#include "phase_damage_anisobrittle.f90"
|
||||
#include "phase_damage_anisoductile.f90"
|
||||
#include "homogenization.f90"
|
||||
#include "homogenization_mech.f90"
|
||||
#include "homogenization_mech_none.f90"
|
||||
#include "homogenization_mech_isostrain.f90"
|
||||
#include "homogenization_mech_RGC.f90"
|
||||
#include "homogenization_mechanical.f90"
|
||||
#include "homogenization_mechanical_pass.f90"
|
||||
#include "homogenization_mechanical_isostrain.f90"
|
||||
#include "homogenization_mechanical_RGC.f90"
|
||||
#include "homogenization_thermal.f90"
|
||||
#include "homogenization_damage.f90"
|
||||
#include "CPFEM.f90"
|
||||
|
|
|
@ -5,16 +5,10 @@
|
|||
!! precedence over material.yaml.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module config
|
||||
use prec
|
||||
use DAMASK_interface
|
||||
use IO
|
||||
use YAML_parse
|
||||
use YAML_types
|
||||
|
||||
#ifdef PETSc
|
||||
#include <petsc/finclude/petscsys.h>
|
||||
use petscsys
|
||||
#endif
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
@ -50,17 +44,12 @@ end subroutine config_init
|
|||
subroutine parse_material
|
||||
|
||||
logical :: fileExists
|
||||
character(len=:), allocatable :: fname
|
||||
|
||||
fname = getSolverJobName()//'.yaml'
|
||||
inquire(file=fname,exist=fileExists)
|
||||
if(.not. fileExists) then
|
||||
fname = 'material.yaml'
|
||||
inquire(file=fname,exist=fileExists)
|
||||
if(.not. fileExists) call IO_error(100,ext_msg=fname)
|
||||
endif
|
||||
print*, 'reading '//fname; flush(IO_STDOUT)
|
||||
config_material => YAML_parse_file(fname)
|
||||
|
||||
inquire(file='material.yaml',exist=fileExists)
|
||||
if(.not. fileExists) call IO_error(100,ext_msg='material.yaml')
|
||||
print*, 'reading material.yaml'; flush(IO_STDOUT)
|
||||
config_material => YAML_parse_file('material.yaml')
|
||||
|
||||
end subroutine parse_material
|
||||
|
||||
|
@ -72,6 +61,7 @@ subroutine parse_numerics
|
|||
|
||||
logical :: fexist
|
||||
|
||||
|
||||
config_numerics => emptyDict
|
||||
inquire(file='numerics.yaml', exist=fexist)
|
||||
if (fexist) then
|
||||
|
@ -89,6 +79,7 @@ subroutine parse_debug
|
|||
|
||||
logical :: fexist
|
||||
|
||||
|
||||
config_debug => emptyDict
|
||||
inquire(file='debug.yaml', exist=fexist)
|
||||
fileExists: if (fexist) then
|
||||
|
|
1434
src/constitutive.f90
1434
src/constitutive.f90
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -686,7 +686,7 @@ module element
|
|||
1, 5,11, 7, 8,12,15,14, &
|
||||
5, 2, 6,11,12, 9,13,15, &
|
||||
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__)
|
||||
],shape(CELL6))
|
||||
#else
|
||||
|
|
|
@ -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
|
|
@ -18,9 +18,9 @@ program DAMASK_grid
|
|||
use CPFEM2
|
||||
use material
|
||||
use spectral_utilities
|
||||
use grid_mech_spectral_basic
|
||||
use grid_mech_spectral_polarisation
|
||||
use grid_mech_FEM
|
||||
use grid_mechanical_spectral_basic
|
||||
use grid_mechanical_spectral_polarisation
|
||||
use grid_mechanical_FEM
|
||||
use grid_damage_spectral
|
||||
use grid_thermal_spectral
|
||||
use results
|
||||
|
@ -36,10 +36,11 @@ program DAMASK_grid
|
|||
integer :: N, & !< number of increments
|
||||
f_out, & !< frequency of result writes
|
||||
f_restart !< frequency of restart writes
|
||||
logical :: drop_guessing !< do not follow trajectory of former loadcase
|
||||
integer(kind(FIELD_UNDEFINED_ID)), allocatable :: ID(:)
|
||||
logical :: estimate_rate !< follow trajectory of former loadcase
|
||||
end type tLoadCase
|
||||
|
||||
integer(kind(FIELD_UNDEFINED_ID)), allocatable :: ID(:)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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)
|
||||
|
@ -53,6 +54,7 @@ program DAMASK_grid
|
|||
integer, parameter :: &
|
||||
subStepFactor = 2 !< for each substep, divide the last time increment by 2.0
|
||||
real(pReal) :: &
|
||||
T_0 = 300.0_pReal, &
|
||||
time = 0.0_pReal, & !< elapsed time
|
||||
time0 = 0.0_pReal, & !< begin of interval
|
||||
timeinc = 1.0_pReal, & !< current time interval
|
||||
|
@ -61,10 +63,12 @@ program DAMASK_grid
|
|||
logical :: &
|
||||
guess, & !< guess along former trajectory
|
||||
stagIterate, &
|
||||
cutBack = .false.
|
||||
cutBack = .false.,&
|
||||
signal
|
||||
integer :: &
|
||||
i, j, m, field, &
|
||||
errorID = 0, &
|
||||
ierr,&
|
||||
cutBackLevel = 0, & !< cut back level \f$ t = \frac{t_{inc}}{2^l} \f$
|
||||
stepFraction = 0, & !< fraction of current time interval
|
||||
l = 0, & !< current load case
|
||||
|
@ -76,30 +80,33 @@ program DAMASK_grid
|
|||
maxCutBack, & !< max number of cut backs
|
||||
stagItMax !< max number of field level staggered iterations
|
||||
character(len=pStringLen) :: &
|
||||
incInfo, &
|
||||
loadcase_string
|
||||
incInfo
|
||||
|
||||
type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases
|
||||
type(tSolutionState), allocatable, dimension(:) :: solres
|
||||
procedure(grid_mech_spectral_basic_init), pointer :: &
|
||||
mech_init
|
||||
procedure(grid_mech_spectral_basic_forward), pointer :: &
|
||||
mech_forward
|
||||
procedure(grid_mech_spectral_basic_solution), pointer :: &
|
||||
mech_solution
|
||||
procedure(grid_mech_spectral_basic_updateCoords), pointer :: &
|
||||
mech_updateCoords
|
||||
procedure(grid_mech_spectral_basic_restartWrite), pointer :: &
|
||||
mech_restartWrite
|
||||
procedure(grid_mechanical_spectral_basic_init), pointer :: &
|
||||
mechanical_init
|
||||
procedure(grid_mechanical_spectral_basic_forward), pointer :: &
|
||||
mechanical_forward
|
||||
procedure(grid_mechanical_spectral_basic_solution), pointer :: &
|
||||
mechanical_solution
|
||||
procedure(grid_mechanical_spectral_basic_updateCoords), pointer :: &
|
||||
mechanical_updateCoords
|
||||
procedure(grid_mechanical_spectral_basic_restartWrite), pointer :: &
|
||||
mechanical_restartWrite
|
||||
|
||||
external :: &
|
||||
quit
|
||||
class (tNode), pointer :: &
|
||||
num_grid, &
|
||||
debug_grid, & ! pointer to grid debug options
|
||||
config_load, &
|
||||
load_steps, &
|
||||
load_step, &
|
||||
solver, &
|
||||
initial_conditions, &
|
||||
ic_thermal, &
|
||||
thermal, &
|
||||
step_bc, &
|
||||
step_mech, &
|
||||
step_discretization, &
|
||||
step_deformation, &
|
||||
|
@ -109,17 +116,11 @@ program DAMASK_grid
|
|||
! init DAMASK (all modules)
|
||||
|
||||
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*, '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
|
||||
|
@ -130,62 +131,69 @@ program DAMASK_grid
|
|||
if (stagItMax < 0) call IO_error(301,ext_msg='maxStaggeredIter')
|
||||
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
|
||||
|
||||
debug_grid => config_debug%get('grid',defaultVal=emptyList)
|
||||
select case (trim(num_grid%get_asString('solver', defaultVal = 'Basic')))
|
||||
case ('Basic')
|
||||
mech_init => grid_mech_spectral_basic_init
|
||||
mech_forward => grid_mech_spectral_basic_forward
|
||||
mech_solution => grid_mech_spectral_basic_solution
|
||||
mech_updateCoords => grid_mech_spectral_basic_updateCoords
|
||||
mech_restartWrite => grid_mech_spectral_basic_restartWrite
|
||||
nActiveFields = 1
|
||||
select case (solver%get_asString('mechanical'))
|
||||
case ('spectral_basic')
|
||||
mechanical_init => grid_mechanical_spectral_basic_init
|
||||
mechanical_forward => grid_mechanical_spectral_basic_forward
|
||||
mechanical_solution => grid_mechanical_spectral_basic_solution
|
||||
mechanical_updateCoords => grid_mechanical_spectral_basic_updateCoords
|
||||
mechanical_restartWrite => grid_mechanical_spectral_basic_restartWrite
|
||||
|
||||
case ('Polarisation')
|
||||
mech_init => grid_mech_spectral_polarisation_init
|
||||
mech_forward => grid_mech_spectral_polarisation_forward
|
||||
mech_solution => grid_mech_spectral_polarisation_solution
|
||||
mech_updateCoords => grid_mech_spectral_polarisation_updateCoords
|
||||
mech_restartWrite => grid_mech_spectral_polarisation_restartWrite
|
||||
case ('spectral_polarization')
|
||||
mechanical_init => grid_mechanical_spectral_polarisation_init
|
||||
mechanical_forward => grid_mechanical_spectral_polarisation_forward
|
||||
mechanical_solution => grid_mechanical_spectral_polarisation_solution
|
||||
mechanical_updateCoords => grid_mechanical_spectral_polarisation_updateCoords
|
||||
mechanical_restartWrite => grid_mechanical_spectral_polarisation_restartWrite
|
||||
|
||||
case ('FEM')
|
||||
mech_init => grid_mech_FEM_init
|
||||
mech_forward => grid_mech_FEM_forward
|
||||
mech_solution => grid_mech_FEM_solution
|
||||
mech_updateCoords => grid_mech_FEM_updateCoords
|
||||
mech_restartWrite => grid_mech_FEM_restartWrite
|
||||
mechanical_init => grid_mechanical_FEM_init
|
||||
mechanical_forward => grid_mechanical_FEM_forward
|
||||
mechanical_solution => grid_mechanical_FEM_solution
|
||||
mechanical_updateCoords => grid_mechanical_FEM_updateCoords
|
||||
mechanical_restartWrite => grid_mechanical_FEM_restartWrite
|
||||
|
||||
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
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
config_load => YAML_parse_file(trim(interface_loadFile))
|
||||
|
||||
load_steps => config_load%get('step')
|
||||
load_steps => config_load%get('loadstep')
|
||||
allocate(loadCases(load_steps%length)) ! array of load cases
|
||||
|
||||
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)
|
||||
|
||||
step_mech => load_step%get('mechanics')
|
||||
step_bc => load_step%get('boundary_conditions')
|
||||
step_mech => step_bc%get('mechanical')
|
||||
loadCases(l)%stress%myType=''
|
||||
readMech: do m = 1, step_mech%length
|
||||
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')
|
||||
|
||||
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('N')) call IO_error(error_ID=837,ext_msg = 'N 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')
|
||||
loadCases(l)%t = step_discretization%get_asFloat('t')
|
||||
loadCases(l)%N = step_discretization%get_asInt ('N')
|
||||
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. &
|
||||
merge(.false.,.true.,l > 1))
|
||||
loadCases(l)%f_restart = load_step%get_asInt('f_restart', defaultVal=huge(0))
|
||||
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
|
||||
write (loadcase_string, '(i0)' ) 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
|
||||
do j = 1, 3
|
||||
if (any(loadCases(l)%deformation%mask(j,1:3) .eqv. .true.) .and. &
|
||||
|
@ -283,13 +289,13 @@ program DAMASK_grid
|
|||
else
|
||||
print'(a,f0.3)', ' r: ', loadCases(l)%r
|
||||
endif
|
||||
print'(a,f0.3)', ' t: ', loadCases(l)%t
|
||||
print'(a,i0)', ' N: ', loadCases(l)%N
|
||||
print'(a,i0)', ' f_out: ', loadCases(l)%f_out
|
||||
print'(a,f0.3)', ' t: ', loadCases(l)%t
|
||||
print'(a,i0)', ' N: ', loadCases(l)%N
|
||||
print'(a,i0)', ' f_out: ', loadCases(l)%f_out
|
||||
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
|
||||
enddo
|
||||
|
@ -298,12 +304,14 @@ program DAMASK_grid
|
|||
! doing initialization depending on active solvers
|
||||
call spectral_Utilities_init
|
||||
do field = 1, nActiveFields
|
||||
select case (loadCases(1)%ID(field))
|
||||
select case (ID(field))
|
||||
case(FIELD_MECH_ID)
|
||||
call mech_init
|
||||
call mechanical_init
|
||||
|
||||
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)
|
||||
call grid_damage_spectral_init
|
||||
|
@ -331,7 +339,7 @@ program DAMASK_grid
|
|||
|
||||
loadCaseLooping: do l = 1, size(loadCases)
|
||||
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
|
||||
totalIncsCounter = totalIncsCounter + 1
|
||||
|
@ -374,9 +382,9 @@ program DAMASK_grid
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
! forward fields
|
||||
do field = 1, nActiveFields
|
||||
select case(loadCases(l)%ID(field))
|
||||
select case(ID(field))
|
||||
case(FIELD_MECH_ID)
|
||||
call mech_forward (&
|
||||
call mechanical_forward (&
|
||||
cutBack,guess,timeinc,timeIncOld,remainingLoadCaseTime, &
|
||||
deformation_BC = loadCases(l)%deformation, &
|
||||
stress_BC = loadCases(l)%stress, &
|
||||
|
@ -394,9 +402,9 @@ program DAMASK_grid
|
|||
stagIterate = .true.
|
||||
do while (stagIterate)
|
||||
do field = 1, nActiveFields
|
||||
select case(loadCases(l)%ID(field))
|
||||
select case(ID(field))
|
||||
case(FIELD_MECH_ID)
|
||||
solres(field) = mech_solution(incInfo)
|
||||
solres(field) = mechanical_solution(incInfo)
|
||||
case(FIELD_THERMAL_ID)
|
||||
solres(field) = grid_thermal_spectral_solution(timeinc)
|
||||
case(FIELD_DAMAGE_ID)
|
||||
|
@ -417,13 +425,13 @@ program DAMASK_grid
|
|||
|
||||
if ( (all(solres(:)%converged .and. solres(:)%stagConverged)) & ! converged
|
||||
.and. .not. solres(1)%termIll) then ! and acceptable solution found
|
||||
call mech_updateCoords
|
||||
call mechanical_updateCoords
|
||||
timeIncOld = timeinc
|
||||
cutBack = .false.
|
||||
guess = .true. ! start guessing after first converged (sub)inc
|
||||
if (worldrank == 0) then
|
||||
write(statUnit,*) totalIncsCounter, time, cutBackLevel, &
|
||||
solres%converged, solres%iterationsNeeded
|
||||
solres(1)%converged, solres(1)%iterationsNeeded
|
||||
flush(statUnit)
|
||||
endif
|
||||
elseif (cutBackLevel < maxCutBack) then ! further cutbacking tolerated?
|
||||
|
@ -449,18 +457,27 @@ program DAMASK_grid
|
|||
print'(/,a,i0,a)', ' increment ', totalIncsCounter, ' NOT converged'
|
||||
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 ......................................'
|
||||
flush(IO_STDOUT)
|
||||
call CPFEM_results(totalIncsCounter,time)
|
||||
endif
|
||||
if (mod(inc,loadCases(l)%f_restart) == 0) then
|
||||
call mech_restartWrite
|
||||
if(signal) call interface_setSIGUSR1(.false.)
|
||||
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
|
||||
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
|
||||
|
||||
enddo incLooping
|
||||
enddo incLooping
|
||||
|
||||
enddo loadCaseLooping
|
||||
|
||||
|
|
|
@ -68,8 +68,11 @@ subroutine discretization_grid_init(restart)
|
|||
|
||||
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)
|
||||
if (ierr /= 0) error stop 'MPI error'
|
||||
|
|
|
@ -15,10 +15,10 @@ module grid_damage_spectral
|
|||
use IO
|
||||
use spectral_utilities
|
||||
use discretization_grid
|
||||
use damage_nonlocal
|
||||
use YAML_types
|
||||
use homogenization
|
||||
use config
|
||||
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
||||
|
@ -43,13 +43,13 @@ module grid_damage_spectral
|
|||
phi_current, & !< field of current damage
|
||||
phi_lastInc, & !< field of previous 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
|
||||
real(pReal), dimension(3,3) :: K_ref
|
||||
real(pReal) :: mu_ref
|
||||
|
||||
|
||||
public :: &
|
||||
grid_damage_spectral_init, &
|
||||
grid_damage_spectral_solution, &
|
||||
|
@ -62,8 +62,8 @@ contains
|
|||
! ToDo: Restart not implemented
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_damage_spectral_init
|
||||
|
||||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
|
||||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
DM :: damage_grid
|
||||
Vec :: uBound, lBound
|
||||
PetscErrorCode :: ierr
|
||||
|
@ -72,22 +72,22 @@ subroutine grid_damage_spectral_init
|
|||
num_generic
|
||||
character(len=pStringLen) :: &
|
||||
snes_type
|
||||
|
||||
|
||||
print'(/,a)', ' <<<+- grid_spectral_damage init -+>>>'
|
||||
|
||||
print*, 'Shanthraj et al., Handbook of Mechanics of Materials, 2019'
|
||||
print*, 'https://doi.org/10.1007/978-981-10-6855-3_80'
|
||||
|
||||
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
! read numerical parameters and do sanity checks
|
||||
num_grid => config_numerics%get('grid',defaultVal=emptyDict)
|
||||
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_rtol = num_grid%get_asFloat ('eps_damage_rtol',defaultVal=1.0e-6_pReal)
|
||||
|
||||
|
||||
num_generic => config_numerics%get('generic',defaultVal=emptyDict)
|
||||
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%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')
|
||||
|
@ -104,7 +104,7 @@ subroutine grid_damage_spectral_init
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize solver specific parts of PETSc
|
||||
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(worldrank) = grid3
|
||||
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 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
|
||||
CHKERRQ(ierr)
|
||||
CHKERRQ(ierr)
|
||||
call SNESSetFromOptions(damage_snes,ierr); CHKERRQ(ierr) ! pull it all together with additional CLI arguments
|
||||
call SNESGetType(damage_snes,snes_type,ierr); CHKERRQ(ierr)
|
||||
if (trim(snes_type) == 'vinewtonrsls' .or. &
|
||||
|
@ -137,12 +137,12 @@ subroutine grid_damage_spectral_init
|
|||
endif
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! init fields
|
||||
! init fields
|
||||
call DMDAGetCorners(damage_grid,xstart,ystart,zstart,xend,yend,zend,ierr)
|
||||
CHKERRQ(ierr)
|
||||
xend = xstart + xend - 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_lastInc(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
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
function grid_damage_spectral_solution(timeinc) result(solution)
|
||||
|
||||
|
||||
real(pReal), intent(in) :: &
|
||||
timeinc !< increment in time for current solution
|
||||
integer :: i, j, k, cell
|
||||
integer :: i, j, k, ce
|
||||
type(tSolutionState) :: solution
|
||||
PetscInt :: devNull
|
||||
PetscReal :: phi_min, phi_max, stagNorm, solnNorm
|
||||
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
SNESConvergedReason :: reason
|
||||
|
||||
solution%converged =.false.
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! set module wide availabe data
|
||||
! set module wide availabe data
|
||||
params%timeinc = timeinc
|
||||
|
||||
|
||||
call SNESSolve(damage_snes,PETSC_NULL_VEC,solution_vec,ierr); CHKERRQ(ierr)
|
||||
call SNESGetConvergedReason(damage_snes,reason,ierr); CHKERRQ(ierr)
|
||||
|
||||
|
||||
if (reason < 1) then
|
||||
solution%converged = .false.
|
||||
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)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! updating damage state
|
||||
cell = 0
|
||||
! updating damage state
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),1,cell)
|
||||
ce = ce + 1
|
||||
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),ce)
|
||||
enddo; enddo; enddo
|
||||
|
||||
|
||||
call VecMin(solution_vec,devNull,phi_min,ierr); CHKERRQ(ierr)
|
||||
call VecMax(solution_vec,devNull,phi_max,ierr); CHKERRQ(ierr)
|
||||
if (solution%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)', ' ==========================================================================='
|
||||
flush(IO_STDOUT)
|
||||
flush(IO_STDOUT)
|
||||
|
||||
end function grid_damage_spectral_solution
|
||||
|
||||
|
@ -214,31 +214,31 @@ end function grid_damage_spectral_solution
|
|||
!> @brief spectral damage forwarding routine
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_damage_spectral_forward(cutBack)
|
||||
|
||||
|
||||
logical, intent(in) :: cutBack
|
||||
integer :: i, j, k, cell
|
||||
integer :: i, j, k, ce
|
||||
DM :: dm_local
|
||||
PetscScalar, dimension(:,:,:), pointer :: x_scal
|
||||
PetscErrorCode :: ierr
|
||||
|
||||
if (cutBack) then
|
||||
if (cutBack) then
|
||||
phi_current = phi_lastInc
|
||||
phi_stagInc = phi_lastInc
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! reverting damage field state
|
||||
cell = 0
|
||||
! reverting damage field state
|
||||
ce = 0
|
||||
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
|
||||
x_scal(xstart:xend,ystart:yend,zstart:zend) = phi_current
|
||||
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)
|
||||
cell = cell + 1
|
||||
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),1,cell)
|
||||
ce = ce + 1
|
||||
call damage_nonlocal_putNonLocalDamage(phi_current(i,j,k),ce)
|
||||
enddo; enddo; enddo
|
||||
else
|
||||
phi_lastInc = phi_current
|
||||
call updateReference
|
||||
endif
|
||||
endif
|
||||
|
||||
end subroutine grid_damage_spectral_forward
|
||||
|
||||
|
@ -247,7 +247,7 @@ end subroutine grid_damage_spectral_forward
|
|||
!> @brief forms the spectral damage residual vector
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||
|
||||
|
||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
||||
in
|
||||
PetscScalar, dimension( &
|
||||
|
@ -258,31 +258,31 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
f_scal
|
||||
PetscObject :: dummy
|
||||
PetscErrorCode :: ierr
|
||||
integer :: i, j, k, cell
|
||||
integer :: i, j, k, ce
|
||||
real(pReal) :: phiDot, dPhiDot_dPhi, mobility
|
||||
|
||||
phi_current = x_scal
|
||||
phi_current = x_scal
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! evaluate polarization field
|
||||
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_fourierScalarGradient !< calculate gradient of damage field
|
||||
call utilities_FFTvectorBackward
|
||||
cell = 0
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
vectorField_real(1:3,i,j,k) = matmul(damage_nonlocal_getDiffusion(1,cell) - K_ref, &
|
||||
ce = ce + 1
|
||||
vectorField_real(1:3,i,j,k) = matmul(damage_nonlocal_getDiffusion(ce) - K_ref, &
|
||||
vectorField_real(1:3,i,j,k))
|
||||
enddo; enddo; enddo
|
||||
call utilities_FFTvectorForward
|
||||
call utilities_fourierVectorDivergence !< calculate damage divergence in fourier field
|
||||
call utilities_FFTscalarBackward
|
||||
cell = 0
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
call damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi_current(i,j,k), 1, cell)
|
||||
mobility = damage_nonlocal_getMobility(1,cell)
|
||||
ce = ce + 1
|
||||
call damage_nonlocal_getSourceAndItsTangent(phiDot, dPhiDot_dPhi, phi_current(i,j,k),ce)
|
||||
mobility = damage_nonlocal_getMobility(ce)
|
||||
scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + phiDot) &
|
||||
+ mobility*(phi_lastInc(i,j,k) - 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
|
||||
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
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! constructing residual
|
||||
f_scal = scalarField_real(1:grid(1),1:grid(2),1:grid3) - phi_current
|
||||
|
@ -310,15 +310,15 @@ end subroutine formResidual
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine updateReference
|
||||
|
||||
integer :: i,j,k,cell,ierr
|
||||
|
||||
cell = 0
|
||||
integer :: i,j,k,ce,ierr
|
||||
|
||||
ce = 0
|
||||
K_ref = 0.0_pReal
|
||||
mu_ref = 0.0_pReal
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
K_ref = K_ref + damage_nonlocal_getDiffusion(1,cell)
|
||||
mu_ref = mu_ref + damage_nonlocal_getMobility(1,cell)
|
||||
ce = ce + 1
|
||||
K_ref = K_ref + damage_nonlocal_getDiffusion(ce)
|
||||
mu_ref = mu_ref + damage_nonlocal_getMobility(ce)
|
||||
enddo; enddo; enddo
|
||||
K_ref = K_ref*wgt
|
||||
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
!> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH
|
||||
!> @brief Grid solver for mechanics: FEM
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module grid_mech_FEM
|
||||
module grid_mechanical_FEM
|
||||
#include <petsc/finclude/petscsnes.h>
|
||||
#include <petsc/finclude/petscdmda.h>
|
||||
use PETScdmda
|
||||
|
@ -45,8 +45,8 @@ module grid_mech_FEM
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! PETSc data
|
||||
DM :: mech_grid
|
||||
SNES :: mech_snes
|
||||
DM :: mechanical_grid
|
||||
SNES :: mechanical_snes
|
||||
Vec :: solution_current, solution_lastInc, solution_rate
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
|
@ -79,18 +79,18 @@ module grid_mech_FEM
|
|||
totalIter = 0 !< total iteration in current increment
|
||||
|
||||
public :: &
|
||||
grid_mech_FEM_init, &
|
||||
grid_mech_FEM_solution, &
|
||||
grid_mech_FEM_forward, &
|
||||
grid_mech_FEM_updateCoords, &
|
||||
grid_mech_FEM_restartWrite
|
||||
grid_mechanical_FEM_init, &
|
||||
grid_mechanical_FEM_solution, &
|
||||
grid_mechanical_FEM_forward, &
|
||||
grid_mechanical_FEM_updateCoords, &
|
||||
grid_mechanical_FEM_restartWrite
|
||||
|
||||
contains
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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, dimension(4,8) :: &
|
||||
|
@ -108,13 +108,11 @@ subroutine grid_mech_FEM_init
|
|||
u_current,u_lastInc
|
||||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
character(len=pStringLen) :: &
|
||||
fileName
|
||||
class(tNode), pointer :: &
|
||||
num_grid, &
|
||||
debug_grid
|
||||
|
||||
print'(/,a)', ' <<<+- grid_mech_FEM init -+>>>'; flush(IO_STDOUT)
|
||||
print'(/,a)', ' <<<+- grid_mechanical_FEM init -+>>>'; flush(IO_STDOUT)
|
||||
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
! debugging options
|
||||
|
@ -141,8 +139,11 @@ subroutine grid_mech_FEM_init
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! set default and user defined options for PETSc
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type newtonls -mech_ksp_type fgmres &
|
||||
&-mech_ksp_max_it 25 -mech_pc_type ml -mech_mg_levels_ksp_type chebyshev',ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS, &
|
||||
'-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)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
@ -155,8 +156,10 @@ subroutine grid_mech_FEM_init
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize solver specific parts of PETSc
|
||||
call SNESCreate(PETSC_COMM_WORLD,mech_snes,ierr); CHKERRQ(ierr)
|
||||
call SNESSetOptionsPrefix(mech_snes,'mech_',ierr);CHKERRQ(ierr)
|
||||
call SNESCreate(PETSC_COMM_WORLD,mechanical_snes,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call SNESSetOptionsPrefix(mechanical_snes,'mechanical_',ierr)
|
||||
CHKERRQ(ierr)
|
||||
localK = 0
|
||||
localK(worldrank) = grid3
|
||||
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, &
|
||||
3, 1, &
|
||||
[grid(1)],[grid(2)],localK, &
|
||||
mech_grid,ierr)
|
||||
mechanical_grid,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call SNESSetDM(mech_snes,mech_grid,ierr); CHKERRQ(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)
|
||||
call SNESSetDM(mechanical_snes,mechanical_grid,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call DMCreateGlobalVector(mech_grid,solution_current,ierr); CHKERRQ(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)
|
||||
call DMsetFromOptions(mechanical_grid,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call DMSNESSetJacobianLocal(mech_grid,formJacobian,PETSC_NULL_SNES,ierr)
|
||||
call DMsetUp(mechanical_grid,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)
|
||||
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
|
||||
call VecSet(solution_current,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 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)
|
||||
|
||||
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)
|
||||
xend = xstart+xend-1
|
||||
yend = ystart+yend-1
|
||||
|
@ -219,8 +232,7 @@ subroutine grid_mech_FEM_init
|
|||
restartRead: if (interface_restartInc > 0) then
|
||||
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(fileName)
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
|
||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||
|
||||
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
|
||||
F, & ! target F
|
||||
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)
|
||||
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr)
|
||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
restartRead2: if (interface_restartInc > 0) then
|
||||
|
@ -257,13 +269,13 @@ subroutine grid_mech_FEM_init
|
|||
|
||||
endif restartRead2
|
||||
|
||||
end subroutine grid_mech_FEM_init
|
||||
end subroutine grid_mechanical_FEM_init
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
|
@ -284,11 +296,13 @@ function grid_mech_FEM_solution(incInfoIn) result(solution)
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
call SNESGetConvergedReason(mech_snes,reason,ierr); CHKERRQ(ierr)
|
||||
call SNESGetConvergedReason(mechanical_snes,reason,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
solution%converged = reason > 0
|
||||
solution%iterationsNeeded = totalIter
|
||||
|
@ -296,14 +310,14 @@ function grid_mech_FEM_solution(incInfoIn) result(solution)
|
|||
terminallyIll = .false.
|
||||
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
|
||||
!> @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)
|
||||
|
||||
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
|
||||
|
||||
|
||||
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)
|
||||
|
||||
if (cutBack) then
|
||||
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 DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr)
|
||||
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr)
|
||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_lastInc,u_lastInc,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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%timeinc = Delta_t
|
||||
|
||||
end subroutine grid_mech_FEM_forward
|
||||
end subroutine grid_mechanical_FEM_forward
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief Update coordinates
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_FEM_updateCoords
|
||||
subroutine grid_mechanical_FEM_updateCoords
|
||||
|
||||
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
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_FEM_restartWrite
|
||||
subroutine grid_mechanical_FEM_restartWrite
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
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)
|
||||
|
||||
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5'
|
||||
fileHandle = HDF5_openFile(fileName,'w')
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
|
||||
groupHandle = HDF5_addGroup(fileHandle,'solver')
|
||||
|
||||
call HDF5_write(groupHandle,P_aim, 'P_aim')
|
||||
|
@ -427,10 +446,12 @@ subroutine grid_mech_FEM_restartWrite
|
|||
call HDF5_closeGroup(groupHandle)
|
||||
call HDF5_closeFile(fileHandle)
|
||||
|
||||
call DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr);CHKERRQ(ierr)
|
||||
call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr);CHKERRQ(ierr)
|
||||
call DMDAVecRestoreArrayF90(mechanical_grid,solution_current,u_current,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
|
||||
real(pReal), dimension(3,3,3,3) :: devNull
|
||||
|
||||
call SNESGetNumberFunctionEvals(mech_snes,nfuncs,ierr); CHKERRQ(ierr)
|
||||
call SNESGetIterationNumber(mech_snes,PETScIter,ierr); CHKERRQ(ierr)
|
||||
call SNESGetNumberFunctionEvals(mechanical_snes,nfuncs,ierr)
|
||||
CHKERRQ(ierr)
|
||||
call SNESGetIterationNumber(mechanical_snes,PETScIter,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
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 module grid_mech_FEM
|
||||
end module grid_mechanical_FEM
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
|
||||
!> @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/petscdmda.h>
|
||||
use PETScdmda
|
||||
|
@ -79,18 +79,18 @@ module grid_mech_spectral_basic
|
|||
totalIter = 0 !< total iteration in current increment
|
||||
|
||||
public :: &
|
||||
grid_mech_spectral_basic_init, &
|
||||
grid_mech_spectral_basic_solution, &
|
||||
grid_mech_spectral_basic_forward, &
|
||||
grid_mech_spectral_basic_updateCoords, &
|
||||
grid_mech_spectral_basic_restartWrite
|
||||
grid_mechanical_spectral_basic_init, &
|
||||
grid_mechanical_spectral_basic_solution, &
|
||||
grid_mechanical_spectral_basic_forward, &
|
||||
grid_mechanical_spectral_basic_updateCoords, &
|
||||
grid_mechanical_spectral_basic_restartWrite
|
||||
|
||||
contains
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
PetscErrorCode :: ierr
|
||||
|
@ -99,13 +99,11 @@ subroutine grid_mech_spectral_basic_init
|
|||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
integer :: fileUnit
|
||||
character(len=pStringLen) :: &
|
||||
fileName
|
||||
class (tNode), pointer :: &
|
||||
num_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:37–53, 2013'
|
||||
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
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type ngmres',ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
|
||||
CHKERRQ(ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
@ -152,7 +150,7 @@ subroutine grid_mech_spectral_basic_init
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize solver specific parts of PETSc
|
||||
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(worldrank) = grid3
|
||||
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
|
||||
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(fileName)
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
|
||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||
|
||||
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_saveReferenceStiffness
|
||||
|
||||
end subroutine grid_mech_spectral_basic_init
|
||||
end subroutine grid_mechanical_spectral_basic_init
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
|
@ -262,14 +259,14 @@ function grid_mech_spectral_basic_solution(incInfoIn) result(solution)
|
|||
terminallyIll = .false.
|
||||
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
|
||||
!> @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)
|
||||
|
||||
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%timeinc = Delta_t
|
||||
|
||||
end subroutine grid_mech_spectral_basic_forward
|
||||
end subroutine grid_mechanical_spectral_basic_forward
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief Update coordinates
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_spectral_basic_updateCoords
|
||||
subroutine grid_mechanical_spectral_basic_updateCoords
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
PetscScalar, dimension(:,:,:,:), pointer :: F
|
||||
|
@ -354,25 +351,23 @@ subroutine grid_mech_spectral_basic_updateCoords
|
|||
call utilities_updateCoords(F)
|
||||
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
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_spectral_basic_restartWrite
|
||||
subroutine grid_mechanical_spectral_basic_restartWrite
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
PetscScalar, dimension(:,:,:,:), pointer :: F
|
||||
character(len=pStringLen) :: fileName
|
||||
|
||||
call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr)
|
||||
|
||||
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(fileName,'w')
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
|
||||
groupHandle = HDF5_addGroup(fileHandle,'solver')
|
||||
|
||||
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)
|
||||
|
||||
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 module grid_mech_spectral_basic
|
||||
end module grid_mechanical_spectral_basic
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
!> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH
|
||||
!> @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/petscdmda.h>
|
||||
use PETScdmda
|
||||
|
@ -90,18 +90,18 @@ module grid_mech_spectral_polarisation
|
|||
totalIter = 0 !< total iteration in current increment
|
||||
|
||||
public :: &
|
||||
grid_mech_spectral_polarisation_init, &
|
||||
grid_mech_spectral_polarisation_solution, &
|
||||
grid_mech_spectral_polarisation_forward, &
|
||||
grid_mech_spectral_polarisation_updateCoords, &
|
||||
grid_mech_spectral_polarisation_restartWrite
|
||||
grid_mechanical_spectral_polarisation_init, &
|
||||
grid_mechanical_spectral_polarisation_solution, &
|
||||
grid_mechanical_spectral_polarisation_forward, &
|
||||
grid_mechanical_spectral_polarisation_updateCoords, &
|
||||
grid_mechanical_spectral_polarisation_restartWrite
|
||||
|
||||
contains
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
PetscErrorCode :: ierr
|
||||
|
@ -112,13 +112,11 @@ subroutine grid_mech_spectral_polarisation_init
|
|||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
integer :: fileUnit
|
||||
character(len=pStringLen) :: &
|
||||
fileName
|
||||
class (tNode), pointer :: &
|
||||
num_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:31–45, 2015'
|
||||
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
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type ngmres',ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type ngmres',ierr)
|
||||
CHKERRQ(ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
@ -172,7 +170,7 @@ subroutine grid_mech_spectral_polarisation_init
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize solver specific parts of PETSc
|
||||
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(worldrank) = grid3
|
||||
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
|
||||
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(fileName)
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','r')
|
||||
groupHandle = HDF5_openGroup(fileHandle,'solver')
|
||||
|
||||
call HDF5_read(groupHandle,P_aim, 'P_aim')
|
||||
|
@ -250,13 +247,13 @@ subroutine grid_mech_spectral_polarisation_init
|
|||
C_scale = 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
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
function grid_mech_spectral_polarisation_solution(incInfoIn) result(solution)
|
||||
function grid_mechanical_spectral_polarisation_solution(incInfoIn) result(solution)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! input data for solution
|
||||
|
@ -294,14 +291,14 @@ function grid_mech_spectral_polarisation_solution(incInfoIn) result(solution)
|
|||
terminallyIll = .false.
|
||||
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
|
||||
!> @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)
|
||||
|
||||
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%timeinc = Delta_t
|
||||
|
||||
end subroutine grid_mech_spectral_polarisation_forward
|
||||
end subroutine grid_mechanical_spectral_polarisation_forward
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief Update coordinates
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_spectral_polarisation_updateCoords
|
||||
subroutine grid_mechanical_spectral_polarisation_updateCoords
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau
|
||||
|
@ -408,18 +405,17 @@ subroutine grid_mech_spectral_polarisation_updateCoords
|
|||
call utilities_updateCoords(FandF_tau(0:8,:,:,:))
|
||||
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
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_mech_spectral_polarisation_restartWrite
|
||||
subroutine grid_mechanical_spectral_polarisation_restartWrite
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
integer(HID_T) :: fileHandle, groupHandle
|
||||
PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau
|
||||
character(len=pStringLen) :: fileName
|
||||
|
||||
call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr)
|
||||
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)
|
||||
|
||||
write(fileName,'(a,a,i0,a)') trim(getSolverJobName()),'_',worldrank,'.hdf5'
|
||||
fileHandle = HDF5_openFile(fileName,'w')
|
||||
fileHandle = HDF5_openFile(getSolverJobName()//'_restart.hdf5','w')
|
||||
groupHandle = HDF5_addGroup(fileHandle,'solver')
|
||||
|
||||
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)
|
||||
|
||||
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 module grid_mech_spectral_polarisation
|
||||
end module grid_mechanical_spectral_polarisation
|
||||
|
|
|
@ -15,11 +15,11 @@ module grid_thermal_spectral
|
|||
use IO
|
||||
use spectral_utilities
|
||||
use discretization_grid
|
||||
use thermal_conduction
|
||||
use homogenization
|
||||
use YAML_types
|
||||
use config
|
||||
use material
|
||||
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
||||
|
@ -45,11 +45,11 @@ module grid_thermal_spectral
|
|||
T_stagInc !< field of staggered temperature
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! reference diffusion tensor, mobility etc.
|
||||
! reference diffusion tensor, mobility etc.
|
||||
integer :: totalIter = 0 !< total iteration in current increment
|
||||
real(pReal), dimension(3,3) :: K_ref
|
||||
real(pReal) :: mu_ref
|
||||
|
||||
|
||||
public :: &
|
||||
grid_thermal_spectral_init, &
|
||||
grid_thermal_spectral_solution, &
|
||||
|
@ -61,10 +61,12 @@ contains
|
|||
!> @brief allocates all neccessary fields and fills them with data
|
||||
! ToDo: Restart not implemented
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_thermal_spectral_init
|
||||
subroutine grid_thermal_spectral_init(T_0)
|
||||
|
||||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
integer :: i, j, k, cell
|
||||
real(pReal), intent(in) :: T_0
|
||||
|
||||
PetscInt, dimension(0:worldsize-1) :: localK
|
||||
integer :: i, j, k, ce
|
||||
DM :: thermal_grid
|
||||
PetscScalar, dimension(:,:,:), pointer :: x_scal
|
||||
PetscErrorCode :: ierr
|
||||
|
@ -93,11 +95,11 @@ subroutine grid_thermal_spectral_init
|
|||
CHKERRQ(ierr)
|
||||
call PetscOptionsInsertString(PETSC_NULL_OPTIONS,num_grid%get_asString('petsc_options',defaultVal=''),ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize solver specific parts of PETSc
|
||||
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(worldrank) = grid3
|
||||
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 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
|
||||
CHKERRQ(ierr)
|
||||
CHKERRQ(ierr)
|
||||
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)
|
||||
CHKERRQ(ierr)
|
||||
xend = xstart + xend - 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_lastInc(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)
|
||||
cell = cell + 1
|
||||
T_current(i,j,k) = temperature(material_homogenizationAt(cell))%p(material_homogenizationMemberAt(1,cell))
|
||||
ce = ce + 1
|
||||
T_current(i,j,k) = T_0
|
||||
T_lastInc(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
|
||||
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
|
||||
|
@ -143,26 +146,26 @@ subroutine grid_thermal_spectral_init
|
|||
|
||||
end subroutine grid_thermal_spectral_init
|
||||
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief solution for the spectral thermal scheme with internal iterations
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
function grid_thermal_spectral_solution(timeinc) result(solution)
|
||||
|
||||
|
||||
real(pReal), intent(in) :: &
|
||||
timeinc !< increment in time for current solution
|
||||
integer :: i, j, k, cell
|
||||
integer :: i, j, k, ce
|
||||
type(tSolutionState) :: solution
|
||||
PetscInt :: devNull
|
||||
PetscReal :: T_min, T_max, stagNorm, solnNorm
|
||||
|
||||
PetscErrorCode :: ierr
|
||||
PetscErrorCode :: ierr
|
||||
SNESConvergedReason :: reason
|
||||
|
||||
solution%converged =.false.
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! set module wide availabe data
|
||||
! set module wide availabe data
|
||||
params%timeinc = timeinc
|
||||
|
||||
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)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! updating thermal state
|
||||
cell = 0
|
||||
! updating thermal state
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
call thermal_conduction_putTemperatureAndItsRate(T_current(i,j,k), &
|
||||
ce = ce + 1
|
||||
call homogenization_thermal_setField(T_current(i,j,k), &
|
||||
(T_current(i,j,k)-T_lastInc(i,j,k))/params%timeinc, &
|
||||
1,cell)
|
||||
ce)
|
||||
enddo; enddo; enddo
|
||||
|
||||
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,f8.4,2x,f8.4,2x,f8.4)', ' Minimum|Maximum|Delta Temperature / K = ', T_min, T_max, stagNorm
|
||||
print'(/,a)', ' ==========================================================================='
|
||||
flush(IO_STDOUT)
|
||||
flush(IO_STDOUT)
|
||||
|
||||
end function grid_thermal_spectral_solution
|
||||
|
||||
|
@ -207,36 +210,35 @@ end function grid_thermal_spectral_solution
|
|||
!> @brief forwarding routine
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine grid_thermal_spectral_forward(cutBack)
|
||||
|
||||
|
||||
logical, intent(in) :: cutBack
|
||||
integer :: i, j, k, cell
|
||||
integer :: i, j, k, ce
|
||||
DM :: dm_local
|
||||
PetscScalar, dimension(:,:,:), pointer :: x_scal
|
||||
PetscErrorCode :: ierr
|
||||
|
||||
if (cutBack) then
|
||||
|
||||
if (cutBack) then
|
||||
T_current = T_lastInc
|
||||
T_stagInc = T_lastInc
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! reverting thermal field state
|
||||
cell = 0
|
||||
! reverting thermal field state
|
||||
ce = 0
|
||||
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
|
||||
x_scal(xstart:xend,ystart:yend,zstart:zend) = T_current
|
||||
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)
|
||||
cell = cell + 1
|
||||
call thermal_conduction_putTemperatureAndItsRate(T_current(i,j,k), &
|
||||
(T_current(i,j,k) - &
|
||||
T_lastInc(i,j,k))/params%timeinc, &
|
||||
1,cell)
|
||||
ce = ce + 1
|
||||
call homogenization_thermal_setField(T_current(i,j,k), &
|
||||
(T_current(i,j,k)-T_lastInc(i,j,k))/params%timeinc, &
|
||||
ce)
|
||||
enddo; enddo; enddo
|
||||
else
|
||||
T_lastInc = T_current
|
||||
call updateReference
|
||||
endif
|
||||
|
||||
|
||||
end subroutine grid_thermal_spectral_forward
|
||||
|
||||
|
||||
|
@ -244,7 +246,7 @@ end subroutine grid_thermal_spectral_forward
|
|||
!> @brief forms the spectral thermal residual vector
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
||||
|
||||
|
||||
DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: &
|
||||
in
|
||||
PetscScalar, dimension( &
|
||||
|
@ -255,33 +257,33 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
f_scal
|
||||
PetscObject :: dummy
|
||||
PetscErrorCode :: ierr
|
||||
integer :: i, j, k, cell
|
||||
real(pReal) :: Tdot, dTdot_dT
|
||||
integer :: i, j, k, ce
|
||||
real(pReal) :: Tdot
|
||||
|
||||
T_current = x_scal
|
||||
T_current = x_scal
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! evaluate polarization field
|
||||
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_fourierScalarGradient !< calculate gradient of temperature field
|
||||
call utilities_FFTvectorBackward
|
||||
cell = 0
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
vectorField_real(1:3,i,j,k) = matmul(thermal_conduction_getConductivity(1,cell) - K_ref, &
|
||||
ce = ce + 1
|
||||
vectorField_real(1:3,i,j,k) = matmul(thermal_conduction_getConductivity(ce) - K_ref, &
|
||||
vectorField_real(1:3,i,j,k))
|
||||
enddo; enddo; enddo
|
||||
call utilities_FFTvectorForward
|
||||
call utilities_fourierVectorDivergence !< calculate temperature divergence in fourier field
|
||||
call utilities_FFTscalarBackward
|
||||
cell = 0
|
||||
ce = 0
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
call thermal_conduction_getSourceAndItsTangent(Tdot, dTdot_dT, T_current(i,j,k), 1, cell)
|
||||
ce = ce + 1
|
||||
call thermal_conduction_getSource(Tdot,1,ce)
|
||||
scalarField_real(i,j,k) = params%timeinc*(scalarField_real(i,j,k) + Tdot) &
|
||||
+ thermal_conduction_getMassDensity (1,cell)* &
|
||||
thermal_conduction_getSpecificHeat(1,cell)*(T_lastInc(i,j,k) - &
|
||||
+ thermal_conduction_getMassDensity (ce)* &
|
||||
thermal_conduction_getSpecificHeat(ce)*(T_lastInc(i,j,k) - &
|
||||
T_current(i,j,k))&
|
||||
+ mu_ref*T_current(i,j,k)
|
||||
enddo; enddo; enddo
|
||||
|
@ -291,7 +293,7 @@ subroutine formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
call utilities_FFTscalarForward
|
||||
call utilities_fourierGreenConvolution(K_ref, mu_ref, params%timeinc)
|
||||
call utilities_FFTscalarBackward
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! constructing residual
|
||||
f_scal = T_current - scalarField_real(1:grid(1),1:grid(2),1:grid3)
|
||||
|
@ -304,15 +306,15 @@ end subroutine formResidual
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine updateReference
|
||||
|
||||
integer :: i,j,k,cell,ierr
|
||||
|
||||
cell = 0
|
||||
integer :: i,j,k,ce,ierr
|
||||
|
||||
ce = 0
|
||||
K_ref = 0.0_pReal
|
||||
mu_ref = 0.0_pReal
|
||||
do k = 1, grid3; do j = 1, grid(2); do i = 1,grid(1)
|
||||
cell = cell + 1
|
||||
K_ref = K_ref + thermal_conduction_getConductivity(1,cell)
|
||||
mu_ref = mu_ref + thermal_conduction_getMassDensity(1,cell)* thermal_conduction_getSpecificHeat(1,cell)
|
||||
ce = ce + 1
|
||||
K_ref = K_ref + thermal_conduction_getConductivity(ce)
|
||||
mu_ref = mu_ref + thermal_conduction_getMassDensity(ce)* thermal_conduction_getSpecificHeat(ce)
|
||||
enddo; enddo; enddo
|
||||
K_ref = K_ref*wgt
|
||||
call MPI_Allreduce(MPI_IN_PLACE,K_ref,9,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD,ierr)
|
||||
|
|
|
@ -10,17 +10,47 @@ module homogenization
|
|||
use config
|
||||
use math
|
||||
use material
|
||||
use constitutive
|
||||
use phase
|
||||
use discretization
|
||||
use thermal_isothermal
|
||||
use thermal_conduction
|
||||
use damage_none
|
||||
use damage_nonlocal
|
||||
use HDF5_utilities
|
||||
use results
|
||||
use lattice
|
||||
|
||||
implicit none
|
||||
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 :: &
|
||||
terminallyIll = .false. !< at least one material point is terminally ill
|
||||
|
||||
|
@ -39,10 +69,6 @@ module homogenization
|
|||
type :: tNumerics
|
||||
integer :: &
|
||||
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
|
||||
|
||||
type(tNumerics) :: num
|
||||
|
@ -50,48 +76,143 @@ module homogenization
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
interface
|
||||
|
||||
module subroutine mech_init(num_homog)
|
||||
module subroutine mechanical_init(num_homog)
|
||||
class(tNode), pointer, intent(in) :: &
|
||||
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) :: &
|
||||
subF
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
end subroutine mech_partition
|
||||
ce
|
||||
end subroutine mechanical_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) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
end subroutine mech_homogenize
|
||||
ce !< cell
|
||||
end subroutine mechanical_homogenize
|
||||
|
||||
module subroutine mech_results(group_base,h)
|
||||
module subroutine mechanical_results(group_base,ho)
|
||||
character(len=*), intent(in) :: group_base
|
||||
integer, intent(in) :: h
|
||||
end subroutine mech_results
|
||||
integer, intent(in) :: ho
|
||||
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) :: &
|
||||
subdt !< current time step
|
||||
subdt !< current time step
|
||||
real(pReal), intent(in), dimension(3,3) :: &
|
||||
subF
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
ce !< cell
|
||||
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
|
||||
|
||||
public :: &
|
||||
homogenization_init, &
|
||||
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_results
|
||||
homogenization_results, &
|
||||
homogenization_restartRead, &
|
||||
homogenization_restartWrite, &
|
||||
THERMAL_CONDUCTION_ID, &
|
||||
DAMAGE_NONLOCAL_ID
|
||||
|
||||
public :: &
|
||||
damage_nonlocal_init, &
|
||||
damage_nonlocal_getDiffusion
|
||||
|
||||
contains
|
||||
|
||||
|
@ -99,7 +220,7 @@ contains
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief module initialization
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine homogenization_init
|
||||
subroutine homogenization_init()
|
||||
|
||||
class (tNode) , pointer :: &
|
||||
num_homog, &
|
||||
|
@ -107,27 +228,21 @@ subroutine homogenization_init
|
|||
|
||||
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_homogGeneric => num_homog%get('generic',defaultVal=emptyDict)
|
||||
|
||||
num%nMPstate = num_homogGeneric%get_asInt ('nMPstate', defaultVal=10)
|
||||
num%subStepMinHomog = num_homogGeneric%get_asFloat('subStepMin', defaultVal=1.0e-3_pReal)
|
||||
num%subStepSizeHomog = num_homogGeneric%get_asFloat('subStepSize', defaultVal=0.25_pReal)
|
||||
num%stepIncreaseHomog = num_homogGeneric%get_asFloat('stepIncrease', defaultVal=1.5_pReal)
|
||||
num%nMPstate = num_homogGeneric%get_asInt('nMPstate',defaultVal=10)
|
||||
if (num%nMPstate < 1) call IO_error(301,ext_msg='nMPstate')
|
||||
|
||||
if (num%nMPstate < 1) call IO_error(301,ext_msg='nMPstate')
|
||||
if (num%subStepMinHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepMinHomog')
|
||||
if (num%subStepSizeHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeHomog')
|
||||
if (num%stepIncreaseHomog <= 0.0_pReal) call IO_error(301,ext_msg='stepIncreaseHomog')
|
||||
|
||||
|
||||
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
|
||||
call mechanical_init(num_homog)
|
||||
call thermal_init()
|
||||
call damage_init()
|
||||
call damage_nonlocal_init()
|
||||
|
||||
|
||||
end subroutine homogenization_init
|
||||
|
@ -144,126 +259,96 @@ subroutine materialpoint_stressAndItsTangent(dt,FEsolving_execIP,FEsolving_execE
|
|||
NiterationMPstate, &
|
||||
ip, & !< integration point number
|
||||
el, & !< element number
|
||||
myNgrains, co, ce, ho, me
|
||||
real(pReal) :: &
|
||||
subFrac, &
|
||||
subStep
|
||||
myNgrains, co, ce, ho, me, ph
|
||||
logical :: &
|
||||
converged
|
||||
logical, dimension(2) :: &
|
||||
doneAndHappy
|
||||
|
||||
|
||||
!$OMP PARALLEL DO PRIVATE(ce,me,ho,myNgrains,NiterationMPstate,subFrac,converged,subStep,doneAndHappy)
|
||||
!$OMP PARALLEL
|
||||
!$OMP DO PRIVATE(ce,me,ho,myNgrains,NiterationMPstate,converged,doneAndHappy)
|
||||
do el = FEsolving_execElem(1),FEsolving_execElem(2)
|
||||
ho = material_homogenizationAt(el)
|
||||
myNgrains = homogenization_Nconstituents(ho)
|
||||
do ip = FEsolving_execIP(1),FEsolving_execIP(2)
|
||||
me = material_homogenizationMemberAt(ip,el)
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! initialize restoration points
|
||||
call constitutive_initializeRestorationPoints(ip,el)
|
||||
ce = (el-1)*discretization_nIPs + ip
|
||||
me = material_homogenizationMemberAt2(ce)
|
||||
|
||||
subFrac = 0.0_pReal
|
||||
converged = .false. ! pretend failed step ...
|
||||
subStep = 1.0_pReal/num%subStepSizeHomog ! ... larger then the requested calculation
|
||||
call phase_restore(ce,.false.) ! wrong name (is more a forward function)
|
||||
|
||||
if (homogState(ho)%sizeState > 0) &
|
||||
homogState(ho)%subState0(:,me) = homogState(ho)%State0(:,me)
|
||||
if (damageState(ho)%sizeState > 0) &
|
||||
damageState(ho)%subState0(:,me) = damageState(ho)%State0(:,me)
|
||||
if(homogState(ho)%sizeState > 0) homogState(ho)%State(:,me) = homogState(ho)%State0(:,me)
|
||||
if(damageState_h(ho)%sizeState > 0) damageState_h(ho)%State(:,me) = damageState_h(ho)%State0(:,me)
|
||||
call damage_partition(ce)
|
||||
|
||||
cutBackLooping: do while (.not. terminallyIll .and. subStep > num%subStepMinHomog)
|
||||
doneAndHappy = [.false.,.true.]
|
||||
|
||||
if (converged) then
|
||||
subFrac = subFrac + subStep
|
||||
subStep = min(1.0_pReal-subFrac,num%stepIncreaseHomog*subStep) ! introduce flexibility for step increase/acceleration
|
||||
NiterationMPstate = 0
|
||||
convergenceLooping: do while (.not. (terminallyIll .or. doneAndHappy(1)) &
|
||||
.and. NiterationMPstate < num%nMPstate)
|
||||
NiterationMPstate = NiterationMPstate + 1
|
||||
|
||||
steppingNeeded: if (subStep > num%subStepMinHomog) then
|
||||
|
||||
! wind forward grain starting point
|
||||
call constitutive_windForward(ip,el)
|
||||
if (.not. doneAndHappy(1)) then
|
||||
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) &
|
||||
homogState(ho)%subState0(:,me) = homogState(ho)%State(:,me)
|
||||
if(damageState(ho)%sizeState > 0) &
|
||||
damageState(ho)%subState0(:,me) = damageState(ho)%State(:,me)
|
||||
|
||||
endif steppingNeeded
|
||||
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)
|
||||
if (.not. converged) then
|
||||
doneAndHappy = [.true.,.false.]
|
||||
else
|
||||
doneAndHappy = mechanical_updateState(dt,homogenization_F(1:3,1:3,ce),ce)
|
||||
converged = all(doneAndHappy)
|
||||
endif
|
||||
endif
|
||||
|
||||
if (subStep > num%subStepMinHomog) doneAndHappy = [.false.,.true.]
|
||||
|
||||
NiterationMPstate = 0
|
||||
convergenceLooping: do while (.not. terminallyIll &
|
||||
.and. .not. doneAndHappy(1) &
|
||||
.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 convergenceLooping
|
||||
if (.not. converged) then
|
||||
if (.not. terminallyIll) print*, ' Integration point ', ip,' at element ', el, ' terminally ill'
|
||||
terminallyIll = .true.
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
!$OMP END PARALLEL DO
|
||||
!$OMP END DO
|
||||
|
||||
if (.not. terminallyIll ) then
|
||||
!$OMP PARALLEL DO PRIVATE(ho,myNgrains)
|
||||
if (.not. terminallyIll) then
|
||||
!$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)
|
||||
ho = material_homogenizationAt(el)
|
||||
myNgrains = homogenization_Nconstituents(ho)
|
||||
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)
|
||||
enddo
|
||||
call mech_homogenize(ip,el)
|
||||
call mechanical_homogenize(dt,ce)
|
||||
enddo IpLooping3
|
||||
enddo elementLooping3
|
||||
!$OMP END PARALLEL DO
|
||||
!$OMP END DO
|
||||
else
|
||||
print'(/,a,/)', ' << HOMOG >> Material Point terminally ill'
|
||||
endif
|
||||
!$OMP END PARALLEL
|
||||
|
||||
end subroutine materialpoint_stressAndItsTangent
|
||||
|
||||
|
@ -283,7 +368,7 @@ subroutine homogenization_results
|
|||
group_base = 'current/homogenization/'//trim(material_name_homogenization(ho))
|
||||
call results_closeGroup(results_addGroup(group_base))
|
||||
|
||||
call mech_results(group_base,ho)
|
||||
call mechanical_results(group_base,ho)
|
||||
|
||||
group = trim(group_base)//'/damage'
|
||||
call results_closeGroup(results_addGroup(group))
|
||||
|
@ -315,9 +400,185 @@ subroutine homogenization_forward
|
|||
|
||||
do ho = 1, size(material_name_homogenization)
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -2,75 +2,72 @@
|
|||
!> @author Martin Diehl, KU Leuven
|
||||
!> @brief Partition F and homogenize P/dPdF
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
submodule(homogenization) homogenization_mech
|
||||
submodule(homogenization) mechanical
|
||||
|
||||
|
||||
interface
|
||||
|
||||
module subroutine mech_none_init
|
||||
end subroutine mech_none_init
|
||||
module subroutine mechanical_pass_init
|
||||
end subroutine mechanical_pass_init
|
||||
|
||||
module subroutine mech_isostrain_init
|
||||
end subroutine mech_isostrain_init
|
||||
module subroutine mechanical_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) :: &
|
||||
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 (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 (3,3), intent(in) :: avgF !< average deformation gradient at material point
|
||||
integer, intent(in) :: &
|
||||
instance, &
|
||||
of
|
||||
end subroutine mech_RGC_partitionDeformation
|
||||
ce
|
||||
end subroutine mechanical_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,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
|
||||
|
||||
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
|
||||
real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
|
||||
integer, intent(in) :: instance
|
||||
end subroutine mech_isostrain_averageStressAndItsTangent
|
||||
integer, intent(in) :: ho
|
||||
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,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
|
||||
|
||||
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
|
||||
real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
|
||||
integer, intent(in) :: instance
|
||||
end subroutine mech_RGC_averageStressAndItsTangent
|
||||
integer, intent(in) :: ho
|
||||
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
|
||||
real(pReal), dimension(:,:,:), intent(in) :: &
|
||||
P,& !< partitioned stresses
|
||||
F,& !< partitioned deformation gradients
|
||||
F0 !< partitioned initial deformation gradients
|
||||
F !< partitioned deformation gradients
|
||||
real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
|
||||
real(pReal), dimension(3,3), intent(in) :: avgF !< average F
|
||||
real(pReal), intent(in) :: dt !< time increment
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point number
|
||||
el !< element number
|
||||
end function mech_RGC_updateState
|
||||
ce !< cell
|
||||
end function mechanical_RGC_updateState
|
||||
|
||||
|
||||
module subroutine mech_RGC_results(instance,group)
|
||||
integer, intent(in) :: instance !< homogenization instance
|
||||
module subroutine mechanical_RGC_results(ho,group)
|
||||
integer, intent(in) :: ho !< homogenization type
|
||||
character(len=*), intent(in) :: group !< group name in HDF5 file
|
||||
end subroutine mech_RGC_results
|
||||
end subroutine mechanical_RGC_results
|
||||
|
||||
end interface
|
||||
|
||||
|
@ -79,7 +76,7 @@ contains
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief Allocate variables and set parameters.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module subroutine mech_init(num_homog)
|
||||
module subroutine mechanical_init(num_homog)
|
||||
|
||||
class(tNode), pointer, intent(in) :: &
|
||||
num_homog
|
||||
|
@ -87,7 +84,7 @@ module subroutine mech_init(num_homog)
|
|||
class(tNode), pointer :: &
|
||||
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)
|
||||
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)
|
||||
|
||||
num_homogMech => num_homog%get('mech',defaultVal=emptyDict)
|
||||
if (any(homogenization_type == HOMOGENIZATION_NONE_ID)) call mech_none_init
|
||||
if (any(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)) call mech_isostrain_init
|
||||
if (any(homogenization_type == HOMOGENIZATION_RGC_ID)) call mech_RGC_init(num_homogMech)
|
||||
if (any(homogenization_type == HOMOGENIZATION_NONE_ID)) call mechanical_pass_init
|
||||
if (any(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)) call mechanical_isostrain_init
|
||||
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.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module subroutine mech_partition(subF,ip,el)
|
||||
module subroutine mechanical_partition(subF,ce)
|
||||
|
||||
real(pReal), intent(in), dimension(3,3) :: &
|
||||
subF
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
ce
|
||||
|
||||
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
|
||||
crystallite_F(1:3,1:3,1,ip,el) = subF
|
||||
Fs(1:3,1:3,1) = subF
|
||||
|
||||
case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization
|
||||
call mech_isostrain_partitionDeformation(&
|
||||
crystallite_F(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
|
||||
subF)
|
||||
call mechanical_isostrain_partitionDeformation(Fs,subF)
|
||||
|
||||
case (HOMOGENIZATION_RGC_ID) chosenHomogenization
|
||||
call mech_RGC_partitionDeformation(&
|
||||
crystallite_F(1:3,1:3,1:homogenization_Nconstituents(material_homogenizationAt(el)),ip,el), &
|
||||
subF,&
|
||||
ip, &
|
||||
el)
|
||||
call mechanical_RGC_partitionDeformation(Fs,subF,ce)
|
||||
|
||||
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.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module subroutine mech_homogenize(ip,el)
|
||||
module subroutine mechanical_homogenize(dt,ce)
|
||||
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
integer :: co,ce
|
||||
real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationAt(el)))
|
||||
real(pReal), intent(in) :: dt
|
||||
integer, intent(in) :: ce
|
||||
|
||||
integer :: co
|
||||
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_homogenizationAt(el)))
|
||||
chosenHomogenization: select case(homogenization_type(material_homogenizationAt2(ce)))
|
||||
|
||||
case (HOMOGENIZATION_NONE_ID) chosenHomogenization
|
||||
homogenization_P(1:3,1:3,ce) = crystallite_P(1:3,1:3,1,ip,el)
|
||||
homogenization_dPdF(1:3,1:3,1:3,1:3,ce) = crystallite_stressTangent(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) = phase_mechanical_dPdF(dt,1,ce)
|
||||
|
||||
case (HOMOGENIZATION_ISOSTRAIN_ID) chosenHomogenization
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el))
|
||||
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el)
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
|
||||
dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(dt,co,ce)
|
||||
Ps(:,:,co) = phase_mechanical_getP(co,ce)
|
||||
enddo
|
||||
call mech_isostrain_averageStressAndItsTangent(&
|
||||
call mechanical_isostrain_averageStressAndItsTangent(&
|
||||
homogenization_P(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), &
|
||||
dPdFs, &
|
||||
homogenization_typeInstance(material_homogenizationAt(el)))
|
||||
Ps,dPdFs, &
|
||||
material_homogenizationAt2(ce))
|
||||
|
||||
case (HOMOGENIZATION_RGC_ID) chosenHomogenization
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el))
|
||||
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el)
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
|
||||
dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(dt,co,ce)
|
||||
Ps(:,:,co) = phase_mechanical_getP(co,ce)
|
||||
enddo
|
||||
call mech_RGC_averageStressAndItsTangent(&
|
||||
call mechanical_RGC_averageStressAndItsTangent(&
|
||||
homogenization_P(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), &
|
||||
dPdFs, &
|
||||
homogenization_typeInstance(material_homogenizationAt(el)))
|
||||
Ps,dPdFs, &
|
||||
material_homogenizationAt2(ce))
|
||||
|
||||
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
|
||||
!> "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) :: &
|
||||
subdt !< current time step
|
||||
real(pReal), intent(in), dimension(3,3) :: &
|
||||
subF
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point
|
||||
el !< element number
|
||||
ce
|
||||
logical, dimension(2) :: doneAndHappy
|
||||
|
||||
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
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt(el))
|
||||
dPdFs(:,:,:,:,co) = crystallite_stressTangent(co,ip,el)
|
||||
if (homogenization_type(material_homogenizationAt2(ce)) == HOMOGENIZATION_RGC_ID) then
|
||||
do co = 1, homogenization_Nconstituents(material_homogenizationAt2(ce))
|
||||
dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(subdt,co,ce)
|
||||
Fs(:,:,co) = phase_mechanical_getF(co,ce)
|
||||
Ps(:,:,co) = phase_mechanical_getP(co,ce)
|
||||
enddo
|
||||
doneAndHappy = &
|
||||
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)
|
||||
doneAndHappy = mechanical_RGC_updateState(Ps,Fs,subF,subdt,dPdFs,ce)
|
||||
else
|
||||
doneAndHappy = .true.
|
||||
endif
|
||||
|
||||
end function mech_updateState
|
||||
end function mechanical_updateState
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief Write results to file.
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
module subroutine mech_results(group_base,h)
|
||||
use material, only: &
|
||||
material_homogenization_type => homogenization_type
|
||||
module subroutine mechanical_results(group_base,ho)
|
||||
|
||||
character(len=*), intent(in) :: group_base
|
||||
integer, intent(in) :: h
|
||||
integer, intent(in) :: ho
|
||||
|
||||
character(len=:), allocatable :: group
|
||||
|
||||
group = trim(group_base)//'/mech'
|
||||
call results_closeGroup(results_addGroup(group))
|
||||
|
||||
select case(material_homogenization_type(h))
|
||||
select case(homogenization_type(ho))
|
||||
|
||||
case(HOMOGENIZATION_rgc_ID)
|
||||
call mech_RGC_results(homogenization_typeInstance(h),group)
|
||||
call mechanical_RGC_results(ho,group)
|
||||
|
||||
end select
|
||||
|
||||
|
@ -249,7 +241,7 @@ module subroutine mech_results(group_base,h)
|
|||
!call results_writeDataset(group,temp,'P',&
|
||||
! '1st Piola-Kirchhoff stress','Pa')
|
||||
|
||||
end subroutine mech_results
|
||||
end subroutine mechanical_results
|
||||
|
||||
|
||||
end submodule homogenization_mech
|
||||
end submodule mechanical
|
|
@ -6,7 +6,7 @@
|
|||
!> @brief Relaxed grain cluster (RGC) homogenization scheme
|
||||
!> 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 lattice
|
||||
|
||||
|
@ -24,9 +24,6 @@ submodule(homogenization:homogenization_mech) homogenization_mech_RGC
|
|||
end type tParameters
|
||||
|
||||
type :: tRGCstate
|
||||
real(pReal), pointer, dimension(:) :: &
|
||||
work, &
|
||||
penaltyEnergy
|
||||
real(pReal), pointer, dimension(:,:) :: &
|
||||
relaxationVector
|
||||
end type tRGCstate
|
||||
|
@ -74,14 +71,13 @@ contains
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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) :: &
|
||||
num_homogMech !< pointer to mechanical homogenization numerics data
|
||||
|
||||
integer :: &
|
||||
Ninstances, &
|
||||
h, &
|
||||
ho, &
|
||||
Nmaterialpoints, &
|
||||
sizeState, nIntFaceTot
|
||||
|
||||
|
@ -91,10 +87,9 @@ module subroutine mech_RGC_init(num_homogMech)
|
|||
homog, &
|
||||
homogMech
|
||||
|
||||
print'(/,a)', ' <<<+- homogenization_mech_rgc init -+>>>'
|
||||
print'(/,a)', ' <<<+- homogenization:mechanical:RGC init -+>>>'
|
||||
|
||||
Ninstances = count(homogenization_type == HOMOGENIZATION_RGC_ID)
|
||||
print'(a,i2)', ' # instances: ',Ninstances; flush(IO_STDOUT)
|
||||
print'(a,i2)', ' # instances: ',count(homogenization_type == HOMOGENIZATION_RGC_ID); flush(IO_STDOUT)
|
||||
|
||||
print*, 'Tjahjanto et al., International Journal of Material Forming 2(1):939–942, 2009'
|
||||
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))
|
||||
allocate(state(Ninstances))
|
||||
allocate(state0(Ninstances))
|
||||
allocate(dependentState(Ninstances))
|
||||
material_homogenization => config_material%get('homogenization')
|
||||
allocate(param(material_homogenization%length))
|
||||
allocate(state(material_homogenization%length))
|
||||
allocate(state0(material_homogenization%length))
|
||||
allocate(dependentState(material_homogenization%length))
|
||||
|
||||
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')
|
||||
|
||||
|
||||
material_homogenization => config_material%get('homogenization')
|
||||
do h = 1, size(homogenization_type)
|
||||
if (homogenization_type(h) /= HOMOGENIZATION_RGC_ID) cycle
|
||||
homog => material_homogenization%get(h)
|
||||
do ho = 1, size(homogenization_type)
|
||||
if (homogenization_type(ho) /= HOMOGENIZATION_RGC_ID) cycle
|
||||
homog => material_homogenization%get(ho)
|
||||
homogMech => homog%get('mechanics')
|
||||
associate(prm => param(homogenization_typeInstance(h)), &
|
||||
stt => state(homogenization_typeInstance(h)), &
|
||||
st0 => state0(homogenization_typeInstance(h)), &
|
||||
dst => dependentState(homogenization_typeInstance(h)))
|
||||
associate(prm => param(ho), &
|
||||
stt => state(ho), &
|
||||
st0 => state0(ho), &
|
||||
dst => dependentState(ho))
|
||||
|
||||
#if defined (__GFORTRAN__)
|
||||
prm%output = output_asStrings(homogMech)
|
||||
|
@ -157,8 +152,8 @@ module subroutine mech_RGC_init(num_homogMech)
|
|||
#endif
|
||||
|
||||
prm%N_constituents = homogMech%get_asInts('cluster_size',requiredSize=3)
|
||||
if (homogenization_Nconstituents(h) /= product(prm%N_constituents)) &
|
||||
call IO_error(211,ext_msg='N_constituents (mech_RGC)')
|
||||
if (homogenization_Nconstituents(ho) /= product(prm%N_constituents)) &
|
||||
call IO_error(211,ext_msg='N_constituents (mechanical_RGC)')
|
||||
|
||||
prm%xi_alpha = homogMech%get_asFloat('xi_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%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) &
|
||||
+ 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))
|
||||
sizeState = nIntFaceTot &
|
||||
+ size(['avg constitutive work ','average penalty energy'])
|
||||
sizeState = nIntFaceTot
|
||||
|
||||
homogState(h)%sizeState = sizeState
|
||||
allocate(homogState(h)%state0 (sizeState,Nmaterialpoints), source=0.0_pReal)
|
||||
allocate(homogState(h)%subState0(sizeState,Nmaterialpoints), source=0.0_pReal)
|
||||
allocate(homogState(h)%state (sizeState,Nmaterialpoints), source=0.0_pReal)
|
||||
homogState(ho)%sizeState = sizeState
|
||||
allocate(homogState(ho)%state0 (sizeState,Nmaterialpoints), source=0.0_pReal)
|
||||
allocate(homogState(ho)%state (sizeState,Nmaterialpoints), source=0.0_pReal)
|
||||
|
||||
stt%relaxationVector => homogState(h)%state(1:nIntFaceTot,:)
|
||||
st0%relaxationVector => homogState(h)%state0(1:nIntFaceTot,:)
|
||||
stt%work => homogState(h)%state(nIntFaceTot+1,:)
|
||||
stt%penaltyEnergy => homogState(h)%state(nIntFaceTot+2,:)
|
||||
stt%relaxationVector => homogState(ho)%state(1:nIntFaceTot,:)
|
||||
st0%relaxationVector => homogState(ho)%state0(1:nIntFaceTot,:)
|
||||
|
||||
allocate(dst%volumeDiscrepancy( 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
|
||||
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)
|
||||
|
||||
end associate
|
||||
|
||||
enddo
|
||||
|
||||
end subroutine mech_RGC_init
|
||||
end subroutine mechanical_RGC_init
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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 (3,3), intent(in) :: avgF !< averaged F
|
||||
integer, intent(in) :: &
|
||||
instance, &
|
||||
of
|
||||
ce
|
||||
|
||||
real(pReal), dimension(3) :: aVect,nVect
|
||||
integer, dimension(4) :: intFace
|
||||
integer, dimension(3) :: iGrain3
|
||||
integer :: iGrain,iFace,i,j
|
||||
|
||||
associate(prm => param(instance))
|
||||
integer :: iGrain,iFace,i,j,ho,me
|
||||
|
||||
associate(prm => param(material_homogenizationAt2(ce)))
|
||||
|
||||
ho = material_homogenizationAt2(ce)
|
||||
me = material_homogenizationMemberAt2(ce)
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! compute the deformation gradient of individual grains due to relaxations
|
||||
F = 0.0_pReal
|
||||
|
@ -226,8 +218,8 @@ module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of)
|
|||
iGrain3 = grain1to3(iGrain,prm%N_constituents)
|
||||
do iFace = 1,6
|
||||
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
|
||||
nVect = interfaceNormal(intFace,instance,of)
|
||||
aVect = relaxationVector(intFace,ho,me) ! get the relaxation vectors for each interface from global relaxation vector array
|
||||
nVect = interfaceNormal(intFace,ho,me)
|
||||
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
|
||||
enddo
|
||||
|
@ -236,29 +228,27 @@ module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of)
|
|||
|
||||
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
|
||||
! "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
|
||||
real(pReal), dimension(:,:,:), intent(in) :: &
|
||||
P,& !< partitioned stresses
|
||||
F,& !< partitioned deformation gradients
|
||||
F0 !< partitioned initial deformation gradients
|
||||
F !< partitioned deformation gradients
|
||||
real(pReal), dimension(:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses
|
||||
real(pReal), dimension(3,3), intent(in) :: avgF !< average F
|
||||
real(pReal), intent(in) :: dt !< time increment
|
||||
integer, intent(in) :: &
|
||||
ip, & !< integration point number
|
||||
el !< element number
|
||||
ce !< cell
|
||||
|
||||
integer, dimension(4) :: intFaceN,intFaceP,faceID
|
||||
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,size(P,3)) :: NN,devNull
|
||||
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
|
||||
endif zeroTimeStep
|
||||
|
||||
instance = homogenization_typeInstance(material_homogenizationAt(el))
|
||||
of = material_homogenizationMemberAt(ip,el)
|
||||
ho = material_homogenizationAt2(ce)
|
||||
|
||||
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)
|
||||
|
@ -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(resid(3*nIntFaceTot), source=0.0_pReal)
|
||||
allocate(tract(nIntFaceTot,3), source=0.0_pReal)
|
||||
relax = stt%relaxationVector(:,of)
|
||||
drelax = stt%relaxationVector(:,of) - st0%relaxationVector(:,of)
|
||||
allocate(resid(3*nIntFaceTot), source=0.0_pReal)
|
||||
allocate(tract(nIntFaceTot,3), source=0.0_pReal)
|
||||
relax = stt%relaxationVector(:,me)
|
||||
drelax = stt%relaxationVector(:,me) - st0%relaxationVector(:,me)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
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
|
||||
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)
|
||||
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)
|
||||
normN = interfaceNormal(intFaceN,instance,of)
|
||||
normN = interfaceNormal(intFaceN,ho,me)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! identify the right/up/front grain (+|P)
|
||||
iGr3P = iGr3N
|
||||
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)
|
||||
normP = interfaceNormal(intFaceP,instance,of)
|
||||
normP = interfaceNormal(intFaceP,ho,me)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
doneAndHappy = .true.
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! compute/update the state for postResult, i.e., all energy densities computed by time-integration
|
||||
do iGrain = 1,product(prm%N_constituents)
|
||||
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
|
||||
dst%mismatch(1:3,me) = sum(NN,2)/real(nGrain,pReal)
|
||||
dst%relaxationRate_avg(me) = sum(abs(drelax))/dt/real(3*nIntFaceTot,pReal)
|
||||
dst%relaxationRate_max(me) = maxval(abs(drelax))/dt
|
||||
|
||||
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"
|
||||
allocate(smatrix(3*nIntFaceTot,3*nIntFaceTot), source=0.0_pReal)
|
||||
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)
|
||||
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
|
||||
normN = interfaceNormal(intFaceN,instance,of)
|
||||
normN = interfaceNormal(intFaceN,ho,me)
|
||||
do iFace = 1,6
|
||||
intFaceN = getInterface(iFace,iGr3N) ! identifying all interfaces that influence relaxation of the above interface
|
||||
mornN = interfaceNormal(intFaceN,instance,of)
|
||||
iMun = interface4to1(intFaceN,param(instance)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
|
||||
mornN = interfaceNormal(intFaceN,ho,me)
|
||||
iMun = interface4to1(intFaceN,param(ho)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
|
||||
if (iMun > 0) then ! get the corresponding tangent
|
||||
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) &
|
||||
|
@ -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)
|
||||
iGr3P = iGr3N
|
||||
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
|
||||
normP = interfaceNormal(intFaceP,instance,of)
|
||||
normP = interfaceNormal(intFaceP,ho,me)
|
||||
do iFace = 1,6
|
||||
intFaceP = getInterface(iFace,iGr3P) ! identifying all interfaces that influence relaxation of the above interface
|
||||
mornP = interfaceNormal(intFaceP,instance,of)
|
||||
iMun = interface4to1(intFaceP,param(instance)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
|
||||
mornP = interfaceNormal(intFaceP,ho,me)
|
||||
iMun = interface4to1(intFaceP,param(ho)%N_constituents) ! translate the interfaces ID into local 4-dimensional index
|
||||
if (iMun > 0) then ! get the corresponding tangent
|
||||
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) &
|
||||
|
@ -430,31 +409,31 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
|
|||
do ipert = 1,3*nIntFaceTot
|
||||
p_relax = relax
|
||||
p_relax(ipert) = relax(ipert) + num%pPert ! perturb the relaxation vector
|
||||
stt%relaxationVector(:,of) = p_relax
|
||||
call grainDeformation(pF,avgF,instance,of) ! 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 volumePenalty(pD,devNull(1,1), avgF,pF,nGrain,instance,of) ! stress penalty due to volume discrepancy from perturbed state
|
||||
stt%relaxationVector(:,me) = p_relax
|
||||
call grainDeformation(pF,avgF,ho,me) ! rain deformation 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) ! stress penalty due to volume discrepancy from perturbed state
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! computing the global stress residual array from the perturbed state
|
||||
p_resid = 0.0_pReal
|
||||
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)
|
||||
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
|
||||
normN = interfaceNormal(intFaceN,instance,of)
|
||||
normN = interfaceNormal(intFaceN,ho,me)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! identify the right/up/front grain (+|P)
|
||||
iGr3P = iGr3N
|
||||
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
|
||||
normP = interfaceNormal(intFaceP,instance,of)
|
||||
normP = interfaceNormal(intFaceP,ho,me)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
drelax(i) = drelax(i) - jnverse(i,j)*resid(j) ! Calculate the correction for the state variable
|
||||
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
|
||||
doneAndHappy = [.true.,.false.]
|
||||
!$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))
|
||||
flush(IO_STDOUT)
|
||||
!$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
|
||||
!------------------------------------------------------------------------------------------------
|
||||
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) :: nMis !< total amount of mismatch
|
||||
|
||||
real(pReal), dimension (:,:,:), intent(in) :: fDef !< deformation gradients
|
||||
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 (3) :: iGrain3,iGNghb3,nGDim
|
||||
real(pReal), dimension (3,3) :: gDef,nDef
|
||||
real(pReal), dimension (3) :: nVect,surfCorr
|
||||
real(pReal), dimension (2) :: Gmoduli
|
||||
integer :: iGrain,iGNghb,iFace,i,j,k,l
|
||||
real(pReal) :: muGrain,muGNghb,nDefNorm
|
||||
real(pReal), parameter :: &
|
||||
nDefToler = 1.0e-10_pReal, &
|
||||
b = 2.5e-10_pReal ! Length of Burgers vector
|
||||
|
||||
nGDim = param(instance)%N_constituents
|
||||
nGDim = param(ho)%N_constituents
|
||||
rPen = 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
|
||||
! the interfaces due to deformations
|
||||
|
||||
surfCorr = surfaceCorrection(avgF,instance,of)
|
||||
|
||||
associate(prm => param(instance))
|
||||
surfCorr = surfaceCorrection(avgF,ho,me)
|
||||
|
||||
associate(prm => param(ho))
|
||||
|
||||
!-----------------------------------------------------------------------------------------------
|
||||
! computing the mismatch and penalty stress tensor of all grains
|
||||
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
|
||||
|
||||
interfaceLoop: do iFace = 1,6
|
||||
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(abs(intFace(1))) = iGNghb3(abs(intFace(1))) &
|
||||
+ int(real(intFace(1),pReal)/real(abs(intFace(1)),pReal))
|
||||
where(iGNghb3 < 1) iGNghb3 = nGDim
|
||||
where(iGNghb3 >nGDim) iGNghb3 = 1
|
||||
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
|
||||
|
||||
!-------------------------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
!------------------------------------------------------------------------------------------------
|
||||
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), 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 (3,3), intent(in) :: fAvg ! overall deformation gradient
|
||||
integer, intent(in) :: &
|
||||
Ngrain, &
|
||||
instance, &
|
||||
of
|
||||
Ngrain
|
||||
|
||||
real(pReal), dimension(size(vPen,3)) :: gVol
|
||||
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
|
||||
! deformation
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
function surfaceCorrection(avgF,instance,of)
|
||||
function surfaceCorrection(avgF,ho,me)
|
||||
|
||||
real(pReal), dimension(3) :: surfaceCorrection
|
||||
|
||||
real(pReal), dimension(3,3), intent(in) :: avgF !< average F
|
||||
integer, intent(in) :: &
|
||||
instance, &
|
||||
of
|
||||
ho, &
|
||||
me
|
||||
real(pReal), dimension(3,3) :: invC
|
||||
real(pReal), dimension(3) :: nVect
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
!-------------------------------------------------------------------------------------------------
|
||||
real(pReal) function equivalentMu(grainID,ip,el)
|
||||
real(pReal) function equivalentMu(grainID,ce)
|
||||
|
||||
integer, intent(in) :: &
|
||||
grainID,&
|
||||
ip, & !< integration point number
|
||||
el !< element number
|
||||
ce
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
! 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(in) :: avgF !< averaged F
|
||||
integer, intent(in) :: &
|
||||
instance, &
|
||||
of
|
||||
ho, &
|
||||
me
|
||||
|
||||
real(pReal), dimension(3) :: aVect,nVect
|
||||
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
|
||||
|
||||
associate(prm => param(instance))
|
||||
associate (prm => param(ho))
|
||||
|
||||
F = 0.0_pReal
|
||||
do iGrain = 1,product(prm%N_constituents)
|
||||
iGrain3 = grain1to3(iGrain,prm%N_constituents)
|
||||
do iFace = 1,6
|
||||
intFace = getInterface(iFace,iGrain3)
|
||||
aVect = relaxationVector(intFace,instance,of)
|
||||
nVect = interfaceNormal(intFace,instance,of)
|
||||
aVect = relaxationVector(intFace,ho,me)
|
||||
nVect = interfaceNormal(intFace,ho,me)
|
||||
forall (i=1:3,j=1:3) &
|
||||
F(i,j,iGrain) = F(i,j,iGrain) + aVect(i)*nVect(j) ! effective relaxations
|
||||
enddo
|
||||
|
@ -721,49 +698,43 @@ module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) result(doneAndHa
|
|||
|
||||
end subroutine grainDeformation
|
||||
|
||||
end function mech_RGC_updateState
|
||||
end function mechanical_RGC_updateState
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point
|
||||
|
||||
real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses
|
||||
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)
|
||||
dAvgPdAvgF = sum(dPdF,5)/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(ho)%N_constituents),pReal)
|
||||
|
||||
end subroutine mech_RGC_averageStressAndItsTangent
|
||||
end subroutine mechanical_RGC_averageStressAndItsTangent
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @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
|
||||
|
||||
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)
|
||||
select case(trim(prm%output(o)))
|
||||
case('W')
|
||||
call results_writeDataset(group,stt%work,trim(prm%output(o)), &
|
||||
'work density','J/m³')
|
||||
case('M')
|
||||
call results_writeDataset(group,dst%mismatch,trim(prm%output(o)), &
|
||||
'average mismatch tensor','1')
|
||||
case('R')
|
||||
call results_writeDataset(group,stt%penaltyEnergy,trim(prm%output(o)), &
|
||||
'mismatch penalty density','J/m³')
|
||||
case('Delta_V')
|
||||
call results_writeDataset(group,dst%volumeDiscrepancy,trim(prm%output(o)), &
|
||||
'volume discrepancy','m³')
|
||||
|
@ -777,17 +748,17 @@ module subroutine mech_RGC_results(instance,group)
|
|||
enddo outputsLoop
|
||||
end associate
|
||||
|
||||
end subroutine mech_RGC_results
|
||||
end subroutine mechanical_RGC_results
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief collect relaxation vectors of an interface
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
pure function relaxationVector(intFace,instance,of)
|
||||
pure function relaxationVector(intFace,ho,me)
|
||||
|
||||
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 :: iNum
|
||||
|
@ -795,29 +766,35 @@ pure function relaxationVector(intFace,instance,of)
|
|||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
relaxationVector = state(instance)%relaxationVector((3*iNum-2):(3*iNum),of)
|
||||
relaxationVector = stt%relaxationVector((3*iNum-2):(3*iNum),me)
|
||||
else
|
||||
relaxationVector = 0.0_pReal
|
||||
endif
|
||||
|
||||
end associate
|
||||
|
||||
end function relaxationVector
|
||||
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
!> @brief identify the normal of an interface
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
pure function interfaceNormal(intFace,instance,of)
|
||||
pure function interfaceNormal(intFace,ho,me)
|
||||
|
||||
real(pReal), dimension(3) :: interfaceNormal
|
||||
|
||||
integer, dimension(4), intent(in) :: intFace !< interface ID in 4D array (normal and position)
|
||||
integer, intent(in) :: &
|
||||
instance, &
|
||||
of
|
||||
ho, &
|
||||
me
|
||||
|
||||
integer :: nPos
|
||||
associate (dst => dependentState(ho))
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
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
|
||||
|
||||
|
@ -970,4 +949,4 @@ pure function interface1to4(iFace1D, nGDim)
|
|||
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
Loading…
Reference in New Issue